@mstar-harness/engine 3.6.2 → 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/audit.d.ts CHANGED
@@ -23,13 +23,13 @@ export type AuditCategory = (typeof AUDIT_CATEGORIES)[number];
23
23
  * - `Effort`: XS | S | M | L | XL
24
24
  * - `Risk`: LOW | MED | HIGH
25
25
  * - `Depends on`: `none` or `plans/NNN-*.md` (the `*` is a literal
26
- * wildcard form — the documented scaffolded scheme; concrete
27
- * `plans/NNN-<slug>.md` paths are accepted too)
26
+ * wildcard form — the documented scaffolded scheme; concrete
27
+ * `plans/NNN-<slug>.md` paths are accepted too)
28
28
  * - `Category`: bug | security | perf | tests | tech-debt | migration |
29
- * dx | docs | direction
29
+ * dx | docs | direction
30
30
  * - `Planned at`: `commit <short SHA>, <YYYY-MM-DD>` — `commit unknown`
31
- * is accepted as the documented fallback (`scaffoldAuditPlan` default
32
- * when the CLI runs outside a git repo)
31
+ * is accepted as the documented fallback (`scaffoldAuditPlan` default
32
+ * when the CLI runs outside a git repo)
33
33
  *
34
34
  * Every `## Status` block in the document is checked; a document without
35
35
  * any block gets `audit.status.missing-block`. Violation codes:
