@mstar-harness/engine 3.9.3 → 3.10.0
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/audit.d.ts +23 -7
- package/dist/audit.js +1015 -177
- package/dist/coordination-write.d.ts +170 -0
- package/dist/coordination.d.ts +369 -0
- package/dist/dispatch.d.ts +15 -1
- package/dist/engine.js +4730 -549
- package/dist/index.d.ts +4 -2
- package/dist/iteration.d.ts +33 -1
- package/dist/lease.d.ts +13 -1
- package/dist/migrate.d.ts +48 -1
- package/dist/path.d.ts +15 -6
- package/dist/sdd.d.ts +9 -1
- package/dist/status.d.ts +21 -1
- package/dist/workflow.d.ts +376 -5
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -45,8 +45,8 @@ export type { PlanRow, ResidualEntry, StatusDoc, StatusV2Doc, WorkflowEntry, } f
|
|
|
45
45
|
export { normalizeSeverity, registerWorkflow, resolveCompassEnforcement, resolveMstarcEnforcement, resolveRepoEnforcement, unregisterWorkflow, validatePlanRow, validateResidual, validateStatus, validateStatusV2, validateWorkflowEntry, } from "./status.js";
|
|
46
46
|
export type { ClaimLeaseFields, ExecutionLease, ExecutionLeaseLocations, IntegrationMergeLease, LeaseTransition, LeaseVerifyResult, } from "./lease.js";
|
|
47
47
|
export { canSteal, claimLease, planExecutionLeaseLocations, releaseLease, sameHolderResume, validateExecutionLease, validateIntegrationMergeLease, verifyPlanExecutionLease, withStatusWriteLock, } from "./lease.js";
|
|
48
|
-
export type { CloseWorkflowOptions, WorkflowBranchAnchors, WorkflowExecutionPolicy, WorkflowLifecycleStatus, WorkflowLifecycleType, WorkflowSnapshot, WorkflowSnapshotRead, } from "./workflow.js";
|
|
49
|
-
export { closeWorkflow, isTerminalSnapshot, LEGACY_WORKTREE_PATH_CODE, WORKFLOW_LIFECYCLE_STATUSES, WORKFLOW_LIFECYCLE_TYPES, WORKFLOW_SNAPSHOT_FILE, WORKFLOW_TERMINAL_STATUSES, readWorkflowSnapshot, validateWorkflowSnapshot, writeWorkflowSnapshot, } from "./workflow.js";
|
|
48
|
+
export type { CloseWorkflowOptions, DeclareWorkflowDeliveryKindOptions, DeliveryRegistrationEvidence, RecordWorkflowDeliveryOptions, RecordWorkflowDeliveryResult, RegisterPlanWorkflowOptions, RegisterPlanWorkflowResult, WorkflowBranchAnchors, WorkflowCompoundOutcome, WorkflowDeliveryEvidence, WorkflowDeliveryKind, WorkflowExecutionPolicy, WorkflowLifecycleStatus, WorkflowLifecycleType, WorkflowSnapshot, WorkflowSnapshotRead, } from "./workflow.js";
|
|
49
|
+
export { assertDeliveryRegistrationCoherence, closeWorkflow, consultDeliveryEvidence, declareWorkflowDeliveryKind, isTerminalSnapshot, LEGACY_WORKTREE_PATH_CODE, recordWorkflowDelivery, registerPlanWorkflow, WORKFLOW_COMPOUND_OUTCOMES, WORKFLOW_DELIVERY_KINDS, WORKFLOW_LIFECYCLE_STATUSES, WORKFLOW_LIFECYCLE_TYPES, WORKFLOW_SNAPSHOT_FILE, WORKFLOW_TERMINAL_STATUSES, readWorkflowSnapshot, validateWorkflowSnapshot, writeWorkflowSnapshot, } from "./workflow.js";
|
|
50
50
|
export type { CleanupDecision, CleanupFacts, CleanupTarget, CleanupTargetKind, } from "./cleanup.js";
|
|
51
51
|
export { planWorktreeCleanup } from "./cleanup.js";
|
|
52
52
|
export type { EvidenceArtifactFact, EvidenceAssessment, EvidenceCaptureRequest, EvidenceCoverage, EvidenceEnvironmentKey, EvidenceExpectation, EvidenceInputEntry, EvidenceInputSnapshot, EvidenceInputSpec, EvidenceLimits, EvidenceLog, EvidenceOutcome, EvidenceToolFingerprint, SddEvidenceRecord, } from "./evidence.js";
|
|
@@ -87,3 +87,5 @@ export type { ArtifactDoc, ArtifactKind, ArtifactRef, ArtifactStore } from "./st
|
|
|
87
87
|
export { assertFsStorePath, createFsStore, getArtifactStore, loadStoreModule, resolveArtifactPath, setArtifactStore } from "./store.js";
|
|
88
88
|
export { collectActiveLifecycleBranches, scanActiveLifecycleBranches, type ActiveLifecycleScan } from "./lifecycle-branches.js";
|
|
89
89
|
export { WorkflowSnapshotValidationError } from "./workflow.js";
|
|
90
|
+
export { CoordinationError, amendPrepareWorkflow, bindPlanSession, mutatePlanCoordination, readCoordinatedArtifact, readPlanCoordination, readSessionEnvelope, replaceCoordinatedArtifact, resolvePlanScope, resolveProcessHarnessDir, showPrepareWorkflow, } from "./coordination.js";
|
|
91
|
+
export type { BindPlanSessionInput, CoordinatedReplacement, CoordinationRequest, CoordinationResult, CoordinationRole, CoordinationSession, HandoffEvidence, PlanCoordinationOperation, PlanCoordinationView, PlanScopeInput, PrepareCoordinationRequest, PreparePlanAppend, PrepareWorkflowPatch, PrepareWorkflowResult, PrepareWorkflowView, ProgressCoordinationRequest, ResidualAddCoordinationRequest, ResidualCloseCoordinationRequest, ResidualInput, ResolvedPlanScope, VersionedArtifact, } from "./coordination.js";
|
package/dist/iteration.d.ts
CHANGED
|
@@ -120,7 +120,39 @@ export declare function evaluatePhaseGate(snapshotDoc: SnapshotDoc, compassDoc:
|
|
|
120
120
|
* `evaluatePhaseGate` / `PhaseGateResult` (Phase 2–5 exit codes stay
|
|
121
121
|
* intact). Stable machine codes: `PHASE6_NOT_TERMINAL`,
|
|
122
122
|
* `PHASE6_ROOT_ENTRY_PRESENT`, `PHASE6_DANGLING_LEASE`,
|
|
123
|
-
* `PHASE6_INVALID_SNAPSHOT`, `PHASE6_INVALID_ROOT
|
|
123
|
+
* `PHASE6_INVALID_SNAPSHOT`, `PHASE6_INVALID_ROOT`,
|
|
124
|
+
* `PHASE6_DELIVERY_KIND_UNREGISTERED`, `PHASE6_DELIVERY_EVIDENCE_INCOMPLETE`,
|
|
125
|
+
* `PHASE6_PLAN_ROW_NOT_DONE`.
|
|
126
|
+
*
|
|
127
|
+
* Plan-type delivery-kind consultation (seam S3, contract §6 S3 + §4g): a
|
|
128
|
+
* terminal `type: plan` snapshot also consults the delivery evidence recorded
|
|
129
|
+
* over the lifecycle — plan rows are the owned plan (no compass input) and
|
|
130
|
+
* remote merge verification stays excluded by contract (§4f is the PM's
|
|
131
|
+
* separate check). The consultation is the shared pure function
|
|
132
|
+
* `consultDeliveryEvidence` (workflow.ts), which `closeWorkflow` runs before
|
|
133
|
+
* writing a terminal snapshot — one implementation, so this read-only gate
|
|
134
|
+
* and the write path can never disagree. It runs for a `completed` close ONLY:
|
|
135
|
+
* `failed`/`stopped` closes are never demanded delivery evidence (§5 — failure
|
|
136
|
+
* closes through its explicit status with a recorded reason and is never
|
|
137
|
+
* treated as delivered), exactly as `closeWorkflow` preserves an
|
|
138
|
+
* already-terminal snapshot unchanged without consulting; the type-generic
|
|
139
|
+
* dangling-lease probe still covers every terminal status. The kind is never
|
|
140
|
+
* inferred (§1): a plan workflow without a registered `delivery_kind` has no
|
|
141
|
+
* close-verifiable delivery evidence — for a legacy terminal snapshot this is
|
|
142
|
+
* outside the gate's automated recovery, because the create-only register
|
|
143
|
+
* cannot backfill terminal bytes, so the remediation names the owner
|
|
144
|
+
* snapshot-amendment path (the audit-promotion grandfather population is
|
|
145
|
+
* disclosed there) instead of the register verb — and a registered kind with
|
|
146
|
+
* incomplete delivery evidence (`development` without its registered
|
|
147
|
+
* source/target branches, its compound disposition, its PR identity or the
|
|
148
|
+
* PM's verified-merge record; `verification/report-only` without the recorded
|
|
149
|
+
* completion policy or its fulfilment record) refuses the same way — missing
|
|
150
|
+
* fields are incomplete registration, not an exempt workflow. A `completed`
|
|
151
|
+
* close additionally requires every owned plan row `Done` (the post-write
|
|
152
|
+
* mirror of `closeWorkflow`'s all-rows-Done guard, §3 terminal stage);
|
|
153
|
+
* `failed`/`stopped` lifecycles keep their statuses and row states (§5 —
|
|
154
|
+
* never rewritten as successfully completed). Every refusal is read-only: the
|
|
155
|
+
* workflow stays registered/resumable.
|
|
124
156
|
*/
|
|
125
157
|
export declare function evaluatePostMergeClose(snapshotDoc: SnapshotDoc, rootDoc: unknown): GateResult;
|
|
126
158
|
/**
|
package/dist/lease.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export type ClaimLeaseFields = {
|
|
|
42
42
|
export type LeaseTransition = {
|
|
43
43
|
ok: boolean;
|
|
44
44
|
row: PlanRow;
|
|
45
|
-
outcome?: "claimed" | "resumed" | "released";
|
|
45
|
+
outcome?: "claimed" | "resumed" | "released" | "transferred";
|
|
46
46
|
violations: ValidationResult[];
|
|
47
47
|
};
|
|
48
48
|
/**
|
|
@@ -103,6 +103,18 @@ export declare function claimLease(row: PlanRow, holder: string, fields: ClaimLe
|
|
|
103
103
|
* protocol); the caller enforces that ordering around the locked update.
|
|
104
104
|
*/
|
|
105
105
|
export declare function releaseLease(row: PlanRow, holder: string): LeaseTransition;
|
|
106
|
+
/**
|
|
107
|
+
* Holder transfer for the scoped coordination `accept` transition (spec §D):
|
|
108
|
+
* move an ACTIVE `execution_lease` to another holder verbatim — same
|
|
109
|
+
* `claimed_at`, `worktree_path`, `working_branch`, extra fields preserved;
|
|
110
|
+
* only `holder` changes. Deliberately NOT `claimLease`: there is no
|
|
111
|
+
* Todo/Blocked → InProgress transition and no steal path here. The locked
|
|
112
|
+
* coordination writer has already authenticated the receiving holder as the
|
|
113
|
+
* workflow's coordinator, so `from` must still match the stored holder — a
|
|
114
|
+
* mismatched `from` is `lease.transfer.other-holder` and leaves the row
|
|
115
|
+
* untouched.
|
|
116
|
+
*/
|
|
117
|
+
export declare function transferLease(row: PlanRow, from: string, to: string): LeaseTransition;
|
|
106
118
|
/**
|
|
107
119
|
* Same-holder resume check (status-and-residuals.md § Claim-before-`InProgress`
|
|
108
120
|
* #2): `true` iff the stored lease `holder` equals the session `holder`.
|
package/dist/migrate.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ProjectRegisterDoc } from "./project.js";
|
|
2
2
|
import { type StatusV2Doc } from "./status.js";
|
|
3
|
-
import { type WorkflowLifecycleStatus, type WorkflowLifecycleType, type WorkflowSnapshot } from "./workflow.js";
|
|
3
|
+
import { type WorkflowDeliveryKind, type WorkflowLifecycleStatus, type WorkflowLifecycleType, type WorkflowSnapshot } from "./workflow.js";
|
|
4
4
|
/** Root status file name inside `{HARNESS_DIR}` (v1 input / v2 output). */
|
|
5
5
|
export declare const MIGRATE_STATUS_FILE = "status.json";
|
|
6
6
|
/** Legacy v1 root copy written by migration (never deleted without it). */
|
|
@@ -62,6 +62,21 @@ export type MigrateOptions = {
|
|
|
62
62
|
dryRun?: boolean;
|
|
63
63
|
/** Project id for the register/roadmap home (default `_default`). */
|
|
64
64
|
projectId?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Delivery kind declared for the ACTIVE standalone plan snapshots this lift
|
|
67
|
+
* produces (contract §1/§4a). A v1 `plans[]` row becomes a `type: plan`
|
|
68
|
+
* lifecycle, so its delivery kind is declared at registration and never
|
|
69
|
+
* inferred: the CLI/API caller passes it explicitly, and a lift that would
|
|
70
|
+
* create an active kind-less plan snapshot without it is refused (see
|
|
71
|
+
* `MigratePlan.deliveryKindRequired`).
|
|
72
|
+
*/
|
|
73
|
+
deliveryKind?: WorkflowDeliveryKind;
|
|
74
|
+
/** Delivery source branch, recorded as `branch.source`. Required for `development`. */
|
|
75
|
+
branchSource?: string;
|
|
76
|
+
/** Delivery target branch, recorded as `branch.target`. Required for `development`. */
|
|
77
|
+
branchTarget?: string;
|
|
78
|
+
/** Completion policy for `verification/report-only` lifts. Required for that kind. */
|
|
79
|
+
completionPolicy?: string;
|
|
65
80
|
};
|
|
66
81
|
/** Full migration plan: every write is described; the executor applies it. */
|
|
67
82
|
export type MigratePlan = {
|
|
@@ -84,11 +99,43 @@ export type MigratePlan = {
|
|
|
84
99
|
*/
|
|
85
100
|
projectDir: string;
|
|
86
101
|
dryRun: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Byte version (`sha256:…`, or `"absent"`) of the source `status.json` this
|
|
104
|
+
* plan was derived from (spec §C3 source-version CAS). The executor
|
|
105
|
+
* re-reads the source under the root lock before its first write and
|
|
106
|
+
* refuses a root whose bytes moved after planning — a still-v1 document
|
|
107
|
+
* changed by another writer is never silently replaced.
|
|
108
|
+
*/
|
|
109
|
+
sourceVersion: string;
|
|
87
110
|
/** Root status.json already at `version: 2` -> nothing to plan/apply. */
|
|
88
111
|
alreadyMigrated: boolean;
|
|
89
112
|
/** Human message (no-op reason when `alreadyMigrated`). */
|
|
90
113
|
message: string;
|
|
91
114
|
snapshots: MigrateSnapshot[];
|
|
115
|
+
/**
|
|
116
|
+
* Ids of the ACTIVE (running/paused) standalone plan snapshots this lift
|
|
117
|
+
* would create WITHOUT a declared delivery kind — i.e. the v1 rows lifted
|
|
118
|
+
* before the operator passed `opts.deliveryKind`. Non-empty means the plan is
|
|
119
|
+
* NOT applicable: `applyMigratePlan` refuses it (a close path could never
|
|
120
|
+
* complete such a lifecycle), and the CLI reports the missing flag as usage
|
|
121
|
+
* (exit 2) before any write. Terminal (completed) lifted snapshots are exempt
|
|
122
|
+
* — a finished lifecycle declares nothing (§1; the legacy terminal dead end
|
|
123
|
+
* is documented, not amended here).
|
|
124
|
+
*/
|
|
125
|
+
deliveryKindRequired: string[];
|
|
126
|
+
/**
|
|
127
|
+
* Ids of the ACTIVE (running/paused) standalone plan snapshots the single
|
|
128
|
+
* `opts.deliveryKind` declaration would be stamped onto when MORE THAN ONE
|
|
129
|
+
* lift qualifies. The declaration is one (kind, anchors, policy) tuple — one
|
|
130
|
+
* delivery identity, and the kind is per-workflow registration evidence (§1)
|
|
131
|
+
* — so it cannot describe several lifecycles at once. Non-empty means the
|
|
132
|
+
* plan is NOT applicable: `applyMigratePlan` refuses it and the CLI reports
|
|
133
|
+
* the ambiguity as usage (exit 2) before any write, so the operator migrates
|
|
134
|
+
* the tree in batches of one declared plan instead of pinning one identity
|
|
135
|
+
* onto several. Empty when no declaration was given or exactly one lift
|
|
136
|
+
* qualifies; terminal lifts are exempt like `deliveryKindRequired`.
|
|
137
|
+
*/
|
|
138
|
+
deliveryKindAmbiguous: string[];
|
|
92
139
|
notesFiles: MigrateNotesFile[];
|
|
93
140
|
register: MigrateRegister | null;
|
|
94
141
|
roadmap: MigrateRoadmap | null;
|
package/dist/path.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ValidationResult } from "./core.js";
|
|
2
2
|
/**
|
|
3
3
|
* Options for `resolveHarnessDir`.
|
|
4
4
|
*/
|
|
@@ -164,11 +164,20 @@ export declare function resolveScaffoldDirs(root: string): {
|
|
|
164
164
|
* `.mstarc`-declared `project_dir`) with a valid `roadmap.md` + empty
|
|
165
165
|
* `residuals.json` (plan-conventions § 初始化 Plan 目录;
|
|
166
166
|
* mstar-project-governance § `_default` 回退). Idempotent: an existing
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
|
|
171
|
-
|
|
167
|
+
* `roadmap.md` is never clobbered, and re-running on an initialized tree only
|
|
168
|
+
* creates missing pieces. Returns the absolute resolved harness dir.
|
|
169
|
+
*
|
|
170
|
+
* The two coordination documents (`status.json`, `_default/residuals.json`)
|
|
171
|
+
* are written create-only through the active `ArtifactStore` inside the
|
|
172
|
+
* private protected-write context, serialized on the target's
|
|
173
|
+
* `withStatusWriteLock` (spec §C4): a concurrent writer's bytes are never
|
|
174
|
+
* replaced, and an existing empty/malformed document fails validation instead
|
|
175
|
+
* of being silently reinitialized. Callers whose target root differs from the
|
|
176
|
+
* active store's root MUST `setArtifactStore(createFsStore(<harnessRoot>))`
|
|
177
|
+
* first (same contract as the other routed writers). No scoped session or
|
|
178
|
+
* coordination record is created here.
|
|
179
|
+
*/
|
|
180
|
+
export declare function scaffoldHarness(root: string): Promise<string>;
|
|
172
181
|
/**
|
|
173
182
|
* Harness kind for the gitignore fence — the canonical snippet is per
|
|
174
183
|
* harness layout (plan-conventions § Git 跟踪策略): `.mstar/` (default) and
|
package/dist/sdd.d.ts
CHANGED
|
@@ -253,7 +253,15 @@ export type SddActionKind = "source" | "artifact" | "launch";
|
|
|
253
253
|
* the context must then match the verified lease exactly. Without an
|
|
254
254
|
* active lease (no row, or a non-InProgress row without lease), the
|
|
255
255
|
* standalone branch policy applies (`assertBranchAlignment`) — an
|
|
256
|
-
* InProgress row without lease is the orphan refusal.
|
|
256
|
+
* InProgress row without lease is the orphan refusal. The one admission
|
|
257
|
+
* exception (lifecycle contract §4b/§6 S2): on a register-governed harness
|
|
258
|
+
* root (readable v2 `status.json` `workflows[]`), a plan with NO active
|
|
259
|
+
* registered row is an unregistered normal-route plan — refused with
|
|
260
|
+
* `sdd.context.plan-not-registered` and the register/recovery path; branch
|
|
261
|
+
* alignment never substitutes for registration, and a plan id retained only
|
|
262
|
+
* in a terminal snapshot is refused the same way (a retained row is history,
|
|
263
|
+
* not registration evidence — §4b). Roots without a v2 register keep the
|
|
264
|
+
* standalone policy byte-for-byte.
|
|
257
265
|
*
|
|
258
266
|
* Throws `SddScriptError` — exit 2 when the declared context itself is
|
|
259
267
|
* malformed (non-absolute path, identity/composition mismatch, missing plan
|
package/dist/status.d.ts
CHANGED
|
@@ -63,6 +63,18 @@ export type PlanRow = {
|
|
|
63
63
|
execution_lease?: unknown;
|
|
64
64
|
[key: string]: unknown;
|
|
65
65
|
};
|
|
66
|
+
/**
|
|
67
|
+
* Every plan id a `plans[]` row can be addressed by (status-and-residuals.md
|
|
68
|
+
* § Compatibility: read accepts `id` or the legacy `plan_id`; write prefers
|
|
69
|
+
* `id`). Both non-empty keys are reported, in canonical-first order: a row
|
|
70
|
+
* whose two keys disagree is ambiguous (`status.plan-row.dual-id`), and an
|
|
71
|
+
* ownership guard keyed on one of them would let the other escape protection.
|
|
72
|
+
* Empty strings never count; a non-object or a row carrying neither key has
|
|
73
|
+
* no address.
|
|
74
|
+
*/
|
|
75
|
+
export declare function rowPlanIds(row: unknown): string[];
|
|
76
|
+
/** The canonical single plan id of a row — `id`, else legacy `plan_id`. */
|
|
77
|
+
export declare function rowPlanId(row: unknown): string | undefined;
|
|
66
78
|
/**
|
|
67
79
|
* Normalize a residual `severity` value for reading/rolling up
|
|
68
80
|
* (status-and-residuals.md § severity 5 + rollup `norm_sev`):
|
|
@@ -156,6 +168,11 @@ export declare const validateStatus: typeof validateStatusV2;
|
|
|
156
168
|
* an invalid entry would fail `validateStatusV2` anyway, but the explicit
|
|
157
169
|
* gate keeps the pre-lock fail-fast contract of `registerWorkflow`).
|
|
158
170
|
*
|
|
171
|
+
* Replacing an existing entry additionally takes that entry's snapshot lock
|
|
172
|
+
* (spec §C3 root → snapshot order, `withRegisteredSnapshotLock`) and holds it
|
|
173
|
+
* across the root write; callers must therefore hold the root lock only, not
|
|
174
|
+
* a snapshot lock.
|
|
175
|
+
*
|
|
159
176
|
* Async-only (architect-locked 2026-08-27): the durable write goes through
|
|
160
177
|
* `getArtifactStore().put({ kind: "status", key: "root", ... })` inside the
|
|
161
178
|
* caller's lock — the store is the persist backend, never a second lock.
|
|
@@ -185,7 +202,10 @@ export declare function registerWorkflow(root: string, entry: WorkflowEntry): Pr
|
|
|
185
202
|
* `withStatusWriteLock`, bumping root `updated_at` only when an entry was
|
|
186
203
|
* actually removed. The final document is validated (removal-at-terminal
|
|
187
204
|
* invariant included) before the write — a v1 root is refused with the
|
|
188
|
-
* `mstar migrate` hint.
|
|
205
|
+
* `mstar migrate` hint. Removing a registered entry additionally takes that
|
|
206
|
+
* entry's snapshot lock (spec §C3 root → snapshot order) and holds it across
|
|
207
|
+
* the root write, so the coordination check cannot be raced by a concurrent
|
|
208
|
+
* bind.
|
|
189
209
|
*
|
|
190
210
|
* Fails loud when the active FsStore would resolve its
|
|
191
211
|
* `status.json` to a path other than the caller's root — the no-op branches
|