@mstar-harness/engine 3.4.1 → 3.5.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.js +326 -46
- package/dist/engine.js +534 -200
- package/dist/index.d.ts +4 -2
- package/dist/project.d.ts +12 -5
- package/dist/prreview.d.ts +65 -0
- package/dist/status.d.ts +13 -1
- package/dist/store.d.ts +76 -0
- package/dist/store.test.d.ts +1 -0
- package/dist/workflow.d.ts +9 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -61,5 +61,7 @@ export type { DetectResult, HostAdapter, HostId, SkillRootPaths, ToolSignal } fr
|
|
|
61
61
|
export { detectHost, resolveSkillRoot } from "./host.js";
|
|
62
62
|
export type { FiveQuestionMode, FiveQuestionSection } from "./skill-authoring.js";
|
|
63
63
|
export { FIVE_QUESTION_SECTIONS, RUNTIME_HEADING_ALIASES, lintFiveQuestion, lintFrontmatter, resolveAssetPath, stripFrontmatter, } from "./skill-authoring.js";
|
|
64
|
-
export type { MergeClass, PrReportTarget, PrReviewSeatPromptOptions, PrReviewSizing, PrReviewTier, PrTierKeyword, PrSizeBand, PrTallyInput, PrTallyResult, PrVerdict, ResolvePrReviewTierInput, ReviewChangesetMode, ReviewInlineComment, ReviewPostPlan, ValidateFindingDocOptions, } from "./prreview.js";
|
|
65
|
-
export { MERGE_CLASSES, PR_VERDICTS, REVIEW_EMOJI, computePrTally, pickReviewBranchName, planReviewPost, preflightChangeset, prReviewReportPath, prReviewSeatPrompt, prReviewSizing, resolvePrReviewTier, validateFindingDoc, validatePrReviewReport, } from "./prreview.js";
|
|
64
|
+
export type { MergeClass, MstarReviewFinding, MstarReviewV1, PrReportTarget, PrReviewSeatPromptOptions, PrReviewSizing, PrReviewTier, PrTierKeyword, PrSizeBand, PrTallyInput, PrTallyResult, PrVerdict, ResolvePrReviewTierInput, ReviewChangesetMode, ReviewInlineComment, ReviewPostPlan, ValidateFindingDocOptions, } from "./prreview.js";
|
|
65
|
+
export { MERGE_CLASSES, PR_VERDICTS, REVIEW_EMOJI, computePrTally, pickReviewBranchName, planReviewPost, preflightChangeset, prReviewReportPath, prReviewSeatPrompt, prReviewSizing, resolvePrReviewTier, synthesizeReview, validateFindingDoc, validateMstarReviewV1, validatePrReviewReport, } from "./prreview.js";
|
|
66
|
+
export type { ArtifactDoc, ArtifactKind, ArtifactRef, ArtifactStore } from "./store.js";
|
|
67
|
+
export { assertFsStorePath, createFsStore, getArtifactStore, loadStoreModule, resolveArtifactPath, setArtifactStore } from "./store.js";
|
package/dist/project.d.ts
CHANGED
|
@@ -138,9 +138,13 @@ export type CloseProjectRegisterEntryOpts = {
|
|
|
138
138
|
* duplicate-id detection), set each entry's `source_plan` to the used key
|
|
139
139
|
* (provenance must match the entries key; the caller cannot know the bumped
|
|
140
140
|
* key beforehand), append preserving every other key, validate the whole
|
|
141
|
-
* register with `validateProjectRegister`, then `
|
|
142
|
-
* temp+rename
|
|
143
|
-
*
|
|
141
|
+
* register with `validateProjectRegister`, then `ArtifactStore.put`
|
|
142
|
+
* (FsStore uses `writeJson` — atomic temp+rename; never `open(w)`).
|
|
143
|
+
* Fails loud (qc3 F-201) when the active FsStore would resolve a register
|
|
144
|
+
* path other than `<projectDir>/residuals.json` — callers whose target root
|
|
145
|
+
* differs from the active store's root MUST
|
|
146
|
+
* `setArtifactStore(createFsStore(root))` first. Fail-loud: any validation
|
|
147
|
+
* failure throws and the register is left untouched. Returns the key used.
|
|
144
148
|
*/
|
|
145
149
|
export declare function appendProjectRegisterEntries(opts: AppendProjectRegisterEntriesOpts): Promise<{
|
|
146
150
|
ok: true;
|
|
@@ -151,8 +155,11 @@ export declare function appendProjectRegisterEntries(opts: AppendProjectRegister
|
|
|
151
155
|
* Task 1): under `withStatusWriteLock(registerPath, ...)`, find `entryId` in
|
|
152
156
|
* `entries[planKey]` (absent → throw), set `lifecycle: resolved` +
|
|
153
157
|
* `closed_at: <today YYYY-MM-DD>` + `closure_note`, validate the whole
|
|
154
|
-
* register with `validateProjectRegister`, then `
|
|
155
|
-
*
|
|
158
|
+
* register with `validateProjectRegister`, then `ArtifactStore.put`
|
|
159
|
+
* (FsStore uses `writeJson` — atomic temp+rename).
|
|
160
|
+
* Fails loud (qc3 F-201) when the active FsStore would resolve a register
|
|
161
|
+
* path other than `<projectDir>/residuals.json`. Fail-loud: an invalid
|
|
162
|
+
* register throws and nothing is written.
|
|
156
163
|
*/
|
|
157
164
|
export declare function closeProjectRegisterEntry(opts: CloseProjectRegisterEntryOpts): Promise<{
|
|
158
165
|
ok: true;
|
package/dist/prreview.d.ts
CHANGED
|
@@ -56,6 +56,71 @@ export type PrTallyResult = {
|
|
|
56
56
|
* never overrides the verdict (override invariant).
|
|
57
57
|
*/
|
|
58
58
|
export declare function computePrTally(input: PrTallyInput): PrTallyResult;
|
|
59
|
+
/**
|
|
60
|
+
* One accepted PR-review finding in the `mstar.review/v1` envelope (SP3 §
|
|
61
|
+
* Schema). `mergeClass` is harness vocab (MERGE_CLASSES); `title`/`body`
|
|
62
|
+
* are non-empty strings; the rest are optional.
|
|
63
|
+
*/
|
|
64
|
+
export type MstarReviewFinding = {
|
|
65
|
+
mergeClass: MergeClass;
|
|
66
|
+
category?: string;
|
|
67
|
+
file_path?: string | null;
|
|
68
|
+
line_start?: number | null;
|
|
69
|
+
line_end?: number | null;
|
|
70
|
+
title: string;
|
|
71
|
+
body: string;
|
|
72
|
+
fingerprint_hint?: string;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* The `mstar.review/v1` envelope (SP3 § Schema) — a parseable review
|
|
76
|
+
* document with harness vocab, sibling to the Markdown pr-review report.
|
|
77
|
+
* `verdict` is PR_VERDICTS; `tally` (when present) must be a full
|
|
78
|
+
* `PrTallyResult` (shape-checked) whose `verdict` must equal the top-level
|
|
79
|
+
* `verdict` (consistency rule).
|
|
80
|
+
*/
|
|
81
|
+
export type MstarReviewV1 = {
|
|
82
|
+
schema: "mstar.review/v1";
|
|
83
|
+
verdict: PrVerdict;
|
|
84
|
+
summary_md: string;
|
|
85
|
+
tally?: PrTallyResult;
|
|
86
|
+
findings: MstarReviewFinding[];
|
|
87
|
+
target?: {
|
|
88
|
+
owner?: string;
|
|
89
|
+
repo?: string;
|
|
90
|
+
pr?: number;
|
|
91
|
+
head_sha?: string;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Validate a `mstar.review/v1` envelope (SP3 § Schema). Fail-loud sibling
|
|
96
|
+
* of {@link validatePrReviewReport} (the Markdown report validator) —
|
|
97
|
+
* shares PR_VERDICTS / MERGE_CLASSES only, never reuses the Markdown
|
|
98
|
+
* parser. Inspector M1 vocab (`comment|request_changes|approve`,
|
|
99
|
+
* `critical|warning|suggestion|info`, or a stray `severity` key) is
|
|
100
|
+
* rejected with `review.inspector-vocab`; a provided `tally` is
|
|
101
|
+
* shape-checked against the `PrTallyResult` {@link computePrTally} produces
|
|
102
|
+
* (verdict vocab, integer `scorePct` in [0, 100], four non-negative-integer
|
|
103
|
+
* counts, string `chatHeader`) and a malformed one is rejected with
|
|
104
|
+
* `review.tally-malformed` (shape only — no arithmetic consistency); a
|
|
105
|
+
* `tally.verdict` disagreeing with the top-level `verdict` is rejected
|
|
106
|
+
* with `review.verdict-tally-mismatch` (consistency rule, architect-locked).
|
|
107
|
+
*/
|
|
108
|
+
export declare function validateMstarReviewV1(doc: unknown): GateResult;
|
|
109
|
+
/**
|
|
110
|
+
* Fold already-vetted findings into a complete `mstar.review/v1` envelope
|
|
111
|
+
* (SP3 § synthesizeReview). Pure and synchronous — verdict/tally come ONLY
|
|
112
|
+
* from {@link computePrTally}; no I/O, no GitHub, no store, no seat
|
|
113
|
+
* dispatch. `findings` pass through untouched; `target` is carried when
|
|
114
|
+
* provided. When `summary_md` is omitted, {@link defaultReviewSummary}
|
|
115
|
+
* builds the locked deterministic template.
|
|
116
|
+
*/
|
|
117
|
+
export declare function synthesizeReview(input: {
|
|
118
|
+
findings: MstarReviewV1["findings"];
|
|
119
|
+
summary_md?: string;
|
|
120
|
+
unverifiedCount?: number;
|
|
121
|
+
unmetAc?: PrTallyInput["unmetAc"];
|
|
122
|
+
target?: MstarReviewV1["target"];
|
|
123
|
+
}): MstarReviewV1;
|
|
59
124
|
/**
|
|
60
125
|
* Which reviewed artifact the report (or evidence file) belongs to.
|
|
61
126
|
*
|
package/dist/status.d.ts
CHANGED
|
@@ -154,8 +154,16 @@ export declare const validateStatus: typeof validateStatusV2;
|
|
|
154
154
|
* acquiring the lock; this helper asserts it as a safety net (cheap —
|
|
155
155
|
* an invalid entry would fail `validateStatusV2` anyway, but the explicit
|
|
156
156
|
* gate keeps the pre-lock fail-fast contract of `registerWorkflow`).
|
|
157
|
+
*
|
|
158
|
+
* Async-only (architect-locked 2026-08-27): the durable write goes through
|
|
159
|
+
* `getArtifactStore().put({ kind: "status", key: "root", ... })` inside the
|
|
160
|
+
* caller's lock — the store is the persist backend, never a second lock.
|
|
161
|
+
* Fails loud (qc3 F-201) when the active FsStore would resolve its
|
|
162
|
+
* `status.json` to a path other than `statusPath` — callers whose root
|
|
163
|
+
* differs from the active store's root MUST
|
|
164
|
+
* `setArtifactStore(createFsStore(root))` first.
|
|
157
165
|
*/
|
|
158
|
-
export declare function registerWorkflowEntryLocked(statusPath: string, entry: WorkflowEntry): StatusV2Doc
|
|
166
|
+
export declare function registerWorkflowEntryLocked(statusPath: string, entry: WorkflowEntry): Promise<StatusV2Doc>;
|
|
159
167
|
/**
|
|
160
168
|
* Register one active workflow entry in the v2 root file (plan Task 3).
|
|
161
169
|
* Idempotent upsert by entry `id` under the root-file `withStatusWriteLock`,
|
|
@@ -177,6 +185,10 @@ export declare function registerWorkflow(root: string, entry: WorkflowEntry): Pr
|
|
|
177
185
|
* actually removed. The final document is validated (removal-at-terminal
|
|
178
186
|
* invariant included) before the write — a v1 root is refused with the
|
|
179
187
|
* `mstar migrate` hint.
|
|
188
|
+
*
|
|
189
|
+
* Fails loud (qc3 F-201) when the active FsStore would resolve its
|
|
190
|
+
* `status.json` to a path other than the caller's root — the no-op branches
|
|
191
|
+
* below never mask a store/path mismatch.
|
|
180
192
|
*/
|
|
181
193
|
export declare function unregisterWorkflow(root: string, id: string): Promise<StatusV2Doc>;
|
|
182
194
|
/**
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** JSON coordination-doc kinds the store persists (spec SP2). */
|
|
2
|
+
export type ArtifactKind = "status" | "snapshot" | "residuals" | "review" | "json";
|
|
3
|
+
/** Stable key inside the kind. Workflow id, project id, or review id;
|
|
4
|
+
* `kind: "status"` always uses key `"root"`. */
|
|
5
|
+
export type ArtifactRef = {
|
|
6
|
+
kind: ArtifactKind;
|
|
7
|
+
key: string;
|
|
8
|
+
};
|
|
9
|
+
/** A store document: the ref plus the payload and an optional schema id. */
|
|
10
|
+
export type ArtifactDoc<T = unknown> = ArtifactRef & {
|
|
11
|
+
payload: T;
|
|
12
|
+
/** Optional content-type / schema id (e.g. mstar.review/v1). */
|
|
13
|
+
schema?: string;
|
|
14
|
+
};
|
|
15
|
+
/** Type-only persist contract (HostAdapter pattern). `put` / `get` /
|
|
16
|
+
* `delete` are async-only — a network-backed store never needs a sync
|
|
17
|
+
* facade (architect-locked 2026-08-27: no `putSync` anywhere). `list?`
|
|
18
|
+
* is optional enumeration (D4): stores that cannot enumerate decline by
|
|
19
|
+
* omitting the member — callers probe `typeof store.list === "function"`
|
|
20
|
+
* (same pattern as `delete?`). */
|
|
21
|
+
export interface ArtifactStore {
|
|
22
|
+
put(doc: ArtifactDoc): Promise<void>;
|
|
23
|
+
get<T = unknown>(ref: ArtifactRef): Promise<T | undefined>;
|
|
24
|
+
delete?(ref: ArtifactRef): Promise<void>;
|
|
25
|
+
/** Enumerate refs of `kind`, sorted by key ascending (spec D4). Uniform
|
|
26
|
+
* rule: report what exists — missing backing dir/file → `[]`; every
|
|
27
|
+
* listed key round-trips through `get`. `json` is not enumerable. */
|
|
28
|
+
list?(kind: ArtifactKind): Promise<ArtifactRef[]>;
|
|
29
|
+
}
|
|
30
|
+
/** Map an artifact ref to its file path under `harnessRoot` (spec SP2
|
|
31
|
+
* FsStore path table — the single kind→path mapping, shared with SP3;
|
|
32
|
+
* SP3 never re-implements or extends it). Exported (qc1 S-002) so SP3
|
|
33
|
+
* imports the contract instead of re-deriving it textually. */
|
|
34
|
+
export declare function resolveArtifactPath(harnessRoot: string, ref: ArtifactRef): string;
|
|
35
|
+
/** Default local adapter: maps kinds to the existing `.mstar/` paths.
|
|
36
|
+
* `put` uses the sync `writeJson` (atomic temp+rename unchanged) and
|
|
37
|
+
* returns a resolved Promise; locks stay with callers (architect-locked
|
|
38
|
+
* 2026-08-27). `get` mirrors `readJson`: missing file → `undefined`,
|
|
39
|
+
* malformed JSON → throw with the path in the message. The returned store
|
|
40
|
+
* also exposes its resolved `root` so the routed writers can fail loud
|
|
41
|
+
* when a caller's explicit target path diverges from the store-resolved
|
|
42
|
+
* path (qc3 F-201); `root` is not part of the `ArtifactStore` contract.
|
|
43
|
+
* `list` enumerates per the D4 table: report what exists — missing
|
|
44
|
+
* backing dir/file → `[]`, `json` throws, keys sorted ascending. */
|
|
45
|
+
export declare function createFsStore(harnessRoot: string): ArtifactStore & {
|
|
46
|
+
root: string;
|
|
47
|
+
};
|
|
48
|
+
export declare function setArtifactStore(store: ArtifactStore | undefined): void;
|
|
49
|
+
/** The active store: the injected one when set, otherwise a lazily
|
|
50
|
+
* created `FsStore` from `resolveHarnessDir(process.cwd())`. A `null`
|
|
51
|
+
* resolution throws the same fail-loud "harness dir not found" style as
|
|
52
|
+
* `resolveHarnessSubdir` — never a silent cwd fallback. */
|
|
53
|
+
export declare function getArtifactStore(): ArtifactStore;
|
|
54
|
+
/**
|
|
55
|
+
* Fail-loud path-agreement guard for the routed writers (qc3 F-201): when
|
|
56
|
+
* `store` is an FsStore, resolve the path the store would compute for
|
|
57
|
+
* `ref` and require it to equal `expectedPath` (the caller's explicit
|
|
58
|
+
* target). A divergence means the caller's path lives outside the active
|
|
59
|
+
* store's root — the lockdir would serialize the parameter path while the
|
|
60
|
+
* put lands at the store root (silent decoupling / split-brain window).
|
|
61
|
+
* Custom (non-FS) stores own their mapping by design and are skipped.
|
|
62
|
+
* Cheap: pure path resolution, no I/O.
|
|
63
|
+
*/
|
|
64
|
+
export declare function assertFsStorePath(store: ArtifactStore, ref: ArtifactRef, expectedPath: string): void;
|
|
65
|
+
/** Load a store module from a filesystem path (spec SP2 § Injection 2–3,
|
|
66
|
+
* SP2-AC6 / SP2-AC7). Resolves against cwd; rejects empty values and any
|
|
67
|
+
* URI scheme before `import()`; throws when the file is missing. Accepts a
|
|
68
|
+
* `createArtifactStore` named export, a default-exported factory, or a
|
|
69
|
+
* default-exported object; the result is structurally verified (`put` +
|
|
70
|
+
* `get` functions) before use.
|
|
71
|
+
*
|
|
72
|
+
* CJS interop: `import()` of a CommonJS module surfaces `module.exports`
|
|
73
|
+
* as `default` (plus statically detected named exports on the namespace);
|
|
74
|
+
* the `?? mod` fallback covers loaders that surface `module.exports`
|
|
75
|
+
* directly as the namespace. No loader protocol beyond `import()`. */
|
|
76
|
+
export declare function loadStoreModule(modulePath: string): Promise<ArtifactStore>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/workflow.d.ts
CHANGED
|
@@ -73,6 +73,14 @@ export declare function validateWorkflowSnapshot(doc: unknown): GateResult;
|
|
|
73
73
|
* `withStatusWriteLock(snapshotPath)` (plan Task 2 — the `.status-write.lockdir`
|
|
74
74
|
* lands inside `workflows/<id>/`, dirname of the snapshot; no harness-root
|
|
75
75
|
* pollution). The snapshot is validated first — an invalid snapshot throws
|
|
76
|
-
* and nothing is written. `dir` is created recursively.
|
|
76
|
+
* and nothing is written. `dir` is created recursively. The durable write
|
|
77
|
+
* routes through the active `ArtifactStore` (spec SP2: snapshot →
|
|
78
|
+
* `{ kind: "snapshot", key: <workflow id> }`) inside the existing lock — the
|
|
79
|
+
* default FsStore resolves `{WORKFLOW_DIR}/<key>/snapshot.json`, identical
|
|
80
|
+
* to `join(dir, WORKFLOW_SNAPSHOT_FILE)` for canonical callers. The write
|
|
81
|
+
* fails loud when the active FsStore would resolve a different path than
|
|
82
|
+
* the caller's `join(dir, WORKFLOW_SNAPSHOT_FILE)` (qc3 F-201) — callers
|
|
83
|
+
* whose target root differs from the active store's root MUST
|
|
84
|
+
* `setArtifactStore(createFsStore(root))` first.
|
|
77
85
|
*/
|
|
78
86
|
export declare function writeWorkflowSnapshot(snapshot: WorkflowSnapshot, dir: string): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mstar-harness/engine",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.1",
|
|
4
4
|
"description": "Morning Star Harness Workflow Engine — deterministic workflow enforcement library (path, status, lease, dispatch, sdd, iteration, lint gates).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|