@@ -121,8 +121,7 @@ export type ScannedSecret = {
121
121
  * pattern evaluation (only the span — a key beside it still fires). Files
122
122
  * that cannot be read are counted in `unreadableFiles` instead of being
123
123
  * silently skipped: a security gate must never report clean over input it
124
- * could not inspect (qc1 W-002).
125
- */
124
+ * could not inspect. */
126
125
  /** Result of {@link scanSecrets}: findings plus how many selected files
127
126
  * could not be read (fail-closed signal for CLI gates). */
128
127
  export type ScanSecretsResult = {
@@ -145,14 +144,14 @@ export type SupplyChainResult = GateResult & {
145
144
  /**
146
145
  * Deterministic supply-chain checks over `repoRoot` (read-only):
147
146
  * - `lockfile-missing`: no recognized lockfile at the repo root
148
- * (package-lock.json / pnpm-lock.yaml / yarn.lock / bun.lock[b] /
149
- * Cargo.lock / poetry.lock / uv.lock / Gemfile.lock / composer.lock).
147
+ * (package-lock.json / pnpm-lock.yaml / yarn.lock / bun.lock[b] /
148
+ * Cargo.lock / poetry.lock / uv.lock / Gemfile.lock / composer.lock).
150
149
  * - `lockfile-duplicate`: two or more distinct lockfiles at the root —
151
- * ambiguous install boundaries.
150
+ * ambiguous install boundaries.
152
151
  * - `action-unpinned`: `.github/workflows/*.yml` steps using mutable refs
153
- * (`@main`, `@master`, `@latest` or any non-SHA ref).
152
+ * (`@main`, `@master`, `@latest` or any non-SHA ref).
154
153
  * - `pull_request_target-head`: a workflow triggers on `pull_request_target`
155
- * AND checks out the PR head — untrusted code with secrets access.
154
+ * AND checks out the PR head — untrusted code with secrets access.
156
155
  *
157
156
  * Tri-age judgment (reachable / runtime-relevant) is deliberately left to
158
157
  * the reviewer (C-class). Violation codes mirror finding kinds with the
@@ -26,14 +26,14 @@ export declare const KNOWLEDGE_CATEGORY_MAP: Readonly<Record<string, string>>;
26
26
  * - `compound.schema.missing-frontmatter` — no `---` block
27
27
  * - `compound.schema.missing-field` — required field absent/empty
28
28
  * - `compound.schema.invalid-date` / `invalid-problem-type` /
29
- * `invalid-severity` / `invalid-resolution-type`
29
+ * `invalid-severity` / `invalid-resolution-type`
30
30
  * - `compound.schema.category-mismatch` — category ≠ mapping for
31
- * problem_type (category-mapping.md rule 1)
31
+ * problem_type (category-mapping.md rule 1)
32
32
  * - `compound.schema.missing-track-field` — bug track missing
33
- * symptoms/root_cause/resolution_type
33
+ * symptoms/root_cause/resolution_type
34
34
  * - `compound.schema.invalid-symptoms` / `invalid-root-cause` /
35
- * `invalid-applies-when` / `invalid-plan-id` / `invalid-tags` /
36
- * `tags-too-many` / `invalid-last-updated` / `invalid-related-components`
35
+ * `invalid-applies-when` / `invalid-plan-id` / `invalid-tags` /
36
+ * `tags-too-many` / `invalid-last-updated` / `invalid-related-components`
37
37
  */
38
38
  export declare function validateSchemaYaml(frontmatterText: string): GateResult;
39
39
  /** Result of `referenceExists`: gate verdict + number of refs verified. */
@@ -46,13 +46,13 @@ export type ReferenceCheckResult = GateResult & {
46
46
  *
47
47
  * Backticked refs are classified conservatively:
48
48
  * - path-like refs (contain `/` or end in a known file extension) are
49
- * resolved against `repoRoot` and must exist — `:line` suffixes and
50
- * `#anchors` are stripped first; violation `compound.reference.missing-file`.
49
+ * resolved against `repoRoot` and must exist — `:line` suffixes and
50
+ * `#anchors` are stripped first; violation `compound.reference.missing-file`.
51
51
  * - `module.symbol` refs use a documented heuristic: a module file named
52
- * `<module>.ts|tsx|js|jsx|mjs|cjs` must exist somewhere under `repoRoot`;
53
- * violation `compound.reference.module-missing` (low severity — heuristic).
52
+ * `<module>.ts|tsx|js|jsx|mjs|cjs` must exist somewhere under `repoRoot`;
53
+ * violation `compound.reference.module-missing` (low severity — heuristic).
54
54
  * - URLs, `{PLACEHOLDER}` refs, globs, absolute paths, and bare symbols are
55
- * skipped (not repo-relative, or not resolvable deterministically).
55
+ * skipped (not repo-relative, or not resolvable deterministically).
56
56
  * `checked` counts unique refs that verified.
57
57
  */
58
58
  export declare function referenceExists(repoRoot: string, docText: string): ReferenceCheckResult;
package/dist/core.d.ts CHANGED
@@ -76,7 +76,7 @@ export declare function readJson(filePath: string): Record<string, unknown>;
76
76
  * Creates parent directories as needed; on failure the temp file is removed
77
77
  * and the error rethrown, so the target is never partially written.
78
78
  *
79
- * Durability note (qc2 F-013): no fsync before the rename — atomicity (no
79
+ * Durability note : no fsync before the rename — atomicity (no
80
80
  * partial file) is guaranteed by the same-dir temp + rename, but a power
81
81
  * loss immediately after rename may lose the write. Acceptable for
82
82
  * coordination files (status.json) whose writers re-read + verify the
@@ -99,8 +99,7 @@ export declare function resolveProjectRoot(startDir?: string): string;
99
99
  * The single-version invariant makes both equivalent in-repo; the
100
100
  * own-manifest-first order fixes published installs, where no
101
101
  * `morning-star` manifest exists anywhere above `node_modules` and the walk
102
- * alone would regress to `"0.0.0"` (qc3 F-1).
103
- */
102
+ * alone would regress to `"0.0.0"`. */
104
103
  export declare function harnessVersionFrom(moduleDir: string): string;
105
104
  /**
106
105
  * Read the harness version (own-manifest first — see `harnessVersionFrom`).
@@ -9,11 +9,11 @@ export type AssignmentFields = {
9
9
  };
10
10
  export type ValidateAssignmentFieldsOptions = {
11
11
  /**
12
- * Whether the assignment produces repo diffs (default `true`). The
13
- * branch-form exactly-one gate applies to writable assignments only —
14
- * read-only assignments (explore/scout orientation) legitimately omit
15
- * branch fields per mstar-branch-worktree ("每个可写 Assignment…").
16
- */
12
+ * Whether the assignment produces repo diffs (default `true`). The
13
+ * branch-form exactly-one gate applies to writable assignments only —
14
+ * read-only assignments (explore/scout orientation) legitimately omit
15
+ * branch fields per mstar-branch-worktree ("每个可写 Assignment…").
16
+ */
17
17
  writable?: boolean;
18
18
  };
19
19
  /** Options for {@link assertDefaultBranchProtected}. */
@@ -38,7 +38,7 @@ export type ExecutionModeToNResult = GateResult & {
38
38
  * captured; values are trimmed. List-bullet prefixes (`- **Field**: value`)
39
39
  * are accepted so the engine parser is the SINGLE grammar for Assignment
40
40
  * header fields (the Slice-2 opencode presence parser tolerated bullets;
41
- * its acceptance is folded into this parser, not forked — qc1 F-002).
41
+ * its acceptance is folded into this parser, not forked —).
42
42
  */
43
43
  export declare function parseAssignmentFields(assignmentText: string): AssignmentFields;
44
44
  /** Where the `Enforcement` flag was declared (roadmap §8.5 C4/D2). */
@@ -53,8 +53,7 @@ export type EnforcementFlag = {
53
53
  * marker (see {@link ASSIGNMENT_BODY_START_RE}). Returns the full text when
54
54
  * no marker is present. The Assignment enforcement flag is parsed against
55
55
  * THIS region only, so an example line `**Enforcement**: hard` quoted in the
56
- * task body cannot harden the dispatch (qc1 F-003 / qc2 F-003).
57
- */
56
+ * task body cannot harden the dispatch. */
58
57
  export declare function assignmentHeaderRegion(assignmentText: string): string;
59
58
  /**
60
59
  * Parse the `Enforcement: hard` flag (roadmap §8.5 C4 + decision D2 — v2
@@ -63,9 +62,9 @@ export declare function assignmentHeaderRegion(assignmentText: string): string;
63
62
  *
64
63
  * Recognized forms, checked in order:
65
64
  * 1. Assignment header `**Enforcement**: hard` / `Enforcement: hard`
66
- * (bold or plain, optional list bullet; value case-insensitive).
65
+ * (bold or plain, optional list bullet; value case-insensitive).
67
66
  * 2. Compass frontmatter YAML key `enforcement: hard` (lowercase key;
68
- * value may be quoted, case-insensitive).
67
+ * value may be quoted, case-insensitive).
69
68
  *
70
69
  * The Assignment form wins over the compass form when both appear in the
71
70
  * input (per-Assignment precedence — a dispatch's own flag is decisive).
@@ -76,8 +75,7 @@ export declare function assignmentHeaderRegion(assignmentText: string): string;
76
75
  * Assignment-form callers MUST pass the header region (see
77
76
  * {@link assignmentHeaderRegion}) — this function itself scans the whole
78
77
  * input because the compass form is fed raw frontmatter, which has no
79
- * body markers (qc1 F-003 / qc2 F-003).
80
- */
78
+ * body markers. */
81
79
  export declare function parseEnforcementFlag(text: string): EnforcementFlag;
82
80
  /**
83
81
  * Parsed branch forms of an Assignment (mstar-branch-worktree § "Assignment
@@ -85,13 +83,12 @@ export declare function parseEnforcementFlag(text: string): EnforcementFlag;
85
83
  * <base>` | `Branch policy: direct on <branch> — <reason>`. Exactly one is
86
84
  * required for writable assignments. This is the engine's SINGLE branch-form
87
85
  * grammar — CLI and host hooks consume it instead of re-implementing the
88
- * regexes (qc1 F-001 / qc3 F-3).
89
- */
86
+ * regexes. */
90
87
  export type AssignmentBranchForms = {
91
88
  /**
92
- * `Working branch: <existing>` — the value's first token (create-form
93
- * values are excluded and land in {@link createForm} instead).
94
- */
89
+ * `Working branch: <existing>` — the value's first token (create-form
90
+ * values are excluded and land in {@link createForm} instead).
91
+ */
95
92
  workingBranch?: string;
96
93
  /** `Working branch: create <new> from <base>` — created branch name (+ base when written). */
97
94
  createForm?: {
@@ -99,11 +96,11 @@ export type AssignmentBranchForms = {
99
96
  base?: string;
100
97
  };
101
98
  /**
102
- * `Branch policy: direct on <branch> — <reason>` — branch captured by the
103
- * loose `direct on <branch>` prefix; `reason` is the strict-form reason
104
- * ("" when the value is not a well-formed direct-on form, i.e. no
105
- * separator + non-empty reason — mirror of `validateAssignmentFields`).
106
- */
99
+ * `Branch policy: direct on <branch> — <reason>` — branch captured by the
100
+ * loose `direct on <branch>` prefix; `reason` is the strict-form reason
101
+ * ("" when the value is not a well-formed direct-on form, i.e. no
102
+ * separator + non-empty reason — mirror of `validateAssignmentFields`).
103
+ */
107
104
  directOn?: {
108
105
  branch: string;
109
106
  reason: string;
@@ -122,16 +119,14 @@ export declare function parseAssignmentBranchForms(assignmentText: string): Assi
122
119
  * form (branch + non-empty reason; separator set [—–]|--|-); undefined when
123
120
  * absent or malformed — the default-branch gate recognizes explicit
124
121
  * direct-on exceptions only. Single engine grammar shared by CLI + plugin
125
- * (qc1 F-001).
126
- */
122
+ *. */
127
123
  export declare function parseBranchPolicyDirectOnBranch(assignmentText: string): string | undefined;
128
124
  /**
129
125
  * True when the Assignment's `Execute as` role is a read-only orientation
130
126
  * role (`scout` / `explore`, case-insensitive). Read-only assignments
131
127
  * legitimately omit branch forms (mstar-branch-worktree § "每个可写
132
128
  * Assignment…") — callers pass `validateAssignmentFields(text, { writable:
133
- * false })` and skip the default-branch gate for them (qc3 F-1 / qc2 S-5).
134
- */
129
+ * false })` and skip the default-branch gate for them. */
135
130
  export declare function isReadOnlyAssignmentRole(roleId: string): boolean;
136
131
  /**
137
132
  * Validate an Assignment's header fields (mstar-dispatch-gates Assignment
@@ -143,8 +138,7 @@ export declare function isReadOnlyAssignmentRole(roleId: string): boolean;
143
138
  * from <base>` without `<base>` (incl. the dangling `create <new> from`
144
139
  * / `create from <base>` typos) and `Branch policy` without branch/reason
145
140
  * are flagged. The three core-field violations carry the legacy
146
- * `assignment.presence.*` codes as aliases (qc1 F-002).
147
- */
141
+ * `assignment.presence.*` codes as aliases. */
148
142
  export declare function validateAssignmentFields(assignmentText: string, opts?: ValidateAssignmentFieldsOptions): GateResult;
149
143
  /**
150
144
  * Flag writable work on a default protected branch (`main`/`master` per
@@ -161,7 +155,7 @@ export declare function assertDefaultBranchProtected(branch: string, opts?: Defa
161
155
  */
162
156
  export declare function executionModeToN(executionMode: string, opts?: ExecutionModeToNOptions): ExecutionModeToNResult;
163
157
  /**
164
- * Assert the initial QC wave's reviewer roles are exactly
158
+ * Assert the initial review wave's reviewer roles are exactly
165
159
  * `qc-specialist` / `qc-specialist-2` / `qc-specialist-3`
166
160
  * (mstar-dispatch-gates § QC tri-review; mstar-roles QC reviewer 参数表).
167
161
  * Any other composition — missing seat, duplicate, or foreign role — fails.
@@ -172,28 +166,28 @@ export declare function assertTriIdentity(reviewerRoles: readonly string[]): Gat
172
166
  */
173
167
  export type ComposeDispatchGateOptions = {
174
168
  /**
175
- * Dispatching agent's OWN harness role (dsh `Config.dispatchBinding`).
176
- * When non-empty, the anti-recursion precheck compares it against the
177
- * Assignment's `Execute as` — equality is self-recursion
178
- * (`dispatch.anti-recursion.self-type`, critical). Leave unset on hosts
179
- * whose tool-call event cannot report the dispatching agent's identity
180
- * (omp/opencode/cursor): the precheck is skipped there and the NEVER red
181
- * line stays prompt-level (mstar-dispatch-gates).
182
- */
169
+ * Dispatching agent's OWN harness role (dsh `Config.dispatchBinding`).
170
+ * When non-empty, the anti-recursion precheck compares it against the
171
+ * Assignment's `Execute as` — equality is self-recursion
172
+ * (`dispatch.anti-recursion.self-type`, critical). Leave unset on hosts
173
+ * whose tool-call event cannot report the dispatching agent's identity
174
+ * (omp/opencode/cursor): the precheck is skipped there and the NEVER red
175
+ * line stays prompt-level (mstar-dispatch-gates).
176
+ */
183
177
  caller?: string;
184
178
  /**
185
- * True on hosts whose contract declares the caller binding mandatory
186
- * (dsh): an empty/missing `caller` then fails closed with
187
- * `dispatch.anti-recursion.empty-binding` (critical) — the host could
188
- * have declared the binding, so an absent one proves nothing and the
189
- * dispatch must not proceed as if the NEVER red line held. Default
190
- * `false`: the precheck is skipped entirely when `caller` is empty.
191
- */
179
+ * True on hosts whose contract declares the caller binding mandatory
180
+ * (dsh): an empty/missing `caller` then fails closed with
181
+ * `dispatch.anti-recursion.empty-binding` (critical) — the host could
182
+ * have declared the binding, so an absent one proves nothing and the
183
+ * dispatch must not proceed as if the NEVER red line held. Default
184
+ * `false`: the precheck is skipped entirely when `caller` is empty.
185
+ */
192
186
  callerRequired?: boolean;
193
187
  /**
194
- * `false` for read-only roles (scout/explore) — skips the branch-form and
195
- * default-branch gates. Default: `true` (writable).
196
- */
188
+ * `false` for read-only roles (scout/explore) — skips the branch-form and
189
+ * default-branch gates. Default: `true` (writable).
190
+ */
197
191
  writable?: boolean;
198
192
  };
199
193
  /**
@@ -207,31 +201,30 @@ export type ComposeDispatchGateResult = GateResult & {
207
201
  enforcement: EnforcementFlag;
208
202
  };
209
203
  /**
210
- * Shared host dispatch-gate composition (qc1 F-001/F-006, qc2 F-005/F-007,
211
- * qc3 F-007/F-008) — the SINGLE dispatch-validation composition consumed by
204
+ * Shared host dispatch-gate composition the SINGLE dispatch-validation composition consumed by
212
205
  * the opencode adapter (`validateDispatchAssignment`), the omp blocking hook
213
206
  * (Gate 2) and the `mstar_dispatch_validate` tool:
214
207
  *
215
208
  * 1. Shape guard: `## Assignment` heading OR any core field line
216
- * (`Execute as` / `Delegation` / `Task category`). Text that is not
217
- * Assignment-shaped passes silently (`shaped: false`).
209
+ * (`Execute as` / `Delegation` / `Task category`). Text that is not
210
+ * Assignment-shaped passes silently (`shaped: false`).
218
211
  * 2. `validateAssignmentFields` with `writable: false` when `opts.writable
219
- * === false` (read-only roles), else the writable default.
212
+ * === false` (read-only roles), else the writable default.
220
213
  * 3. Anti-recursion precheck — CALLER semantics (issue #156): runs only
221
- * when the host supplies its own role binding (`caller`), or fails
222
- * closed on an empty one when the host contract requires it
223
- * (`callerRequired`, dsh). A caller equal to `Execute as` is the
224
- * `dispatch.anti-recursion.self-type` critical; a required-but-empty
225
- * caller is `dispatch.anti-recursion.empty-binding`. Target-only hosts
226
- * (omp/opencode/cursor) skip the leg — their binding field carries the
227
- * spawn TARGET, which equals `Execute as` on every compliant dispatch.
214
+ * when the host supplies its own role binding (`caller`), or fails
215
+ * closed on an empty one when the host contract requires it
216
+ * (`callerRequired`, dsh). A caller equal to `Execute as` is the
217
+ * `dispatch.anti-recursion.self-type` critical; a required-but-empty
218
+ * caller is `dispatch.anti-recursion.empty-binding`. Target-only hosts
219
+ * (omp/opencode/cursor) skip the leg — their binding field carries the
220
+ * spawn TARGET, which equals `Execute as` on every compliant dispatch.
228
221
  * 4. Default-branch gate for writable text: the branch comes from the
229
- * Assignment's own branch forms (create-form name / Working branch /
230
- * Branch policy branch), else `$MSTAR_WORKING_BRANCH`; a well-formed
231
- * `Branch policy: direct on <branch> — <reason>` exception is honored
232
- * only when its branch is the one being checked.
222
+ * Assignment's own branch forms (create-form name / Working branch /
223
+ * Branch policy branch), else `$MSTAR_WORKING_BRANCH`; a well-formed
224
+ * `Branch policy: direct on <branch> — <reason>` exception is honored
225
+ * only when its branch is the one being checked.
233
226
  * 5. Enforcement flag parsed from the Assignment HEADER region only; the
234
- * result carries `hardBlocked` via `applyEnforcement`.
227
+ * result carries `hardBlocked` via `applyEnforcement`.
235
228
  *
236
229
  * Never throws on text errors: unexpected failures degrade to the same
237
230
  * silent non-shaped result.