@mstar-harness/engine 3.8.3 → 3.9.1
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.js +4 -4
- package/dist/cleanup.d.ts +90 -0
- package/dist/engine.js +3127 -1525
- package/dist/evidence.d.ts +174 -0
- package/dist/index.d.ts +18 -7
- package/dist/iteration.d.ts +35 -5
- package/dist/lifecycle-branches.d.ts +17 -0
- package/dist/sdd.d.ts +22 -15
- package/dist/status.d.ts +1 -0
- package/dist/workflow.d.ts +60 -5
- package/dist/worktree.d.ts +65 -15
- package/package.json +1 -1
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type { GateResult } from "./core.js";
|
|
2
|
+
import type { SddExecutionContext } from "./sdd.js";
|
|
3
|
+
export type EvidenceEnvironmentKey = "CI" | "NODE_ENV" | "TZ" | "LANG";
|
|
4
|
+
export type EvidenceInputSpec = {
|
|
5
|
+
path: string;
|
|
6
|
+
kind: "file" | "directory";
|
|
7
|
+
purpose: "source" | "test" | "fixture" | "config" | "dependency";
|
|
8
|
+
};
|
|
9
|
+
export type EvidenceCoverage = {
|
|
10
|
+
acIds: string[];
|
|
11
|
+
behavior: string;
|
|
12
|
+
declaration: "reviewed" | "unknown";
|
|
13
|
+
sourceRationale: string;
|
|
14
|
+
dependencyRationale: string;
|
|
15
|
+
runtimeRationale: string;
|
|
16
|
+
environmentRationale: string;
|
|
17
|
+
};
|
|
18
|
+
export type EvidenceLimits = {
|
|
19
|
+
timeoutMs: number;
|
|
20
|
+
maxLogBytesPerStream: number;
|
|
21
|
+
maxInputBytes: number;
|
|
22
|
+
maxInputEntries: number;
|
|
23
|
+
maxInputMs: number;
|
|
24
|
+
maxSnapshotBytes: number;
|
|
25
|
+
};
|
|
26
|
+
export type EvidenceCaptureRequest = {
|
|
27
|
+
context: SddExecutionContext;
|
|
28
|
+
taskId: string;
|
|
29
|
+
coverage: EvidenceCoverage;
|
|
30
|
+
inputs: EvidenceInputSpec[];
|
|
31
|
+
environmentKeys: EvidenceEnvironmentKey[];
|
|
32
|
+
timeoutMs?: number;
|
|
33
|
+
};
|
|
34
|
+
export type EvidenceInputEntry = {
|
|
35
|
+
path: string;
|
|
36
|
+
kind: "file" | "directory" | "symlink" | "missing" | "unknown";
|
|
37
|
+
sha256: string | null;
|
|
38
|
+
bytes: number | null;
|
|
39
|
+
executable: boolean | null;
|
|
40
|
+
linkText: string | null;
|
|
41
|
+
resolvedRelativePath: string | null;
|
|
42
|
+
error: string | null;
|
|
43
|
+
};
|
|
44
|
+
export type EvidenceToolFingerprint = {
|
|
45
|
+
requested: string;
|
|
46
|
+
resolvedPath: string | null;
|
|
47
|
+
sha256: string | null;
|
|
48
|
+
bytes: number | null;
|
|
49
|
+
platform: string;
|
|
50
|
+
arch: string;
|
|
51
|
+
runnerRuntimeVersion: string;
|
|
52
|
+
error: string | null;
|
|
53
|
+
};
|
|
54
|
+
export type EvidenceInputSnapshot = {
|
|
55
|
+
repoCommonDir: string | null;
|
|
56
|
+
head: string | null;
|
|
57
|
+
branch: string | null;
|
|
58
|
+
dirty: boolean | null;
|
|
59
|
+
dirtyStatusSha256: string | null;
|
|
60
|
+
entries: EvidenceInputEntry[];
|
|
61
|
+
tool: EvidenceToolFingerprint;
|
|
62
|
+
environment: Partial<Record<EvidenceEnvironmentKey, string | null>>;
|
|
63
|
+
unknowns: string[];
|
|
64
|
+
stable: boolean;
|
|
65
|
+
digest: string;
|
|
66
|
+
};
|
|
67
|
+
export type EvidenceOutcome = {
|
|
68
|
+
kind: "running";
|
|
69
|
+
} | {
|
|
70
|
+
kind: "exit";
|
|
71
|
+
code: number;
|
|
72
|
+
} | {
|
|
73
|
+
kind: "signal";
|
|
74
|
+
signal: string;
|
|
75
|
+
} | {
|
|
76
|
+
kind: "timeout";
|
|
77
|
+
} | {
|
|
78
|
+
kind: "interrupted";
|
|
79
|
+
signal: "SIGINT" | "SIGTERM";
|
|
80
|
+
} | {
|
|
81
|
+
kind: "spawn-error";
|
|
82
|
+
code: string;
|
|
83
|
+
};
|
|
84
|
+
export type EvidenceLog = {
|
|
85
|
+
path: "stdout.log" | "stderr.log";
|
|
86
|
+
bytes: number;
|
|
87
|
+
sha256: string | null;
|
|
88
|
+
truncated: boolean;
|
|
89
|
+
};
|
|
90
|
+
export type SddEvidenceRecord = {
|
|
91
|
+
schema: "mstar.sdd-evidence/v1";
|
|
92
|
+
producer: {
|
|
93
|
+
name: "mstar-harness";
|
|
94
|
+
version: string;
|
|
95
|
+
};
|
|
96
|
+
runId: string;
|
|
97
|
+
request: EvidenceCaptureRequest;
|
|
98
|
+
command: {
|
|
99
|
+
argv: string[];
|
|
100
|
+
cwd: string;
|
|
101
|
+
};
|
|
102
|
+
startedAt: string;
|
|
103
|
+
endedAt: string | null;
|
|
104
|
+
state: "running" | "finished";
|
|
105
|
+
outcome: EvidenceOutcome;
|
|
106
|
+
before: EvidenceInputSnapshot;
|
|
107
|
+
after: EvidenceInputSnapshot | null;
|
|
108
|
+
logs: {
|
|
109
|
+
stdout: EvidenceLog;
|
|
110
|
+
stderr: EvidenceLog;
|
|
111
|
+
};
|
|
112
|
+
limits: EvidenceLimits;
|
|
113
|
+
captureErrors: string[];
|
|
114
|
+
counts: null;
|
|
115
|
+
};
|
|
116
|
+
export type EvidenceArtifactFact = {
|
|
117
|
+
path: "stdout.log" | "stderr.log";
|
|
118
|
+
state: "regular" | "missing" | "symlink" | "other" | "unreadable";
|
|
119
|
+
bytes: number | null;
|
|
120
|
+
sha256: string | null;
|
|
121
|
+
};
|
|
122
|
+
export type EvidenceExpectation = {
|
|
123
|
+
planId: string;
|
|
124
|
+
taskId: string;
|
|
125
|
+
runId: string;
|
|
126
|
+
};
|
|
127
|
+
export type EvidenceAssessment = {
|
|
128
|
+
integrity: GateResult;
|
|
129
|
+
outcome: "passed" | "failed" | "incomplete" | "unknown";
|
|
130
|
+
applicability: "not-assessed" | "candidate" | "changed" | "uncertain";
|
|
131
|
+
coverage: "review-required";
|
|
132
|
+
changedInputs: string[];
|
|
133
|
+
reasons: string[];
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* SHA-256 over the canonical serialization of the snapshot projection.
|
|
137
|
+
* Expects the typed, shape-bounded snapshot; out-of-contract direct input
|
|
138
|
+
* (missing fields, cycles, non-JSON values) throws `TypeError` rather than
|
|
139
|
+
* fabricating a digest. Public unknown-record validators catch that as an
|
|
140
|
+
* `evidence.schema` violation. Never call full record validation from here.
|
|
141
|
+
*/
|
|
142
|
+
export declare function evidenceInputDigest(snapshot: EvidenceInputSnapshot): string;
|
|
143
|
+
/**
|
|
144
|
+
* Validate one retained evidence record. Malformed unknown input yields
|
|
145
|
+
* `GateResult` violations (all severity high) and never throws. Checks the
|
|
146
|
+
* exact property sets at every object level, the fixed v1 collection
|
|
147
|
+
* limits, state/outcome/endedAt consistency, log slot literals and caps,
|
|
148
|
+
* entry/tool/environment fact rules, command cwd agreement with the
|
|
149
|
+
* recorded context, and recomputation of every snapshot digest.
|
|
150
|
+
*/
|
|
151
|
+
export declare function validateSddEvidenceRecord(record: unknown): GateResult;
|
|
152
|
+
/**
|
|
153
|
+
* Verify that the retained artifacts match the recorded facts and that the
|
|
154
|
+
* record is complete: exactly one regular-file fact per fixed log slot,
|
|
155
|
+
* exact bytes and hash, finished state, non-truncated logs and no capture
|
|
156
|
+
* errors. A completed nonzero exit with complete artifacts verifies as
|
|
157
|
+
* valid failure evidence — integrity is independent of the recorded
|
|
158
|
+
* outcome. Gate codes are fixed; no hard-blocked override exists.
|
|
159
|
+
*/
|
|
160
|
+
export declare function verifySddEvidence(record: unknown, artifacts: readonly EvidenceArtifactFact[], expected: EvidenceExpectation): GateResult;
|
|
161
|
+
/**
|
|
162
|
+
* Assess whether one retained evidence bundle still applies to the current
|
|
163
|
+
* declared inputs. Read-only: no child execution, discovery, version probe
|
|
164
|
+
* or write. The four outputs stay separate — a damaged log or an identity
|
|
165
|
+
* mismatch never rewrites the recorded outcome, and a failed or incomplete
|
|
166
|
+
* run can never become a reuse candidate. `changedInputs` discloses sorted
|
|
167
|
+
* known differing paths (or `$tool`/`$environment`/`$repository` labels)
|
|
168
|
+
* even when an earlier rule already forces uncertainty; no-target mode
|
|
169
|
+
* returns an empty list. Digest equality is consulted only after the
|
|
170
|
+
* preceding first-match checks, so an unknown marker never becomes a false
|
|
171
|
+
* changed/candidate result. A malformed target snapshot is downgraded to
|
|
172
|
+
* the unknown lane instead of throwing.
|
|
173
|
+
*/
|
|
174
|
+
export declare function assessSddEvidenceReuse(record: unknown, artifacts: readonly EvidenceArtifactFact[], expected: EvidenceExpectation, target?: EvidenceInputSnapshot): EvidenceAssessment;
|
package/dist/index.d.ts
CHANGED
|
@@ -24,7 +24,12 @@
|
|
|
24
24
|
* gate core (target classification + content/edit validation + reason
|
|
25
25
|
* formatting, shared by the omp and ZCode host gates), and `skill-authoring`
|
|
26
26
|
* lints frontmatter +
|
|
27
|
-
* 5-question bodies and resolves skill-relative asset paths
|
|
27
|
+
* 5-question bodies and resolves skill-relative asset paths, and
|
|
28
|
+
* `cleanup` is the pure worktree/branch cleanup planner (immutable facts
|
|
29
|
+
* in, stable `cleanup.*` remove/keep/refuse decisions out), and `evidence`
|
|
30
|
+
* is the pure SDD test-evidence contract (record schema validation,
|
|
31
|
+
* artifact verification, input fingerprinting and reuse assessment —
|
|
32
|
+
* values in, decisions out).
|
|
28
33
|
*/
|
|
29
34
|
export type { GateResult, Severity, ValidationResult } from "./core.js";
|
|
30
35
|
export { DSH_LLM_FALLBACKS_VERSION, SEVERITY_ORDER, applyEnforcement, readHarnessVersion, readJson, resolveProjectRoot, writeJson } from "./core.js";
|
|
@@ -36,16 +41,20 @@ export type { PlanRow, ResidualEntry, StatusDoc, StatusV2Doc, WorkflowEntry, } f
|
|
|
36
41
|
export { normalizeSeverity, registerWorkflow, resolveCompassEnforcement, resolveMstarcEnforcement, resolveRepoEnforcement, unregisterWorkflow, validatePlanRow, validateResidual, validateStatus, validateStatusV2, validateWorkflowEntry, } from "./status.js";
|
|
37
42
|
export type { ClaimLeaseFields, ExecutionLease, ExecutionLeaseLocations, IntegrationMergeLease, LeaseTransition, LeaseVerifyResult, } from "./lease.js";
|
|
38
43
|
export { canSteal, claimLease, planExecutionLeaseLocations, releaseLease, sameHolderResume, validateExecutionLease, validateIntegrationMergeLease, verifyPlanExecutionLease, withStatusWriteLock, } from "./lease.js";
|
|
39
|
-
export type { WorkflowBranchAnchors, WorkflowExecutionPolicy, WorkflowLifecycleStatus, WorkflowLifecycleType, WorkflowSnapshot, } from "./workflow.js";
|
|
40
|
-
export { WORKFLOW_LIFECYCLE_STATUSES, WORKFLOW_LIFECYCLE_TYPES, WORKFLOW_SNAPSHOT_FILE, WORKFLOW_TERMINAL_STATUSES, validateWorkflowSnapshot, writeWorkflowSnapshot, } from "./workflow.js";
|
|
44
|
+
export type { CloseWorkflowOptions, WorkflowBranchAnchors, WorkflowExecutionPolicy, WorkflowLifecycleStatus, WorkflowLifecycleType, WorkflowSnapshot, WorkflowSnapshotRead, } from "./workflow.js";
|
|
45
|
+
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";
|
|
46
|
+
export type { CleanupDecision, CleanupFacts, CleanupTarget, CleanupTargetKind, } from "./cleanup.js";
|
|
47
|
+
export { planWorktreeCleanup } from "./cleanup.js";
|
|
48
|
+
export type { EvidenceArtifactFact, EvidenceAssessment, EvidenceCaptureRequest, EvidenceCoverage, EvidenceEnvironmentKey, EvidenceExpectation, EvidenceInputEntry, EvidenceInputSnapshot, EvidenceInputSpec, EvidenceLimits, EvidenceLog, EvidenceOutcome, EvidenceToolFingerprint, SddEvidenceRecord, } from "./evidence.js";
|
|
49
|
+
export { assessSddEvidenceReuse, evidenceInputDigest, validateSddEvidenceRecord, verifySddEvidence, } from "./evidence.js";
|
|
41
50
|
export type { AssignmentBranchForms, AssignmentFields, ComposeDispatchGateOptions, ComposeDispatchGateResult, DefaultBranchOptions, EnforcementFlag, EnforcementSource, ExecutionModeToNOptions, ExecutionModeToNResult, ValidateAssignmentFieldsOptions, } from "./dispatch.js";
|
|
42
51
|
export { antiRecursionPrecheck, assertDefaultBranchProtected, assertTriIdentity, assignmentHeaderRegion, composeDispatchGate, executionModeToN, isReadOnlyAssignmentRole, parseAssignmentBranchForms, parseAssignmentFields, parseBranchPolicyDirectOnBranch, parseEnforcementFlag, validateAssignmentFields, } from "./dispatch.js";
|
|
43
|
-
export type { BranchProbeOptions, L1PreDispatchInput, L2PreDispatchInput, QcAlignmentAssignment, QcSnapshotAssignment, WorktreeTrack, } from "./worktree.js";
|
|
44
|
-
export { assertBranchAlignment, assertControlVsFeaturePath, assertQcAlignment, isDistinctCheckout, l1PreDispatchCheck, l2PreDispatchCheck, probeCheckoutRoot, singleReviewSnapshot, } from "./worktree.js";
|
|
52
|
+
export type { BranchProbeOptions, L1PreDispatchInput, L2PreDispatchInput, MainWorktreeInfo, QcAlignmentAssignment, QcSnapshotAssignment, WorktreeTrack, } from "./worktree.js";
|
|
53
|
+
export { assertBranchAlignment, assertControlVsFeaturePath, assertMainWorktreeResidency, assertQcAlignment, isDistinctCheckout, l1PreDispatchCheck, l2PreDispatchCheck, probeCheckoutRoot, readMainWorktree, singleReviewSnapshot, } from "./worktree.js";
|
|
45
54
|
export type { ImplementerSessionLedger, ReviewPackageOptions, SddAction, SddActionKind, SddExecutionContext, SddWorkspaceOptions, StickyRulesInput, StickyRulesResult, TaskBriefOptions, } from "./sdd.js";
|
|
46
55
|
export { GIT_CAPTURE_MAX_BYTES, SddScriptError, assertBaseSha, checkSddAction, implementerSessionStickyRules, readProgressLedger, resolveSddExecutionContext, reviewPackage, runInSddContext, sddWorkspace, taskBrief, taskReportExists, } from "./sdd.js";
|
|
47
|
-
export type { CompassDoc, PhaseGateOptions, PhaseGateResult, PhaseTransition, } from "./iteration.js";
|
|
48
|
-
export { assertIndexRowObligations, evaluatePhaseGate, parseCompassFrontmatter, parseCompassFrontmatterText, pushCadenceProbe, validateCompassFrontmatter, } from "./iteration.js";
|
|
56
|
+
export type { CompassDoc, PhaseGateOptions, PhaseGateResult, PhaseTransition, SnapshotDoc, } from "./iteration.js";
|
|
57
|
+
export { assertIndexRowObligations, evaluatePhaseGate, evaluatePostMergeClose, parseCompassFrontmatter, parseCompassFrontmatterText, pushCadenceProbe, validateCompassFrontmatter, } from "./iteration.js";
|
|
49
58
|
export type { AppendProjectRegisterEntriesOpts, CloseProjectRegisterEntryOpts, FindingsCleanupMode, ProjectRegisterDoc, ProjectRegisterEntry, RoadmapFrontmatter, RoadmapStatus, RoadmapValidation, TechDebtCheck, TechDebtRollup, TechDebtSummary, } from "./project.js";
|
|
50
59
|
export { PROJECT_REFERENCES_DIR, PROJECT_REGISTER_FILE, PROJECT_ROADMAP_FILE, ROADMAP_STATUSES, _DEFAULT_PROJECT, appendProjectRegisterEntries, closeProjectRegisterEntry, findingsCleanupGate, listProjectReferenceFiles, techDebtRollup, validateProjectRegister, validateRoadmap, } from "./project.js";
|
|
51
60
|
export type { HarnessDocKind, ValidateStatusWriteDocOptions } from "./gates.js";
|
|
@@ -70,3 +79,5 @@ export type { MergeClass, MstarReviewFinding, MstarReviewV1, PrReportTarget, PrR
|
|
|
70
79
|
export { MERGE_CLASSES, PR_REVIEW_TIER_BUDGETS, PR_VERDICTS, REVIEW_EMOJI, computePrTally, pickReviewBranchName, planReviewPost, preflightChangeset, prReviewReportPath, prReviewSeatPrompt, prReviewSizing, resolvePrReviewTier, synthesizeReview, validateFindingDoc, validateMstarReviewV1, validatePrReviewReport, } from "./prreview.js";
|
|
71
80
|
export type { ArtifactDoc, ArtifactKind, ArtifactRef, ArtifactStore } from "./store.js";
|
|
72
81
|
export { assertFsStorePath, createFsStore, getArtifactStore, loadStoreModule, resolveArtifactPath, setArtifactStore } from "./store.js";
|
|
82
|
+
export { collectActiveLifecycleBranches, scanActiveLifecycleBranches, type ActiveLifecycleScan } from "./lifecycle-branches.js";
|
|
83
|
+
export { WorkflowSnapshotValidationError } from "./workflow.js";
|
package/dist/iteration.d.ts
CHANGED
|
@@ -6,11 +6,13 @@ import type { GateResult, ValidationResult } from "./core.js";
|
|
|
6
6
|
* verbatim () — `findPlanRow` accepts `id` or `plan_id`.
|
|
7
7
|
*
|
|
8
8
|
* Deliberate decoupling: this is a loose LOCAL re-declaration,
|
|
9
|
-
* NOT an import of `WorkflowSnapshot` from workflow.ts.
|
|
10
|
-
* reads `plans[].status
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
9
|
+
* NOT an import of `WorkflowSnapshot` from workflow.ts. The loose phase-gate
|
|
10
|
+
* reads (`evaluatePhaseGate`) only touch `plans[].status`, so the full
|
|
11
|
+
* schema stays out of those call paths. The Phase-6 gate
|
|
12
|
+
* (`evaluatePostMergeClose`) DOES consume the strict T1 validator directly
|
|
13
|
+
* (static edge iteration → workflow; workflow's closure never imports this
|
|
14
|
+
* module, so no cycle is created). Keep this shape in sync manually when
|
|
15
|
+
* the snapshot schema changes.
|
|
14
16
|
*/
|
|
15
17
|
export type SnapshotDoc = {
|
|
16
18
|
plans?: unknown;
|
|
@@ -93,6 +95,34 @@ export declare function validateCompassFrontmatter(doc: unknown): GateResult;
|
|
|
93
95
|
* `prBaseBranch`) come from the caller via `opts`.
|
|
94
96
|
*/
|
|
95
97
|
export declare function evaluatePhaseGate(snapshotDoc: SnapshotDoc, compassDoc: CompassDoc, opts?: PhaseGateOptions): PhaseGateResult;
|
|
98
|
+
/**
|
|
99
|
+
* Phase 6 post-merge close local-state gate (phase-6-post-merge-close.md
|
|
100
|
+
* §6.4 + Evidence): verifies the checkable post-close state — the workflow
|
|
101
|
+
* snapshot is a valid v3 document (T1 `validateWorkflowSnapshot`, with the
|
|
102
|
+
* single legacy `control_worktree_path` alias non-blocking exactly as the
|
|
103
|
+
* canonical reader accepts and migrates it) in a
|
|
104
|
+
* terminal status (completed | failed | stopped, T1 `isTerminalSnapshot`),
|
|
105
|
+
* no `plans[].execution_lease` or top-level `integration_merge_lease`
|
|
106
|
+
* survived the close, and the root `status.json` validates as a v2 registry
|
|
107
|
+
* (`validateStatusV2`, structure-only) and no longer registers the
|
|
108
|
+
* workflow (removal-at-terminal).
|
|
109
|
+
*
|
|
110
|
+
* Deliberately does NOT verify remote merge evidence or physical cleanup —
|
|
111
|
+
* the gate only reads local state. An invalid/unreadable ROOT — any
|
|
112
|
+
* `validateStatusV2` failure (non-v2 version, missing `updated_at`,
|
|
113
|
+
* malformed `workflows[]` or entries) — is a
|
|
114
|
+
* violation (`PHASE6_INVALID_ROOT`): it is not proof of the entry's
|
|
115
|
+
* absence. The lease probe runs on terminal documents only — mid-flight
|
|
116
|
+
* leases on a running lifecycle are legitimate and the actionable code is
|
|
117
|
+
* `PHASE6_NOT_TERMINAL`.
|
|
118
|
+
*
|
|
119
|
+
* Pure and additive: consumes T1's validators unchanged and does not touch
|
|
120
|
+
* `evaluatePhaseGate` / `PhaseGateResult` (Phase 2–5 exit codes stay
|
|
121
|
+
* intact). Stable machine codes: `PHASE6_NOT_TERMINAL`,
|
|
122
|
+
* `PHASE6_ROOT_ENTRY_PRESENT`, `PHASE6_DANGLING_LEASE`,
|
|
123
|
+
* `PHASE6_INVALID_SNAPSHOT`, `PHASE6_INVALID_ROOT`.
|
|
124
|
+
*/
|
|
125
|
+
export declare function evaluatePostMergeClose(snapshotDoc: SnapshotDoc, rootDoc: unknown): GateResult;
|
|
96
126
|
/**
|
|
97
127
|
* §5.1a push-cadence probe (HARD): never push the PR head while required CI
|
|
98
128
|
* is still queued/in_progress or an AI/bot review wave is running. Pure
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ValidationResult } from "./core.js";
|
|
2
|
+
/** Collect ownership, including retained L2 tracks; base/target are not ownership. */
|
|
3
|
+
export declare function collectActiveLifecycleBranches(snapshots: readonly Record<string, unknown>[]): string[];
|
|
4
|
+
export type ActiveLifecycleScan = {
|
|
5
|
+
kind: "ok";
|
|
6
|
+
branches: string[];
|
|
7
|
+
notes: ValidationResult[];
|
|
8
|
+
} | {
|
|
9
|
+
kind: "refusal";
|
|
10
|
+
code: string;
|
|
11
|
+
detail: string;
|
|
12
|
+
};
|
|
13
|
+
/** Read all other registered active snapshots through the canonical reader.
|
|
14
|
+
* Missing register means no siblings; malformed register or unreadable sibling
|
|
15
|
+
* refuses. Governing snapshot is supplied by the caller, never read twice.
|
|
16
|
+
*/
|
|
17
|
+
export declare function scanActiveLifecycleBranches(harnessDir: string, governingWorkflowId: string | null): ActiveLifecycleScan;
|
package/dist/sdd.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare class SddScriptError extends Error {
|
|
|
12
12
|
* usage plus the harness-root override (plan finding 2026-08-08).
|
|
13
13
|
*/
|
|
14
14
|
export type SddWorkspaceOptions = {
|
|
15
|
-
/**
|
|
15
|
+
/** Main worktree repo root — CLI 2nd arg / `MSTAR_CONTROL_ROOT`. */
|
|
16
16
|
controlRoot?: string;
|
|
17
17
|
/** Explicit harness root — `MSTAR_HARNESS_DIR` / `--harness-dir`. */
|
|
18
18
|
harnessDir?: string;
|
|
@@ -63,19 +63,24 @@ export declare const GIT_CAPTURE_MAX_BYTES: number;
|
|
|
63
63
|
* Resolve and ensure `{SDD_DIR}` = `{HARNESS_DIR}/sdd/<plan-id>/` (prints
|
|
64
64
|
* the absolute path). Resolution order:
|
|
65
65
|
*
|
|
66
|
-
* 1.
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* `
|
|
78
|
-
*
|
|
66
|
+
* 1. Git-derived MAIN discovery FIRST (fail-closed): the process-SSOT
|
|
67
|
+
* control root is the MAIN worktree (`readMainWorktree` — the first
|
|
68
|
+
* `git worktree list --porcelain -z` record). From a linked checkout the
|
|
69
|
+
* first record still reaches main; a failed/unavailable probe (null)
|
|
70
|
+
* refuses BEFORE any harness resolution or mkdir — nothing is written.
|
|
71
|
+
* 2. An explicit `controlRoot` (CLI 2nd arg / `MSTAR_CONTROL_ROOT`) must BE
|
|
72
|
+
* the main worktree when Git is available — an integration/foreign
|
|
73
|
+
* linked checkout is refused, never silently redirected; explicit
|
|
74
|
+
* non-Git standalone roots are preserved;
|
|
75
|
+
* 3. explicit harness-root override (`opts.harnessDir` / `MSTAR_HARNESS_DIR`)
|
|
76
|
+
* — resolved relative to the established main root;
|
|
77
|
+
* 4. `.mstarc` `[config] harness_dir` at the main root (repo-declared root;
|
|
78
|
+
* resolved against the config file's directory);
|
|
79
|
+
* 5. `status.json` probe at the main root (`.mstar` → `.agents`);
|
|
80
|
+
* 6. fallback: existing `.mstar`/`.agents` dir under the main root, else
|
|
81
|
+
* `.mstar`;
|
|
82
|
+
* 7. the resolved harness dir must not redirect the process SSOT into a
|
|
83
|
+
* linked/foreign Git checkout — refused before any mkdir/write.
|
|
79
84
|
*/
|
|
80
85
|
export declare function sddWorkspace(planId: string, opts?: SddWorkspaceOptions): string;
|
|
81
86
|
/**
|
|
@@ -242,7 +247,9 @@ export type SddActionKind = "source" | "artifact" | "launch";
|
|
|
242
247
|
* `workflows[]`; a retained terminal snapshot never satisfies lease
|
|
243
248
|
* enforcement, and a plan claimed by multiple active workflows fails
|
|
244
249
|
* closed), its lease is verified (`verifyPlanExecutionLease`) and the
|
|
245
|
-
* L1 checklist runs (`l1PreDispatchCheck` with the
|
|
250
|
+
* L1 checklist runs (`l1PreDispatchCheck` with the Git-derived MAIN
|
|
251
|
+
* worktree, the governing snapshot's integration topology, the recorded
|
|
252
|
+
* residency expectation and the active lifecycle-branch ownership set);
|
|
246
253
|
* the context must then match the verified lease exactly. Without an
|
|
247
254
|
* active lease (no row, or a non-InProgress row without lease), the
|
|
248
255
|
* standalone branch policy applies (`assertBranchAlignment`) — an
|
package/dist/status.d.ts
CHANGED
|
@@ -58,6 +58,7 @@ export type PlanRow = {
|
|
|
58
58
|
title?: unknown;
|
|
59
59
|
file?: unknown;
|
|
60
60
|
status?: unknown;
|
|
61
|
+
/** Opaque plan metadata; metadata.track_branches retains active L2 Assignment working branches. */
|
|
61
62
|
metadata?: unknown;
|
|
62
63
|
execution_lease?: unknown;
|
|
63
64
|
[key: string]: unknown;
|
package/dist/workflow.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GateResult } from "./core.js";
|
|
1
|
+
import type { GateResult, ValidationResult } from "./core.js";
|
|
2
2
|
import { type IntegrationMergeLease } from "./lease.js";
|
|
3
3
|
import { type PlanRow } from "./status.js";
|
|
4
4
|
/** Snapshot file name inside `workflows/<id>/` ( — writer contract). */
|
|
@@ -33,6 +33,14 @@ export type WorkflowBranchAnchors = {
|
|
|
33
33
|
* per-row `execution_lease` stays on the row, `integration_merge_lease` is
|
|
34
34
|
* top-level.
|
|
35
35
|
*
|
|
36
|
+
* Integration worktree path: the canonical member is
|
|
37
|
+
* `integration_worktree_path` — the dedicated integration checkout, on
|
|
38
|
+
* `branch.integration`, distinct from the main worktree. The v1
|
|
39
|
+
* `control_worktree_path` key has NO canonical member: legacy-only
|
|
40
|
+
* documents stay readable through `readWorkflowSnapshot` (in-memory
|
|
41
|
+
* normalization + medium migration diagnostic); writers emit only the
|
|
42
|
+
* canonical shape — no dual writer.
|
|
43
|
+
*
|
|
36
44
|
* Notes dual-home SSOT: a plan row's `notes` array is the
|
|
37
45
|
* LEGACY VERBATIM copy preserved at migrate time — the RUNTIME ledger is
|
|
38
46
|
* `notes.jsonl` in the workflow dir (`migrate.ts` NOTES_LEDGER_FILE). New
|
|
@@ -52,7 +60,7 @@ export type WorkflowSnapshot = {
|
|
|
52
60
|
execution_policy?: WorkflowExecutionPolicy;
|
|
53
61
|
integration_merge_lease?: IntegrationMergeLease;
|
|
54
62
|
branch?: WorkflowBranchAnchors;
|
|
55
|
-
|
|
63
|
+
integration_worktree_path?: string;
|
|
56
64
|
legacy_metadata?: Record<string, unknown>;
|
|
57
65
|
compass_ref?: string;
|
|
58
66
|
};
|
|
@@ -63,11 +71,48 @@ export type WorkflowSnapshot = {
|
|
|
63
71
|
* `execution_lease` shape delegated to `validateExecutionLease`,
|
|
64
72
|
* `integration_merge_lease` shape delegated to
|
|
65
73
|
* `validateIntegrationMergeLease`, `execution_policy` keys accepted-but-
|
|
66
|
-
* opaque.
|
|
67
|
-
* `
|
|
68
|
-
*
|
|
74
|
+
* opaque. Integration worktree path: the canonical member is
|
|
75
|
+
* `integration_worktree_path`; the v1 `control_worktree_path` key is a
|
|
76
|
+
* read-only alias whose presence keeps this STRICT validation a failing
|
|
77
|
+
* gate carrying the medium `workflow.snapshot.legacy-control-worktree-path`
|
|
78
|
+
* migration diagnostic (read acceptance is not write permission — the
|
|
79
|
+
* canonical reader is the only consumer that normalizes it, in memory);
|
|
80
|
+
* both keys present is `workflow.snapshot.conflicting-worktree-paths`
|
|
81
|
+
* (high), even when the values are equal. Terminal invariant: `status` ∈
|
|
82
|
+
* completed|failed|stopped ⇒ `ended_at` present AND no row carries
|
|
83
|
+
* `execution_lease` AND no `integration_merge_lease` (no dangling leases).
|
|
69
84
|
*/
|
|
70
85
|
export declare function validateWorkflowSnapshot(doc: unknown): GateResult;
|
|
86
|
+
/** Machine code of the v1 read-alias migration diagnostic (`readWorkflowSnapshot`). */
|
|
87
|
+
export declare const LEGACY_WORKTREE_PATH_CODE = "workflow.snapshot.legacy-control-worktree-path";
|
|
88
|
+
/**
|
|
89
|
+
* Result of the canonical snapshot read: the validated snapshot plus the
|
|
90
|
+
* non-blocking diagnostics collected while reading (currently only the
|
|
91
|
+
* `workflow.snapshot.legacy-control-worktree-path` migration diagnostic for
|
|
92
|
+
* v1-shaped documents). A read with diagnostics is NOT write permission —
|
|
93
|
+
* writers keep strict validation and emit only the canonical shape.
|
|
94
|
+
*/
|
|
95
|
+
export type WorkflowSnapshotRead = {
|
|
96
|
+
snapshot: WorkflowSnapshot;
|
|
97
|
+
diagnostics: ValidationResult[];
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Canonical snapshot reader (`{WORKFLOW_DIR}/<id>/snapshot.json`): reads
|
|
101
|
+
* `dir/snapshot.json`, validates the raw document, normalizes the single
|
|
102
|
+
* permitted legacy alias (`control_worktree_path` →
|
|
103
|
+
* `integration_worktree_path`) IN MEMORY and returns its medium migration
|
|
104
|
+
* diagnostic separately. Any other validation violation refuses the read
|
|
105
|
+
* (throw) — read acceptance extends only to the migration diagnostic, so
|
|
106
|
+
* this never weakens the strict writer gate. Performs no writes: the
|
|
107
|
+
* source file's bytes are never touched; legacy snapshots migrate on their
|
|
108
|
+
* next authorized read-modify-write through the canonical writer. Missing
|
|
109
|
+
* files, malformed JSON, and non-object documents throw.
|
|
110
|
+
*/
|
|
111
|
+
export declare class WorkflowSnapshotValidationError extends Error {
|
|
112
|
+
readonly violations: ValidationResult[];
|
|
113
|
+
constructor(message: string, violations: ValidationResult[]);
|
|
114
|
+
}
|
|
115
|
+
export declare function readWorkflowSnapshot(dir: string): WorkflowSnapshotRead;
|
|
71
116
|
/**
|
|
72
117
|
* Write a workflow snapshot as a whole-rewrite of `dir/snapshot.json` under
|
|
73
118
|
* `withStatusWriteLock(snapshotPath)` ( — the `.status-write.lockdir`
|
|
@@ -84,3 +129,13 @@ export declare function validateWorkflowSnapshot(doc: unknown): GateResult;
|
|
|
84
129
|
* `setArtifactStore(createFsStore(root))` first.
|
|
85
130
|
*/
|
|
86
131
|
export declare function writeWorkflowSnapshot(snapshot: WorkflowSnapshot, dir: string): Promise<void>;
|
|
132
|
+
/** Terminal enum predicate only; callers validate document shape separately. */
|
|
133
|
+
export declare function isTerminalSnapshot(doc: WorkflowSnapshot): boolean;
|
|
134
|
+
export type CloseWorkflowOptions = {
|
|
135
|
+
endedAt: string;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Complete the latest snapshot under its write lock. Never releases leases.
|
|
139
|
+
* A valid terminal snapshot is returned unchanged, including failed/stopped.
|
|
140
|
+
*/
|
|
141
|
+
export declare function closeWorkflow(workflowId: string, dir: string, opts: CloseWorkflowOptions): Promise<WorkflowSnapshot>;
|
package/dist/worktree.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { GateResult } from "./core.js";
|
|
2
|
+
import type { WorkflowLifecycleType } from "./workflow.js";
|
|
3
|
+
export declare function gitProbeTimeoutMs(): number;
|
|
2
4
|
/** One L2 parallel implement track (mstar-branch-worktree L2 table). */
|
|
3
5
|
export type WorktreeTrack = {
|
|
4
6
|
/** Absolute worktree checkout path for the track. */
|
|
@@ -6,13 +8,57 @@ export type WorktreeTrack = {
|
|
|
6
8
|
/** PM-approved Working branch checked out in that worktree. */
|
|
7
9
|
workingBranch: string;
|
|
8
10
|
};
|
|
11
|
+
/** The Git-derived main worktree of the repository containing a cwd. */
|
|
12
|
+
export type MainWorktreeInfo = {
|
|
13
|
+
/** Absolute (realpath'd) main-worktree checkout root. */
|
|
14
|
+
root: string;
|
|
15
|
+
/** Branch checked out at the main worktree (`""` when detached). */
|
|
16
|
+
branch: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Discover the main worktree of the repository containing `cwd` (default
|
|
20
|
+
* `process.cwd()`): the FIRST record of `git worktree list --porcelain -z`,
|
|
21
|
+
* never the first attached branch or a name-matched path. Bounded by the
|
|
22
|
+
* shared probe timeout; unavailable Git, a hung git, a bare repository,
|
|
23
|
+
* malformed output, or an inaccessible root yield `null` — callers fail
|
|
24
|
+
* closed (`worktree.main.unresolved`), never fall through.
|
|
25
|
+
*/
|
|
26
|
+
export declare function readMainWorktree(cwd?: string): MainWorktreeInfo | null;
|
|
9
27
|
/**
|
|
10
|
-
*
|
|
11
|
-
* (`
|
|
28
|
+
* Primary-residency equality primitive: the main worktree must be on the
|
|
29
|
+
* branch RECORDED at lifecycle start (`expectedBranch` — callers transport
|
|
30
|
+
* the recorded value or the explicit `branch.base` fallback, never the
|
|
31
|
+
* branch observed at check time as its own expected value). Detached main
|
|
32
|
+
* (`branch: ""`) and any mismatch are `worktree.main.residency-switched`
|
|
33
|
+
* (high). Never switch main to satisfy this check.
|
|
34
|
+
*/
|
|
35
|
+
export declare function assertMainWorktreeResidency(main: MainWorktreeInfo, expectedBranch: string): GateResult;
|
|
36
|
+
/**
|
|
37
|
+
* L1 pre-dispatch checklist input — the three-domain topology: the
|
|
38
|
+
* Git-derived main worktree (process-SSOT holder), the governing snapshot's
|
|
39
|
+
* dedicated integration checkout, and the plan's feature worktree
|
|
40
|
+
* (`plans[].execution_lease`). Callers carry the actual snapshot type and
|
|
41
|
+
* resolve the recorded residency expectation + active lifecycle branches
|
|
42
|
+
* from the governing snapshots.
|
|
12
43
|
*/
|
|
13
44
|
export type L1PreDispatchInput = {
|
|
14
|
-
/**
|
|
15
|
-
|
|
45
|
+
/** Governing snapshot lifecycle type — `plan` standalone or `iteration`. */
|
|
46
|
+
workflowType: WorkflowLifecycleType;
|
|
47
|
+
/**
|
|
48
|
+
* `integration_worktree_path` — the dedicated integration checkout, on
|
|
49
|
+
* `branch.integration`. A standalone plan without integration passes `""`
|
|
50
|
+
* (both fields empty); if either field is supplied, both and the full
|
|
51
|
+
* checks are required.
|
|
52
|
+
*/
|
|
53
|
+
integrationWorktreePath: string;
|
|
54
|
+
/** `branch.integration` — the branch that must be checked out at the integration worktree (`""` for a standalone plan without integration). */
|
|
55
|
+
integrationBranch: string;
|
|
56
|
+
/** Git-derived main worktree (`readMainWorktree`); `null` = unresolved — a failure, never a skipped row. */
|
|
57
|
+
mainWorktree: MainWorktreeInfo | null;
|
|
58
|
+
/** Recorded main-worktree branch (plan header) or the explicit `branch.base` fallback — never the branch observed at check time. */
|
|
59
|
+
expectedMainBranch: string;
|
|
60
|
+
/** Branches owned by ANY active lifecycle (integration/plan/track) — main must not sit on any of them, even when the recorded expectation matches. */
|
|
61
|
+
lifecycleBranches: readonly string[];
|
|
16
62
|
/** `execution_lease.worktree_path` — the plan's feature worktree. */
|
|
17
63
|
leaseWorktreePath: string;
|
|
18
64
|
/** `execution_lease.working_branch` — the plan's Working branch. */
|
|
@@ -78,9 +124,13 @@ export declare function isDistinctCheckout(controlPath: string, candidatePath: s
|
|
|
78
124
|
export declare function probeCheckoutRoot(path: string, opts?: BranchProbeOptions): string | null;
|
|
79
125
|
/**
|
|
80
126
|
* L1 cross-plan pre-dispatch checklist (mstar-branch-worktree L1 table +
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
127
|
+
* iteration spec worktree-write-model § "Locked interfaces (P1 engine)"):
|
|
128
|
+
* main residency against the recorded expectation + non-ownership of any
|
|
129
|
+
* active lifecycle branch, integration presence/alignment (iterations
|
|
130
|
+
* require both integration fields; a standalone plan without integration
|
|
131
|
+
* checks main vs feature only), pairwise main/integration/feature
|
|
132
|
+
* Git-checkout identity, and the existing feature/lease checks. Null main
|
|
133
|
+
* discovery is a failure (`worktree.main.unresolved`), never a skipped row.
|
|
84
134
|
*/
|
|
85
135
|
export declare function l1PreDispatchCheck(input: L1PreDispatchInput, opts?: BranchProbeOptions): GateResult;
|
|
86
136
|
/**
|
|
@@ -94,14 +144,14 @@ export declare function l1PreDispatchCheck(input: L1PreDispatchInput, opts?: Bra
|
|
|
94
144
|
*/
|
|
95
145
|
export declare function l2PreDispatchCheck(input: L2PreDispatchInput, opts?: BranchProbeOptions): GateResult;
|
|
96
146
|
/**
|
|
97
|
-
* L1 hard rule (
|
|
98
|
-
* be a Git checkout DISTINCT from
|
|
99
|
-
* same checkout, a plain subdirectory, or a symlink
|
|
100
|
-
* checkout is refused (checkout identity via the
|
|
101
|
-
* git dir; probe failure fails closed). Both-empty
|
|
102
|
-
* recorded, per the lease validator contract); one
|
|
103
|
-
* compare and passes (the lease validator's
|
|
104
|
-
* empty lease paths).
|
|
147
|
+
* L1 hard rule (main control root vs feature): `execution_lease.worktree_path`
|
|
148
|
+
* MUST be a Git checkout DISTINCT from the MAIN worktree (the process-SSOT
|
|
149
|
+
* control root) — the same checkout, a plain subdirectory, or a symlink
|
|
150
|
+
* alias of the main checkout is refused (checkout identity via the
|
|
151
|
+
* canonical per-worktree git dir; probe failure fails closed). Both-empty
|
|
152
|
+
* stays a match (nothing recorded, per the lease validator contract); one
|
|
153
|
+
* empty has nothing to compare and passes (the lease validator's
|
|
154
|
+
* absolute-path requirement owns empty lease paths).
|
|
105
155
|
*/
|
|
106
156
|
export declare function assertControlVsFeaturePath(controlWorktreePath: string, featureWorktreePath: string, opts?: BranchProbeOptions): GateResult;
|
|
107
157
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mstar-harness/engine",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.9.1",
|
|
4
4
|
"description": "Morning Star Harness Workflow Engine — deterministic workflow enforcement library (path, status, lease, dispatch, sdd, iteration, lint gates).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|