@mstar-harness/engine 3.6.3 → 3.7.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/index.d.ts CHANGED
@@ -25,10 +25,10 @@
25
25
  */
26
26
  export type { GateResult, Severity, ValidationResult } from "./core.js";
27
27
  export { SEVERITY_ORDER, applyEnforcement, readHarnessVersion, readJson, resolveProjectRoot, writeJson } from "./core.js";
28
- export type { HarnessKind, ResolveHarnessDirOptions, ResolveSpecsDirOptions } from "./path.js";
28
+ export type { HarnessKind, ResolveHarnessDirOptions, ResolveSpecsDirOptions, } from "./path.js";
29
29
  export type { MstarcConfig } from "./mstarc.js";
30
30
  export { MSTARC_FILE, MSTARC_HARNESS_DIR_KEY, MSTARC_PROJECT_DIR_KEY, MSTARC_SECTION, MSTARC_WORKFLOW_DIR_KEY, findMstarc, parseMstarc, } from "./mstarc.js";
31
- export { assertPlanWritingPath, detectHarnessKind, emitGitignoreSnippet, resolveHarnessDir, resolveIterationDir, resolveKnowledgeDir, resolvePlanDir, resolveProjectDir, resolveScaffoldDirs, resolveSddDir, resolveSpecsDir, resolveWorkflowDir, scaffoldHarness, validateGitignore, } from "./path.js";
31
+ export { assertPlanWritingPath, canonicalizeNearestExisting, detectHarnessKind, emitGitignoreSnippet, resolveHarnessDir, resolveIterationDir, resolveKnowledgeDir, resolvePlanDir, resolveProjectDir, resolveScaffoldDirs, resolveSddDir, resolveSpecsDir, resolveWorkflowDir, scaffoldHarness, validateGitignore, } from "./path.js";
32
32
  export type { PlanRow, ResidualEntry, StatusDoc, StatusV2Doc, WorkflowEntry, } from "./status.js";
33
33
  export { normalizeSeverity, registerWorkflow, resolveCompassEnforcement, resolveMstarcEnforcement, resolveRepoEnforcement, unregisterWorkflow, validatePlanRow, validateResidual, validateStatus, validateStatusV2, validateWorkflowEntry, } from "./status.js";
34
34
  export type { ClaimLeaseFields, ExecutionLease, ExecutionLeaseLocations, IntegrationMergeLease, LeaseTransition, LeaseVerifyResult, } from "./lease.js";
