@adhdev/daemon-core 0.9.82-rc.261 → 0.9.82-rc.263

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -83,6 +83,24 @@ export declare function buildMeshActiveWork(opts: BuildMeshActiveWorkOptions): {
83
83
  terminalDirectWork: MeshActiveWorkRecord[];
84
84
  summary: MeshActiveWorkSummary;
85
85
  };
86
+ /**
87
+ * staleReason strings (produced by sessionStatusFromNodes above) that indicate the original
88
+ * node/session is GONE from the live mesh — i.e. the staleDirect record is an orphaned ledger
89
+ * artifact, not active or recoverable work. These are the only reasons safe to prune from the
90
+ * active staleDirect surface. The "no provider acknowledgement" reason is deliberately excluded:
91
+ * those entries have a still-live node/session (staleDispatchUnacknowledged) and represent
92
+ * recoverable dispatch failures, never orphans.
93
+ */
94
+ export declare const PRUNABLE_ORPHAN_STALE_REASONS: ReadonlySet<string>;
95
+ export type StaleDirectPruneClassification = 'prunable_orphan' | 'prunable_terminal' | 'preserve_unacknowledged' | 'preserve_active';
96
+ /**
97
+ * Classify a direct-work record for the staleDirect prune path. Pure function — the prune tool
98
+ * uses this so the safety rules (never touch active work or recoverable unacknowledged dispatches)
99
+ * live next to the staleReason producers and are independently testable.
100
+ */
101
+ export declare function classifyStaleDirectForPrune(record: Pick<MeshActiveWorkRecord, 'staleReason' | 'staleDispatchUnacknowledged' | 'terminal'>, opts?: {
102
+ includeTerminal?: boolean;
103
+ }): StaleDirectPruneClassification;
86
104
  export declare function buildCompactStaleDirectWorkSummary(staleDirectWork: MeshActiveWorkRecord[], opts?: {
87
105
  sampleLimit?: number;
88
106
  detailHint?: string;
@@ -10,19 +10,50 @@ export interface MeshFastForwardNodeArgs {
10
10
  submoduleIgnorePaths?: string[];
11
11
  timeoutMs?: number;
12
12
  trigger?: 'manual' | 'idle_auto' | string;
13
+ /**
14
+ * Operation mode. 'merge' (default) absorbs upstream commits into the local
15
+ * branch via git merge --ff-only (requires ahead=0, behind>0). 'push' publishes
16
+ * local commits to origin via a strict ff-only push (requires HEAD to be a
17
+ * descendant of origin/<branch>); it never force-pushes, resets, or rebases.
18
+ */
19
+ mode?: 'merge' | 'push';
20
+ /**
21
+ * When mode='push', also fast-forward push submodule (e.g. oss) HEADs to their
22
+ * origin main branch. Gated by allowAutoPublishSubmoduleMainCommits — skipped
23
+ * unless that policy is true. Each submodule must still pass the descendant gate.
24
+ * Defaults false (root push only).
25
+ */
26
+ pushSubmodules?: boolean;
27
+ /**
28
+ * Mesh policy flag mirrored from RepoMeshPolicy.allowAutoPublishSubmoduleMainCommits.
29
+ * Submodule pushes are refused unless this is true.
30
+ */
31
+ allowAutoPublishSubmoduleMainCommits?: boolean;
13
32
  }
14
33
  export interface MeshFastForwardPlannedStep {
15
- operation: 'refresh_upstream' | 'verify_clean_worktree' | 'verify_fast_forward' | 'merge_ff_only' | 'submodule_update' | 'verify_post_status';
34
+ operation: 'refresh_upstream' | 'verify_clean_worktree' | 'verify_fast_forward' | 'merge_ff_only' | 'submodule_update' | 'verify_post_status' | 'verify_push_descendant' | 'push_ff_only' | 'push_submodules_ff_only';
16
35
  description: string;
17
36
  safe: true;
18
37
  willMutateWorktree: boolean;
19
38
  }
39
+ export interface MeshFastForwardSubmodulePushResult {
40
+ path: string;
41
+ commit?: string;
42
+ remote: string;
43
+ remoteBranch: string;
44
+ pushed: boolean;
45
+ skipped: boolean;
46
+ code: string;
47
+ refspec?: string;
48
+ error?: string;
49
+ }
20
50
  export interface MeshFastForwardResult {
21
51
  success: boolean;
22
52
  code: string;
23
53
  nodeId?: string;
24
54
  meshId?: string;
25
55
  workspace: string;
56
+ mode: 'merge' | 'push';
26
57
  allowed: boolean;
27
58
  dryRun: boolean;
28
59
  willRun: boolean;
@@ -33,9 +64,18 @@ export interface MeshFastForwardResult {
33
64
  current?: GitRepoStatus;
34
65
  preStatus?: GitRepoStatus;
35
66
  postStatus?: GitRepoStatus;
67
+ /** Push target derived from the tracked upstream (mode='push'). */
68
+ pushTarget?: {
69
+ remote: string;
70
+ remoteBranch: string;
71
+ refspec: string;
72
+ };
73
+ /** Submodule ff-only push outcomes (mode='push' with pushSubmodules). */
74
+ submodulePushes?: MeshFastForwardSubmodulePushResult[];
36
75
  finalBranchConvergenceState?: Record<string, unknown>;
37
76
  operationError?: string;
38
77
  ledgerError?: string;
78
+ nextStep?: string;
39
79
  trigger?: string;
40
80
  }
41
81
  export declare function fastForwardMeshNode(args: MeshFastForwardNodeArgs): Promise<MeshFastForwardResult>;
@@ -14,7 +14,7 @@
14
14
  */
15
15
  import { EventEmitter } from 'events';
16
16
  import { MeshRuntimeStore } from './mesh-runtime-store.js';
17
- export type MeshLedgerKind = 'task_dispatched' | 'task_completed' | 'task_failed' | 'task_stalled' | 'task_approval_needed' | 'p2p_dispatch_failed' | 'session_launched' | 'session_auto_launch' | 'session_stopped' | 'checkpoint_created' | 'node_cloned' | 'node_joined' | 'node_removed' | 'coordinator_started' | 'recovery_attempted' | 'ledger_replicated' | 'ledger_reconciled' | 'direct_fast_forward' | 'delivery_unroutable';
17
+ export type MeshLedgerKind = 'task_dispatched' | 'task_completed' | 'task_failed' | 'task_stalled' | 'task_approval_needed' | 'p2p_dispatch_failed' | 'session_launched' | 'session_auto_launch' | 'session_stopped' | 'checkpoint_created' | 'node_cloned' | 'node_joined' | 'node_removed' | 'coordinator_started' | 'recovery_attempted' | 'ledger_replicated' | 'ledger_reconciled' | 'direct_fast_forward' | 'delivery_unroutable' | 'direct_dispatch_pruned';
18
18
  export interface MeshLedgerEntry {
19
19
  id: string;
20
20
  meshId: string;
@@ -72,6 +72,12 @@ export declare class MeshRuntimeStore {
72
72
  updateDirectDispatchStatus(meshId: string, sessionId: string, status: 'acked' | 'completed' | 'failed' | 'stale'): void;
73
73
  cleanupTerminalDirectDispatches(olderThanMs: number): void;
74
74
  deleteDirectDispatches(meshId: string): void;
75
+ /**
76
+ * Delete specific direct dispatch rows by taskId for a mesh. Used by the staleDirect prune
77
+ * path to remove orphaned/terminal dispatch records whose node/session is no longer in the
78
+ * live mesh. Returns the number of rows actually deleted. No-op for an empty taskId list.
79
+ */
80
+ deleteDirectDispatchesByTaskId(meshId: string, taskIds: string[]): number;
75
81
  markStaleDirectDispatches(meshId: string, olderThanMs: number): void;
76
82
  setRemoteIdleSession(nodeId: string, sessionId: string, providerType: string, expiresAt: number, metadata?: any): void;
77
83
  getRemoteIdleSessions(): Array<{
@@ -243,6 +243,12 @@ export declare function getActiveDirectDispatches(meshId: string): DirectDispatc
243
243
  export declare function updateDirectDispatchStatus(meshId: string, sessionId: string, status: 'acked' | 'completed' | 'failed' | 'stale'): void;
244
244
  export declare function cleanupTerminalDirectDispatches(olderThanMs?: number): void;
245
245
  export declare function markStaleDirectDispatches(meshId: string, olderThanMs?: number): void;
246
+ /**
247
+ * Delete specific direct dispatch rows by taskId. Returns the number of rows deleted.
248
+ * Used by the staleDirect prune path to evict orphaned/terminal dispatch records from the
249
+ * active staleDirect surface while leaving the append-only mesh ledger (audit history) intact.
250
+ */
251
+ export declare function deleteDirectDispatchesByTaskId(meshId: string, taskIds: string[]): number;
246
252
  export type MeshToolCallRateResult = {
247
253
  rateLimitExceeded: boolean;
248
254
  callsInWindow: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.82-rc.261",
3
+ "version": "0.9.82-rc.263",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Daemon build stamp — single runtime source for "which commit is this running
3
+ * daemon built from?".
4
+ *
5
+ * The values are injected at BUILD time via tsup `define` (esbuild global
6
+ * replacement). Every build config that bundles daemon-core into a shippable
7
+ * daemon (daemon-core's own dist, daemon-standalone, daemon-cloud) replaces
8
+ * these `__DAEMON_BUILD_*` identifiers with the literal git commit/version that
9
+ * was current when the bundle was produced. See:
10
+ * - oss/packages/daemon-core/tsup.config.ts (standalone consumes this dist)
11
+ * - packages/daemon-cloud/tsup.config.ts (re-bundles daemon-core from source)
12
+ *
13
+ * If a bundle is produced WITHOUT the define (e.g. running src directly through
14
+ * tsx in dev, or a build env without git), the identifiers stay undefined and
15
+ * we fall back to `"unknown"` — never a ReferenceError, never a build failure.
16
+ *
17
+ * IMPORTANT (live-reflection caveat): a fresh local `daemon-core dist` rebuild +
18
+ * daemon restart is NOT enough to make a *cloud* daemon report a new commit —
19
+ * daemon-cloud ships its own re-bundle of daemon-core, so the build stamp only
20
+ * advances after the cloud daemon is rebuilt/redeployed and restarted. This is
21
+ * precisely the gap `mesh_status`'s `staleDaemonBuild` warning exists to surface.
22
+ */
23
+
24
+ // These are replaced at build time by tsup `define`. `typeof` guards keep this
25
+ // safe when the define is absent (the identifiers are simply not declared).
26
+ declare const __DAEMON_BUILD_COMMIT__: string | undefined;
27
+ declare const __DAEMON_BUILD_COMMIT_SHORT__: string | undefined;
28
+ declare const __DAEMON_BUILD_VERSION__: string | undefined;
29
+ declare const __DAEMON_BUILD_AT__: string | undefined;
30
+
31
+ export interface DaemonBuildInfo {
32
+ /** Full 40-char git commit the daemon bundle was built from, or 'unknown'. */
33
+ commit: string;
34
+ /** Short (7-char) form of the same commit, or 'unknown'. */
35
+ commitShort: string;
36
+ /** package.json version baked in at build time, or 'unknown'. */
37
+ version: string;
38
+ /** ISO build timestamp if the build config injected one. */
39
+ builtAt?: string;
40
+ }
41
+
42
+ function readInjected(value: string | undefined): string | undefined {
43
+ if (typeof value !== 'string') return undefined;
44
+ const trimmed = value.trim();
45
+ if (!trimmed || trimmed === 'unknown') return undefined;
46
+ return trimmed;
47
+ }
48
+
49
+ let cached: DaemonBuildInfo | undefined;
50
+
51
+ /**
52
+ * Resolve the build stamp baked into the running daemon bundle. Pure read of
53
+ * build-time constants — no I/O, safe to call from any runtime path. Cached.
54
+ */
55
+ export function getDaemonBuildInfo(): DaemonBuildInfo {
56
+ if (cached) return cached;
57
+
58
+ const commit =
59
+ readInjected(typeof __DAEMON_BUILD_COMMIT__ !== 'undefined' ? __DAEMON_BUILD_COMMIT__ : undefined)
60
+ ?? 'unknown';
61
+ const commitShort =
62
+ readInjected(typeof __DAEMON_BUILD_COMMIT_SHORT__ !== 'undefined' ? __DAEMON_BUILD_COMMIT_SHORT__ : undefined)
63
+ ?? (commit !== 'unknown' ? commit.slice(0, 7) : 'unknown');
64
+ const version =
65
+ readInjected(typeof __DAEMON_BUILD_VERSION__ !== 'undefined' ? __DAEMON_BUILD_VERSION__ : undefined)
66
+ // Fall back to the runtime-injected package version env used elsewhere.
67
+ ?? readInjected(typeof process !== 'undefined' ? process.env?.ADHDEV_PKG_VERSION : undefined)
68
+ ?? 'unknown';
69
+ const builtAt = readInjected(typeof __DAEMON_BUILD_AT__ !== 'undefined' ? __DAEMON_BUILD_AT__ : undefined);
70
+
71
+ cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
72
+ return cached;
73
+ }