@mstar-harness/engine 3.6.3 → 3.7.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/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
@@ -57,8 +57,7 @@ export type PrTallyResult = {
57
57
  */
58
58
  export declare function computePrTally(input: PrTallyInput): PrTallyResult;
59
59
  /**
60
- * One accepted PR-review finding in the `mstar.review/v1` envelope (SP3 §
61
- * Schema). `mergeClass` is harness vocab (MERGE_CLASSES); `title`/`body`
60
+ * One accepted PR-review finding in the `mstar.review/v1` envelope (the review envelope schema). `mergeClass` is harness vocab (MERGE_CLASSES); `title`/`body`
62
61
  * are non-empty strings; the rest are optional.
63
62
  */
64
63
  export type MstarReviewFinding = {
@@ -72,7 +71,7 @@ export type MstarReviewFinding = {
72
71
  fingerprint_hint?: string;
73
72
  };
74
73
  /**
75
- * The `mstar.review/v1` envelope (SP3 § Schema) — a parseable review
74
+ * The `mstar.review/v1` envelope (the review envelope schema) — a parseable review
76
75
  * document with harness vocab, sibling to the Markdown pr-review report.
77
76
  * `verdict` is PR_VERDICTS; `tally` (when present) must be a full
78
77
  * `PrTallyResult` (shape-checked) whose `verdict` must equal the top-level
@@ -92,7 +91,7 @@ export type MstarReviewV1 = {
92
91
  };
93
92
  };
94
93
  /**
95
- * Validate a `mstar.review/v1` envelope (SP3 § Schema). Fail-loud sibling
94
+ * Validate a `mstar.review/v1` envelope (the review envelope schema). Fail-loud sibling
96
95
  * of {@link validatePrReviewReport} (the Markdown report validator) —
97
96
  * shares PR_VERDICTS / MERGE_CLASSES only, never reuses the Markdown
98
97
  * parser. Inspector M1 vocab (`comment|request_changes|approve`,
@@ -108,7 +107,7 @@ export type MstarReviewV1 = {
108
107
  export declare function validateMstarReviewV1(doc: unknown): GateResult;
109
108
  /**
110
109
  * Fold already-vetted findings into a complete `mstar.review/v1` envelope
111
- * (SP3 § synthesizeReview). Pure and synchronous — verdict/tally come ONLY
110
+ * . Pure and synchronous — verdict/tally come ONLY
112
111
  * from {@link computePrTally}; no I/O, no GitHub, no store, no seat
113
112
  * dispatch. `findings` pass through untouched; `target` is carried when
114
113
  * provided. When `summary_md` is omitted, {@link defaultReviewSummary}
@@ -126,11 +125,11 @@ export declare function synthesizeReview(input: {
126
125
  *
127
126
  * - `pr` — reviewed PR number `n`.
128
127
  * - `branch` — bare branch, `slug` is the pre-slugged `<branch-slug>`
129
- * (caller slugs; the resolver only guards path safety).
128
+ * (caller slugs; the resolver only guards path safety).
130
129
  * - `diff` — arbitrary changeset. When `headSha` is a non-empty string its
131
- * short form (first 7 hex chars) lands in the filename; when absent or an
132
- * empty string the bare `-diff` stem is used — a missing SHA is **never
133
- * fabricated** (pr-review.md § Local report archive, Filename bullet).
130
+ * short form (first 7 hex chars) lands in the filename; when absent or an
131
+ * empty string the bare `-diff` stem is used — a missing SHA is **never
132
+ * fabricated** (pr-review.md § Local report archive, Filename bullet).
134
133
  */
135
134
  export type PrReportTarget = {
136
135
  kind: "pr";
@@ -148,16 +147,16 @@ export type PrReportTarget = {
148
147
  * never writes and never overwrites):
149
148
  *
150
149
  * - `<YYYY-MM-DD>-pr<N>.md` for PR targets; bare branch →
151
- * `<YYYY-MM-DD>-<branch-slug>.md`; diff with head SHA →
152
- * `<YYYY-MM-DD>-diff-<short-head-sha>.md`; diff without →
153
- * `<YYYY-MM-DD>-diff.md` (never fabricate a SHA).
150
+ * `<YYYY-MM-DD>-<branch-slug>.md`; diff with head SHA →
151
+ * `<YYYY-MM-DD>-diff-<short-head-sha>.md`; diff without →
152
+ * `<YYYY-MM-DD>-diff.md` (never fabricate a SHA).
154
153
  * - `stage: 1 | 2` requires `slug` (the seat Assignment's `<domain>-<seat>`
155
- * slug) and produces the Stage 1/2 evidence-file stem
156
- * `<stem>-stage<1|2>-<slug>.md`.
154
+ * slug) and produces the Stage 1/2 evidence-file stem
155
+ * `<stem>-stage<1|2>-<slug>.md`.
157
156
  * - Same day, same target (same final stem): scans ALL existing files in
158
- * `reportsDir` with that stem and appends `-r2`, `-r3`, ... on collision —
159
- * a prior report is never overwritten. Report files and evidence files
160
- * escalate independently (different stems).
157
+ * `reportsDir` with that stem and appends `-r2`, `-r3`, ... on collision —
158
+ * a prior report is never overwritten. Report files and evidence files
159
+ * escalate independently (different stems).
161
160
  * - `date` defaults to the local calendar date and must be `YYYY-MM-DD`.
162
161
  */
163
162
  export declare function prReviewReportPath(opts: {
@@ -174,22 +173,22 @@ export declare function prReviewReportPath(opts: {
174
173
  *
175
174
  * - `type: pr-review` required.
176
175
  * - `verdict` exactly one of the three verdict tokens (§ Verdict synthesis)
177
- * and CONSISTENT with the tally (any must_fix -> blocked; else any
178
- * should_fix -> needs fixes; else ship it).
176
+ * and CONSISTENT with the tally (any must_fix -> blocked; else any
177
+ * should_fix -> needs fixes; else ship it).
179
178
  * - `score_pct` integer 0-100 and equal to the locked-formula recompute
180
- * from the document's own tally via {@link computePrTally}
181
- * (mismatch = hand-arithmetic drift — the exact defect class this gate
182
- * exists to catch).
179
+ * from the document's own tally via {@link computePrTally}
180
+ * (mismatch = hand-arithmetic drift — the exact defect class this gate
181
+ * exists to catch).
183
182
  * - `tally` flow map with the four classes.
184
183
  * - `comments` tri-state: `posted` (alias `yes`) | `n/a-no-pr` | `failed`.
185
- * The states are distinct: a FAILED POST IS `FAILED`, never
186
- * `n/a-no-pr`; `review_url` must pair accordingly (`http(s)://` for
187
- * posted, `n/a` for n/a-no-pr, a `failed: <gh error summary>` for failed).
184
+ * The states are distinct: a FAILED POST IS `FAILED`, never
185
+ * `n/a-no-pr`; `review_url` must pair accordingly (`http(s)://` for
186
+ * posted, `n/a` for n/a-no-pr, a `failed: <gh error summary>` for failed).
188
187
  * - `generated_at` must be `YYYY-MM-DD` (DATE_RE).
189
188
  * - `tier` optional: `quick | default | deep`; absent is valid (legacy
190
- * reports without tier still pass — SP-A amendment).
189
+ * reports without tier still pass — SP-A amendment).
191
190
  * - `elapsed` optional: non-negative integer minutes; absent is valid
192
- * (legacy reports without elapsed still pass).
191
+ * (legacy reports without elapsed still pass).
193
192
  */
194
193
  export declare function validatePrReviewReport(text: string): GateResult;
195
194
  /** One inline review comment: `path` + `line` in the three-dot diff, RIGHT
@@ -221,14 +220,14 @@ export type ReviewPostPlan = {
221
220
  * 422 fallback stay with the CLI, which owns the network):
222
221
  *
223
222
  * - Resolves the target from `gh pr view --json url,headRefOid` output:
224
- * parse `owner/repo` from `url` ONLY — the BASE repo that owns the PR
225
- * number. `headRepository` (fork head-repo data) is IGNORED: fork PRs
226
- * are legal, and a fork's owner/name must never leak into the API path.
227
- * It is never used as a fallback either.
223
+ * parse `owner/repo` from `url` ONLY — the BASE repo that owns the PR
224
+ * number. `headRepository` (fork head-repo data) is IGNORED: fork PRs
225
+ * are legal, and a fork's owner/name must never leak into the API path.
226
+ * It is never used as a fallback either.
228
227
  * - Missing/invalid `headRefOid` throws — there is no commit_id without
229
- * it.
228
+ * it.
230
229
  * - `event` is always the literal `"COMMENT"`; no other value exists in
231
- * this contract.
230
+ * this contract.
232
231
  * - Inline comments validated per-entry (path / positive line / RIGHT).
233
232
  */
234
233
  export declare function planReviewPost(prView: {
@@ -256,13 +255,13 @@ export type ReviewChangesetMode = "pr" | "branch" | "diff" | "working-tree" | "c
256
255
  * (pr-review.md § Worktree isolation Pre-flight bullet, all modes):
257
256
  *
258
257
  * - Named refs must resolve in modes that HAVE refs (pr / branch / commit);
259
- * establish them with explicit refspecs first.
258
+ * establish them with explicit refspecs first.
260
259
  * - The changeset must be NON-empty in ALL modes — an empty changeset
261
- * reports "no changes to review" and stops before any lens fan-out.
260
+ * reports "no changes to review" and stops before any lens fan-out.
262
261
  * - For working-tree input, untracked-only changes ARE a non-empty
263
- * changeset: the caller folds `git ls-files --others
264
- * --exclude-standard` output into `changesetEmpty: false` when anything
265
- * is listed.
262
+ * changeset: the caller folds `git ls-files --others
263
+ * --exclude-standard` output into `changesetEmpty: false` when anything
264
+ * is listed.
266
265
  */
267
266
  export declare function preflightChangeset(mode: ReviewChangesetMode, probe: {
268
267
  refsResolve: boolean;
@@ -277,12 +276,12 @@ export type PrReviewSizing = {
277
276
  /** True for too-large (>~1000) — advise a split, never auto-blocked. */
278
277
  adviseSplit: boolean;
279
278
  /** Stage 1 collect seats (§ Scale-driven fan-out table). Kept-wave
280
- * qualifier: these seats apply only when the deep collect wave is KEPT —
281
- * by default (pinned diff pack present) the fold dispatches none
282
- * (pr-review.md § Review pipeline fold default). */
279
+ * qualifier: these seats apply only when the deep collect wave is KEPT —
280
+ * by default (pinned diff pack present) the fold dispatches none
281
+ * (pr-review.md § Review pipeline fold default). */
283
282
  collectSeats: 2 | 3;
284
283
  /** File-size watch fired → advise extract/decompose ("decompose, then
285
- * add"). Independent of the diff size. */
284
+ * add"). Independent of the diff size. */
286
285
  fileDecomposeAdvice: boolean;
287
286
  };
288
287
  /**
@@ -290,13 +289,13 @@ export type PrReviewSizing = {
290
289
  * (pr-review.md § Sizing & change shape + § Scale-driven fan-out):
291
290
  *
292
291
  * - ≤~300 reviewable/acceptable → band `small`; >~300 → `large`;
293
- * >~1000 → `too-large` + split advice (a should-fix finding with split
294
- * advice or a verdict note — never auto-`blocked`).
292
+ * >~1000 → `too-large` + split advice (a should-fix finding with split
293
+ * advice or a verdict note — never auto-`blocked`).
295
294
  * - Stage 1 collect seats: small → 2 (code + security); large/too-large →
296
- * 3 by domain.
295
+ * 3 by domain.
297
296
  * - `largestTouchedFileTotal` drives `fileDecomposeAdvice` INDEPENDENTLY
298
- * of the diff size — a small diff materially growing a file past ~1000
299
- * total lines gets "decompose, then add".
297
+ * of the diff size — a small diff materially growing a file past ~1000
298
+ * total lines gets "decompose, then add".
300
299
  */
301
300
  export declare function prReviewSizing(input: {
302
301
  changedLines: number;
@@ -310,23 +309,23 @@ export declare function prReviewSizing(input: {
310
309
  * includes everything. */
311
310
  export type PrReviewTier = "quick" | "default" | "deep";
312
311
  /**
313
- * Per-tier time budget for the `amazing-pr-review` pipeline (SP1 tier
312
+ * Per-tier time budget for the `amazing-pr-review` pipeline (tier
314
313
  * time-budget). Prose SSOT: pr-review.md § Review depth — its Budget column
315
314
  * carries the wall-clock minutes; the per-seat caps below are the engine
316
315
  * contract, rendered into seat prompts, never duplicated as numbers in prose.
317
316
  *
318
317
  * - `wallClockMinutes`: prompt-discipline target for the whole review,
319
- * measured worktree-setup → local report saved by the main agent.
320
- * Overruns are declared in the report `- notes:` — budgets are never a
321
- * host-level hard kill.
318
+ * measured worktree-setup → local report saved by the main agent.
319
+ * Overruns are declared in the report `- notes:` — budgets are never a
320
+ * host-level hard kill.
322
321
  * - `maxSeats`: review seats only — Stage 2 domain seats + the independent
323
- * cross-domain security seat; NOT Stage 1 collect seats (collect fan-out
324
- * stays governed by pr-review.md § Scale-driven fan-out).
322
+ * cross-domain security seat; NOT Stage 1 collect seats (collect fan-out
323
+ * stays governed by pr-review.md § Scale-driven fan-out).
325
324
  * - `perSeatFindingsCap` / `evidenceTokensCap` / `fileOpenCap`: per-seat
326
- * expansion stops (findings / evidence payload tokens / file opens; the
327
- * pinned diff snapshot read does not count). Baseline assumption: 100
328
- * tok/s output — wall-clock is dominated by reads/tool latency, which
329
- * `fileOpenCap` bounds.
325
+ * expansion stops (findings / evidence payload tokens / file opens; the
326
+ * pinned diff snapshot read does not count). Baseline assumption: 100
327
+ * tok/s output — wall-clock is dominated by reads/tool latency, which
328
+ * `fileOpenCap` bounds.
330
329
  *
331
330
  * No new sizing bands: the table references tiers only (pr-review.md
332
331
  * § Sizing & change shape stays the only sizing SSOT). */
@@ -349,18 +348,18 @@ export type PrReviewSeatPromptOptions = {
349
348
  securitySeat?: boolean;
350
349
  tier?: PrReviewTier;
351
350
  /** Absolute path to the pinned diff snapshot written by `worktree-setup`
352
- * (review artifact beside the sidecar). Non-empty → the prompt gains a
353
- * read-first ingredient line pointing at it. */
351
+ * (review artifact beside the sidecar). Non-empty → the prompt gains a
352
+ * read-first ingredient line pointing at it. */
354
353
  diffFile?: string;
355
354
  /** Stage-2 only (`true` + `stage: 1` throws): the collect wave was folded
356
- * onto this domain seat — the deep-tier fold default (pinned diff pack
357
- * present; SSOT pr-review.md § Review pipeline; prose "collection folded
358
- * in = seat reuse" = § Review depth default-tier row). Kept-wave
359
- * exceptions dispatch collect seats instead. Requires a non-empty
360
- * `diffFile`, and the independent cross-domain security seat is never
361
- * folded — either contradiction throws. The prompt gains one bullet after
362
- * the `## Budget` block telling the seat to do its own collection, staying
363
- * within the budget block. Omitted/`false` → no line. */
355
+ * onto this domain seat — the deep-tier fold default (pinned diff pack
356
+ * present; SSOT pr-review.md § Review pipeline; prose "collection folded
357
+ * in = seat reuse" = § Review depth default-tier row). Kept-wave
358
+ * exceptions dispatch collect seats instead. Requires a non-empty
359
+ * `diffFile`, and the independent cross-domain security seat is never
360
+ * folded — either contradiction throws. The prompt gains one bullet after
361
+ * the `## Budget` block telling the seat to do its own collection, staying
362
+ * within the budget block. Omitted/`false` → no line. */
364
363
  collectFolded?: boolean;
365
364
  };
366
365
  /**
@@ -370,30 +369,30 @@ export type PrReviewSeatPromptOptions = {
370
369
  * Ingredients:
371
370
  *
372
371
  * - Absolute path to `references/pr-review.md` under `skillRoot` + the
373
- * sections to read; absolute review `worktreePath`.
374
- * - Per-seat budget block (`## Budget`, SP1 tier time-budget): findings /
375
- * evidence-token / file-open caps interpolated from `PR_REVIEW_TIER_BUDGETS`
376
- * — expansion stops for the seat, never a host-level hard stop.
372
+ * sections to read; absolute review `worktreePath`.
373
+ * - Per-seat budget block (`## Budget`, tier time budget): findings /
374
+ * evidence-token / file-open caps interpolated from `PR_REVIEW_TIER_BUDGETS`
375
+ * — expansion stops for the seat, never a host-level hard stop.
377
376
  * - `collectFolded: true` (stage 2 only; stage 1, a missing `diffFile`, or
378
- * the security seat throws): one bullet after the `## Budget` block — the
379
- * collect wave folded onto this seat, so it collects itself (pinned diff
380
- * snapshot/pack first, then in-domain changed files) within the budget
381
- * block.
377
+ * the security seat throws): one bullet after the `## Budget` block — the
378
+ * collect wave folded onto this seat, so it collects itself (pinned diff
379
+ * snapshot/pack first, then in-domain changed files) within the budget
380
+ * block.
382
381
  * - Recon facts + decided tradeoffs.
383
382
  * - Hard Rules 4/5 VERBATIM.
384
383
  * - Payload-return contract (write-blocked-safe; main agent writes files).
385
384
  * - No-verdict / never-post clauses.
386
385
  * - Slug mandate `<domain>-<seat>`.
387
386
  * - Stage 2 adds finding-format.md (+ security-review.md for security
388
- * seats) and the Merge-class instruction.
387
+ * seats) and the Merge-class instruction.
389
388
  * - Tier cuts (SP-A amendment): quick drops the cross-domain /
390
- * independent-security block, the collect-wave wording AND shrinks the
391
- * lens/prompt-ingredient set; default drops the same blocks (SSOT
392
- * pr-review.md § Review depth, default-tier row: "collection folded in =
393
- * seat reuse" — no separate Stage-1 wave, so collect-wave wording is
394
- * deep-only); deep keeps everything.
395
- * Tier omitted → `default` (pr-review.md § Review depth: the no-flag
396
- * landing tier).
389
+ * independent-security block, the collect-wave wording AND shrinks the
390
+ * lens/prompt-ingredient set; default drops the same blocks (SSOT
391
+ * pr-review.md § Review depth, default-tier row: "collection folded in =
392
+ * seat reuse" — no separate Stage-1 wave, so collect-wave wording is
393
+ * deep-only); deep keeps everything.
394
+ * Tier omitted → `default` (pr-review.md § Review depth: the no-flag
395
+ * landing tier).
397
396
  */
398
397
  export declare function prReviewSeatPrompt(opts: PrReviewSeatPromptOptions): string;
399
398
  /** Options for {@link validateFindingDoc}: `prVariant` gates the Merge
@@ -407,18 +406,18 @@ export type ValidateFindingDocOptions = {
407
406
  * PR-only Merge class contract (pr-review.md § Merge class):
408
407
  *
409
408
  * - Every finding opens with `### [CATEGORY-NN] Title`; CATEGORY ∈
410
- * `AUDIT_CATEGORIES` (case-insensitive read, canonical uppercase forms
411
- * per category codes), NN numeric.
409
+ * `AUDIT_CATEGORIES` (case-insensitive read, canonical uppercase forms
410
+ * per category codes), NN numeric.
412
411
  * - Required fields: Evidence / Impact / Effort / Risk / Confidence —
413
- * Effort / Risk / Confidence each validated as their LEADING token
414
- * (Effort via `AUDIT_EFFORTS`, Risk via `AUDIT_RISKS`, Confidence via
415
- * HIGH | MED | LOW with `MEDIUM` tolerated as the MED alias); free-text
416
- * gloss after a separator is allowed and ignored.
412
+ * Effort / Risk / Confidence each validated as their LEADING token
413
+ * (Effort via `AUDIT_EFFORTS`, Risk via `AUDIT_RISKS`, Confidence via
414
+ * HIGH | MED | LOW with `MEDIUM` tolerated as the MED alias); free-text
415
+ * gloss after a separator is allowed and ignored.
417
416
  * - Each Evidence citation matches `path:line` (`\S+:\d+` — the path may
418
- * but need not carry an extension).
417
+ * but need not carry an extension).
419
418
  * - `prVariant` (default false): every finding additionally carries
420
- * **Merge class** ∈ {must-fix, should-fix, nit} placed IMMEDIATELY after
421
- * Confidence.
419
+ * **Merge class** ∈ {must-fix, should-fix, nit} placed IMMEDIATELY after
420
+ * Confidence.
422
421
  */
423
422
  export declare function validateFindingDoc(text: string, opts?: ValidateFindingDocOptions): GateResult;
424
423
  /** Tier keywords the CLI may have matched from argv — the three explicit
@@ -441,16 +440,16 @@ export type ResolvePrReviewTierInput = {
441
440
  * (SP-A amendment; first hit wins):
442
441
  *
443
442
  * 1. Explicit keyword → that tier (user intent beats heuristics; a lone
444
- * `default` returns `default` BEFORE the band/sensitive heuristics).
445
- * Any two DISTINCT keywords (quick / default / deep) → hard-stop
446
- * conflict error — never silently take a priority. (Empty/omitted =
447
- * no flag.)
443
+ * `default` returns `default` BEFORE the band/sensitive heuristics).
444
+ * Any two DISTINCT keywords (quick / default / deep) → hard-stop
445
+ * conflict error — never silently take a priority. (Empty/omitted =
446
+ * no flag.)
448
447
  * 2. Too large (>~1000 / band too-large) → advise split; review anyway →
449
- * deep.
448
+ * deep.
450
449
  * 3. Sensitive surface (auth / LLM / supply chain / data) → deep at any
451
- * size.
450
+ * size.
452
451
  * 4. Large (>~300 / band large) → deep.
453
452
  * 5. Small: tiny-mechanical shape (docs-only / rename / formatting / pure
454
- * deletion) → quick; anything else (real code change) → default.
453
+ * deletion) → quick; anything else (real code change) → default.
455
454
  */
456
455
  export declare function resolvePrReviewTier(input: ResolvePrReviewTierInput): PrReviewTier;
package/dist/roles.d.ts CHANGED
@@ -47,14 +47,14 @@ export type RoleMappingOptions = {
47
47
  * layout (mstar-roles § Role Reference Mapping / § Parameter Table (SSOT)
48
48
  * / § Maintenance Rules):
49
49
  * - every mapped agent id resolves to `references/<role>.md` under
50
- * `rolesDir`;
50
+ * `rolesDir`;
51
51
  * - shared families (`fullstack-dev*`, `qc-specialist*`) resolve to ONE
52
- * shared reference file each;
52
+ * shared reference file each;
53
53
  * - every parameter row references a mapped role, exactly once;
54
54
  * - dev track values are `primary` / `parallel_secondary`;
55
55
  * - the QC parameter table contract holds: reviewer_index is exactly
56
- * {1, 2, 3} across the three seats, each seat has a focus, and
57
- * `report_suffix === qc<reviewer_index>`.
56
+ * {1, 2, 3} across the three seats, each seat has a focus, and
57
+ * `report_suffix === qc<reviewer_index>`.
58
58
  *
59
59
  * Violations:
60
60
  * - `roles.mapping.reference.missing` — mapped reference file not on disk
@@ -70,18 +70,28 @@ export type RoleMappingOptions = {
70
70
  export declare function validateRoleMapping(rolesDir: string, options?: RoleMappingOptions): GateResult;
71
71
  /**
72
72
  * Lint load-order declarations across skill texts (mstar-harness-core
73
- * § 加载约定: every `mstar-*` topic skill presumes the reader has Read core
74
- * first, so each must declare `mstar-harness-core` in its Load Order /
75
- * First action section).
73
+ * § 与其它 `mstar-*` skill 的加载契约 + mstar-roles § Load Order; Spec A2 —
74
+ * single load-selection authority).
76
75
  *
77
76
  * Input: `skillTexts` maps skill name → full SKILL.md text. `mstar-harness-
78
- * core` itself and non-`mstar-*` skills are exempt. Heuristic: a section
79
- * headed Load Order / Load order / First action must exist and mention
80
- * `mstar-harness-core` inside that section (mentions in later sections do
81
- * not count).
77
+ * core` itself and non-`mstar-*` skills are exempt.
78
+ *
79
+ * - Every `mstar-*` topic skill (reached by direct invocation) must have a
80
+ * Load Order / First action section (heading Load Order / Load order /
81
+ * First action) that names `mstar-harness-core` as its first dependency
82
+ * (mentions in later sections do not count).
83
+ * - The `mstar-roles` hub bootstrap is the ONE exception (narrow, keyed on
84
+ * the skill name — broad exemptions are rejected): it does not declare
85
+ * core-first; instead its Load Order section must declare the preset
86
+ * decision matrix (`roles.loadorder.hub.bootstrap.missing` when tokens
87
+ * are missing) and keep the conditional `mstar-harness-core`
88
+ * conflict-authority pointer (`roles.loadorder.core.missing`).
82
89
  *
83
90
  * Violations:
84
91
  * - `roles.loadorder.section.missing` — no Load Order / First action section
85
- * - `roles.loadorder.core.missing` — section exists without the core mention
92
+ * - `roles.loadorder.core.missing` — topic section without the core-first
93
+ * declaration, or hub section without the core conflict-authority pointer
94
+ * - `roles.loadorder.hub.bootstrap.missing` — hub section missing the
95
+ * identity→none/standard/methods/unknown-preset decision matrix
86
96
  */
87
97
  export declare function lintLoadOrder(skillTexts: Record<string, string>): GateResult;