@mstar-harness/dsh 3.1.2 → 3.2.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.
Files changed (81) hide show
  1. package/README.md +1 -1
  2. package/README.zh.md +1 -1
  3. package/dist/client/panel/graph/schema.d.ts +1 -1
  4. package/dist/gates/_shared.d.ts +1 -1
  5. package/dist/gates/status.d.ts +7 -1
  6. package/dist/gates/workflow-selection.d.ts +7 -0
  7. package/dist/index.js +220 -154
  8. package/harness-commands/codebase-audit.md +3 -3
  9. package/harness-commands/iteration-drive.md +9 -90
  10. package/harness-commands/iteration-loop.md +22 -62
  11. package/harness-commands/iteration-start.md +20 -77
  12. package/harness-commands/pr-deep-review.md +37 -0
  13. package/harness-skills/{mstar-plan-artifacts → mstar-artifacts}/SKILL.md +3 -3
  14. package/harness-skills/{mstar-plan-artifacts → mstar-artifacts}/references/knowledge-and-designs.md +8 -8
  15. package/harness-skills/{mstar-plan-artifacts → mstar-artifacts}/references/plan-files-and-reports.md +6 -6
  16. package/harness-skills/{mstar-plan-artifacts → mstar-artifacts}/references/status-and-residuals.md +3 -3
  17. package/harness-skills/mstar-artifacts/templates/README.md +7 -0
  18. package/harness-skills/{mstar-plan-artifacts → mstar-artifacts}/templates/plan.main.md +1 -1
  19. package/harness-skills/mstar-audit/SKILL.md +36 -89
  20. package/harness-skills/mstar-audit/references/audit-playbook.md +1 -1
  21. package/harness-skills/mstar-audit/references/codebase-audit.md +85 -0
  22. package/harness-skills/mstar-audit/references/pr-review.md +139 -0
  23. package/harness-skills/mstar-branch-worktree/SKILL.md +5 -5
  24. package/harness-skills/mstar-compound/SKILL.md +4 -4
  25. package/harness-skills/mstar-compound/references/compound-workflow.md +1 -1
  26. package/harness-skills/mstar-compound-refresh/SKILL.md +4 -4
  27. package/harness-skills/mstar-compound-refresh/references/project-knowledge-bootstrap.md +3 -3
  28. package/harness-skills/{mstar-plan-conventions → mstar-conventions}/SKILL.md +9 -9
  29. package/harness-skills/{mstar-plan-conventions → mstar-conventions}/references/artifact-storage-paths.md +13 -13
  30. package/harness-skills/{mstar-plan-conventions → mstar-conventions}/references/harness-bootstrap-and-agents-layering.md +5 -5
  31. package/harness-skills/mstar-design-md/SKILL.md +3 -3
  32. package/harness-skills/mstar-dispatch-gates/SKILL.md +3 -3
  33. package/harness-skills/mstar-engine-legacy/SKILL.md +1 -1
  34. package/harness-skills/mstar-engine-legacy/references/lease-protocol.md +1 -1
  35. package/harness-skills/mstar-engine-legacy/references/status-field-history.md +1 -1
  36. package/harness-skills/mstar-harness-core/SKILL.md +21 -20
  37. package/harness-skills/mstar-host/references/_shared/plan-mode-bridge-core.md +5 -5
  38. package/harness-skills/mstar-host/references/cursor-plan-mode-bridge.md +7 -7
  39. package/harness-skills/mstar-host/references/cursor.md +1 -1
  40. package/harness-skills/mstar-host/references/kimi-plan-mode-bridge.md +1 -1
  41. package/harness-skills/mstar-host/references/omp-plan-mode-bridge.md +1 -1
  42. package/harness-skills/mstar-host/references/parallel-dispatch.md +1 -1
  43. package/harness-skills/mstar-host/references/zcode-plan-mode-bridge.md +1 -1
  44. package/harness-skills/mstar-iteration/SKILL.md +21 -15
  45. package/harness-skills/mstar-iteration/references/command-shared-invariants.md +62 -0
  46. package/harness-skills/mstar-iteration/references/iteration-artifact-boundaries.md +1 -1
  47. package/harness-skills/mstar-iteration/references/phase-2-worktree-lease.md +5 -5
  48. package/harness-skills/mstar-iteration/references/phase-3-iteration-close.md +1 -1
  49. package/harness-skills/mstar-iteration/references/phase-4-5-pr-delivery.md +1 -1
  50. package/harness-skills/mstar-iteration/references/phase5-helper-discovery.md +1 -1
  51. package/harness-skills/mstar-phase-gates/SKILL.md +5 -5
  52. package/harness-skills/mstar-project-governance/SKILL.md +9 -9
  53. package/harness-skills/mstar-review-qc/SKILL.md +4 -4
  54. package/harness-skills/mstar-roles/SKILL.md +7 -7
  55. package/harness-skills/mstar-roles/references/_shared/leaf-executor-core.md +20 -2
  56. package/harness-skills/mstar-roles/references/architect.md +7 -10
  57. package/harness-skills/mstar-roles/references/code-reviewer.md +7 -10
  58. package/harness-skills/mstar-roles/references/frontend-dev.md +6 -5
  59. package/harness-skills/mstar-roles/references/fullstack-dev-shared.md +6 -5
  60. package/harness-skills/mstar-roles/references/ops-engineer.md +3 -7
  61. package/harness-skills/mstar-roles/references/product-manager.md +8 -11
  62. package/harness-skills/mstar-roles/references/project-manager/dispatch-and-assignment.md +1 -1
  63. package/harness-skills/mstar-roles/references/project-manager/plan-management.md +3 -3
  64. package/harness-skills/mstar-roles/references/project-manager/qa-trigger-matrix.md +2 -2
  65. package/harness-skills/mstar-roles/references/project-manager/qc-and-residuals.md +3 -3
  66. package/harness-skills/mstar-roles/references/project-manager.md +5 -5
  67. package/harness-skills/mstar-roles/references/prompt-engineer.md +4 -7
  68. package/harness-skills/mstar-roles/references/qa-engineer/acceptance-gate.md +2 -2
  69. package/harness-skills/mstar-roles/references/qa-engineer.md +4 -8
  70. package/harness-skills/mstar-roles/references/qc-specialist/report-template.md +1 -1
  71. package/harness-skills/mstar-roles/references/qc-specialist/reviewer-workflow.md +1 -1
  72. package/harness-skills/mstar-roles/references/qc-specialist-shared.md +5 -8
  73. package/harness-skills/mstar-roles/references/writing-specialist.md +3 -6
  74. package/harness-skills/mstar-sdd/SKILL.md +2 -2
  75. package/harness-skills/mstar-sdd/references/file-handoffs.md +1 -1
  76. package/harness-skills/mstar-strategy/SKILL.md +8 -38
  77. package/package.json +14 -14
  78. package/harness-skills/mstar-plan-artifacts/templates/README.md +0 -7
  79. /package/harness-skills/{mstar-plan-artifacts → mstar-artifacts}/references/plan-quality-bar.md +0 -0
  80. /package/harness-skills/{mstar-plan-artifacts → mstar-artifacts}/templates/status.empty.json +0 -0
  81. /package/harness-skills/{mstar-plan-conventions → mstar-conventions}/references/effort-estimation.md +0 -0
package/dist/index.js CHANGED
@@ -1106,7 +1106,7 @@ var require_lib2 = __commonJS((exports, module) => {
1106
1106
  });
1107
1107
 
1108
1108
  // src/index.ts
1109
- import { existsSync as existsSync21, readFileSync as readFileSync18, readdirSync as readdirSync14 } from "node:fs";
1109
+ import { existsSync as existsSync22, readFileSync as readFileSync18, readdirSync as readdirSync14 } from "node:fs";
1110
1110
  import { join as join23 } from "node:path";
1111
1111
  import { fileURLToPath as fileURLToPath3 } from "node:url";
