@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/audit.d.ts +11 -12
- package/dist/compound.d.ts +10 -10
- package/dist/core.d.ts +2 -3
- package/dist/dispatch.d.ts +57 -64
- package/dist/engine.js +820 -133
- package/dist/gates.d.ts +69 -0
- package/dist/gates.test.d.ts +1 -0
- package/dist/index.d.ts +13 -8
- package/dist/iteration.d.ts +3 -3
- package/dist/lint.d.ts +49 -49
- package/dist/migrate.d.ts +22 -22
- package/dist/path.d.ts +35 -25
- package/dist/project.d.ts +24 -26
- package/dist/prreview.d.ts +98 -99
- package/dist/roles.d.ts +22 -12
- package/dist/sdd.d.ts +198 -8
- package/dist/skill-authoring.d.ts +36 -9
- package/dist/status.d.ts +10 -11
- package/dist/store.d.ts +9 -12
- package/dist/workflow.d.ts +11 -11
- package/dist/worktree.d.ts +30 -6
- package/package.json +1 -1
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>/` (
|
|
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
|
|
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>/` (
|
|
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 (
|
|
9
|
+
/** Fallback project id for project-less flows ( — compass ruling 2). */
|
|
10
10
|
export declare const _DEFAULT_PROJECT = "_default";
|
|
11
|
-
/** Roadmap status enum (
|
|
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 (
|
|
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
|
|
37
|
-
*
|
|
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` (
|
|
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 (
|
|
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
|
-
*
|
|
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
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
package/dist/prreview.d.ts
CHANGED
|
@@ -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 (
|
|
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 (
|
|
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 (
|
|
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
|
-
*
|
|
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
|
-
*
|
|
128
|
+
* (caller slugs; the resolver only guards path safety).
|
|
130
129
|
* - `diff` — arbitrary changeset. When `headSha` is a non-empty string its
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
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
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
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
|
-
*
|
|
156
|
-
*
|
|
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
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
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
|
-
*
|
|
178
|
-
*
|
|
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
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
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
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
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
|
-
*
|
|
189
|
+
* reports without tier still pass — SP-A amendment).
|
|
191
190
|
* - `elapsed` optional: non-negative integer minutes; absent is valid
|
|
192
|
-
*
|
|
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
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
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
|
-
*
|
|
228
|
+
* it.
|
|
230
229
|
* - `event` is always the literal `"COMMENT"`; no other value exists in
|
|
231
|
-
*
|
|
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
|
-
*
|
|
258
|
+
* establish them with explicit refspecs first.
|
|
260
259
|
* - The changeset must be NON-empty in ALL modes — an empty changeset
|
|
261
|
-
*
|
|
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
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
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
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
294
|
-
*
|
|
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
|
-
*
|
|
295
|
+
* 3 by domain.
|
|
297
296
|
* - `largestTouchedFileTotal` drives `fileDecomposeAdvice` INDEPENDENTLY
|
|
298
|
-
*
|
|
299
|
-
*
|
|
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 (
|
|
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
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
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
|
-
*
|
|
324
|
-
*
|
|
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
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
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
|
-
|
|
353
|
-
|
|
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
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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
|
-
*
|
|
374
|
-
* - Per-seat budget block (`## Budget`,
|
|
375
|
-
*
|
|
376
|
-
*
|
|
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
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
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
|
-
*
|
|
387
|
+
* seats) and the Merge-class instruction.
|
|
389
388
|
* - Tier cuts (SP-A amendment): quick drops the cross-domain /
|
|
390
|
-
*
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
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
|
-
*
|
|
411
|
-
*
|
|
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
|
-
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
*
|
|
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
|
-
*
|
|
417
|
+
* but need not carry an extension).
|
|
419
418
|
* - `prVariant` (default false): every finding additionally carries
|
|
420
|
-
*
|
|
421
|
-
*
|
|
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
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
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
|
-
*
|
|
448
|
+
* deep.
|
|
450
449
|
* 3. Sensitive surface (auth / LLM / supply chain / data) → deep at any
|
|
451
|
-
*
|
|
450
|
+
* size.
|
|
452
451
|
* 4. Large (>~300 / band large) → deep.
|
|
453
452
|
* 5. Small: tiny-mechanical shape (docs-only / rename / formatting / pure
|
|
454
|
-
*
|
|
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
|
-
*
|
|
50
|
+
* `rolesDir`;
|
|
51
51
|
* - shared families (`fullstack-dev*`, `qc-specialist*`) resolve to ONE
|
|
52
|
-
*
|
|
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
|
-
*
|
|
57
|
-
*
|
|
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
|
-
* §
|
|
74
|
-
*
|
|
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.
|
|
79
|
-
*
|
|
80
|
-
* `mstar
|
|
81
|
-
*
|
|
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
|
|
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;
|