@mstar-harness/engine 2.4.1 → 3.1.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/core.d.ts +1 -1
- package/dist/dispatch.d.ts +1 -1
- package/dist/engine.js +1600 -515
- package/dist/host.d.ts +2 -2
- package/dist/index.d.ts +12 -4
- package/dist/iteration.d.ts +37 -6
- package/dist/lease.d.ts +26 -25
- package/dist/lint.d.ts +1 -2
- package/dist/migrate.d.ts +134 -0
- package/dist/mstarc.d.ts +72 -0
- package/dist/path.d.ts +61 -21
- package/dist/project.d.ts +150 -0
- package/dist/sdd.d.ts +6 -4
- package/dist/status.d.ts +93 -65
- package/dist/workflow.d.ts +78 -0
- package/package.json +1 -1
package/dist/host.d.ts
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
* cursor → opencode → omp → kimi → zcode → codex ("Order matters").
|
|
10
10
|
* - `mstar-host` SKILL.md § Resolve loaded skill root — per-host skill-root
|
|
11
11
|
* resolution.
|
|
12
|
-
* -
|
|
12
|
+
* - roadmap §8.4 — the
|
|
13
13
|
* `HostAdapter` shared contract (all hooks optional; no concrete adapters
|
|
14
14
|
* in the engine; pi deferred).
|
|
15
|
-
* -
|
|
15
|
+
* - dsh-adapter roadmap §4 D5 (this iteration) —
|
|
16
16
|
* the dsh detection row + skill-root form; mirror text lands in the
|
|
17
17
|
* mstar-host skill when this module is upstreamed.
|
|
18
18
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -23,11 +23,15 @@
|
|
|
23
23
|
export type { GateResult, Severity, ValidationResult } from "./core.js";
|
|
24
24
|
export { SEVERITY_ORDER, applyEnforcement, readHarnessVersion, readJson, resolveProjectRoot, writeJson } from "./core.js";
|
|
25
25
|
export type { HarnessKind, ResolveHarnessDirOptions, ResolveSpecsDirOptions } from "./path.js";
|
|
26
|
-
export {
|
|
27
|
-
export
|
|
28
|
-
export {
|
|
26
|
+
export type { MstarcConfig } from "./mstarc.js";
|
|
27
|
+
export { MSTARC_FILE, MSTARC_HARNESS_DIR_KEY, MSTARC_PROJECT_DIR_KEY, MSTARC_SECTION, MSTARC_WORKFLOW_DIR_KEY, findMstarc, parseMstarc, } from "./mstarc.js";
|
|
28
|
+
export { assertPlanWritingPath, emitGitignoreSnippet, resolveHarnessDir, resolveIterationDir, resolveKnowledgeDir, resolvePlanDir, resolveProjectDir, resolveSddDir, resolveSpecsDir, resolveWorkflowDir, scaffoldHarness, validateGitignore, } from "./path.js";
|
|
29
|
+
export type { PlanRow, ResidualEntry, StatusDoc, StatusV2Doc, WorkflowEntry, } from "./status.js";
|
|
30
|
+
export { normalizeSeverity, registerWorkflow, resolveCompassEnforcement, resolveMstarcEnforcement, resolveRepoEnforcement, unregisterWorkflow, validatePlanRow, validateResidual, validateStatus, validateStatusV2, validateWorkflowEntry, } from "./status.js";
|
|
29
31
|
export type { ClaimLeaseFields, ExecutionLease, ExecutionLeaseLocations, IntegrationMergeLease, LeaseTransition, LeaseVerifyResult, } from "./lease.js";
|
|
30
32
|
export { canSteal, claimLease, planExecutionLeaseLocations, releaseLease, sameHolderResume, validateExecutionLease, validateIntegrationMergeLease, verifyPlanExecutionLease, withStatusWriteLock, } from "./lease.js";
|
|
33
|
+
export type { WorkflowBranchAnchors, WorkflowExecutionPolicy, WorkflowLifecycleStatus, WorkflowLifecycleType, WorkflowSnapshot, } from "./workflow.js";
|
|
34
|
+
export { WORKFLOW_LIFECYCLE_STATUSES, WORKFLOW_LIFECYCLE_TYPES, WORKFLOW_SNAPSHOT_FILE, WORKFLOW_TERMINAL_STATUSES, validateWorkflowSnapshot, writeWorkflowSnapshot, } from "./workflow.js";
|
|
31
35
|
export type { AssignmentBranchForms, AssignmentFields, ComposeDispatchGateOptions, ComposeDispatchGateResult, DefaultBranchOptions, EnforcementFlag, EnforcementSource, ExecutionModeToNOptions, ExecutionModeToNResult, ValidateAssignmentFieldsOptions, } from "./dispatch.js";
|
|
32
36
|
export { antiRecursionPrecheck, assertDefaultBranchProtected, assertTriIdentity, assignmentHeaderRegion, composeDispatchGate, executionModeToN, isReadOnlyAssignmentRole, parseAssignmentBranchForms, parseAssignmentFields, parseBranchPolicyDirectOnBranch, parseEnforcementFlag, validateAssignmentFields, } from "./dispatch.js";
|
|
33
37
|
export type { BranchProbeOptions, L1PreDispatchInput, L2PreDispatchInput, QcAlignmentAssignment, QcSnapshotAssignment, WorktreeTrack, } from "./worktree.js";
|
|
@@ -35,7 +39,11 @@ export { assertBranchAlignment, assertControlVsFeaturePath, assertQcAlignment, l
|
|
|
35
39
|
export type { ImplementerSessionLedger, ReviewPackageOptions, SddWorkspaceOptions, StickyRulesInput, StickyRulesResult, TaskBriefOptions, } from "./sdd.js";
|
|
36
40
|
export { SddScriptError, assertBaseSha, implementerSessionStickyRules, readProgressLedger, reviewPackage, sddWorkspace, taskBrief, taskReportExists, } from "./sdd.js";
|
|
37
41
|
export type { CompassDoc, PhaseGateOptions, PhaseGateResult, PhaseTransition, } from "./iteration.js";
|
|
38
|
-
export { assertIndexRowObligations, evaluatePhaseGate, parseCompassFrontmatter, pushCadenceProbe, validateCompassFrontmatter, } from "./iteration.js";
|
|
42
|
+
export { assertIndexRowObligations, evaluatePhaseGate, parseCompassFrontmatter, parseCompassFrontmatterText, pushCadenceProbe, validateCompassFrontmatter, } from "./iteration.js";
|
|
43
|
+
export type { FindingsCleanupMode, ProjectRegisterDoc, ProjectRegisterEntry, RoadmapFrontmatter, RoadmapStatus, RoadmapValidation, TechDebtCheck, TechDebtRollup, TechDebtSummary, } from "./project.js";
|
|
44
|
+
export { PROJECT_REFERENCES_DIR, PROJECT_REGISTER_FILE, PROJECT_ROADMAP_FILE, ROADMAP_STATUSES, _DEFAULT_PROJECT, findingsCleanupGate, listProjectReferenceFiles, techDebtRollup, validateProjectRegister, validateRoadmap, } from "./project.js";
|
|
45
|
+
export type { MigrateNotesFile, MigrateOptions, MigratePlan, MigrateRegister, MigrateResult, MigrateRoadmap, MigrateRootV2, MigrateSnapshot, MigrateStep, } from "./migrate.js";
|
|
46
|
+
export { ARCHIVED_STATUS_V1_FILE, MIGRATE_STATUS_FILE, NOTES_LEDGER_FILE, applyMigratePlan, migrateHarnessTree, } from "./migrate.js";
|
|
39
47
|
export type { CompletenessItem, CompletenessLevel, CompletenessPlaceholder, CompletenessResult, DesignFrontmatter, } from "./design-md.js";
|
|
40
48
|
export { assertLightDarkParity, completenessLevel, parseDesignFrontmatter, validateDesignTokenFrontmatter, } from "./design-md.js";
|
|
41
49
|
export type { AuditCategory, AuditEffort, AuditFinding, AuditPriority, AuditRisk, RedactResult, ScaffoldAuditPlanOptions, ScaffoldAuditPlanResult, SecretFinding, } from "./audit.js";
|
package/dist/iteration.d.ts
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import type { GateResult, ValidationResult } from "./core.js";
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Loose shape of a parsed workflow snapshot (`workflows/<id>/snapshot.json`).
|
|
4
|
+
* All fields are `unknown` because documents come from JSON at runtime;
|
|
5
|
+
* validators narrow them. `plans[]` rows are the legacy PlanRow shape
|
|
6
|
+
* verbatim (plan Task 2) — `findPlanRow` accepts `id` or `plan_id`.
|
|
7
|
+
*
|
|
8
|
+
* Deliberate decoupling (qc wave-1 S-f): this is a loose LOCAL re-declaration,
|
|
9
|
+
* NOT an import of `WorkflowSnapshot` from workflow.ts. This module only
|
|
10
|
+
* reads `plans[].status`; importing the full schema would add a module edge
|
|
11
|
+
* to workflow.ts (which imports status.ts, which workflow.ts cycles back
|
|
12
|
+
* through — the call-time-safe loop family stays static-edge-free this
|
|
13
|
+
* way). Keep this shape in sync manually when the snapshot schema changes.
|
|
14
|
+
*/
|
|
15
|
+
export type SnapshotDoc = {
|
|
16
|
+
plans?: unknown;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
};
|
|
3
19
|
/**
|
|
4
20
|
* Loose shape of a parsed delivery-compass.md frontmatter. All fields are
|
|
5
21
|
* `unknown` because documents come from YAML at runtime; validators narrow
|
|
@@ -63,14 +79,20 @@ export type PhaseGateResult = {
|
|
|
63
79
|
export declare function validateCompassFrontmatter(doc: unknown): GateResult;
|
|
64
80
|
/**
|
|
65
81
|
* Evaluate the Phase transition gates (mstar-iteration Phase transition
|
|
66
|
-
* gates table): all compass-registered plans `Done` (per
|
|
67
|
-
* status) → Phase 3 required, with the checkable subsets
|
|
68
|
-
* and §3.5 exit checklists as missing-item violations.
|
|
82
|
+
* gates table): all compass-registered plans `Done` (per the workflow
|
|
83
|
+
* snapshot plans[] status) → Phase 3 required, with the checkable subsets
|
|
84
|
+
* of the §3.1 entry and §3.5 exit checklists as missing-item violations.
|
|
85
|
+
*
|
|
86
|
+
* v3 relocation: the first doc is the workflow snapshot
|
|
87
|
+
* (`workflows/<id>/snapshot.json`); the compass stays the second input.
|
|
88
|
+
* The §3.1 residual item relocated to the project-layer
|
|
89
|
+
* `findingsCleanupGate(register, planId)` — the snapshot carries no
|
|
90
|
+
* residuals (residual close is a project-register state change).
|
|
69
91
|
*
|
|
70
92
|
* Pure function — git probes (`currentBranch`, `specIntegrationBranch`,
|
|
71
93
|
* `prBaseBranch`) come from the caller via `opts`.
|
|
72
94
|
*/
|
|
73
|
-
export declare function evaluatePhaseGate(
|
|
95
|
+
export declare function evaluatePhaseGate(snapshotDoc: SnapshotDoc, compassDoc: CompassDoc, opts?: PhaseGateOptions): PhaseGateResult;
|
|
74
96
|
/**
|
|
75
97
|
* §5.1a push-cadence probe (HARD): never push the PR head while required CI
|
|
76
98
|
* is still queued/in_progress or an AI/bot review wave is running. Pure
|
|
@@ -94,9 +116,18 @@ export declare function assertIndexRowObligations(iterationsDir: string): GateRe
|
|
|
94
116
|
* iteration-compass-template.md` Fields guide); `validateCompassFrontmatter`
|
|
95
117
|
* validates the parsed doc. The engine deliberately has no YAML dependency,
|
|
96
118
|
* so this hand-rolled flat-subset parser lives here — the single shared
|
|
97
|
-
* parser used by the CLI
|
|
119
|
+
* parser used by the CLI, the omp `mstar_iteration_gate` tool, and the
|
|
120
|
+
* roadmap validator (no fork). Path wrapper over
|
|
121
|
+
* `parseCompassFrontmatterText`.
|
|
98
122
|
*
|
|
99
123
|
* Throws with the file path on structural errors (no fence / unterminated
|
|
100
124
|
* fence / unsupported line) so callers can fail with a precise message.
|
|
101
125
|
*/
|
|
102
126
|
export declare function parseCompassFrontmatter(filePath: string): Record<string, unknown>;
|
|
127
|
+
/**
|
|
128
|
+
* Parse flat-subset YAML frontmatter from raw file content — the single
|
|
129
|
+
* shared parser core behind `parseCompassFrontmatter` (path wrapper) and
|
|
130
|
+
* the roadmap validator (plan `20260819-workflow-engine-core.md` Task 4 —
|
|
131
|
+
* extract/reuse the same parsing, no fork).
|
|
132
|
+
*/
|
|
133
|
+
export declare function parseCompassFrontmatterText(content: string, filePath: string): Record<string, unknown>;
|
package/dist/lease.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { GateResult, ValidationResult } from "./core.js";
|
|
2
2
|
import type { PlanRow } from "./status.js";
|
|
3
3
|
/**
|
|
4
|
-
* `plans[].execution_lease`
|
|
5
|
-
*
|
|
4
|
+
* `plans[].execution_lease` on a workflow snapshot's plan row (v3 data
|
|
5
|
+
* home — the snapshot's `plans[]` rows are the legacy PlanRow shape
|
|
6
|
+
* verbatim) — see spec header. Extra fields (e.g. the real control data's
|
|
7
|
+
* `base_sha`) are allowed and preserved.
|
|
6
8
|
*/
|
|
7
9
|
export type ExecutionLease = {
|
|
8
10
|
holder: string;
|
|
@@ -13,7 +15,8 @@ export type ExecutionLease = {
|
|
|
13
15
|
[key: string]: unknown;
|
|
14
16
|
};
|
|
15
17
|
/**
|
|
16
|
-
*
|
|
18
|
+
* Snapshot top-level `integration_merge_lease` (v3 — relocated from the v1
|
|
19
|
+
* root `metadata.integration_merge_lease`) — see spec header. Absent =
|
|
17
20
|
* unclaimed; writers delete the key on release (never `null`/tombstone).
|
|
18
21
|
*/
|
|
19
22
|
export type IntegrationMergeLease = {
|
|
@@ -52,9 +55,9 @@ export type LeaseTransition = {
|
|
|
52
55
|
*/
|
|
53
56
|
export declare function validateExecutionLease(lease: unknown): GateResult;
|
|
54
57
|
/**
|
|
55
|
-
* Validate one
|
|
56
|
-
* (status-and-residuals.md §
|
|
57
|
-
* required `holder` / `claimed_at` / `plan_id` / `source_branch` /
|
|
58
|
+
* Validate one snapshot top-level `integration_merge_lease` object
|
|
59
|
+
* (status-and-residuals.md § Snapshot top-level `integration_merge_lease`
|
|
60
|
+
* (v3)): required `holder` / `claimed_at` / `plan_id` / `source_branch` /
|
|
58
61
|
* `target_branch`; optional `session_label`. Absent = unclaimed; `null` and
|
|
59
62
|
* tombstone objects are invalid (writers delete the key on release).
|
|
60
63
|
* Integration merges into `spec_integration_branch` are serial — one holder
|
|
@@ -83,7 +86,8 @@ export declare function validateIntegrationMergeLease(lease: unknown): GateResul
|
|
|
83
86
|
* (the written lease must itself pass the validator).
|
|
84
87
|
*
|
|
85
88
|
* Pure: returns the resulting row; the caller performs the locked
|
|
86
|
-
* read-check-replace-verify around `
|
|
89
|
+
* read-check-replace-verify around `workflows/<id>/snapshot.json` (v3 data
|
|
90
|
+
* home) and persists the whole snapshot.
|
|
87
91
|
*/
|
|
88
92
|
export declare function claimLease(row: PlanRow, holder: string, fields: ClaimLeaseFields): LeaseTransition;
|
|
89
93
|
/**
|
|
@@ -118,46 +122,43 @@ export declare function sameHolderResume(lease: unknown, holder: string): boolea
|
|
|
118
122
|
export declare function canSteal(lease: unknown, holder: string, opts?: {
|
|
119
123
|
userOverride?: boolean;
|
|
120
124
|
}): boolean;
|
|
121
|
-
/** Execution lease
|
|
125
|
+
/** Execution lease location found on one plan row (SSOT). */
|
|
122
126
|
export type ExecutionLeaseLocations = {
|
|
123
127
|
/** SSOT location: `plans[].execution_lease`. */
|
|
124
128
|
row: unknown;
|
|
125
|
-
/** Legacy/hand-written read-compat location: `plans[].metadata.execution_lease`. */
|
|
126
|
-
metadata: unknown;
|
|
127
129
|
};
|
|
128
130
|
export declare function planExecutionLeaseLocations(row: Record<string, unknown>): ExecutionLeaseLocations;
|
|
129
131
|
export type LeaseVerifyResult = {
|
|
130
132
|
ok: boolean;
|
|
131
133
|
violations: ValidationResult[];
|
|
132
|
-
/** The lease chosen for validation (row-level
|
|
134
|
+
/** The lease chosen for validation (row-level) — absent when the row has none. */
|
|
133
135
|
lease?: unknown;
|
|
134
136
|
};
|
|
135
137
|
/**
|
|
136
|
-
* Verify a plan's `execution_lease`
|
|
138
|
+
* Verify a plan's `execution_lease` at its SSOT location
|
|
137
139
|
* (status-and-residuals.md § `plans[].execution_lease`; ADR
|
|
138
140
|
* 2026-07-22-iteration-worktree-plan-lease.md A3 — the plan row is the
|
|
139
141
|
* claim/hold/release SSOT):
|
|
140
|
-
* - Row-level `plans[].execution_lease`
|
|
141
|
-
* - Metadata-only (`plans[].metadata.execution_lease`) → high-severity
|
|
142
|
-
* `lease.verify.non-ssot-location`: the metadata location is a
|
|
143
|
-
* legacy/hand-written read-compat fallback, NOT equivalent to SSOT
|
|
144
|
-
* success. Always a FAIL (non-zero exit) with the lease shape still
|
|
145
|
-
* validated and reported.
|
|
146
|
-
* - Both locations present → `lease.verify.dual-write`: the row-level lease
|
|
147
|
-
* wins and is validated; the metadata copy must be deleted.
|
|
142
|
+
* - Row-level `plans[].execution_lease` present, valid → OK.
|
|
148
143
|
* - Neither present → `lease.verify.missing` (non-InProgress) /
|
|
149
144
|
* `lease.verify.orphan` (InProgress).
|
|
150
145
|
*
|
|
146
|
+
* The v1-era legacy read-compat location (`plans[].metadata.execution_lease`)
|
|
147
|
+
* is deleted in the v3 cutover: the workflow snapshot is machine-written
|
|
148
|
+
* (whole-rewrite), so the hand-written fallback is a v1 dead path — no
|
|
149
|
+
* dual-track.
|
|
150
|
+
*
|
|
151
151
|
* Kept in the engine so every host hook / CLI entry / Slice-2+ consumer
|
|
152
152
|
* imports ONE gate (CLI `mstar lease verify` is a thin wrapper).
|
|
153
153
|
*/
|
|
154
154
|
export declare function verifyPlanExecutionLease(row: Record<string, unknown>, planId: string): LeaseVerifyResult;
|
|
155
155
|
/**
|
|
156
|
-
* Same-host exclusive write lock around
|
|
157
|
-
* (status-and-residuals.md
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
156
|
+
* Same-host exclusive write lock around coordination writes — the root
|
|
157
|
+
* `status.json` AND `workflows/<id>/snapshot.json` (status-and-residuals.md
|
|
158
|
+
* § "Same-host exclusive write lock (control status.json)";
|
|
159
|
+
* phase-2-worktree-lease.md § "Same-host exclusive write lock"). Lease
|
|
160
|
+
* mutations and plan-status transitions that touch leases MUST run inside
|
|
161
|
+
* this lock for the full read-check-replace-verify sequence.
|
|
161
162
|
*
|
|
162
163
|
* Acquires by atomic `mkdir` on `<status dir>/.status-write.lockdir/`
|
|
163
164
|
* (success acquires; existing dir → another writer holds the lock). While
|
package/dist/lint.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Engine lint module — deterministic lint checks ported from skill prose.
|
|
3
3
|
*
|
|
4
|
-
* Roadmap
|
|
5
|
-
* row + §4.5 Lint layer (`simplify:` / `temporary` marker presence; SDD TDD
|
|
4
|
+
* Roadmap §8.2 `lint` row + §4.5 Lint layer (`simplify:` / `temporary` marker presence; SDD TDD
|
|
6
5
|
* triple in completion reports; plan-quality-bar checks; skill frontmatter
|
|
7
6
|
* contract; STRATEGY.md required sections). Skill text stays the semantic
|
|
8
7
|
* SSOT (roadmap D5) — this module implements the deterministic subset and
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { type ProjectRegisterDoc } from "./project.js";
|
|
2
|
+
import { type StatusV2Doc } from "./status.js";
|
|
3
|
+
import { type WorkflowLifecycleStatus, type WorkflowLifecycleType, type WorkflowSnapshot } from "./workflow.js";
|
|
4
|
+
/** Root status file name inside `{HARNESS_DIR}` (v1 input / v2 output). */
|
|
5
|
+
export declare const MIGRATE_STATUS_FILE = "status.json";
|
|
6
|
+
/** Legacy v1 root copy written by migration (never deleted without it). */
|
|
7
|
+
export declare const ARCHIVED_STATUS_V1_FILE = "archived/status.v1.json";
|
|
8
|
+
/** Notes ledger file name inside `workflows/<id>/` (schema v1 event kinds). */
|
|
9
|
+
export declare const NOTES_LEDGER_FILE = "notes.jsonl";
|
|
10
|
+
/** One planned apply step (kind + source -> destination labels for dry-run). */
|
|
11
|
+
export type MigrateStep = {
|
|
12
|
+
kind: "archive-status-v1" | "write-snapshot" | "write-notes" | "write-register" | "write-roadmap" | "replace-root-v2";
|
|
13
|
+
source: string;
|
|
14
|
+
destination: string;
|
|
15
|
+
};
|
|
16
|
+
/** One planned workflow snapshot (id = plan id or iteration id). */
|
|
17
|
+
export type MigrateSnapshot = {
|
|
18
|
+
id: string;
|
|
19
|
+
type: WorkflowLifecycleType;
|
|
20
|
+
status: WorkflowLifecycleStatus;
|
|
21
|
+
/**
|
|
22
|
+
* Canonical (default-layout) harness-relative snapshot path, e.g.
|
|
23
|
+
* `workflows/<id>/snapshot.json`. The actual write target derives from
|
|
24
|
+
* `MigratePlan.workflowDir` (Phase-5 F1 — a `.mstarc` custom
|
|
25
|
+
* `workflow_dir` is honored by the executor); this field keeps the
|
|
26
|
+
* default-layout rel name for display/provenance.
|
|
27
|
+
*/
|
|
28
|
+
file: string;
|
|
29
|
+
/** Provenance label (compass file / status.json row). */
|
|
30
|
+
source: string;
|
|
31
|
+
data: WorkflowSnapshot;
|
|
32
|
+
};
|
|
33
|
+
/** One planned notes ledger (`workflows/<id>/notes.jsonl`). */
|
|
34
|
+
export type MigrateNotesFile = {
|
|
35
|
+
/** Canonical (default-layout) rel path; actual target = `plan.workflowDir` + the suffix. */
|
|
36
|
+
file: string;
|
|
37
|
+
source: string;
|
|
38
|
+
/** Serialized JSON lines (each ends with `\n` when joined). */
|
|
39
|
+
lines: string[];
|
|
40
|
+
};
|
|
41
|
+
/** One planned project register document (`projects/<id>/residuals.json`). */
|
|
42
|
+
export type MigrateRegister = {
|
|
43
|
+
/** Canonical (default-layout) rel path; actual target = `plan.projectDir` + the suffix. */
|
|
44
|
+
file: string;
|
|
45
|
+
source: string;
|
|
46
|
+
data: ProjectRegisterDoc;
|
|
47
|
+
};
|
|
48
|
+
/** One planned roadmap seed (`projects/<id>/roadmap.md`). */
|
|
49
|
+
export type MigrateRoadmap = {
|
|
50
|
+
/** Canonical (default-layout) rel path; actual target = `plan.projectDir` + the suffix. */
|
|
51
|
+
file: string;
|
|
52
|
+
source: string;
|
|
53
|
+
content: string;
|
|
54
|
+
};
|
|
55
|
+
/** The root v2 replacement (commit point; empty `workflows[]` until re-registered). */
|
|
56
|
+
export type MigrateRootV2 = {
|
|
57
|
+
file: string;
|
|
58
|
+
data: StatusV2Doc;
|
|
59
|
+
};
|
|
60
|
+
/** Planner options (plan Task 6 — `--dry-run` returns steps, zero writes). */
|
|
61
|
+
export type MigrateOptions = {
|
|
62
|
+
dryRun?: boolean;
|
|
63
|
+
/** Project id for the register/roadmap home (default `_default`). */
|
|
64
|
+
projectId?: string;
|
|
65
|
+
};
|
|
66
|
+
/** Full migration plan: every write is described; the executor applies it. */
|
|
67
|
+
export type MigratePlan = {
|
|
68
|
+
/** Resolved harness dir. */
|
|
69
|
+
root: string;
|
|
70
|
+
/**
|
|
71
|
+
* Resolved `{WORKFLOW_DIR}` (Phase-5 F1): the `.mstarc` `[config]
|
|
72
|
+
* workflow_dir` declaration wins, else `{HARNESS_DIR}/workflows`. The
|
|
73
|
+
* snapshot/notes `file` fields below keep the canonical default-layout
|
|
74
|
+
* rel names for display/provenance; the executor derives the actual
|
|
75
|
+
* write targets from this dir so a custom layout lands where the v3
|
|
76
|
+
* runtime reads.
|
|
77
|
+
*/
|
|
78
|
+
workflowDir: string;
|
|
79
|
+
/**
|
|
80
|
+
* Resolved `{PROJECT_DIR}` (Phase-5 F1): the `.mstarc` `[config]
|
|
81
|
+
* project_dir` declaration wins, else `{HARNESS_DIR}/projects`. Same
|
|
82
|
+
* canonical-`file`-vs-actual-target split as `workflowDir` for the
|
|
83
|
+
* register/roadmap writes.
|
|
84
|
+
*/
|
|
85
|
+
projectDir: string;
|
|
86
|
+
dryRun: boolean;
|
|
87
|
+
/** Root status.json already at `version: 2` -> nothing to plan/apply. */
|
|
88
|
+
alreadyMigrated: boolean;
|
|
89
|
+
/** Human message (no-op reason when `alreadyMigrated`). */
|
|
90
|
+
message: string;
|
|
91
|
+
snapshots: MigrateSnapshot[];
|
|
92
|
+
notesFiles: MigrateNotesFile[];
|
|
93
|
+
register: MigrateRegister | null;
|
|
94
|
+
roadmap: MigrateRoadmap | null;
|
|
95
|
+
rootV2: MigrateRootV2;
|
|
96
|
+
archive: {
|
|
97
|
+
file: string;
|
|
98
|
+
source: string;
|
|
99
|
+
};
|
|
100
|
+
/** Informational notes surfaced in dry-run output (never silent drops). */
|
|
101
|
+
migrationNotes: string[];
|
|
102
|
+
/** Ordered apply steps (additive-first; root v2 replacement last). */
|
|
103
|
+
steps: MigrateStep[];
|
|
104
|
+
};
|
|
105
|
+
/** Executor result. */
|
|
106
|
+
export type MigrateResult = {
|
|
107
|
+
applied: boolean;
|
|
108
|
+
message: string;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Pure migration planner (plan Task 6): reads the v1 tree under `root` and
|
|
112
|
+
* returns the full v2 migration plan — snapshots, notes ledgers, project
|
|
113
|
+
* register, roadmap seeds, the archived v1 copy and the root v2
|
|
114
|
+
* replacement — with an ordered step list (source -> destination). ZERO
|
|
115
|
+
* writes; the caller applies via `applyMigratePlan`.
|
|
116
|
+
*
|
|
117
|
+
* A v2 root (`status.json` `version === 2`) yields an `alreadyMigrated`
|
|
118
|
+
* plan with no steps (idempotence); `opts.dryRun` marks the plan so apply
|
|
119
|
+
* is a no-op too.
|
|
120
|
+
*/
|
|
121
|
+
export declare function migrateHarnessTree(root: string, opts?: MigrateOptions): MigratePlan;
|
|
122
|
+
/**
|
|
123
|
+
* Execute a migration plan (plan Task 6). Additive-first ordering: the v1
|
|
124
|
+
* root is archived, workflow snapshots/notes, the project register and the
|
|
125
|
+
* roadmap are written BEFORE the root v2 replacement — the LAST step, the
|
|
126
|
+
* commit point. A failure before it leaves the v1 tree intact (re-run
|
|
127
|
+
* applies the same deterministic plan). Re-running on a v2 root, or with a
|
|
128
|
+
* `dryRun` plan, is a no-op. Every destination stays inside the harness
|
|
129
|
+
* dir; every snapshot is validated fail-closed inside `writeWorkflowSnapshot`
|
|
130
|
+
* — the writer is the authoritative validator, so the apply loop does not
|
|
131
|
+
* pre-validate (qc wave-1 S-h: a gate here would run the same O(rows) pass
|
|
132
|
+
* twice per snapshot).
|
|
133
|
+
*/
|
|
134
|
+
export declare function applyMigratePlan(plan: MigratePlan): Promise<MigrateResult>;
|
package/dist/mstarc.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** Canonical config file name. */
|
|
2
|
+
export declare const MSTARC_FILE = ".mstarc";
|
|
3
|
+
/** INI section holding the harness config. */
|
|
4
|
+
export declare const MSTARC_SECTION = "config";
|
|
5
|
+
/** `[config]` key declaring the harness root. */
|
|
6
|
+
export declare const MSTARC_HARNESS_DIR_KEY = "harness_dir";
|
|
7
|
+
/** `[config]` key declaring `{PLAN_DIR}`. */
|
|
8
|
+
export declare const MSTARC_PLAN_DIR_KEY = "plan_dir";
|
|
9
|
+
/** `[config]` key declaring the `{SDD_DIR}` per-plan base. */
|
|
10
|
+
export declare const MSTARC_SDD_DIR_KEY = "sdd_dir";
|
|
11
|
+
/** `[config]` key declaring `{ITERATION_DIR}`. */
|
|
12
|
+
export declare const MSTARC_ITERATION_DIR_KEY = "iteration_dir";
|
|
13
|
+
/** `[config]` key declaring `{KNOWLEDGE_DIR}`. */
|
|
14
|
+
export declare const MSTARC_KNOWLEDGE_DIR_KEY = "knowledge_dir";
|
|
15
|
+
/** `[config]` key declaring `{SPECS_DIR}`. */
|
|
16
|
+
export declare const MSTARC_SPECS_DIR_KEY = "specs_dir";
|
|
17
|
+
/** `[config]` key declaring `{WORKFLOW_DIR}` (v3 workflow lifecycle layout). */
|
|
18
|
+
export declare const MSTARC_WORKFLOW_DIR_KEY = "workflow_dir";
|
|
19
|
+
/** `[config]` key declaring `{PROJECT_DIR}` (v3 project roadmap/register). */
|
|
20
|
+
export declare const MSTARC_PROJECT_DIR_KEY = "project_dir";
|
|
21
|
+
/** `[config]` key declaring the repo hard-gate policy (`hard` / `soft`). */
|
|
22
|
+
export declare const MSTARC_ENFORCEMENT_KEY = "enforcement";
|
|
23
|
+
/** Parsed `.mstarc` harness config (unknown sections/keys are ignored). */
|
|
24
|
+
export type MstarcConfig = {
|
|
25
|
+
/** Declared harness root, relative to the `.mstarc` directory or absolute. */
|
|
26
|
+
harnessDir?: string;
|
|
27
|
+
/** Declared `{PLAN_DIR}`. */
|
|
28
|
+
planDir?: string;
|
|
29
|
+
/** Declared `{SDD_DIR}` base (the per-plan dir joins `<plan-id>`). */
|
|
30
|
+
sddDir?: string;
|
|
31
|
+
/** Declared `{ITERATION_DIR}`. */
|
|
32
|
+
iterationDir?: string;
|
|
33
|
+
/** Declared `{KNOWLEDGE_DIR}`. */
|
|
34
|
+
knowledgeDir?: string;
|
|
35
|
+
/** Declared `{SPECS_DIR}` (authoritative — skips the candidate chain). */
|
|
36
|
+
specsDir?: string;
|
|
37
|
+
/** Declared `{WORKFLOW_DIR}` (v3 workflow snapshots live under it). */
|
|
38
|
+
workflowDir?: string;
|
|
39
|
+
/** Declared `{PROJECT_DIR}` (v3 project roadmap + register live under it). */
|
|
40
|
+
projectDir?: string;
|
|
41
|
+
/** Declared hard-gate policy — `hard` or `soft` (anything else ignored). */
|
|
42
|
+
enforcement?: "hard" | "soft";
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Parse `.mstarc` text — minimal INI subset: `#`/`;` comments, `[section]`
|
|
46
|
+
* headers, `key=value` pairs (trimmed). Only the `[config]` section is
|
|
47
|
+
* read; unknown keys are ignored (forward compatibility). The last
|
|
48
|
+
* occurrence of a key wins; an empty value is treated as unset.
|
|
49
|
+
*/
|
|
50
|
+
export declare function parseMstarc(text: string): MstarcConfig;
|
|
51
|
+
/**
|
|
52
|
+
* Find the nearest `.mstarc` walking up from `startDir`, never above
|
|
53
|
+
* `boundary` (find-first-stop, mirroring the `{HARNESS_DIR}` probe stop
|
|
54
|
+
* rule — plan-conventions § {HARNESS_DIR} 解析顺序: a config above the
|
|
55
|
+
* workspace root is never adopted, same class as the `~/.mstar`
|
|
56
|
+
* global-collision defect). Returns the absolute file path, or `null`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function findMstarc(startDir: string, boundary: string): string | null;
|
|
59
|
+
/** A discovered `.mstarc` plus its parsed config. */
|
|
60
|
+
export type LoadedMstarc = {
|
|
61
|
+
/** Absolute path of the `.mstarc` file. */
|
|
62
|
+
file: string;
|
|
63
|
+
/** Directory containing the `.mstarc` file — base for relative values. */
|
|
64
|
+
dir: string;
|
|
65
|
+
/** Parsed `[config]` contents. */
|
|
66
|
+
config: MstarcConfig;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Find + parse the nearest `.mstarc` at or below `boundary` from
|
|
70
|
+
* `startDir`. Returns `null` when no config exists in scope.
|
|
71
|
+
*/
|
|
72
|
+
export declare function loadMstarc(startDir: string, boundary: string): LoadedMstarc | null;
|
package/dist/path.d.ts
CHANGED
|
@@ -27,12 +27,17 @@ export type ResolveHarnessDirOptions = {
|
|
|
27
27
|
};
|
|
28
28
|
/**
|
|
29
29
|
* Resolve `{HARNESS_DIR}` per plan-conventions § {HARNESS_DIR} 解析顺序
|
|
30
|
-
* (find-first-stop): `.
|
|
31
|
-
* from `startDir` but NEVER
|
|
32
|
-
* default = git top-level
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
30
|
+
* (find-first-stop): `.mstarc` `[config] harness_dir` → `.mstar/` →
|
|
31
|
+
* `.agents/` → `.plans/`/`plans/`, walking up from `startDir` but NEVER
|
|
32
|
+
* above the workspace root (`opts.workspaceRoot`, default = git top-level
|
|
33
|
+
* of `startDir`). The `.mstarc` layer: the nearest config file at or below
|
|
34
|
+
* the boundary declares `harness_dir`, resolved against the config file's
|
|
35
|
+
* own directory — no dir-existence requirement (callers may scaffold) and
|
|
36
|
+
* no boundary check on the result (explicit layers keep authority; only
|
|
37
|
+
* the config discovery walk is bounded). Harness candidates from probing
|
|
38
|
+
* are dir-existence checks (the empty-dir rule applies to `{SPECS_DIR}`
|
|
39
|
+
* only). An explicit override via `opts.harnessDir` or `MSTAR_HARNESS_DIR`
|
|
40
|
+
* wins over both and short-circuits before any boundary logic.
|
|
36
41
|
*
|
|
37
42
|
* Returns the absolute harness dir, or `null` when no candidate exists
|
|
38
43
|
* within the workspace boundary.
|
|
@@ -50,21 +55,26 @@ export type ResolveSpecsDirOptions = {
|
|
|
50
55
|
create?: boolean;
|
|
51
56
|
};
|
|
52
57
|
/**
|
|
53
|
-
* Resolve `{SPECS_DIR}` per plan-conventions § {SPECS_DIR} 解析:
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* `{HARNESS_DIR}/
|
|
58
|
+
* Resolve `{SPECS_DIR}` per plan-conventions § {SPECS_DIR} 解析: a
|
|
59
|
+
* `.mstarc` `[config] specs_dir` declaration is authoritative — returned
|
|
60
|
+
* directly (resolved against the config file's directory; created when
|
|
61
|
+
* `create` is not false; no candidate chain, no empty-dir rule). Otherwise
|
|
62
|
+
* the first non-empty candidate wins — `{HARNESS_DIR}/specs/` →
|
|
63
|
+
* `docs/specs/` → repo-root `specs/` (repo root = parent of the harness
|
|
64
|
+
* dir), then the legacy read-only `designs/` candidates
|
|
65
|
+
* (`{HARNESS_DIR}/designs/` → repo-root `designs/`, § {SPECS_DIR} 解析
|
|
66
|
+
* Legacy — 兼容读 only, never created by init). A candidate that exists
|
|
67
|
+
* but holds no files is treated as absent (empty-dir rule, recursive).
|
|
68
|
+
* When all candidates are absent, `{HARNESS_DIR}/specs/` is created and
|
|
69
|
+
* returned (unless `create: false`).
|
|
61
70
|
*/
|
|
62
71
|
export declare function resolveSpecsDir(harnessDir: string, opts?: ResolveSpecsDirOptions): string;
|
|
63
72
|
/**
|
|
64
73
|
* Compose `{PLAN_DIR}` from the harness dir (plan-conventions § 路径符号).
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
74
|
+
* A `.mstarc` `[config] plan_dir` declaration wins (resolved against the
|
|
75
|
+
* config file's directory). Legacy layout: when the harness root is a plans
|
|
76
|
+
* dir itself (`.plans/` or `plans/`, resolution rung 3),
|
|
77
|
+
* `{HARNESS_DIR}={PLAN_DIR}` — the same directory is returned.
|
|
68
78
|
*/
|
|
69
79
|
export declare function resolvePlanDir(harnessDir: string): string;
|
|
70
80
|
/**
|
|
@@ -77,16 +87,46 @@ export declare function resolvePlanDir(harnessDir: string): string;
|
|
|
77
87
|
export declare function assertSafePathComponent(value: string, what: string): void;
|
|
78
88
|
/**
|
|
79
89
|
* Compose `{SDD_DIR}` = `{HARNESS_DIR}/sdd/<plan-id>/` (plan-conventions
|
|
80
|
-
* § 路径符号).
|
|
81
|
-
*
|
|
82
|
-
*
|
|
90
|
+
* § 路径符号). A `.mstarc` `[config] sdd_dir` declaration replaces the
|
|
91
|
+
* `sdd` base (the `<plan-id>` segment is still appended). The per-plan
|
|
92
|
+
* directory is created by the sdd workspace flow, not here. `planId` must
|
|
93
|
+
* be a single safe path component (traversal guard) — see
|
|
94
|
+
* `assertSafePathComponent`.
|
|
83
95
|
*/
|
|
84
96
|
export declare function resolveSddDir(harnessDir: string, planId: string): string;
|
|
85
97
|
/**
|
|
86
98
|
* Compose `{ITERATION_DIR}` = `{HARNESS_DIR}/iterations/` (plan-conventions
|
|
87
|
-
* § 路径符号).
|
|
99
|
+
* § 路径符号). A `.mstarc` `[config] iteration_dir` declaration wins
|
|
100
|
+
* (resolved against the config file's directory).
|
|
88
101
|
*/
|
|
89
102
|
export declare function resolveIterationDir(harnessDir: string): string;
|
|
103
|
+
/**
|
|
104
|
+
* Compose `{KNOWLEDGE_DIR}` = `{HARNESS_DIR}/knowledge/` (plan-conventions
|
|
105
|
+
* § 路径符号). A `.mstarc` `[config] knowledge_dir` declaration wins
|
|
106
|
+
* (resolved against the config file's directory).
|
|
107
|
+
*/
|
|
108
|
+
export declare function resolveKnowledgeDir(harnessDir: string): string;
|
|
109
|
+
/**
|
|
110
|
+
* Resolve `{WORKFLOW_DIR}` — default `{HARNESS_DIR}/workflows/`
|
|
111
|
+
* (v3 workflow lifecycle layout: snapshot.json + notes per workflow id).
|
|
112
|
+
* A `.mstarc` `[config] workflow_dir` declaration wins (resolved against
|
|
113
|
+
* the config file's directory). The dir need not exist — writers
|
|
114
|
+
* (`writeWorkflowSnapshot` / register paths) create it on demand.
|
|
115
|
+
*
|
|
116
|
+
* Deferred-by-design (qc1 S-3): the startDir-first signature is asymmetric
|
|
117
|
+
* with the harnessDir-first sibling resolvers — brief-mandated for the CLI
|
|
118
|
+
* consumer (it probes from the cwd). Revisit with a harness-dir-first
|
|
119
|
+
* variant when a third v3 subdir resolver appears.
|
|
120
|
+
*/
|
|
121
|
+
export declare function resolveWorkflowDir(startDir?: string, opts?: ResolveHarnessDirOptions): string;
|
|
122
|
+
/**
|
|
123
|
+
* Resolve `{PROJECT_DIR}` — default `{HARNESS_DIR}/projects/` (v3 project
|
|
124
|
+
* layer: roadmap.md + residuals register per project id). A `.mstarc`
|
|
125
|
+
* `[config] project_dir` declaration wins (resolved against the config
|
|
126
|
+
* file's directory). Same deferred-by-design signature asymmetry as
|
|
127
|
+
* `resolveWorkflowDir` (qc1 S-3).
|
|
128
|
+
*/
|
|
129
|
+
export declare function resolveProjectDir(startDir?: string, opts?: ResolveHarnessDirOptions): string;
|
|
90
130
|
/**
|
|
91
131
|
* Initialize the harness directory under `root`: create `.mstar/` with
|
|
92
132
|
* `plans/`, `iterations/`, `knowledge/`, `specs/`, `sdd/` and write
|