1112
1112
  import {
@@ -1136,9 +1136,9 @@ import { execFileSync as execFileSync3 } from "node:child_process";
1136
1136
  import { mkdirSync as mkdirSync5, readdirSync as readdirSync3, readFileSync as readFileSync5, realpathSync as realpathSync3, statSync as statSync4, writeFileSync as writeFileSync3 } from "node:fs";
1137
1137
  import { basename as basename3, dirname as dirname6, isAbsolute as isAbsolute5, join as join7, resolve as resolve7 } from "node:path";
1138
1138
  import { existsSync as existsSync5, readdirSync as readdirSync4, readFileSync as readFileSync6 } from "node:fs";
1139
- import { existsSync as existsSync7, readdirSync as readdirSync8, readFileSync as readFileSync10 } from "node:fs";
1140
- import { basename as basename4, isAbsolute as isAbsolute7, join as join12, relative as relative4, resolve as resolve10, sep as sep3 } from "node:path";
1141
- import { existsSync as existsSync8 } from "node:fs";
1139
+ import { existsSync as existsSync8, readdirSync as readdirSync8, readFileSync as readFileSync10 } from "node:fs";
1140
+ import { basename as basename5, isAbsolute as isAbsolute7, join as join12, relative as relative4, resolve as resolve10, sep as sep4 } from "node:path";
1141
+ import { existsSync as existsSync9 } from "node:fs";
1142
1142
  import { join as join13 } from "node:path";
1143
1143
  var SEVERITY_ORDER = ["critical", "high", "medium", "low", "nit"];
1144
1144
  function applyEnforcement(gate, opts) {
@@ -2080,7 +2080,7 @@ function validateStatusV2(docOrPath, opts = {}) {
2080
2080
  violations.push(violation4("medium", "status.workflow.mismatched-type", `workflows[] entry ${JSON.stringify(label)} type ${JSON.stringify(entry.type)} does not match its snapshot type ${JSON.stringify(snapshot.type)} — the root entry mirrors the snapshot; align them`));
2081
2081
  }
2082
2082
  if (typeof entry.started_at === "string" && typeof snapshot.started_at === "string" && entry.started_at !== snapshot.started_at) {
2083
- violations.push(violation4("medium", "status.workflow.mismatched-started-at", `workflows[] entry ${JSON.stringify(label)} started_at ${JSON.stringify(entry.started_at)} does not match its snapshot started_at ${JSON.stringify(snapshot.started_at)} — the root entry mirrors the snapshot; align them`));
2083
+ violations.push(violation4("medium", "status.workflow.mismatched-started-at", `workflows[] entry ${JSON.stringify(label)} started_at ${JSON.stringify(entry.started_at)} does not match its snapshot started_at ${JSON.stringify(snapshot.started_at)} — workflow ${JSON.stringify(label)} collided with another writer (e.g. a concurrent/re-run \`audit promote\` with the same workflow id rewrote the snapshot); the root entry mirrors the snapshot align them or remove the colliding workflow`));
2084
2084
  }
2085
2085
  }
2086
2086
  }