@@ -39,8 +39,8 @@ export type { AssignmentBranchForms, AssignmentFields, ComposeDispatchGateOption
39
39
  export { antiRecursionPrecheck, assertDefaultBranchProtected, assertTriIdentity, assignmentHeaderRegion, composeDispatchGate, executionModeToN, isReadOnlyAssignmentRole, parseAssignmentBranchForms, parseAssignmentFields, parseBranchPolicyDirectOnBranch, parseEnforcementFlag, validateAssignmentFields, } from "./dispatch.js";
40
40
  export type { BranchProbeOptions, L1PreDispatchInput, L2PreDispatchInput, QcAlignmentAssignment, QcSnapshotAssignment, WorktreeTrack, } from "./worktree.js";
41
41
  export { assertBranchAlignment, assertControlVsFeaturePath, assertQcAlignment, l1PreDispatchCheck, l2PreDispatchCheck, singleReviewSnapshot, } from "./worktree.js";
42
- export type { ImplementerSessionLedger, ReviewPackageOptions, SddWorkspaceOptions, StickyRulesInput, StickyRulesResult, TaskBriefOptions, } from "./sdd.js";
43
- export { GIT_CAPTURE_MAX_BYTES, SddScriptError, assertBaseSha, implementerSessionStickyRules, readProgressLedger, reviewPackage, sddWorkspace, taskBrief, taskReportExists, } from "./sdd.js";
42
+ export type { ImplementerSessionLedger, ReviewPackageOptions, SddAction, SddActionKind, SddExecutionContext, SddWorkspaceOptions, StickyRulesInput, StickyRulesResult, TaskBriefOptions, } from "./sdd.js";
43
+ export { GIT_CAPTURE_MAX_BYTES, SddScriptError, assertBaseSha, checkSddAction, implementerSessionStickyRules, readProgressLedger, resolveSddExecutionContext, reviewPackage, runInSddContext, sddWorkspace, taskBrief, taskReportExists, } from "./sdd.js";
44
44
  export type { CompassDoc, PhaseGateOptions, PhaseGateResult, PhaseTransition, } from "./iteration.js";
45
45
  export { assertIndexRowObligations, evaluatePhaseGate, parseCompassFrontmatter, parseCompassFrontmatterText, pushCadenceProbe, validateCompassFrontmatter, } from "./iteration.js";
46
46
  export type { AppendProjectRegisterEntriesOpts, CloseProjectRegisterEntryOpts, FindingsCleanupMode, ProjectRegisterDoc, ProjectRegisterEntry, RoadmapFrontmatter, RoadmapStatus, RoadmapValidation, TechDebtCheck, TechDebtRollup, TechDebtSummary, } from "./project.js";
@@ -59,8 +59,8 @@ export type { DevTrackParam, QcReviewerParam, RoleFamily, RoleMappingEntry, Role
59
59
  export { DEV_TRACK_PARAMS, QC_REVIEWER_PARAMS, ROLE_MAPPING, SHARED_FAMILIES, lintLoadOrder, validateRoleMapping, } from "./roles.js";
60
60
  export type { DetectResult, HostAdapter, HostId, SkillRootPaths, ToolSignal } from "./host.js";
61
61
  export { detectHost, resolveSkillRoot } from "./host.js";
62
- export type { FiveQuestionMode, FiveQuestionSection } from "./skill-authoring.js";
63
- export { FIVE_QUESTION_SECTIONS, RUNTIME_HEADING_ALIASES, lintFiveQuestion, lintFrontmatter, resolveAssetPath, stripFrontmatter, } from "./skill-authoring.js";
62
+ export type { FiveQuestionMode, FiveQuestionSection, SkillLintKind, SkillLintProfile } from "./skill-authoring.js";
63
+ export { classifySkillLint, FIVE_QUESTION_SECTIONS, RUNTIME_HEADING_ALIASES, lintFiveQuestion, lintFrontmatter, resolveAssetPath, stripFrontmatter, } from "./skill-authoring.js";
64
64
  export type { MergeClass, MstarReviewFinding, MstarReviewV1, PrReportTarget, PrReviewSeatPromptOptions, PrReviewSizing, PrReviewTier, PrTierKeyword, PrSizeBand, PrTallyInput, PrTallyResult, PrVerdict, ResolvePrReviewTierInput, ReviewChangesetMode, ReviewInlineComment, ReviewPostPlan, ValidateFindingDocOptions, } from "./prreview.js";
65
65
  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";
66
66
  export type { ArtifactDoc, ArtifactKind, ArtifactRef, ArtifactStore } from "./store.js";
@@ -3,9 +3,9 @@ import type { GateResult, ValidationResult } from "./core.js";
3
3
  * Loose shape of a parsed workflow snapshot (`workflows/<id>/snapshot.json`).
4
4
  * All fields are `unknown` because documents come from JSON at runtime;
5
5
  * validators narrow them. `plans[]` rows are the legacy PlanRow shape
6
- * verbatim (plan Task 2) — `findPlanRow` accepts `id` or `plan_id`.
6
+ * verbatim () — `findPlanRow` accepts `id` or `plan_id`.
7
7
  *
8
- * Deliberate decoupling (qc wave-1 S-f): this is a loose LOCAL re-declaration,
8
+ * Deliberate decoupling: this is a loose LOCAL re-declaration,
9
9
  * NOT an import of `WorkflowSnapshot` from workflow.ts. This module only
10
10
  * reads `plans[].status`; importing the full schema would add a module edge
11
11
  * to workflow.ts (which imports status.ts, which workflow.ts cycles back
@@ -54,7 +54,7 @@ export type PhaseGateOptions = {
54
54
  * required; missing items listed in `violations`).
55
55
  * - all plans Done and both checklists clean → `phase-4-pr-delivery`.
56
56
  *
57
- * Note (qc2 F-003): during the Phase-3 window `ok` is false because the
57
+ * Note : during the Phase-3 window `ok` is false because the
58
58
  * §3.4 close items (`status: completed` + `end_date`) are only written at
59
59
  * the END of close — the exit checklist gates Phase 4, not the Phase-3
60
60
  * entry, so callers (e.g. the CLI, which exits 1) must treat that as "close
package/dist/lint.d.ts CHANGED
@@ -9,27 +9,27 @@
9
9
  *
10
10
  * Spec sources (each function cites the source section):
11
11
  * - simplify:/temporary markers: `mstar-coding-behavior` SKILL.md § Simplicity
12
- * First → "Simplification markers": a deliberate shortcut with a known
13
- * ceiling is marked with a `simplify:` comment naming the ceiling and the
14
- * upgrade path; a workaround is labeled `simplify:` / `temporary`, explains
15
- * why, and records the removal path in the plan/status artifact before the
16
- * task is claimed complete.
12
+ * First → "Simplification markers": a deliberate shortcut with a known
13
+ * ceiling is marked with a `simplify:` comment naming the ceiling and the
14
+ * upgrade path; a workaround is labeled `simplify:` / `temporary`, explains
15
+ * why, and records the removal path in the plan/status artifact before the
16
+ * task is claimed complete.
17
17
  * - SDD TDD triple: `mstar-coding-behavior` SKILL.md § Integration Notes —
18
- * completion evidence must include the TDD triple (test file(s), command,
19
- * output) in `task-N-report.md`; `mstar-sdd/references/file-handoffs.md` —
20
- * fix subagents append covering test file(s), command run, output.
18
+ * completion evidence must include the TDD triple (test file(s), command,
19
+ * output) in `task-N-report.md`; `mstar-sdd/references/file-handoffs.md` —
20
+ * fix subagents append covering test file(s), command run, output.
21
21
  * - Plan quality bar: `mstar-artifacts/references/plan-quality-bar.md`
22
- * § Quality checklist + `templates/plan.main.md` self-review
23
- * ("Placeholder scan: no TBD").
22
+ * § Quality checklist + `templates/plan.main.md` self-review
23
+ * ("Placeholder scan: no TBD").
24
24
  * - Skill frontmatter contract: `mstar-skill-authoring` SKILL.md § Frontmatter
25
- * Contract — `name` stable lowercase-hyphen; `description` is the trigger
26
- * contract (not a workflow summary), third person.
25
+ * Contract — `name` stable lowercase-hyphen; `description` is the trigger
26
+ * contract (not a workflow summary), third person.
27
27
  * - STRATEGY.md structure: `mstar-strategy` SKILL.md § STRATEGY.md structure —
28
- * six required sections.
28
+ * six required sections.
29
29
  * - Ephemeral citations: knowledge `conventions/skill-content-porting-discipline.md`
30
- * §3 ("No ephemeral citations in durable skill text") + session evaluation
31
- * 2026-08-16 discrimination contract — concrete task-artifact references
32
- * and SDD deeplinks are ephemeral; placeholder forms are not.
30
+ * §3 ("No ephemeral citations in durable skill text") + session evaluation
31
+ * 2026-08-16 discrimination contract — concrete task-artifact references
32
+ * and SDD deeplinks are ephemeral; placeholder forms are not.
33
33
  *
34
34
  * Enforcement depth: roadmap §8.5 C4 — v1 lints are non-blocking
35
35
  * `ValidationResult`s; callers surface them as warnings.
@@ -112,8 +112,8 @@ export type EphemeralCitation = {
112
112
  /** The matched citation token (artifact name or deeplink prefix). */
113
113
  match: string;
114
114
  /** `task-artifact`: `task-<digits>-(brief|report|fix-report|diff)`;
115
- * `sdd-deeplink`: `.mstar/sdd/` / `.agents/sdd/` + a concrete first
116
- * segment. */
115
+ * `sdd-deeplink`: `.mstar/sdd/` / `.agents/sdd/` + a concrete first
116
+ * segment. */
117
117
  kind: "task-artifact" | "sdd-deeplink";
118
118
  };
119
119
  /**
@@ -123,12 +123,12 @@ export type EphemeralCitation = {
123
123
  *
124
124
  * Discrimination (HARD — zero false positives on the skills corpus):
125
125
  * - `task-<digits>-(brief|report|fix-report|diff)` with 1+ digits is a
126
- * concrete instance → reported (`task-2-report`, `task-1.diff`).
127
- * Placeholders (`task-N-brief`, `task-N-report`, `<plan-id>`,
128
- * `{SDD_DIR}/task-N-report.md`) never match.
126
+ * concrete instance → reported (`task-2-report`, `task-1.diff`).
127
+ * Placeholders (`task-N-brief`, `task-N-report`, `<plan-id>`,
128
+ * `{SDD_DIR}/task-N-report.md`) never match.
129
129
  * - `.mstar/sdd/<segment>` / `.agents/sdd/<segment>` with a concrete first
130
- * segment (`20260815-x`) → reported; `<plan-id>` / `{SDD_DIR}` segments
131
- * are template forms → never match.
130
+ * segment (`20260815-x`) → reported; `<plan-id>` / `{SDD_DIR}` segments
131
+ * are template forms → never match.
132
132
  *
133
133
  * Discovery only — a finder returning an array, same shape as
134
134
  * `findSimplifyMarkers`, NOT a GateResult; callers wrap findings into
@@ -151,17 +151,17 @@ export declare function findEphemeralCitations(skillText: string): EphemeralCita
151
151
  *
152
152
  * Heuristics (documented, conservative — tuned so prose alone never counts):
153
153
  * - tests: a `.test.<ext>` / `.spec.<ext>` path, or the phrase "test file(s)"
154
- * (the handoff template's exact header). "I added tests" without a file or
155
- * the phrase does not count.
154
+ * (the handoff template's exact header). "I added tests" without a file or
155
+ * the phrase does not count.
156
156
  * - command: a `$`-prefixed line, or a known runner invocation (bun/pnpm/
157
- * npm/yarn/npx/bunx test|run|exec, npx/bunx exec, tsc/vitest/jest/mocha/
158
- * pytest/go test/cargo test). Prose "run the tests" names no runner and
159
- * does not count (plan-quality-bar marks it a weak step anyway).
157
+ * npm/yarn/npx/bunx test|run|exec, npx/bunx exec, tsc/vitest/jest/mocha/
158
+ * pytest/go test/cargo test). Prose "run the tests" names no runner and
159
+ * does not count (plan-quality-bar marks it a weak step anyway).
160
160
  * - output: check marks, PASS/FAIL tokens, counts ("12 pass"), `N ok` /
161
- * TAP `ok N` / "all ok" verdicts, exit-code statements. Bare prose
162
- * `OK`/`ERROR` ("OK, moving on") does NOT count — output evidence must
163
- * look like output. Line-based and fence-insensitive: real output usually
164
- * lives in fenced blocks, so fence content is scanned too.
161
+ * TAP `ok N` / "all ok" verdicts, exit-code statements. Bare prose
162
+ * `OK`/`ERROR` ("OK, moving on") does NOT count — output evidence must
163
+ * look like output. Line-based and fence-insensitive: real output usually
164
+ * lives in fenced blocks, so fence content is scanned too.
165
165
  */
166
166
  export declare function assertSddTddTriple(reportText: string): GateResult;
167
167
  /**
@@ -188,16 +188,16 @@ export type PlanQualityResult = GateResult & {
188
188
  *
189
189
  * Heuristic (documented, conservative):
190
190
  * - tokens: `TBD`, `TODO`, `TBA` (case-insensitive, word-boundary, plural
191
- * forms included) and the prose ellipsis `...`. One finding per line per
192
- * token (a line with two TBDs yields one finding).
191
+ * forms included) and the prose ellipsis `...`. One finding per line per
192
+ * token (a line with two TBDs yields one finding).
193
193
  * - negation guard: a token preceded by a negation word (`no/not/without/
194
- * none`) in the same segment (split at `(`/`[`/`{`/`.`/`;`/`,`/line
195
- * start) is an absence assertion ("no TBD/placeholder/TODO" states the
196
- * rule), not a placeholder — not flagged.
194
+ * none`) in the same segment (split at `(`/`[`/`{`/`.`/`;`/`,`/line
195
+ * start) is an absence assertion ("no TBD/placeholder/TODO" states the
196
+ * rule), not a placeholder — not flagged.
197
197
  * - exemptions: fenced code blocks (```` ``` ```` / `~~~`) and inline code
198
- * spans are skipped — `...` in a file-list or example is not a placeholder.
198
+ * spans are skipped — `...` in a file-list or example is not a placeholder.
199
199
  * - out of scope (judgment stays prompt): "add tests" without code, and
200
- * `FIXME`/`XXX` code markers.
200
+ * `FIXME`/`XXX` code markers.
201
201
  */
202
202
  export declare function planQualityBar(planText: string): PlanQualityResult;
203
203
  /**
@@ -205,7 +205,7 @@ export declare function planQualityBar(planText: string): PlanQualityResult;
205
205
  * Frontmatter Contract:
206
206
  * - `name` — stable, lowercase-hyphen (`example-skill`);
207
207
  * - `description` — the trigger contract, third person, not a workflow
208
- * summary.
208
+ * summary.
209
209
  *
210
210
  * Accepts a full document (leading `---`-fenced block is parsed) or a bare
211
211
  * frontmatter body (`name:`/`description:` lines at the start). Violations:
@@ -214,21 +214,21 @@ export declare function planQualityBar(planText: string): PlanQualityResult;
214
214
  * - `lint.frontmatter.name.format` — `name` not lowercase-hyphen
215
215
  * - `lint.frontmatter.description.missing` — `description` absent/empty
216
216
  * - `lint.frontmatter.description.person` — first/second-person pronoun in
217
- * the description (third-person heuristic, low severity)
217
+ * the description (third-person heuristic, low severity)
218
218
  * - `lint.frontmatter.description.workflow` — description reads as a
219
- * workflow summary (verb-start or paragraph-length heuristic, low
220
- * severity)
219
+ * workflow summary (verb-start or paragraph-length heuristic, low
220
+ * severity)
221
221
  *
222
222
  * Heuristics (documented, conservative; corpus regression tests in
223
223
  * lint.test.ts cover the 20 real skill frontmatters):
224
224
  * - pronouns: `I`/`we`/`you`/`my`/`our`/`your`/`us`, word-boundary,
225
- * case-insensitive, after stripping quoted and backticked spans; `I/`
226
- * (I/O) and all-caps `US` exempt.
225
+ * case-insensitive, after stripping quoted and backticked spans; `I/`
226
+ * (I/O) and all-caps `US` exempt.
227
227
  * - workflow shape: description starts with a workflow verb ("Explains how
228
- * …", "Describes …") — the contract's own bad example — or exceeds 120
229
- * words (corpus max 114). Bold/quote prefixes are stripped before the
230
- * verb check. No content judgment (e.g. whether the trigger is narrow
231
- * enough) — that stays prompt.
228
+ * …", "Describes …") — the contract's own bad example — or exceeds 120
229
+ * words (corpus max 114). Bold/quote prefixes are stripped before the
230
+ * verb check. No content judgment (e.g. whether the trigger is narrow
231
+ * enough) — that stays prompt.
232
232
  */
233
233
  export declare function lintSkillFrontmatter(frontmatterText: string): GateResult;
234
234
  /**
package/dist/migrate.d.ts CHANGED
@@ -19,12 +19,12 @@ export type MigrateSnapshot = {
19
19
  type: WorkflowLifecycleType;
20
20
  status: WorkflowLifecycleStatus;
21
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
- */
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
28
  file: string;
29
29
  /** Provenance label (compass file / status.json row). */
30
30
  source: string;
@@ -57,7 +57,7 @@ export type MigrateRootV2 = {
57
57
  file: string;
58
58
  data: StatusV2Doc;
59
59
  };
60
- /** Planner options (plan Task 6 — `--dry-run` returns steps, zero writes). */
60
+ /** Planner options ( — `--dry-run` returns steps, zero writes). */
61
61
  export type MigrateOptions = {
62
62
  dryRun?: boolean;
63
63
  /** Project id for the register/roadmap home (default `_default`). */
@@ -68,20 +68,20 @@ export type MigratePlan = {
68
68
  /** Resolved harness dir. */
69
69
  root: string;
70
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
- */
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
78
  workflowDir: string;
79
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
- */
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
85
  projectDir: string;
86
86
  dryRun: boolean;
87
87
  /** Root status.json already at `version: 2` -> nothing to plan/apply. */
@@ -108,7 +108,7 @@ export type MigrateResult = {
108
108
  message: string;
109
109
  };
110
110
  /**
111
- * Pure migration planner (plan Task 6): reads the v1 tree under `root` and
111
+ * Pure migration planner (): reads the v1 tree under `root` and
112
112
  * returns the full v2 migration plan — snapshots, notes ledgers, project
113
113
  * register, roadmap seeds, the archived v1 copy and the root v2
114
114
  * replacement — with an ordered step list (source -> destination). ZERO
@@ -120,7 +120,7 @@ export type MigrateResult = {
120
120
  */
121
121
  export declare function migrateHarnessTree(root: string, opts?: MigrateOptions): MigratePlan;
122
122
  /**
123
- * Execute a migration plan (plan Task 6). Additive-first ordering: the v1
123
+ * Execute a migration plan (). Additive-first ordering: the v1
124
124
  * root is archived, workflow snapshots/notes, the project register and the
125
125
  * roadmap are written BEFORE the root v2 replacement — the LAST step, the
126
126
  * commit point. A failure before it leaves the v1 tree intact (re-run
@@ -128,7 +128,7 @@ export declare function migrateHarnessTree(root: string, opts?: MigrateOptions):
128
128
  * `dryRun` plan, is a no-op. Every destination stays inside the harness
129
129
  * dir; every snapshot is validated fail-closed inside `writeWorkflowSnapshot`
130
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
131
+ * pre-validate (a gate here would run the same O(rows) pass
132
132
  * twice per snapshot).
133
133
  */
134
134
  export declare function applyMigratePlan(plan: MigratePlan): Promise<MigrateResult>;
package/dist/path.d.ts CHANGED
@@ -4,25 +4,25 @@ import { type ValidationResult } from "./core.js";
4
4
  */
5
5
  export type ResolveHarnessDirOptions = {
6
6
  /**
7
- * Explicit harness root. Resolved against `startDir` when relative.
8
- * Takes precedence over `MSTAR_HARNESS_DIR` and over default probing.
9
- * Authoritative: the path is returned even when it does not exist yet
10
- * (the caller may scaffold it).
11
- */
7
+ * Explicit harness root. Resolved against `startDir` when relative.
8
+ * Takes precedence over `MSTAR_HARNESS_DIR` and over default probing.
9
+ * Authoritative: the path is returned even when it does not exist yet
10
+ * (the caller may scaffold it).
11
+ */
12
12
  harnessDir?: string;
13
13
  /**
14
- * Workspace-root stop boundary (roadmap §7c / plan
15
- * 20260810-harness-root-boundary). The upward probe keeps walking only
16
- * while `dir` is at or below this root — a harness dir above it is never
17
- * returned (the `~/.mstar` global-collision defect is the special case).
18
- * Resolved against `startDir` when relative. When omitted, the default
19
- * boundary is the git top-level of `startDir` (sync `git rev-parse
20
- * --show-cdup`; on failure / non-git start it falls back to
21
- * `startDir` itself — a non-git start probes only itself, never upward;
22
- * deliberate tightening). The boundary is an explicit caller value: the
23
- * engine git-probes only for this default resolution, never during the
24
- * walk.
25
- */
14
+ * Workspace-root stop boundary (roadmap §7c / plan
15
+ * 20260810-harness-root-boundary). The upward probe keeps walking only
16
+ * while `dir` is at or below this root — a harness dir above it is never
17
+ * returned (the `~/.mstar` global-collision defect is the special case).
18
+ * Resolved against `startDir` when relative. When omitted, the default
19
+ * boundary is the git top-level of `startDir` (sync `git rev-parse
20
+ * --show-cdup`; on failure / non-git start it falls back to
21
+ * `startDir` itself — a non-git start probes only itself, never upward;
22
+ * deliberate tightening). The boundary is an explicit caller value: the
23
+ * engine git-probes only for this default resolution, never during the
24
+ * walk.
25
+ */
26
26
  workspaceRoot?: string;
27
27
  };
28
28
  /**
@@ -48,10 +48,10 @@ export declare function resolveHarnessDir(startDir?: string, opts?: ResolveHarne
48
48
  */
49
49
  export type ResolveSpecsDirOptions = {
50
50
  /**
51
- * Default true: when every candidate is absent or empty, create
52
- * `{HARNESS_DIR}/specs/` (plan-conventions § 创建默认). Read-only callers
53
- * (e.g. `mstar path resolve`) pass `false` to skip the side effect.
54
- */
51
+ * Default true: when every candidate is absent or empty, create
52
+ * `{HARNESS_DIR}/specs/` (plan-conventions § 创建默认). Read-only callers
53
+ * (e.g. `mstar path resolve`) pass `false` to skip the side effect.
54
+ */
55
55
  create?: boolean;
56
56
  };
57
57
  /**
@@ -79,12 +79,23 @@ export declare function resolveSpecsDir(harnessDir: string, opts?: ResolveSpecsD
79
79
  export declare function resolvePlanDir(harnessDir: string): string;
80
80
  /**
81
81
  * Single safe path component for per-plan path composition
82
- * (qc2 F-001 — path traversal guard): rejects `""`, `.`, `..`, and any
82
+ * (path traversal guard): rejects `""`, `.`, `..`, and any
83
83
  * `/` or `\`; allows `[A-Za-z0-9._-]+` only. Throws with a clear message so
84
84
  * callers interpolating a plan id into a path (archive files, SDD dirs)
85
85
  * can never escape the intended parent directory.
86
86
  */
87
87
  export declare function assertSafePathComponent(value: string, what: string): void;
88
+ /**
89
+ * Canonicalize `path` for containment checks when the leaf may not exist
90
+ * (A3 nonexistent-leaf rule): canonicalize the nearest existing ancestor
91
+ * (realpath — resolves macOS `/var` → `/private/var` and any symlinked
92
+ * ancestors) and append the not-yet-existing remaining segments lexically.
93
+ * `..`/`.` segments are collapsed lexically by `resolve` before the walk,
94
+ * so the result is the path a later write would actually land at. Pure
95
+ * read-only (stat/realpath only — never creates anything). When nothing up
96
+ * to the filesystem root exists, the lexically resolved input is returned.
97
+ */
98
+ export declare function canonicalizeNearestExisting(path: string): string;
88
99
  /**
89
100
  * Compose `{SDD_DIR}` = `{HARNESS_DIR}/sdd/<plan-id>/` (plan-conventions
90
101
  * § 路径符号). A `.mstarc` `[config] sdd_dir` declaration replaces the
@@ -113,7 +124,7 @@ export declare function resolveKnowledgeDir(harnessDir: string): string;
113
124
  * the config file's directory). The dir need not exist — writers
114
125
  * (`writeWorkflowSnapshot` / register paths) create it on demand.
115
126
  *
116
- * Deferred-by-design (qc1 S-3): the startDir-first signature is asymmetric
127
+ * Deferred-by-design : the startDir-first signature is asymmetric
117
128
  * with the harnessDir-first sibling resolvers — brief-mandated for the CLI
118
129
  * consumer (it probes from the cwd). Revisit with a harness-dir-first
119
130
  * variant when a third v3 subdir resolver appears.
@@ -124,8 +135,7 @@ export declare function resolveWorkflowDir(startDir?: string, opts?: ResolveHarn
124
135
  * layer: roadmap.md + residuals register per project id). A `.mstarc`
125
136
  * `[config] project_dir` declaration wins (resolved against the config
126
137
  * file's directory). Same deferred-by-design signature asymmetry as
127
- * `resolveWorkflowDir` (qc1 S-3).
128
- */
138
+ * `resolveWorkflowDir`. */
129
139
  export declare function resolveProjectDir(startDir?: string, opts?: ResolveHarnessDirOptions): string;
130
140
  /**
131
141
  * Resolve the scaffold target dirs for `root` — the harness dir and the
package/dist/project.d.ts CHANGED
@@ -1,18 +1,18 @@
1
1
  import { type GateResult, type ValidationResult } from "./core.js";
2
2
  import { type ResidualEntry } from "./status.js";
3
- /** Roadmap file name inside `projects/<id>/` (plan Task 4 — writer contract). */
3
+ /** Roadmap file name inside `projects/<id>/` ( — writer contract). */
4
4
  export declare const PROJECT_ROADMAP_FILE = "roadmap.md";
5
- /** Theme-scoped research directory name inside `projects/<id>/` (plan 20260820-project-research-corpus Task 1 — compass ruling 1). */
5
+ /** Theme-scoped research directory name inside `projects/<id>/`. */
6
6
  export declare const PROJECT_REFERENCES_DIR = "references";
7
- /** Project register file name inside `projects/<id>/` (plan Task 4). */
7
+ /** Project register file name inside `projects/<id>/` (). */
8
8
  export declare const PROJECT_REGISTER_FILE = "residuals.json";
9
- /** Fallback project id for project-less flows (plan Task 4 — compass ruling 2). */
9
+ /** Fallback project id for project-less flows ( — compass ruling 2). */
10
10
  export declare const _DEFAULT_PROJECT = "_default";
11
- /** Roadmap status enum (plan Task 4 — frontmatter schema). */
11
+ /** Roadmap status enum ( — frontmatter schema). */
12
12
  export declare const ROADMAP_STATUSES: readonly ["active", "paused", "completed"];
13
13
  export type RoadmapStatus = (typeof ROADMAP_STATUSES)[number];
14
14
  /**
15
- * Roadmap frontmatter (plan Task 4): machine-checkable subset. All fields
15
+ * Roadmap frontmatter (): machine-checkable subset. All fields
16
16
  * are `unknown` because documents come from YAML at runtime; the validator
17
17
  * narrows them. `milestones` / `residuals_ref` are optional; goal-item body
18
18
  * conventions are warnings only.
@@ -33,8 +33,8 @@ export type ProjectRegisterEntry = ResidualEntry & {
33
33
  lifecycle_id?: string;
34
34
  };
35
35
  /**
36
- * Register document shape (`projects/<id>/residuals.json`, plan Task 4;
37
- * QC wave-1 W-E): `entries` keyed by plan id, each value an ARRAY of
36
+ * Register document shape (`projects/<id>/residuals.json`(;
37
+ * `entries` keyed by plan id, each value an ARRAY of
38
38
  * register entries — v1 `residual_findings[plan-id] = entries[]`
39
39
  * multi-finding semantics preserved verbatim (a plan can hold 2+ open
40
40
  * residuals). `migration_notes[]` (the old single-entry collapse record)
@@ -46,7 +46,7 @@ export type ProjectRegisterDoc = {
46
46
  };
47
47
  /**
48
48
  * Roadmap validation result: schema violations decide `ok`; body-convention
49
- * findings are collected as `warnings` and never flip `ok` (plan Task 4
49
+ * findings are collected as `warnings` and never flip `ok` ( —
50
50
  * goal-item body is not a hard gate).
51
51
  */
52
52
  export type RoadmapValidation = GateResult & {
@@ -79,7 +79,7 @@ export type TechDebtRollup = {
79
79
  overall: "PASS" | "DRIFT";
80
80
  };
81
81
  /**
82
- * Validate a roadmap.md file (plan Task 4): parse the frontmatter with the
82
+ * Validate a roadmap.md file (): parse the frontmatter with the
83
83
  * shared flat-subset parser and check the schema
84
84
  * `{ project_id, title, status: active|paused|completed, created_at,
85
85
  * milestones[]?, residuals_ref? }`. A roadmap file whose body follows the
@@ -90,7 +90,7 @@ export type TechDebtRollup = {
90
90
  export declare function validateRoadmap(filePath: string): RoadmapValidation;
91
91
  /**
92
92
  * Validate a project register document (`projects/<id>/residuals.json`,
93
- * plan Task 4; QC wave-1 W-E): `{ entries: { [key]: entry[] } }` keyed by
93
+ * `{ entries: { [key]: entry[] } }` keyed by
94
94
  * plan id, each value an ARRAY of entries (v1 `residual_findings[plan-id]`
95
95
  * multi-finding semantics preserved — a plan may hold 2+ open residuals).
96
96
  * Each entry is validated by the v1 `validateResidual` verbatim (severity
@@ -100,21 +100,21 @@ export declare function validateRoadmap(filePath: string): RoadmapValidation;
100
100
  * `lifecycle_id`.
101
101
  */
102
102
  export declare function validateProjectRegister(doc: unknown): GateResult;
103
- /** Options for `appendProjectRegisterEntries` (plan 20260826-backlog-register-cli Task 1 + B-9). */
103
+ /** Options for `appendProjectRegisterEntries`. */
104
104
  export type AppendProjectRegisterEntriesOpts = {
105
105
  /** Absolute path to the per-project directory (`<harness>/projects/<id>`; `_default` for project-less flows). */
106
106
  projectDir: string;
107
107
  /**
108
- * Base entries key (`<plan-id>`), e.g. `pr-deep-review-2026-08-26`. The
109
- * first free same-day key (`basePlanKey`, `basePlanKey-2`, `-3`, …) is
110
- * selected INSIDE the status write lock — a caller-computed key would be a
111
- * cross-lock TOCTOU (B-9 correction ①).
112
- */
108
+ * Base entries key (`<plan-id>`), e.g. `pr-deep-review-2026-08-26`. The
109
+ * first free same-day key (`basePlanKey`, `basePlanKey-2`, `-3`, …) is
110
+ * selected INSIDE the status write lock — a caller-computed key would be a
111
+ * cross-lock TOCTOU (B-9 correction ①).
112
+ */
113
113
  basePlanKey: string;
114
114
  /** Residual entries to append — nine required fields + provenance. `source_plan` is overwritten with the used key; `registered_at` is required and must be set by the caller. */
115
115
  entries: ResidualEntry[];
116
116
  };
117
- /** Options for `closeProjectRegisterEntry` (plan 20260826-backlog-register-cli Task 1). */
117
+ /** Options for `closeProjectRegisterEntry`. */
118
118
  export type CloseProjectRegisterEntryOpts = {
119
119
  /** Absolute path to the per-project directory (`<harness>/projects/<id>`; `_default` for project-less flows). */
120
120
  projectDir: string;
@@ -126,8 +126,7 @@ export type CloseProjectRegisterEntryOpts = {
126
126
  closureNote: string;
127
127
  };
128
128
  /**
129
- * Append residual entries to a project register (plan 20260826-backlog-register-cli
130
- * Task 1 + B-9): resolve `<projectDir>/residuals.json` and run the WHOLE
129
+ * Append residual entries to a project register: resolve `<projectDir>/residuals.json` and run the WHOLE
131
130
  * critical section inside `withStatusWriteLock(registerPath, ...)` (lease.ts —
132
131
  * the `<register dir>/.status-write.lockdir/` lock is reused, never
133
132
  * reimplemented). Read the register (absent → empty doc), select the first
@@ -140,7 +139,7 @@ export type CloseProjectRegisterEntryOpts = {
140
139
  * key beforehand), append preserving every other key, validate the whole
141
140
  * register with `validateProjectRegister`, then `ArtifactStore.put`
142
141
  * (FsStore uses `writeJson` — atomic temp+rename; never `open(w)`).
143
- * Fails loud (qc3 F-201) when the active FsStore would resolve a register
142
+ * Fails loud when the active FsStore would resolve a register
144
143
  * path other than `<projectDir>/residuals.json` — callers whose target root
145
144
  * differs from the active store's root MUST
146
145
  * `setArtifactStore(createFsStore(root))` first. Fail-loud: any validation
@@ -151,13 +150,12 @@ export declare function appendProjectRegisterEntries(opts: AppendProjectRegister
151
150
  key: string;
152
151
  }>;
153
152
  /**
154
- * Close one project-register entry in place (plan 20260826-backlog-register-cli
155
- * Task 1): under `withStatusWriteLock(registerPath, ...)`, find `entryId` in
153
+ * Close one project-register entry in place under `withStatusWriteLock(registerPath, ...)`, find `entryId` in
156
154
  * `entries[planKey]` (absent → throw), set `lifecycle: resolved` +
157
155
  * `closed_at: <today YYYY-MM-DD>` + `closure_note`, validate the whole
158
156
  * register with `validateProjectRegister`, then `ArtifactStore.put`
159
157
  * (FsStore uses `writeJson` — atomic temp+rename).
160
- * Fails loud (qc3 F-201) when the active FsStore would resolve a register
158
+ * Fails loud when the active FsStore would resolve a register
161
159
  * path other than `<projectDir>/residuals.json`. Fail-loud: an invalid
162
160
  * register throws and nothing is written.
163
161
  */
@@ -166,7 +164,7 @@ export declare function closeProjectRegisterEntry(opts: CloseProjectRegisterEntr
166
164
  }>;
167
165
  /**
168
166
  * Findings cleanup gate (status-and-residuals.md § Findings cleanup modes;
169
- * QC wave-1 W-D relocation — the input is the project register
167
+ * The input is the project register
170
168
  * `projects/<id>/residuals.json`, entries keyed by plan id with an ARRAY of
171
169
  * residuals per plan, and the plan id links the register entries to the
172
170
  * snapshot's plan row). Every OPEN entry of the plan is checked.
@@ -181,7 +179,7 @@ export declare function findingsCleanupGate(register: ProjectRegisterDoc, planId
181
179
  mode?: FindingsCleanupMode;
182
180
  }): GateResult;
183
181
  /**
184
- * Compute the tech-debt rollup over the project registers (QC wave-1 W-D
182
+ * Compute the tech-debt rollup over the project registers
185
183
  * relocation — status-and-residuals.md § `metadata.tech_debt_summary`
186
184
  * semantics preserved at the project layer): `total_open` / `by_severity` /
187
185
  * `by_target` / `by_plan` over open entries of every