@adhdev/daemon-core 0.9.82-rc.523 → 0.9.82-rc.525
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.
- package/dist/commands/router-refine.d.ts +86 -5
- package/dist/commands/router.d.ts +9 -0
- package/dist/git/git-status.d.ts +14 -1
- package/dist/index.js +641 -159
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +641 -159
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-queue-assignment.d.ts +13 -0
- package/dist/mesh/mesh-refine-gates.d.ts +5 -0
- package/dist/mesh/refine-config.d.ts +36 -0
- package/package.json +3 -3
- package/src/commands/router-refine.ts +756 -164
- package/src/commands/router.ts +9 -0
- package/src/git/git-status.ts +38 -6
- package/src/mesh/mesh-queue-assignment.ts +64 -2
- package/src/mesh/mesh-reconcile-loop.ts +18 -1
- package/src/mesh/mesh-refine-gates.ts +49 -1
- package/src/mesh/refine-config.ts +44 -0
|
@@ -13,6 +13,23 @@ export declare function buildRefineJobHandle(self: DaemonCommandRouter, args: {
|
|
|
13
13
|
retryOfJobId?: string;
|
|
14
14
|
coordinatorDaemonId?: string;
|
|
15
15
|
}): MeshRefineJobHandle;
|
|
16
|
+
/**
|
|
17
|
+
* QW2: extract a compact failure diagnostic from a validation summary — the first
|
|
18
|
+
* failing command's name, its exit code, its failureKind, and a bounded output tail.
|
|
19
|
+
* Surfaced in BOTH the slim coordinator event and the ledger blockerContext so a
|
|
20
|
+
* coordinator can decide next-step without pulling and parsing the full ledger record.
|
|
21
|
+
*
|
|
22
|
+
* A command record carries `passed` (boolean), never `success` (see QW1) — the first
|
|
23
|
+
* record with passed===false is the gate's failing command. Returns undefined when the
|
|
24
|
+
* summary did not fail on a command (e.g. bootstrap-stage failure with no commandsRun
|
|
25
|
+
* entry), in which case the top-level failureCode/failureKind still describe the cause.
|
|
26
|
+
*/
|
|
27
|
+
export declare function extractValidationFailureDiagnostics(validationSummary: Record<string, unknown> | undefined): {
|
|
28
|
+
firstFailedCommand?: string;
|
|
29
|
+
exitCode?: unknown;
|
|
30
|
+
failureKind?: unknown;
|
|
31
|
+
outputTail?: string;
|
|
32
|
+
} | undefined;
|
|
16
33
|
/**
|
|
17
34
|
* Slim the terminal-stage refine result down to the fields a coordinator needs to
|
|
18
35
|
* decide next-step, dropping the heavy per-command / per-entry detail.
|
|
@@ -52,6 +69,26 @@ export declare function executeMeshRefineNodeSynchronously(self: DaemonCommandRo
|
|
|
52
69
|
* branch head. Seeds the RefineContext consumed by every later stage.
|
|
53
70
|
*/
|
|
54
71
|
export declare function refineResolveRefsStage(self: DaemonCommandRouter, meshId: string, nodeId: string, args: any, refineStages: Array<Record<string, unknown>>): Promise<RefineStageOutcome>;
|
|
72
|
+
/**
|
|
73
|
+
* DS2 sync_base stage: bring the worktree branch up to the pinned baseHead BEFORE
|
|
74
|
+
* validation, so every later gate (validation, patch_equivalence, merge) sees the
|
|
75
|
+
* final rebased tree rather than a stale pre-rebase one.
|
|
76
|
+
*
|
|
77
|
+
* The old auto-rebase lived inside patch_equivalence and only fired when branchHead
|
|
78
|
+
* was a STRICT ANCESTOR of baseHead (`merge-base --is-ancestor`). A diverged laggard
|
|
79
|
+
* — the branch has its own commits AND base moved underneath it (ahead>0 AND behind>0)
|
|
80
|
+
* — failed that ancestor check, so it was never rebased and fell straight to
|
|
81
|
+
* patch_equivalence_failed / blocked_review even though a clean rebase would have
|
|
82
|
+
* converged it. Here we compute ahead/behind explicitly and rebase whenever behind>0
|
|
83
|
+
* (strictly-behind OR diverged), aborting to blocked_review only on a real conflict.
|
|
84
|
+
*
|
|
85
|
+
* On a successful rebase we recompute branchHead and re-derive changeImpact against
|
|
86
|
+
* the rebased tree (its baseHead..branchHead diff changed), and record the
|
|
87
|
+
* `patch_equivalence_after_auto_rebase` stage so the batch/ancestry assertions can see
|
|
88
|
+
* the rebase happened. When the branch is already up to date (behind===0), this is a
|
|
89
|
+
* no-op passed stage.
|
|
90
|
+
*/
|
|
91
|
+
export declare function refineSyncBaseStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
|
|
55
92
|
/**
|
|
56
93
|
* validation stage: run the refinery validation gate (typecheck / test /
|
|
57
94
|
* lint / build per node config) and block on failure or when no allowlisted
|
|
@@ -59,11 +96,11 @@ export declare function refineResolveRefsStage(self: DaemonCommandRouter, meshId
|
|
|
59
96
|
*/
|
|
60
97
|
export declare function refineValidationStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
|
|
61
98
|
/**
|
|
62
|
-
* patch_equivalence stage: preflight that the worktree branch's cumulative
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* already-merged-via-another-path
|
|
66
|
-
*
|
|
99
|
+
* patch_equivalence stage: preflight that the worktree branch's cumulative patch is
|
|
100
|
+
* equivalent to base+branch. The DS2 sync_base stage already rebased any behind/diverged
|
|
101
|
+
* branch onto the pinned baseHead, so this is now a pure check: equivalent → continue;
|
|
102
|
+
* empty merge-tree with real branch changes → already-merged-via-another-path
|
|
103
|
+
* short-circuit to cleanup; otherwise → patch_equivalence_failed / blocked_review.
|
|
67
104
|
*/
|
|
68
105
|
export declare function refinePatchEquivalenceStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
|
|
69
106
|
/**
|
|
@@ -80,6 +117,33 @@ export declare function refineSubmoduleReachabilityStage(self: DaemonCommandRout
|
|
|
80
117
|
* never committed, so the merge would land nothing real on main.
|
|
81
118
|
*/
|
|
82
119
|
export declare function refineEffectiveDiffStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
|
|
120
|
+
/**
|
|
121
|
+
* DS3: after a successful Refinery push advanced origin/<baseBranch>, bring the
|
|
122
|
+
* ORIGINATING COORDINATOR daemon's own local base checkout up to the pushed commit so
|
|
123
|
+
* the coordinator isn't silently left behind (the "merged to main but my local main is
|
|
124
|
+
* stale" gap). Guarded and NON-destructive:
|
|
125
|
+
*
|
|
126
|
+
* - If the coordinator's base node is hosted by THIS daemon and is reachable locally,
|
|
127
|
+
* run fastForwardMeshNode(mode:'merge') on it directly. That helper is itself the
|
|
128
|
+
* guard: it only ff-only-merges when the workspace is clean, ahead=0 and behind>0;
|
|
129
|
+
* an ahead/diverged/dirty coordinator returns a structured block (never a rebase).
|
|
130
|
+
* - If the coordinator is a DIFFERENT daemon (remote), we cannot touch its checkout
|
|
131
|
+
* from here, so we queue a `coordinator_catchup` pending event targeted at that
|
|
132
|
+
* coordinator daemon; its reconcile loop / next mesh-tool call drains it and runs the
|
|
133
|
+
* same guarded fast-forward locally (busy → naturally deferred to the next idle edge).
|
|
134
|
+
*
|
|
135
|
+
* Best-effort and advisory: the caller never fails the refine on a catch-up problem. The
|
|
136
|
+
* refine's own repoRoot IS the base it just merged+pushed, so when the coordinator IS this
|
|
137
|
+
* daemon and IS repoRoot the ff is a no-op `already_up_to_date` — correct and harmless.
|
|
138
|
+
* Returns a compact summary for the stage record, or undefined when there's nothing to do.
|
|
139
|
+
*/
|
|
140
|
+
export declare function requestCoordinatorLocalCatchup(self: DaemonCommandRouter, params: {
|
|
141
|
+
meshId: string;
|
|
142
|
+
ctx: RefineContext;
|
|
143
|
+
mesh: any;
|
|
144
|
+
baseBranch: string;
|
|
145
|
+
repoRoot: string;
|
|
146
|
+
}): Promise<Record<string, unknown> | undefined>;
|
|
83
147
|
/**
|
|
84
148
|
* merge + finalize stage: perform the --no-ff merge, align submodule
|
|
85
149
|
* checkouts after merge, clean up (remove) the worktree node per policy,
|
|
@@ -87,6 +151,16 @@ export declare function refineEffectiveDiffStage(self: DaemonCommandRouter, ctx:
|
|
|
87
151
|
* base branch. Always terminal — produces the final CommandRouterResult.
|
|
88
152
|
*/
|
|
89
153
|
export declare function refineMergeAndFinalizeStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
|
|
154
|
+
/**
|
|
155
|
+
* DS2 CAS + DS1 order: the base-lease-protected core of merge/finalize. Before the
|
|
156
|
+
* merge it re-fetches origin/<baseBranch> and compare-and-swaps the live origin SHA
|
|
157
|
+
* against the pinned baseHead from resolve_refs; if the base moved, it terminates
|
|
158
|
+
* retryable (base_moved) WITHOUT merging so a re-run rebases onto and validates the
|
|
159
|
+
* new base. DS1: on the auto-push path the order is merge → push → cleanup, so a push
|
|
160
|
+
* failure leaves the worktree/branch intact (cleanup withheld) and is reported as a
|
|
161
|
+
* terminal blocked state — the batch never counts an un-pushed node as merged.
|
|
162
|
+
*/
|
|
163
|
+
export declare function runRefineMergeAndFinalizeLocked(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
|
|
90
164
|
/**
|
|
91
165
|
* Batch refinery: converge multiple sibling worktree nodes onto the base branch
|
|
92
166
|
* in one sequential pipeline, absorbing the rebase + patch-equivalence churn that
|
|
@@ -101,6 +175,13 @@ export declare function refineMergeAndFinalizeStage(self: DaemonCommandRouter, c
|
|
|
101
175
|
* isolated as blocked_review while the rest of the batch proceeds.
|
|
102
176
|
*/
|
|
103
177
|
export declare function batchRefineMeshNodes(self: DaemonCommandRouter, meshId: string, requestedNodeIds: string[] | undefined, args: any): Promise<CommandRouterResult>;
|
|
178
|
+
export type BatchNodeConvergence = 'merged_to_main' | 'blocked_review' | 'skipped_patch_equivalent' | 'not_mergeable';
|
|
179
|
+
export declare function classifyBatchNodeConvergence(result: Record<string, unknown>): {
|
|
180
|
+
convergence: BatchNodeConvergence;
|
|
181
|
+
code: string;
|
|
182
|
+
stage?: string;
|
|
183
|
+
retryable: boolean;
|
|
184
|
+
};
|
|
104
185
|
/**
|
|
105
186
|
* Convergence core shared by the synchronous batch entry and the async batch job.
|
|
106
187
|
* Refines each node in order: the per-node refine pipeline fetches origin/<base>
|
|
@@ -137,6 +137,15 @@ export declare class DaemonCommandRouter {
|
|
|
137
137
|
runningRefineBatchJobs: Map<string, MeshRefineBatchJobHandle>;
|
|
138
138
|
/** Terminal async batch Refinery jobs preserve the last batch outcome for late readers. */
|
|
139
139
|
terminalRefineBatchJobs: Map<string, MeshRefineBatchTerminalJob>;
|
|
140
|
+
/**
|
|
141
|
+
* DS2: in-process refinement leases keyed by `${repoRoot}::${baseBranch}`. Serialize
|
|
142
|
+
* the base-mutating window (candidate-SHA pin → merge → push) of concurrent single-node
|
|
143
|
+
* refines that target the SAME base branch in the same repo, so two refines cannot both
|
|
144
|
+
* validate against one baseHead and then race their merges (the base-movement race). The
|
|
145
|
+
* batch path is already sequential, so this only matters for overlapping single-node
|
|
146
|
+
* async jobs. Value = the meshId:nodeId job key holding the lease (for diagnostics).
|
|
147
|
+
*/
|
|
148
|
+
refineBaseLeases: Map<string, string>;
|
|
140
149
|
constructor(deps: CommandRouterDeps);
|
|
141
150
|
private hydrateCachedAggregateMeshStatusFromInline;
|
|
142
151
|
private getCachedAggregateMeshStatus;
|
package/dist/git/git-status.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { GitRepoStatus } from './git-types.js';
|
|
2
2
|
import { type DaemonBuildInfo } from '../build-info.js';
|
|
3
|
-
import { type ChangeImpactConfig } from './change-impact-config.js';
|
|
3
|
+
import { type ChangeImpactConfig, type ChangeImpactKind } from './change-impact-config.js';
|
|
4
4
|
/**
|
|
5
5
|
* TTL for the happy-path result cache (C1). reconcile fires every 4s and mesh_status
|
|
6
6
|
* is polled; a single getGitRepoStatus on a 1-submodule repo spawns ~13-15 git
|
|
@@ -71,6 +71,19 @@ export declare function getGitRepoStatus(workspace: string, options?: GitStatusO
|
|
|
71
71
|
export interface ChangedPackageClassification {
|
|
72
72
|
isDaemonAffecting: boolean;
|
|
73
73
|
affectedPackages: string[];
|
|
74
|
+
/**
|
|
75
|
+
* DOCS-ROOT: three-way change area, refining the binary isDaemonAffecting so a
|
|
76
|
+
* docs-only branch is distinguishable from a code (web) branch:
|
|
77
|
+
* 'daemon' — a daemon-runtime package (or an unknown/ambiguous path) changed;
|
|
78
|
+
* full validation + daemon rebuild/restart required.
|
|
79
|
+
* 'web' — only web-only packages changed; web validation but no daemon restart.
|
|
80
|
+
* 'none' — no package changed at all; every changed file is a benign non-runtime
|
|
81
|
+
* root file (docs/markers). No code validation is meaningful — only an
|
|
82
|
+
* explicit docs-scoped profile (e.g. docs:verify) should run.
|
|
83
|
+
* Derived from the same facts as isDaemonAffecting, so it never contradicts it
|
|
84
|
+
* (changeArea === 'daemon' ⇔ isDaemonAffecting === true).
|
|
85
|
+
*/
|
|
86
|
+
changeArea: ChangeImpactKind;
|
|
74
87
|
}
|
|
75
88
|
/**
|
|
76
89
|
* Ref-parameterized change-impact classification for a repo/worktree, reusing the
|