@mstar-harness/engine 3.8.1 → 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/core.d.ts CHANGED
@@ -109,3 +109,11 @@ export declare function harnessVersionFrom(moduleDir: string): string;
109
109
  * single-version invariant keeps root, engine, cli and opencode aligned.
110
110
  */
111
111
  export declare function readHarnessVersion(): string;
112
+ /**
113
+ * Exact `dsh-llm-fallbacks` version shared by the workspace pin and the
114
+ * published CLI `init --target dsh` install spec. Two literals only: this
115
+ * constant and `packages/dsh/package.json` `devDependencies["dsh-llm-fallbacks"]`.
116
+ * A drift test asserts they match. CLI src must not import JSON (no
117
+ * resolveJsonModule; published dist cannot see the repo).
118
+ */
119
+ export declare const DSH_LLM_FALLBACKS_VERSION = "0.5.2";
package/dist/engine.js CHANGED
@@ -81,6 +81,7 @@ function harnessVersionFrom(moduleDir) {
81
81
  function readHarnessVersion() {
82
82
  return harnessVersionFrom(dirname(fileURLToPath(import.meta.url)));
83
83
  }
84
+ var DSH_LLM_FALLBACKS_VERSION = "0.5.2";
84
85
  // src/mstarc.ts
85
86
  import { readFileSync as readFileSync2, statSync } from "node:fs";
86
87
  import { dirname as dirname2, isAbsolute, join as join2, relative, resolve as resolve2 } from "node:path";
@@ -5595,18 +5596,62 @@ function findEphemeralCitations(skillText) {
5595
5596
  return citations;
5596
5597
  }
5597
5598
  var TEST_FILE_PATH_RE = /[\w./-]+\.(?:test|spec)\.[a-z0-9]+/i;
5598
- var TEST_FILE_PHRASE_RE = /\btest files?\b/i;
5599
+ var TEST_FILE_PHRASE_RE = /\btest file(?:s|\(s\))?\s*:[ \t]*(.+)/i;
5599
5600
  var COMMAND_PROMPT_RE = /^\s*[$>]\s*\S/;
5600
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;
5601
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
+ }
5602
5607
  function assertSddTddTriple(reportText) {
5603
5608
  const violations = [];
5604
- const lines = reportText.split(/\r?\n/);
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
+ }
5605
5650
  let hasTests = false;
5606
5651
  let hasCommand = false;
5607
5652
  let hasOutput = false;
5608
5653
  for (const line of lines) {
5609
- if (!hasTests && (TEST_FILE_PATH_RE.test(line) || TEST_FILE_PHRASE_RE.test(line)))
5654
+ if (!hasTests && (TEST_FILE_PATH_RE.test(line) || hasEvidenceDetail(line.match(TEST_FILE_PHRASE_RE)?.[1] ?? "")))
5610
5655
  hasTests = true;
5611
5656
  if (!hasCommand && (COMMAND_PROMPT_RE.test(line) || RUNNER_RE.test(line)))
5612
5657
  hasCommand = true;
@@ -6823,6 +6868,7 @@ export {
6823
6868
  AUDIT_PRIORITIES,
6824
6869
  AUDIT_RISKS,
6825
6870
  DEV_TRACK_PARAMS,
6871
+ DSH_LLM_FALLBACKS_VERSION,
6826
6872
  FIVE_QUESTION_SECTIONS,
6827
6873
  GIT_CAPTURE_MAX_BYTES,
6828
6874
  KNOWLEDGE_BUG_PROBLEM_TYPES,
package/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@
27
27
  * 5-question bodies and resolves skill-relative asset paths.
28
28
  */
29
29
  export type { GateResult, Severity, ValidationResult } from "./core.js";
30
- export { SEVERITY_ORDER, applyEnforcement, readHarnessVersion, readJson, resolveProjectRoot, writeJson } from "./core.js";
30
+ export { DSH_LLM_FALLBACKS_VERSION, SEVERITY_ORDER, applyEnforcement, readHarnessVersion, readJson, resolveProjectRoot, writeJson } from "./core.js";
31
31
  export type { HarnessKind, ResolveHarnessDirOptions, ResolveSpecsDirOptions, } from "./path.js";
32
32
  export type { MstarcConfig } from "./mstarc.js";
33
33
  export { MSTARC_FILE, MSTARC_HARNESS_DIR_KEY, MSTARC_PROJECT_DIR_KEY, MSTARC_SECTION, MSTARC_WORKFLOW_DIR_KEY, findMstarc, parseMstarc, } from "./mstarc.js";
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
- * Assert the SDD TDD triple is present in a `task-N-report.md` text
142
- * (mstar-coding-behavior § Integration Notes "completion evidence must
143
- * include TDD triple test file(s), command, output in task-N-report.md";
144
- * mstar-sdd/references/file-handoffs.md fix subagents append covering test
145
- * file(s), command run, output).
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 the phrase "test file(s)"
154
- * (the handoff template's exact header). "I added tests" without a file or
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.1",
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": {