@mstar-harness/engine 3.8.2 → 3.8.3
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/engine.js +47 -3
- package/dist/lint.d.ts +8 -8
- package/package.json +1 -1
package/dist/engine.js
CHANGED
|
@@ -5596,18 +5596,62 @@ function findEphemeralCitations(skillText) {
|
|
|
5596
5596
|
return citations;
|
|
5597
5597
|
}
|
|
5598
5598
|
var TEST_FILE_PATH_RE = /[\w./-]+\.(?:test|spec)\.[a-z0-9]+/i;
|
|
5599
|
-
var TEST_FILE_PHRASE_RE = /\btest
|
|
5599
|
+
var TEST_FILE_PHRASE_RE = /\btest file(?:s|\(s\))?\s*:[ \t]*(.+)/i;
|
|
5600
5600
|
var COMMAND_PROMPT_RE = /^\s*[$>]\s*\S/;
|
|
5601
5601
|
var RUNNER_RE = /\b(?:bun|pnpm|npm|yarn|npx|bunx)\s+(?:test|run|exec)\b|\b(?:npx|bunx)\s+[\w./-]+\b|\b(?:tsc|vitest|jest|mocha|pytest)\b|\bgo\s+test\b|\bcargo\s+test\b/i;
|
|
5602
5602
|
var OUTPUT_TOKEN_RE = /[\u2713\u2714\u2717\u2718]|\b(?:PASS|FAIL)\b|\b\d+\s+(?:pass(?:es|ed)?|fail(?:s|ed|ing)?|skipped|tests?|ok)\b|\bok\s+\d+\b|\ball\s+ok\b|exit(?:ed)?\s+(?:with\s+)?(?:code\s+)?\d+/i;
|
|
5603
|
+
function hasEvidenceDetail(value) {
|
|
5604
|
+
const detail = value.trim().replace(/^`+|`+$/g, "").trim();
|
|
5605
|
+
return detail.length > 0 && !/^(?:n\/a|none|tbd|todo|tba|unknown|skipped|not[- ]run|\.\.\.|\u2026|<[^>]+>)$/i.test(detail);
|
|
5606
|
+
}
|
|
5603
5607
|
function assertSddTddTriple(reportText) {
|
|
5604
5608
|
const violations = [];
|
|
5605
|
-
const
|
|
5609
|
+
const activeRound = [...reportText.matchAll(/^## Verification round:[ \t]*(.*)$/gm)].at(-1);
|
|
5610
|
+
if (activeRound && !hasEvidenceDetail(activeRound[1])) {
|
|
5611
|
+
return {
|
|
5612
|
+
ok: false,
|
|
5613
|
+
violations: [violation11("medium", "lint.sdd-evidence.invalid-round", "Verification round requires a concrete label.")]
|
|
5614
|
+
};
|
|
5615
|
+
}
|
|
5616
|
+
const activeText = activeRound ? reportText.slice(activeRound.index + activeRound[0].length) : reportText;
|
|
5617
|
+
const lines = activeText.split(/\r?\n/);
|
|
5618
|
+
const fields = new Map;
|
|
5619
|
+
for (const line of lines) {
|
|
5620
|
+
const match = line.match(/^\s*(Verification mode|Changed files|Tests|Reason|Check command|Check result):[ \t]*(.*)$/i);
|
|
5621
|
+
if (match) {
|
|
5622
|
+
const key = match[1].toLowerCase();
|
|
5623
|
+
fields.set(key, [...fields.get(key) ?? [], match[2].trim()]);
|
|
5624
|
+
}
|
|
5625
|
+
}
|
|
5626
|
+
const modes = fields.get("verification mode");
|
|
5627
|
+
if (modes) {
|
|
5628
|
+
if (modes.length !== 1 || modes[0] !== "scoped-check") {
|
|
5629
|
+
return {
|
|
5630
|
+
ok: false,
|
|
5631
|
+
violations: [violation11("medium", "lint.sdd-evidence.invalid-mode", "Use exactly one Verification mode: scoped-check declaration in the active round; unknown or duplicate modes are invalid.")]
|
|
5632
|
+
};
|
|
5633
|
+
}
|
|
5634
|
+
for (const key of ["changed files", "tests", "reason", "check command", "check result"]) {
|
|
5635
|
+
const values = fields.get(key) ?? [];
|
|
5636
|
+
const value = values[0] ?? "";
|
|
5637
|
+
const valid = values.length === 1 && (key === "tests" ? value === "N/A" : hasEvidenceDetail(value));
|
|
5638
|
+
if (!valid) {
|
|
5639
|
+
violations.push(violation11("medium", `lint.sdd-evidence.${key.replaceAll(" ", "-")}`, `scoped-check requires one concrete ${key} field${key === "tests" ? " with value N/A" : ""}; missing, duplicate, or placeholder evidence is invalid.`));
|
|
5640
|
+
}
|
|
5641
|
+
}
|
|
5642
|
+
return { ok: violations.length === 0, violations };
|
|
5643
|
+
}
|
|
5644
|
+
if (lines.some((line) => /^\s*(?:Tests|(?:Covering )?test file(?:s|\(s\))?):\s*`?N\/A`?\s*$/i.test(line))) {
|
|
5645
|
+
return {
|
|
5646
|
+
ok: false,
|
|
5647
|
+
violations: [violation11("medium", "lint.sdd-tdd.missing-tests", "Bare N/A is not test evidence; document/policy checks need an explicit, complete scoped-check declaration.")]
|
|
5648
|
+
};
|
|
5649
|
+
}
|
|
5606
5650
|
let hasTests = false;
|
|
5607
5651
|
let hasCommand = false;
|
|
5608
5652
|
let hasOutput = false;
|
|
5609
5653
|
for (const line of lines) {
|
|
5610
|
-
if (!hasTests && (TEST_FILE_PATH_RE.test(line) ||
|
|
5654
|
+
if (!hasTests && (TEST_FILE_PATH_RE.test(line) || hasEvidenceDetail(line.match(TEST_FILE_PHRASE_RE)?.[1] ?? "")))
|
|
5611
5655
|
hasTests = true;
|
|
5612
5656
|
if (!hasCommand && (COMMAND_PROMPT_RE.test(line) || RUNNER_RE.test(line)))
|
|
5613
5657
|
hasCommand = true;
|
package/dist/lint.d.ts
CHANGED
|
@@ -138,11 +138,12 @@ export type EphemeralCitation = {
|
|
|
138
138
|
*/
|
|
139
139
|
export declare function findEphemeralCitations(skillText: string): EphemeralCitation[];
|
|
140
140
|
/**
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
141
|
+
* Validate task report evidence: an explicit scoped-check declaration for
|
|
142
|
+
* document/policy checks, otherwise the executable-change TDD triple.
|
|
143
|
+
* This checks structure, not whether the declared mode fits the actual diff
|
|
144
|
+
* or a command ran. PM/QC own applicability and evidence authenticity.
|
|
145
|
+
* Scoped check results may be arbitrary concrete static-tool output; the
|
|
146
|
+
* output-token heuristic below applies only to executable test triples.
|
|
146
147
|
*
|
|
147
148
|
* One violation per missing part:
|
|
148
149
|
* - `lint.sdd-tdd.missing-tests` — no test file reference
|
|
@@ -150,9 +151,8 @@ export declare function findEphemeralCitations(skillText: string): EphemeralCita
|
|
|
150
151
|
* - `lint.sdd-tdd.missing-output` — no output evidence
|
|
151
152
|
*
|
|
152
153
|
* Heuristics (documented, conservative — tuned so prose alone never counts):
|
|
153
|
-
* - tests: a `.test.<ext>` / `.spec.<ext>` path, or
|
|
154
|
-
* (
|
|
155
|
-
* the phrase does not count.
|
|
154
|
+
* - tests: a `.test.<ext>` / `.spec.<ext>` path, or a non-placeholder
|
|
155
|
+
* "test file(s): <reference>" field. Bare N/A is not test evidence.
|
|
156
156
|
* - command: a `$`-prefixed line, or a known runner invocation (bun/pnpm/
|
|
157
157
|
* npm/yarn/npx/bunx test|run|exec, npx/bunx exec, tsc/vitest/jest/mocha/
|
|
158
158
|
* pytest/go test/cargo test). Prose "run the tests" names no runner and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mstar-harness/engine",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.3",
|
|
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": {
|