@@ -3217,14 +3217,14 @@ function validateAuditStatusBlocks(planText) {
3217
3217
  const violations = [];
3218
3218
  const blocks = parseStatusBlocks(planText);
3219
3219
  if (blocks.length === 0) {
3220
- violations.push(violation9("medium", "audit.status.missing-block", "no `## Status` block found — audit plan files carry the Status block fields (mstar-audit SKILL § Plan files)", "add a `## Status` block with Priority, Effort, Risk, Depends on, Category, Planned at"));
3220
+ violations.push(violation9("medium", "audit.status.missing-block", "no `## Status` block found — audit plan files carry the Status block fields (mstar-audit SKILL.md § Plan output)", "add a `## Status` block with Priority, Effort, Risk, Depends on, Category, Planned at"));
3221
3221
  return { ok: false, violations };
3222
3222
  }
3223
3223
  blocks.forEach((block, index) => {
3224
3224
  const label = blocks.length > 1 ? ` #${index + 1}` : "";
3225
3225
  for (const field of AUDIT_STATUS_FIELDS) {
3226
3226
  if (!block.fields.has(field)) {
3227
- violations.push(violation9("medium", "audit.status.missing-field", `Status block${label} missing required field "${field}" (mstar-audit SKILL § Plan files)`, `add \`- **${field}**: <value>\` to the Status block`));
3227
+ violations.push(violation9("medium", "audit.status.missing-field", `Status block${label} missing required field "${field}" (mstar-audit SKILL.md § Plan output)`, `add \`- **${field}**: <value>\` to the Status block`));
3228
3228
  }
3229
3229
  }
3230
3230
  const check = (field, pattern, code, expected) => {
@@ -3232,7 +3232,7 @@ function validateAuditStatusBlocks(planText) {
3232
3232
  if (value === undefined)
3233
3233
  return;
3234
3234
  if (!pattern.test(value)) {
3235
- violations.push(violation9("medium", code, `Status block${label} "${field}" = "${value}" — expected ${expected} (mstar-audit SKILL § Plan files)`, `fix \`- **${field}**:\` to one of: ${expected}`));
3235
+ violations.push(violation9("medium", code, `Status block${label} "${field}" = "${value}" — expected ${expected} (mstar-audit SKILL.md § Plan output)`, `fix \`- **${field}**:\` to one of: ${expected}`));
3236
3236
  }
3237
3237
  };
3238
3238
  check("Priority", /^P[123]$/, "audit.status.invalid-priority", "P1 | P2 | P3");
@@ -3244,74 +3244,6 @@ function validateAuditStatusBlocks(planText) {
3244
3244
  });
3245
3245
  return { ok: violations.length === 0, violations };
3246
3246
  }
3247
- var WHOLE_MATCH_PATTERNS = [
3248
- { type: "private-key", re: /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----/g },
3249
- { type: "aws-access-key", re: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g },
3250
- { type: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{36,}\b/g },
3251
- { type: "slack-token", re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g },
3252
- { type: "jwt", re: /\beyJ[A-Za-z0-9_-]{10,1024}\.[A-Za-z0-9_-]{10,1024}\.[A-Za-z0-9_-]{10,1024}\b/g },
3253
- { type: "api-secret-key", re: /\bsk-[A-Za-z0-9-]{20,}\b/g }
3254
- ];
3255
- var VALUE_PATTERNS = [
3256
- {
3257
- typeOf: (key) => key.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase().replace(/[_-]+/g, "-"),
3258
- re: /(["']?)\b(password|passwd|api[_-]?key|access[_-]?token|auth[_-]?token|secret|token)\b(["']?)(\s*[:=]\s*)("[^"\n]{8,}"|'[^'\n]{8,}'|[A-Za-z0-9_./+\-=]{16,})/gi
3259
- }
3260
- ];
3261
- function buildLineStarts(text) {
3262
- const starts = [0];
3263
- for (let i = 0;i < text.length; i++) {
3264
- if (text[i] === `
3265
- `)
3266
- starts.push(i + 1);
3267
- }
3268
- return starts;
3269
- }
3270
- function lineAt(starts, index) {
3271
- let lo = 0;
3272
- let hi = starts.length - 1;
3273
- while (lo < hi) {
3274
- const mid = lo + hi + 1 >> 1;
3275
- if (starts[mid] <= index)
3276
- lo = mid;
3277
- else
3278
- hi = mid - 1;
3279
- }
3280
- return lo + 1;
3281
- }
3282
- function redactSecrets(text, filePath) {
3283
- const starts = buildLineStarts(text);
3284
- const marker = (type, index) => `[REDACTED ${type}@${lineAt(starts, index)}${filePath === undefined ? "" : ` in ${filePath}`}]`;
3285
- const replacements = [];
3286
- const findings = [];
3287
- for (const pattern of WHOLE_MATCH_PATTERNS) {
3288
- for (const match of text.matchAll(pattern.re)) {
3289
- if (match.index === undefined)
3290
- continue;
3291
- replacements.push({ index: match.index, length: match[0].length, text: marker(pattern.type, match.index) });
3292
- findings.push({ line: lineAt(starts, match.index), type: pattern.type });
3293
- }
3294
- }
3295
- for (const pattern of VALUE_PATTERNS) {
3296
- for (const match of text.matchAll(pattern.re)) {
3297
- if (match.index === undefined)
3298
- continue;
3299
- const type = pattern.typeOf(match[2]);
3300
- const replacement = `${match[1]}${match[2]}${match[3]}${match[4]}${marker(type, match.index)}`;
3301
- replacements.push({ index: match.index, length: match[0].length, text: replacement });
3302
- findings.push({ line: lineAt(starts, match.index), type });
3303
- }
3304
- }
3305
- replacements.sort((a, b) => b.index - a.index);
3306
- let out = text;
3307
- for (const r of replacements)
3308
- out = out.slice(0, r.index) + r.text + out.slice(r.index + r.length);
3309
- const deduped = new Map;
3310
- for (const f of findings)
3311
- deduped.set(`${f.line}:${f.type}`, f);
3312
- const sorted = [...deduped.values()].sort((a, b) => a.line - b.line || a.type.localeCompare(b.type));
3313
- return { text: out, findings: sorted };
3314
- }
3315
3247
  function violation10(severity, code, message, fix) {
3316
3248
  return { ok: false, severity, code, message, fix };
3317
3249
  }
@@ -3606,7 +3538,7 @@ function referenceExists(repoRoot, docText) {
3606
3538
  for (const { ref, isSymbol, module } of refs) {
3607
3539
  if (!isSymbol || module === undefined) {
3608
3540
  const candidate = ref.replace(LINE_SUFFIX_RE, "").replace(ANCHOR_RE, "");
3609
- if (existsSync7(resolve10(repoRoot, candidate))) {
3541
+ if (existsSync8(resolve10(repoRoot, candidate))) {
3610
3542
  checked++;
3611
3543
  } else {
3612
3544
  violations.push(violation10("medium", "compound.reference.missing-file", `referenced path \`${ref}\` does not exist under ${repoRoot} (compound-refresh Phase 2: referenced code still exists?)`, "update the doc to reference an existing path, or delete the stale reference"));
@@ -3637,7 +3569,7 @@ function collectKnowledgeDocs(dir) {
3637
3569
  if (entry.isDirectory()) {
3638
3570
  stack.push(full);
3639
3571
  } else if (entry.name.endsWith(".md") && entry.name !== "README.md" && entry.name !== "index.md") {
3640
- docs.push(relative4(dir, full).split(sep3).join("/"));
3572
+ docs.push(relative4(dir, full).split(sep4).join("/"));
3641
3573
  }
3642
3574
  }
3643
3575
  }
@@ -3654,7 +3586,7 @@ function normalizeIndexRef(cell) {
3654
3586
  function assertIndexRows(knowledgeDir) {
3655
3587
  const violations = [];
3656
3588
  const readmePath = join12(knowledgeDir, "README.md");
3657
- if (!existsSync7(readmePath)) {
3589
+ if (!existsSync8(readmePath)) {
3658
3590
  violations.push(violation10("medium", "compound.index.missing-readme", `missing ${readmePath} — the knowledge index is required (mstar-compound Phase 6: every doc gets a README.md row)`, "create knowledge/README.md with a Document / Source Plan / Description / Status table"));
3659
3591
  return { ok: false, violations };
3660
3592
  }
@@ -3678,7 +3610,7 @@ function assertIndexRows(knowledgeDir) {
3678
3610
  return { ok: violations.length === 0, violations };
3679
3611
  }
3680
3612
  function isFileLikeRoot(root) {
3681
- return /^[^.]*\.[A-Za-z0-9]{1,10}$/.test(basename4(root));
3613
+ return /^[^.]*\.[A-Za-z0-9]{1,10}$/.test(basename5(root));
3682
3614
  }
3683
3615
  function scopeGuard(path, allowedRoots) {
3684
3616
  const resolved = resolve10(path);
@@ -3687,7 +3619,7 @@ function scopeGuard(path, allowedRoots) {
3687
3619
  if (isFileLikeRoot(r)) {
3688
3620
  if (resolved === r)
3689
3621
  return { ok: true, violations: [] };
3690
- } else if (resolved === r || resolved.startsWith(r + sep3)) {
3622
+ } else if (resolved === r || resolved.startsWith(r + sep4)) {
3691
3623
  return { ok: true, violations: [] };
3692
3624
  }
3693
3625
  }
@@ -3841,7 +3773,7 @@ function validateRoleMapping(rolesDir, options = {}) {
3841
3773
  const violations = [];
3842
3774
  const referenceById = new Map(mapping.map((m) => [m.agentId, m.reference]));
3843
3775
  for (const { agentId, reference } of mapping) {
3844
- if (!existsSync8(join13(rolesDir, reference))) {
3776
+ if (!existsSync9(join13(rolesDir, reference))) {
3845
3777
  violations.push(violation12("medium", "roles.mapping.reference.missing", `role "${agentId}" maps to ${reference} which does not exist under ${rolesDir} (mstar-roles § Role Reference Mapping)`, `create ${join13(rolesDir, reference)} or fix the mapping row`));
3846
3778
  }
3847
3779
  }
@@ -4194,21 +4126,21 @@ function skillLocalConfig(config) {
4194
4126
  }
4195
4127
 
4196
4128
  // src/gates/catalog.ts
4197
- import { existsSync as existsSync13, readFileSync as readFileSync9, readdirSync as readdirSync7 } from "node:fs";
4129
+ import { existsSync as existsSync14, readFileSync as readFileSync9, readdirSync as readdirSync7 } from "node:fs";
4198
4130
  import { join as join11 } from "node:path";
4199
4131
  import { createUserMessage } from "@deepseek-ai/dsh-llm";
4200
4132
 
4201
4133
  // src/gates/agent-flow.ts
4202
- import { appendFileSync, closeSync, existsSync as existsSync12, mkdirSync as mkdirSync3, openSync, readFileSync as readFileSync7, readSync, renameSync as renameSync2, rmdirSync, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
4134
+ import { appendFileSync, closeSync, existsSync as existsSync13, mkdirSync as mkdirSync3, openSync, readFileSync as readFileSync7, readSync, renameSync as renameSync2, rmdirSync, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
4203
4135
  import { join as join10 } from "node:path";
4204
4136
 
4205
4137
  // src/gates/dispatch.ts
4206
- import { existsSync as existsSync11 } from "node:fs";
4207
- import { basename as basename5, join as join8, resolve as resolve11 } from "node:path";
4138
+ import { existsSync as existsSync12 } from "node:fs";
4139
+ import { basename as basename4, join as join8, resolve as resolve11 } from "node:path";
4208
4140
 
4209
4141
  // src/gates/workflow-selection.ts
4210
- import { existsSync as existsSync9, readdirSync as readdirSync5, statSync as statSync3 } from "node:fs";
4211
- import { join as join5, relative as relative3 } from "node:path";
4142
+ import { existsSync as existsSync10, readdirSync as readdirSync5, statSync as statSync3 } from "node:fs";
4143
+ import { dirname as dirname7, join as join5, relative as relative3 } from "node:path";
4212
4144
  var TERMINAL_STATUS_CACHE_MAX = 64;
4213
4145
  var terminalStatusCache = new Map;
4214
4146
  function terminalStatusOf(snapshotPath) {
@@ -4216,6 +4148,7 @@ function terminalStatusOf(snapshotPath) {
4216
4148
  try {
4217
4149
  mtimeMs = statSync3(snapshotPath).mtimeMs;
4218
4150
  } catch {
4151
+ terminalStatusCache.delete(snapshotPath);
4219
4152
  return;
4220
4153
  }
4221
4154
  const cached = terminalStatusCache.get(snapshotPath);
@@ -4241,7 +4174,7 @@ function terminalStatusOf(snapshotPath) {
4241
4174
  }
4242
4175
  function resolveActiveWorkflow(harnessDir) {
4243
4176
  const statusPath = join5(harnessDir, STATUS_FILE);
4244
- if (!existsSync9(statusPath)) {
4177
+ if (!existsSync10(statusPath)) {
4245
4178
  return {
4246
4179
  kind: "error",
4247
4180
  code: "status.missing",
@@ -4299,7 +4232,7 @@ function resolveReadWorkflow(harnessDir) {
4299
4232
  if (active.kind === "error" && active.code !== "workflow.selection.no-active")
4300
4233
  return active;
4301
4234
  const workflowsDir = resolveWorkflowDir(harnessDir, { harnessDir });
4302
- if (!existsSync9(workflowsDir)) {
4235
+ if (!existsSync10(workflowsDir)) {
4303
4236
  return {
4304
4237
  kind: "error",
4305
4238
  code: "workflow.selection.no-snapshot",
@@ -4321,8 +4254,10 @@ function resolveReadWorkflow(harnessDir) {
4321
4254
  if (!entry.isDirectory())
4322
4255
  continue;
4323
4256
  const snapshotPath = join5(workflowsDir, entry.name, WORKFLOW_SNAPSHOT_FILE);
4324
- if (!existsSync9(snapshotPath))
4257
+ if (!existsSync10(snapshotPath)) {
4258
+ terminalStatusCache.delete(snapshotPath);
4325
4259
  continue;
4260
+ }
4326
4261
  const verdict = terminalStatusOf(snapshotPath);
4327
4262
  if (verdict === undefined || !verdict.terminal)
4328
4263
  continue;
@@ -4330,6 +4265,11 @@ function resolveReadWorkflow(harnessDir) {
4330
4265
  best = { workflowId: entry.name, dir: join5(relative3(harnessDir, workflowsDir), entry.name), mtimeMs: verdict.mtimeMs };
4331
4266
  }
4332
4267
  }
4268
+ for (const cachedPath of terminalStatusCache.keys()) {
4269
+ if (!existsSync10(join5(dirname7(cachedPath), WORKFLOW_SNAPSHOT_FILE))) {
4270
+ terminalStatusCache.delete(cachedPath);
4271
+ }
4272
+ }
4333
4273
  if (best === undefined) {
4334
4274
  return {
4335
4275
  kind: "error",
@@ -4489,12 +4429,12 @@ function isNaValue(value) {
4489
4429
  function planIdOf(headerRegion) {
4490
4430
  const planPath = assignmentHeaderValue(headerRegion, "Plan Path");
4491
4431
  if (!isNaValue(planPath)) {
4492
- const id = basename5(firstToken(planPath) ?? "");
4432
+ const id = basename4(firstToken(planPath) ?? "");
4493
4433
  return id.endsWith(".md") ? id.slice(0, -3) : id;
4494
4434
  }
4495
4435
  const sddDir = assignmentHeaderValue(headerRegion, "SDD dir");
4496
4436
  if (!isNaValue(sddDir)) {
4497
- const id = basename5(firstToken(sddDir) ?? "");
4437
+ const id = basename4(firstToken(sddDir) ?? "");
4498
4438
  return id === "" ? undefined : id;
4499
4439
  }
4500
4440
  const planId = assignmentHeaderValue(headerRegion, "plan_id");
@@ -4524,7 +4464,7 @@ function leaseGateViolations(harnessDir, exec, writable, prompt) {
4524
4464
  return [leaseViolation("lease.dispatch.unverifiable", `${join8(harnessDir, STATUS_FILE)}: ${selection.kind === "error" ? selection.message : "no active workflow"} — the plan's execution_lease state is unverifiable; STOP before writable dispatch`, "create a valid v2 status.json registering an active workflow (first implement dispatch requires a plan row + lease)")];
4525
4465
  }
4526
4466
  const snapshotPath = join8(harnessDir, selection.dir, WORKFLOW_SNAPSHOT_FILE);
4527
- if (!existsSync11(snapshotPath)) {
4467
+ if (!existsSync12(snapshotPath)) {
4528
4468
  if (!sdd)
4529
4469
  return [];
4530
4470
  return [leaseViolation("lease.dispatch.unverifiable", `${snapshotPath} is missing — the plan's execution_lease state is unverifiable; STOP before writable dispatch`, "create a valid workflow snapshot registering the plan row (first implement dispatch requires a plan row)")];
@@ -4598,7 +4538,7 @@ function worktreeL2Violations(header) {
4598
4538
  return violations;
4599
4539
  }
4600
4540
  function activeSnapshotRows(harnessDir) {
4601
- if (!existsSync11(join8(harnessDir, STATUS_FILE)))
4541
+ if (!existsSync12(join8(harnessDir, STATUS_FILE)))
4602
4542
  return { rows: null, controlWorktreePath: undefined, unreadable: false };
4603
4543
  const selection = resolveActiveWorkflow(harnessDir);
4604
4544
  if (selection.kind !== "active") {
@@ -4609,7 +4549,7 @@ function activeSnapshotRows(harnessDir) {
4609
4549
  };
4610
4550
  }
4611
4551
  const snapshotPath = join8(harnessDir, selection.dir, WORKFLOW_SNAPSHOT_FILE);
4612
- if (!existsSync11(snapshotPath))
4552
+ if (!existsSync12(snapshotPath))
4613
4553
  return { rows: null, controlWorktreePath: undefined, unreadable: true };
4614
4554
  let doc;
4615
4555
  try {
@@ -5339,7 +5279,7 @@ function ledgerContent(file, n) {
5339
5279
  }
5340
5280
  function readAgentFlow(workflowDir, limit) {
5341
5281
  const file = join10(workflowDir, AGENT_FLOW_FILE);
5342
- if (!existsSync12(file)) {
5282
+ if (!existsSync13(file)) {
5343
5283
  return { events: [], summary: [] };
5344
5284
  }
5345
5285
  const n = limit === undefined ? AGENT_FLOW_DEFAULT_LIMIT : Math.max(0, Math.floor(limit));
@@ -5594,7 +5534,7 @@ function harnessStateSource(harnessDir) {
5594
5534
  if (harnessDir === null)
5595
5535
  return null;
5596
5536
  const statusPath = join11(harnessDir, STATUS_FILE);
5597
- if (!existsSync13(statusPath))
5537
+ if (!existsSync14(statusPath))
5598
5538
  return null;
5599
5539
  try {
5600
5540
  const selection = resolveReadWorkflow(harnessDir);
@@ -5615,7 +5555,7 @@ function harnessStateSource(harnessDir) {
5615
5555
  }
5616
5556
  const snapshotPath = join11(harnessDir, selection.dir, WORKFLOW_SNAPSHOT_FILE);
5617
5557
  let snapshot;
5618
- if (!existsSync13(snapshotPath)) {
5558
+ if (!existsSync14(snapshotPath)) {
5619
5559
  return selectionErrorState({
5620
5560
  kind: "error",
5621
5561
  code: "workflow.selection.snapshot-unreadable",
@@ -5707,7 +5647,7 @@ function selectionErrorState(selection, rollup, harnessDir, compass) {
5707
5647
  function projectRollupSource(harnessDir, residuals) {
5708
5648
  const milestones = [];
5709
5649
  const projectsDir = resolveProjectDir(harnessDir, { harnessDir });
5710
- if (existsSync13(projectsDir)) {
5650
+ if (existsSync14(projectsDir)) {
5711
5651
  let entries;
5712
5652
  try {
5713
5653
  entries = readdirSync7(projectsDir, { withFileTypes: true });
@@ -5718,7 +5658,7 @@ function projectRollupSource(harnessDir, residuals) {
5718
5658
  if (!entry.isDirectory())
5719
5659
  continue;
5720
5660
  const roadmapPath = join11(projectsDir, entry.name, PROJECT_ROADMAP_FILE);
5721
- if (!existsSync13(roadmapPath))
5661
+ if (!existsSync14(roadmapPath))
5722
5662
  continue;
5723
5663
  try {
5724
5664
  const doc = parseCompassFrontmatterText(readFileSync9(roadmapPath, "utf8"), roadmapPath);
@@ -5783,7 +5723,7 @@ function residualRollup(harnessDir) {
5783
5723
  }
5784
5724
  function projectRegisters(harnessDir) {
5785
5725
  const projectsDir = resolveProjectDir(harnessDir, { harnessDir });
5786
- if (!existsSync13(projectsDir))
5726
+ if (!existsSync14(projectsDir))
5787
5727
  return [];
5788
5728
  let entries;
5789
5729
  try {
@@ -5796,7 +5736,7 @@ function projectRegisters(harnessDir) {
5796
5736
  if (!entry.isDirectory())
5797
5737
  continue;
5798
5738
  const registerPath = join11(projectsDir, entry.name, PROJECT_REGISTER_FILE);
5799
- if (!existsSync13(registerPath))
5739
+ if (!existsSync14(registerPath))
5800
5740
  continue;
5801
5741
  try {
5802
5742
  registers.push({ projectId: entry.name, doc: readJson(registerPath) });
@@ -5808,7 +5748,7 @@ function projectRegisters(harnessDir) {
5808
5748
  }
5809
5749
  function knowledgeDigest(harnessDir) {
5810
5750
  const indexPath = join11(harnessDir, "knowledge", "README.md");
5811
- if (!existsSync13(indexPath))
5751
+ if (!existsSync14(indexPath))
5812
5752
  return null;
5813
5753
  try {
5814
5754
  const categories = new Set;
@@ -5853,7 +5793,7 @@ function compassDirection(compassPath) {
5853
5793
  }
5854
5794
  function steeringCompassPath(harnessDir) {
5855
5795
  const iterationsDir = resolveIterationDir(harnessDir);
5856
- if (!existsSync13(iterationsDir))
5796
+ if (!existsSync14(iterationsDir))
5857
5797
  return;
5858
5798
  let entries;
5859
5799
  try {
@@ -5865,7 +5805,7 @@ function steeringCompassPath(harnessDir) {
5865
5805
  if (!entry.isDirectory())
5866
5806
  continue;
5867
5807
  const compassPath = join11(iterationsDir, entry.name, "delivery-compass.md");
5868
- if (!existsSync13(compassPath))
5808
+ if (!existsSync14(compassPath))
5869
5809
  continue;
5870
5810
  let content;
5871
5811
  try {
@@ -5884,7 +5824,7 @@ function iterationGateSource(harnessDir) {
5884
5824
  if (harnessDir === null)
5885
5825
  return;
5886
5826
  const statusPath = join11(harnessDir, STATUS_FILE);
5887
- if (!existsSync13(statusPath))
5827
+ if (!existsSync14(statusPath))
5888
5828
  return;
5889
5829
  const compass = steeringCompassPath(harnessDir);
5890
5830
  if (compass === undefined)
@@ -5946,12 +5886,12 @@ function agentDigestKey(agent, cwd) {
5946
5886
  }
5947
5887
 
5948
5888
  // src/gates/status.ts
5949
- import { existsSync as existsSync14, readdirSync as readdirSync9 } from "node:fs";
5950
- import { basename as basename7, join as join14, relative as relative5, resolve as resolve13 } from "node:path";
5889
+ import { existsSync as existsSync15, readdirSync as readdirSync9 } from "node:fs";
5890
+ import { basename as basename6, join as join14, relative as relative5, resolve as resolve13 } from "node:path";
5951
5891
  var LOGGER_NAME = "mstar/status-gate";
5952
5892
  function harnessDocKindOfTarget(harnessDir, targetPath) {
5953
5893
  const resolved = resolve13(targetPath);
5954
- const name = basename7(resolved);
5894
+ const name = basename6(resolved);
5955
5895
  if (name !== STATUS_FILE && name !== WORKFLOW_SNAPSHOT_FILE && name !== PROJECT_REGISTER_FILE)
5956
5896
  return null;
5957
5897
  const rel = relative5(harnessDir, resolved);
@@ -6029,7 +5969,7 @@ function projectRegisterDocs(harnessDir) {
6029
5969
  if (!entry.isDirectory())
6030
5970
  continue;
6031
5971
  const registerPath = join14(projectsDir, entry.name, PROJECT_REGISTER_FILE);
6032
- if (!existsSync14(registerPath))
5972
+ if (!existsSync15(registerPath))
6033
5973
  continue;
6034
5974
  try {
6035
5975
  registers.push({ projectId: entry.name, doc: readJson(registerPath) });
@@ -6082,7 +6022,11 @@ ${verdict.violations.map(formatViolation).join(`
6082
6022
  } catch (error) {
6083
6023
  ctx.logger(LOGGER_NAME).error(`status gate degraded to allow: ${error.message}`);
6084
6024
  try {
6085
- ctx.emit("mstar/status-gate", { operation, target: target.displayPath, result: { ok: true, violations: [] }, hard: false, degraded: true });
6025
+ let hard = false;
6026
+ try {
6027
+ hard = harnessDir !== null && resolveHard(harnessDir, config);
6028
+ } catch {}
6029
+ ctx.emit("mstar/status-gate", { operation, target: target.displayPath, result: { ok: true, violations: [] }, hard, degraded: true });
6086
6030
  } catch (emitError) {
6087
6031
  ctx.logger(LOGGER_NAME).error(`status gate degraded advisory emit failed: ${emitError.message}`);
6088
6032
  }
@@ -6098,8 +6042,8 @@ async function editIntentListener(ctx, resolver, config, adapter, target, actor,
6098
6042
  }
6099
6043
 
6100
6044
  // src/gates/skill-lint.ts
6101
- import { existsSync as existsSync15, readFileSync as readFileSync11 } from "node:fs";
6102
- import { basename as basename8, dirname as dirname7, resolve as resolve14, sep as sep2 } from "node:path";
6045
+ import { existsSync as existsSync16, readFileSync as readFileSync11 } from "node:fs";
6046
+ import { basename as basename7, dirname as dirname9, resolve as resolve14, sep as sep2 } from "node:path";
6103
6047
  var SKILL_LINT_LOGGER = "mstar/skill-lint";
6104
6048
 
6105
6049
  class SkillLintVetoError extends Error {
@@ -6160,13 +6104,13 @@ function skillRootsOf(config) {
6160
6104
  return roots.map((root) => root.trim()).filter((root) => root !== "");
6161
6105
  }
6162
6106
  function isSkillTarget(roots, target) {
6163
- if (basename8(target.displayPath) !== "SKILL.md")
6107
+ if (basename7(target.displayPath) !== "SKILL.md")
6164
6108
  return false;
6165
6109
  const resolvedPath = resolve14(target.displayPath);
6166
6110
  return roots.some((root) => resolvedPath.startsWith(resolve14(root) + sep2));
6167
6111
  }
6168
6112
  function skillNameOf(target) {
6169
- return basename8(dirname7(target.displayPath));
6113
+ return basename7(dirname9(target.displayPath));
6170
6114
  }
6171
6115
  function skillCanonicalForm(target) {
6172
6116
  return resolveSkillRoot("dsh", { skill: skillNameOf(target), rel: "SKILL.md" });
@@ -6179,7 +6123,7 @@ function gateSkillIntent(ctx, harnessDir, config, target) {
6179
6123
  if (!isSkillTarget(roots, target))
6180
6124
  return;
6181
6125
  const skillPath = resolve14(target.displayPath);
6182
- if (!existsSync15(skillPath))
6126
+ if (!existsSync16(skillPath))
6183
6127
  return;
6184
6128
  let doc;
6185
6129
  try {
@@ -6230,8 +6174,130 @@ async function skillWriteIntentListener(ctx, resolver, config, target, actor, ne
6230
6174
  }
6231
6175
 
6232
6176
  // src/gates/seams.ts
6233
- import { existsSync as existsSync16, readFileSync as readFileSync13, readdirSync as readdirSync11 } from "node:fs";
6234
- import { basename as basename9, dirname as dirname9, join as join16, resolve as resolve15, sep as sep4 } from "node:path";
6177
+ import { existsSync as existsSync17, readFileSync as readFileSync13, readdirSync as readdirSync11 } from "node:fs";
6178
+ import { basename as basename8, dirname as dirname10, join as join16, resolve as resolve15, sep as sep3 } from "node:path";
6179
+
6180
+ // ../engine/dist/audit.js
6181
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
6182
+ var DATE_PART2 = String.raw`\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])`;
6183
+ var RFC3339_Z_RE2 = new RegExp(String.raw`^${DATE_PART2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$`);
6184
+ var DATE_ONLY_RE2 = new RegExp(String.raw`^${DATE_PART2}$`);
6185
+ var heldLockDirs2 = new AsyncLocalStorage2;
6186
+ var MSTARC_HARNESS_DIR_KEY2 = "harness_dir";
6187
+ var MSTARC_PLAN_DIR_KEY2 = "plan_dir";
6188
+ var MSTARC_SDD_DIR_KEY2 = "sdd_dir";
6189
+ var MSTARC_ITERATION_DIR_KEY2 = "iteration_dir";
6190
+ var MSTARC_KNOWLEDGE_DIR_KEY2 = "knowledge_dir";
6191
+ var MSTARC_SPECS_DIR_KEY2 = "specs_dir";
6192
+ var MSTARC_WORKFLOW_DIR_KEY2 = "workflow_dir";
6193
+ var MSTARC_PROJECT_DIR_KEY2 = "project_dir";
6194
+ var MSTARC_ENFORCEMENT_KEY2 = "enforcement";
6195
+ var CONFIG_KEYS2 = {
6196
+ [MSTARC_HARNESS_DIR_KEY2]: "harnessDir",
6197
+ [MSTARC_PLAN_DIR_KEY2]: "planDir",
6198
+ [MSTARC_SDD_DIR_KEY2]: "sddDir",
6199
+ [MSTARC_ITERATION_DIR_KEY2]: "iterationDir",
6200
+ [MSTARC_KNOWLEDGE_DIR_KEY2]: "knowledgeDir",
6201
+ [MSTARC_SPECS_DIR_KEY2]: "specsDir",
6202
+ [MSTARC_WORKFLOW_DIR_KEY2]: "workflowDir",
6203
+ [MSTARC_PROJECT_DIR_KEY2]: "projectDir",
6204
+ [MSTARC_ENFORCEMENT_KEY2]: "enforcement"
6205
+ };
6206
+ var GITIGNORE_SNIPPET2 = `# Morning Star harness (.mstar/)
6207
+ # Principle: process stays local; results are shared with the team.
6208
+ # Default-ignore everything under .mstar/, then re-include the tracked results.
6209
+ .mstar/**
6210
+ !.mstar/AGENTS.md
6211
+ !.mstar/knowledge/
6212
+ !.mstar/knowledge/**
6213
+ !.mstar/specs/
6214
+ !.mstar/specs/**
6215
+ # .mstarc — repo-local harness config (may declare [config] harness_dir=<name>)
6216
+ .mstarc
6217
+ `;
6218
+ var GITIGNORE_SNIPPET_AGENTS2 = `# Morning Star harness (.agents/) — legacy
6219
+ # Default-ignore everything under .agents/, then re-include the tracked results.
6220
+ .agents/**
6221
+ !.agents/AGENTS.md
6222
+ !.agents/knowledge/
6223
+ !.agents/knowledge/**
6224
+ !.agents/specs/
6225
+ !.agents/specs/**
6226
+ `;
6227
+ var GITIGNORE_PROCESS_ENTRIES2 = GITIGNORE_SNIPPET2.split(`
6228
+ `).filter((line) => line.startsWith(".mstar/") || line.startsWith("!.mstar/")).map((line) => line.trim());
6229
+ var GITIGNORE_PROCESS_ENTRIES_AGENTS2 = GITIGNORE_SNIPPET_AGENTS2.split(`
6230
+ `).filter((line) => line.startsWith(".agents/") || line.startsWith("!.agents/")).map((line) => line.trim());
6231
+ var WHOLE_MATCH_PATTERNS = [
6232
+ { type: "private-key", re: /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----/g },
6233
+ { type: "aws-access-key", re: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g },
6234
+ { type: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{36,}\b/g },
6235
+ { type: "slack-token", re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g },
6236
+ { type: "jwt", re: /\beyJ[A-Za-z0-9_-]{10,1024}\.[A-Za-z0-9_-]{10,1024}\.[A-Za-z0-9_-]{10,1024}\b/g },
6237
+ { type: "api-secret-key", re: /\bsk-[A-Za-z0-9-]{20,}\b/g }
6238
+ ];
6239
+ var VALUE_PATTERNS = [
6240
+ {
6241
+ typeOf: (key) => key.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase().replace(/[_-]+/g, "-"),
6242
+ re: /(["']?)\b(password|passwd|api[_-]?key|access[_-]?token|auth[_-]?token|secret|token)\b(["']?)(\s*[:=]\s*)("[^"\n]{8,}"|'[^'\n]{8,}'|[A-Za-z0-9_./+\-=]{16,})/gi
6243
+ }
6244
+ ];
6245
+ function buildLineStarts(text) {
6246
+ const starts = [0];
6247
+ for (let i = 0;i < text.length; i++) {
6248
+ if (text[i] === `
6249
+ `)
6250
+ starts.push(i + 1);
6251
+ }
6252
+ return starts;
6253
+ }
6254
+ function lineAt(starts, index) {
6255
+ let lo = 0;
6256
+ let hi = starts.length - 1;
6257
+ while (lo < hi) {
6258
+ const mid = lo + hi + 1 >> 1;
6259
+ if (starts[mid] <= index)
6260
+ lo = mid;
6261
+ else
6262
+ hi = mid - 1;
6263
+ }
6264
+ return lo + 1;
6265
+ }
6266
+ function redactSecrets(text, filePath) {
6267
+ const starts = buildLineStarts(text);
6268
+ const marker = (type, index) => `[REDACTED ${type}@${lineAt(starts, index)}${filePath === undefined ? "" : ` in ${filePath}`}]`;
6269
+ const replacements = [];
6270
+ const findings = [];
6271
+ for (const pattern of WHOLE_MATCH_PATTERNS) {
6272
+ for (const match of text.matchAll(pattern.re)) {
6273
+ if (match.index === undefined)
6274
+ continue;
6275
+ replacements.push({ index: match.index, length: match[0].length, text: marker(pattern.type, match.index) });
6276
+ findings.push({ line: lineAt(starts, match.index), type: pattern.type });
6277
+ }
6278
+ }
6279
+ for (const pattern of VALUE_PATTERNS) {
6280
+ for (const match of text.matchAll(pattern.re)) {
6281
+ if (match.index === undefined)
6282
+ continue;
6283
+ const type = pattern.typeOf(match[2]);
6284
+ const replacement = `${match[1]}${match[2]}${match[3]}${match[4]}${marker(type, match.index)}`;
6285
+ replacements.push({ index: match.index, length: match[0].length, text: replacement });
6286
+ findings.push({ line: lineAt(starts, match.index), type });
6287
+ }
6288
+ }
6289
+ replacements.sort((a, b) => b.index - a.index);
6290
+ let out = text;
6291
+ for (const r of replacements)
6292
+ out = out.slice(0, r.index) + r.text + out.slice(r.index + r.length);
6293
+ const deduped = new Map;
6294
+ for (const f of findings)
6295
+ deduped.set(`${f.line}:${f.type}`, f);
6296
+ const sorted = [...deduped.values()].sort((a, b) => a.line - b.line || a.type.localeCompare(b.type));
6297
+ return { text: out, findings: sorted };
6298
+ }
6299
+
6300
+ // src/gates/seams.ts
6235
6301
  var SEAM_LOGGERS = {
6236
6302
  "design-md": "mstar/design-md-lint",
6237
6303
  audit: "mstar/audit-lint",
@@ -6239,7 +6305,7 @@ var SEAM_LOGGERS = {
6239
6305
  roles: "mstar/roles-lint"
6240
6306
  };
6241
6307
  function isIndexFile(path) {
6242
- const base = basename9(path);
6308
+ const base = basename8(path);
6243
6309
  return base === "README.md" || base === "index.md";
6244
6310
  }
6245
6311
  function isMarkdownDoc(path) {
@@ -6248,7 +6314,7 @@ function isMarkdownDoc(path) {
6248
6314
  function isAuditPlanTarget(path) {
6249
6315
  if (!isMarkdownDoc(path))
6250
6316
  return false;
6251
- const segments = resolve15(path).split(sep4);
6317
+ const segments = resolve15(path).split(sep3);
6252
6318
  for (let i = 0;i < segments.length; i++) {
6253
6319
  if (segments[i] !== "plans")
6254
6320
  continue;
@@ -6259,7 +6325,7 @@ function isAuditPlanTarget(path) {
6259
6325
  return false;
6260
6326
  }
6261
6327
  function isRolesTarget(path) {
6262
- const segments = resolve15(path).split(sep4);
6328
+ const segments = resolve15(path).split(sep3);
6263
6329
  const idx = segments.indexOf("mstar-roles");
6264
6330
  if (idx === -1)
6265
6331
  return false;
@@ -6269,17 +6335,17 @@ function isRolesTarget(path) {
6269
6335
  return rest[0] === "SKILL.md" || rest[0] === "references" && rest[rest.length - 1].endsWith(".md");
6270
6336
  }
6271
6337
  function rolesDirOf(path) {
6272
- const segments = resolve15(path).split(sep4);
6338
+ const segments = resolve15(path).split(sep3);
6273
6339
  const idx = segments.indexOf("mstar-roles");
6274
6340
  if (idx === -1)
6275
- return dirname9(path);
6276
- return idx === 0 ? sep4 : join16(sep4, ...segments.slice(1, idx + 1));
6341
+ return dirname10(path);
6342
+ return idx === 0 ? sep3 : join16(sep3, ...segments.slice(1, idx + 1));
6277
6343
  }
6278
6344
  function isSeamTarget(seam, harnessDir, target) {
6279
6345
  const path = resolve15(target.displayPath);
6280
6346
  switch (seam) {
6281
6347
  case "design-md": {
6282
- const base = basename9(path);
6348
+ const base = basename8(path);
6283
6349
  return base === "DESIGN.md" || base === "DESIGN.dark.md";
6284
6350
  }
6285
6351
  case "audit":
@@ -6287,7 +6353,7 @@ function isSeamTarget(seam, harnessDir, target) {
6287
6353
  case "compound": {
6288
6354
  if (harnessDir === null)
6289
6355
  return false;
6290
- return path.startsWith(resolve15(join16(harnessDir, "knowledge")) + sep4) && isMarkdownDoc(path);
6356
+ return path.startsWith(resolve15(join16(harnessDir, "knowledge")) + sep3) && isMarkdownDoc(path);
6291
6357
  }
6292
6358
  case "roles":
6293
6359
  return isRolesTarget(path);
@@ -6304,9 +6370,9 @@ function auditSecretsViolations(findings, file) {
6304
6370
  }
6305
6371
  function validateDesignDoc(doc, path) {
6306
6372
  const violations = [...validateDesignTokenFrontmatter(doc).violations];
6307
- const isDark = basename9(path) === "DESIGN.dark.md";
6308
- const sibling = join16(dirname9(path), isDark ? "DESIGN.md" : "DESIGN.dark.md");
6309
- if (existsSync16(sibling)) {
6373
+ const isDark = basename8(path) === "DESIGN.dark.md";
6374
+ const sibling = join16(dirname10(path), isDark ? "DESIGN.md" : "DESIGN.dark.md");
6375
+ if (existsSync17(sibling)) {
6310
6376
  const light = isDark ? readFileSync13(sibling, "utf8") : doc;
6311
6377
  const dark = isDark ? doc : readFileSync13(sibling, "utf8");
6312
6378
  violations.push(...assertLightDarkParity(light, dark).violations);
@@ -6322,18 +6388,18 @@ function validateAuditDoc(doc, path) {
6322
6388
  function validateCompoundDoc(doc, _path, harnessDir) {
6323
6389
  const violations = [...validateSchemaYaml(doc).violations];
6324
6390
  if (harnessDir !== null) {
6325
- violations.push(...referenceExists(dirname9(harnessDir), doc).violations);
6391
+ violations.push(...referenceExists(dirname10(harnessDir), doc).violations);
6326
6392
  }
6327
6393
  return violations.length === 0 ? { ok: true, violations } : { ok: false, violations };
6328
6394
  }
6329
- function validateRolesState(rolesDir, skillsRoot = dirname9(rolesDir)) {
6395
+ function validateRolesState(rolesDir, skillsRoot = dirname10(rolesDir)) {
6330
6396
  const violations = [...validateRoleMapping(rolesDir).violations];
6331
6397
  const skillTexts = {};
6332
6398
  for (const entry of readdirSync11(skillsRoot, { withFileTypes: true })) {
6333
6399
  if (!entry.isDirectory() || !entry.name.startsWith("mstar-"))
6334
6400
  continue;
6335
6401
  const skillFile = join16(skillsRoot, entry.name, "SKILL.md");
6336
- if (!existsSync16(skillFile))
6402
+ if (!existsSync17(skillFile))
6337
6403
  continue;
6338
6404
  try {
6339
6405
  skillTexts[entry.name] = readFileSync13(skillFile, "utf8");
@@ -6367,7 +6433,7 @@ function gateSeamIntent(ctx, harnessDir, config, seam, target) {
6367
6433
  if (!isSeamTarget(seam, harnessDir, target))
6368
6434
  return;
6369
6435
  const path = resolve15(target.displayPath);
6370
- if (!existsSync16(path))
6436
+ if (!existsSync17(path))
6371
6437
  return;
6372
6438
  let doc;
6373
6439
  try {
@@ -6383,12 +6449,12 @@ function gateSeamIntent(ctx, harnessDir, config, seam, target) {
6383
6449
  const hard = resolveSeamHard(harnessDir, config);
6384
6450
  const verdict = applyEnforcement(result, { hard });
6385
6451
  if (verdict.hardBlocked) {
6386
- logger.error(`${basename9(path)} write to ${target.displayPath} ALLOWED as repair (Enforcement: hard; the current on-disk document is already invalid — the intent carries no incoming content, so the vetoable signal is only the pre-write state):
6452
+ logger.error(`${basename8(path)} write to ${target.displayPath} ALLOWED as repair (Enforcement: hard; the current on-disk document is already invalid — the intent carries no incoming content, so the vetoable signal is only the pre-write state):
6387
6453
  ${verdict.violations.map(formatViolation).join(`
6388
6454
  `)}`);
6389
6455
  emitSeamAdvisory(ctx, seam, target.displayPath, verdict, hard, { repair: true });
6390
6456
  } else {
6391
- logger.warn(`${basename9(path)} write to ${target.displayPath} (advisory):
6457
+ logger.warn(`${basename8(path)} write to ${target.displayPath} (advisory):
6392
6458
  ${verdict.violations.map(formatViolation).join(`
6393
6459
  `)}`);
6394
6460
  emitSeamAdvisory(ctx, seam, target.displayPath, verdict, hard);
@@ -6437,7 +6503,7 @@ function lintRolesWrite(doc, options) {
6437
6503
  }
6438
6504
 
6439
6505
  // src/gates/tools.ts
6440
- import { existsSync as existsSync17, readFileSync as readFileSync14 } from "node:fs";
6506
+ import { existsSync as existsSync18, readFileSync as readFileSync14 } from "node:fs";
6441
6507
  import { join as join17, resolve as resolve16 } from "node:path";
6442
6508
  import { defineTool } from "@deepseek-ai/dsh-tools";
6443
6509
  var ITERATION_VIOLATION_SCHEMA = {
@@ -6603,9 +6669,9 @@ function registerSddIterationTools(ctx, resolver) {
6603
6669
  presentResult: (_args, _result) => ({ card: "generic", title: "Iteration gate evaluation" }),
6604
6670
  isConcurrencySafe: () => false,
6605
6671
  async execute(args) {
6606
- if (!existsSync17(args.snapshot_path))
6672
+ if (!existsSync18(args.snapshot_path))
6607
6673
  throw new Error(`workflow snapshot not found: ${args.snapshot_path}`);
6608
- if (!existsSync17(args.compass_path))
6674
+ if (!existsSync18(args.compass_path))
6609
6675
  throw new Error(`compass file not found: ${args.compass_path}`);
6610
6676
  const snapshotDoc = readJson(args.snapshot_path);
6611
6677
  const compassDoc = parseCompassFrontmatter(args.compass_path);
@@ -6660,7 +6726,7 @@ function registerSeamTools(ctx, resolver) {
6660
6726
  async execute(args) {
6661
6727
  const abs = resolve16(args.dir);
6662
6728
  const lightPath = join17(abs, "DESIGN.md");
6663
- if (!existsSync17(lightPath))
6729
+ if (!existsSync18(lightPath))
6664
6730
  throw new Error(`design file not found: ${lightPath}`);
6665
6731
  const light = readFileSync14(lightPath, "utf8");
6666
6732
  const result = validateDesignDoc(light, lightPath);
@@ -6713,7 +6779,7 @@ function registerSeamTools(ctx, resolver) {
6713
6779
  isConcurrencySafe: () => false,
6714
6780
  async execute(args) {
6715
6781
  const abs = resolve16(args.plan_path);
6716
- if (!existsSync17(abs))
6782
+ if (!existsSync18(abs))
6717
6783
  throw new Error(`plan file not found: ${abs}`);
6718
6784
  const text = readFileSync14(abs, "utf8");
6719
6785
  const result = validateAuditDoc(text, abs);
@@ -6753,7 +6819,7 @@ function registerSeamTools(ctx, resolver) {
6753
6819
  isConcurrencySafe: () => false,
6754
6820
  async execute(args, exec) {
6755
6821
  const abs = resolve16(args.doc_path);
6756
- if (!existsSync17(abs))
6822
+ if (!existsSync18(abs))
6757
6823
  throw new Error(`knowledge doc not found: ${abs}`);
6758
6824
  const text = readFileSync14(abs, "utf8");
6759
6825
  const base = validateCompoundDoc(text, abs, args.repo_root !== undefined ? null : resolver.forAgent(exec.agent));
@@ -6798,7 +6864,7 @@ function registerSeamTools(ctx, resolver) {
6798
6864
  isConcurrencySafe: () => false,
6799
6865
  async execute(args) {
6800
6866
  const rolesDir = resolve16(args.roles_dir);
6801
- if (!existsSync17(join17(rolesDir, "SKILL.md")))
6867
+ if (!existsSync18(join17(rolesDir, "SKILL.md")))
6802
6868
  throw new Error(`roles dir not found: ${rolesDir}`);
6803
6869
  const result = validateRolesState(rolesDir, args.skills_root !== undefined ? resolve16(args.skills_root) : undefined);
6804
6870
  return { ok: result.ok, violations: result.violations.map(iterationViolationView) };
@@ -6808,7 +6874,7 @@ function registerSeamTools(ctx, resolver) {
6808
6874
  }
6809
6875
 
6810
6876
  // src/gates/adapter.ts
6811
- import { existsSync as existsSync18 } from "node:fs";
6877
+ import { existsSync as existsSync19 } from "node:fs";
6812
6878
  import { join as join18 } from "node:path";
6813
6879
  import { Service as Service2 } from "@deepseek-ai/cordis";
6814
6880
  var HOST_LOGGER = "mstar/host-adapter";
@@ -6845,7 +6911,7 @@ class DshHostAdapter extends Service2 {
6845
6911
  this.logSink(level, msg);
6846
6912
  }
6847
6913
  statusGate(path, kind, harnessDir) {
6848
- if (!existsSync18(path))
6914
+ if (!existsSync19(path))
6849
6915
  return { ok: true, violations: [] };
6850
6916
  return validateStatusDoc(path, kind, harnessDir);
6851
6917
  }
@@ -6927,7 +6993,7 @@ class DshHostAdapter extends Service2 {
6927
6993
 
6928
6994
  // src/gates/agent-personas.ts
6929
6995
  import { readFileSync as readFileSync15, readdirSync as readdirSync12, statSync as statSync6 } from "node:fs";
6930
- import { join as join19, resolve as resolve17, sep as sep6 } from "node:path";
6996
+ import { join as join19, resolve as resolve17, sep as sep5 } from "node:path";
6931
6997
  var ROLE_ID_PATTERN = /^[a-z0-9-]{1,32}$/;
6932
6998
  var defaultCache = new Map;
6933
6999
  function personaFor(roleId, lookup, warn) {
@@ -6970,7 +7036,7 @@ function defaultFromMirror(agentsDir, roleId, warn) {
6970
7036
  return;
6971
7037
  const root = resolve17(agentsDir);
6972
7038
  const file = resolve17(agentsDir, `${roleId}.md`);
6973
- if (!file.startsWith(root + sep6))
7039
+ if (!file.startsWith(root + sep5))
6974
7040
  return;
6975
7041
  let stat;
6976
7042
  try {
@@ -7457,7 +7523,7 @@ function registerWorkflowLedger(ctx, resolver, workflowAskCache) {
7457
7523
  }
7458
7524
 
7459
7525
  // src/gates/goal-bridge.ts
7460
- import { existsSync as existsSync19, readFileSync as readFileSync17, readdirSync as readdirSync13 } from "node:fs";
7526
+ import { existsSync as existsSync20, readFileSync as readFileSync17, readdirSync as readdirSync13 } from "node:fs";
7461
7527
  import { join as join21 } from "node:path";
7462
7528
  var GOAL_BRIDGE_LOGGER = "mstar/goal-bridge";
7463
7529
  var DEFAULT_MAX_GOAL_ROUNDS = 256;
@@ -7486,7 +7552,7 @@ function projectRegisterPointer(harnessDir) {
7486
7552
  if (!entry.isDirectory())
7487
7553
  continue;
7488
7554
  const registerPath = join21(projectsDir, entry.name, PROJECT_REGISTER_FILE);
7489
- if (existsSync19(registerPath))
7555
+ if (existsSync20(registerPath))
7490
7556
  return registerPath;
7491
7557
  }
7492
7558
  } catch {}
@@ -7501,7 +7567,7 @@ function iterationGoalObjective(iterationId) {
7501
7567
  }
7502
7568
  function steeringCompass(harnessDir) {
7503
7569
  const iterationsDir = resolveIterationDir(harnessDir);
7504
- if (!existsSync19(iterationsDir))
7570
+ if (!existsSync20(iterationsDir))
7505
7571
  return;
7506
7572
  let entries;
7507
7573
  try {
@@ -7513,7 +7579,7 @@ function steeringCompass(harnessDir) {
7513
7579
  if (!entry.isDirectory())
7514
7580
  continue;
7515
7581
  const compassPath = join21(iterationsDir, entry.name, "delivery-compass.md");
7516
- if (!existsSync19(compassPath))
7582
+ if (!existsSync20(compassPath))
7517
7583
  continue;
7518
7584
  let content;
7519
7585
  try {
@@ -7693,7 +7759,7 @@ function registerGoalBridge(ctx, resolver, config) {
7693
7759
  }
7694
7760
 
7695
7761
  // src/gates/plan-mode-bridge.ts
7696
- import { existsSync as existsSync20 } from "node:fs";
7762
+ import { existsSync as existsSync21 } from "node:fs";
7697
7763
  import { join as join22 } from "node:path";
7698
7764
  var PLAN_MODE_BRIDGE_LOGGER = "mstar/plan-mode-bridge";
7699
7765
  var PLAN_STATUS_TODO = "Todo";
@@ -7711,7 +7777,7 @@ function errorMessage5(error) {
7711
7777
  }
7712
7778
  function hasPrepareWindow(harnessDir) {
7713
7779
  const statusPath = join22(harnessDir, STATUS_FILE);
7714
- if (!existsSync20(statusPath))
7780
+ if (!existsSync21(statusPath))
7715
7781
  return false;
7716
7782
  const selection = resolveReadWorkflow(harnessDir);
7717
7783
  if (selection.kind === "error")
@@ -8170,7 +8236,7 @@ var inject = ["loader"];
8170
8236
  function packagedCommandsDir() {
8171
8237
  try {
8172
8238
  const dir = fileURLToPath3(new URL("../harness-commands", import.meta.url));
8173
- return existsSync21(dir) ? dir : undefined;
8239
+ return existsSync22(dir) ? dir : undefined;
8174
8240
  } catch {
8175
8241
  return;
8176
8242
  }