@mstar-harness/dsh 3.9.4 → 3.10.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 (39) hide show
  1. package/dist/gates/dispatch.d.ts +9 -3
  2. package/dist/index.js +175 -89
  3. package/harness-skills/mstar-artifacts/SKILL.md +4 -2
  4. package/harness-skills/mstar-artifacts/references/plan-files-and-reports.md +1 -1
  5. package/harness-skills/mstar-artifacts/references/plan-quality-bar.md +10 -0
  6. package/harness-skills/mstar-artifacts/references/plan-workflow-lifecycle-contract.md +115 -0
  7. package/harness-skills/mstar-artifacts/references/status-and-residuals.md +24 -3
  8. package/harness-skills/mstar-artifacts/templates/plan.main.md +6 -1
  9. package/harness-skills/mstar-compound/SKILL.md +4 -4
  10. package/harness-skills/mstar-conventions/SKILL.md +1 -0
  11. package/harness-skills/mstar-conventions/references/effort-estimation.md +2 -0
  12. package/harness-skills/mstar-dispatch-gates/SKILL.md +1 -1
  13. package/harness-skills/mstar-harness-core/SKILL.md +2 -2
  14. package/harness-skills/mstar-host/SKILL.md +8 -2
  15. package/harness-skills/mstar-host/references/_shared/plan-mode-bridge-core.md +2 -0
  16. package/harness-skills/mstar-host/references/dsh.md +8 -4
  17. package/harness-skills/mstar-host/references/omp.md +61 -1
  18. package/harness-skills/mstar-iteration/SKILL.md +1 -1
  19. package/harness-skills/mstar-iteration/references/command-shared-invariants.md +2 -0
  20. package/harness-skills/mstar-iteration/references/phase-1-prepare.md +2 -0
  21. package/harness-skills/mstar-iteration/references/phase-2-worktree-lease.md +38 -3
  22. package/harness-skills/mstar-iteration/references/phase-3-iteration-close.md +3 -3
  23. package/harness-skills/mstar-iteration/references/phase-4-5-pr-delivery.md +3 -2
  24. package/harness-skills/mstar-iteration/references/phase-6-post-merge-close.md +5 -2
  25. package/harness-skills/mstar-iteration/references/plan-scoped-pm.md +2 -0
  26. package/harness-skills/mstar-phase-gates/SKILL.md +7 -5
  27. package/harness-skills/mstar-project-governance/SKILL.md +3 -3
  28. package/harness-skills/mstar-review-qc/SKILL.md +4 -4
  29. package/harness-skills/mstar-review-qc/references/review-responsibility-boundaries.md +1 -1
  30. package/harness-skills/mstar-roles/references/_shared/leaf-executor-core.md +1 -0
  31. package/harness-skills/mstar-roles/references/project-manager/dispatch-and-assignment.md +5 -2
  32. package/harness-skills/mstar-roles/references/project-manager/plan-management.md +15 -0
  33. package/harness-skills/mstar-roles/references/project-manager/qa-trigger-matrix.md +3 -3
  34. package/harness-skills/mstar-roles/references/project-manager/qc-and-residuals.md +7 -5
  35. package/harness-skills/mstar-roles/references/project-manager.md +2 -3
  36. package/harness-skills/mstar-sdd/SKILL.md +5 -2
  37. package/harness-skills/mstar-sdd/references/implementer-continuation-prompt.md +4 -1
  38. package/harness-skills/mstar-sdd/references/implementer-prompt.md +4 -0
  39. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1122,7 +1122,7 @@ var require_lib2 = __commonJS(function(exports, module) {
1122
1122
  });
1123
1123
 
1124
1124
  // src/index.ts
1125
- import { existsSync as existsSync24, readFileSync as readFileSync19, readdirSync as readdirSync14 } from "node:fs";
1125
+ import { existsSync as existsSync24, readFileSync as readFileSync19, readdirSync as readdirSync15 } from "node:fs";
1126
1126
  import { join as join29 } from "node:path";
1127
1127
  import { fileURLToPath as fileURLToPath3 } from "node:url";
1128
1128
  import {
@@ -1138,28 +1138,28 @@ import { basename, dirname, join, resolve } from "node:path";
1138
1138
  import { fileURLToPath } from "node:url";
1139
1139
  import { readFileSync as readFileSync2, statSync } from "node:fs";
1140
1140
  import { dirname as dirname2, isAbsolute, join as join2, relative, resolve as resolve2 } from "node:path";
1141
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync5, readFileSync as readFileSync8, realpathSync as realpathSync3, statSync as statSync3, writeFileSync as writeFileSync3 } from "node:fs";
1141
+ import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync6, readFileSync as readFileSync8, realpathSync as realpathSync3, statSync as statSync3, writeFileSync as writeFileSync3 } from "node:fs";
1142
1142
  import { execFileSync } from "node:child_process";
1143
- import { basename as basename5, dirname as dirname6, isAbsolute as isAbsolute6, join as join10, relative as relative2, resolve as resolve8 } from "node:path";
1144
- import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync6 } from "node:fs";
1145
- import { existsSync as existsSync5, readFileSync as readFileSync5, readdirSync as readdirSync2, realpathSync as realpathSync2 } from "node:fs";
1146
- import { dirname as dirname5, join as join7, resolve as resolve6, sep as sep2 } from "node:path";
1143
+ import { basename as basename5, dirname as dirname6, isAbsolute as isAbsolute6, join as join10, relative as relative2, resolve as resolve9 } from "node:path";
1144
+ import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync6 } from "node:fs";
1145
+ import { existsSync as existsSync5, readFileSync as readFileSync5, readdirSync as readdirSync3, realpathSync as realpathSync2 } from "node:fs";
1146
+ import { dirname as dirname5, join as join7, resolve as resolve7, sep as sep2 } from "node:path";
1147
1147
  import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, resolve as resolve3 } from "node:path";
1148
1148
  import { AsyncLocalStorage } from "node:async_hooks";
1149
1149
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
1150
1150
  import { basename as basename2, dirname as dirname4, isAbsolute as isAbsolute3, join as join4, resolve as resolve4 } from "node:path";
1151
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4 } from "node:fs";
1152
- import { isAbsolute as isAbsolute5, join as join6 } from "node:path";
1151
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, readdirSync as readdirSync2, rmdirSync as rmdirSync2 } from "node:fs";
1152
+ import { isAbsolute as isAbsolute5, join as join6, resolve as resolve6 } from "node:path";
1153
1153
  import { execFileSync as execFileSync2 } from "node:child_process";
1154
1154
  import { existsSync as existsSync9, realpathSync as realpathSync4 } from "node:fs";
1155
- import { isAbsolute as isAbsolute7, join as join11, resolve as resolve9 } from "node:path";
1155
+ import { isAbsolute as isAbsolute7, join as join11, resolve as resolve10 } from "node:path";
1156
1156
  import { existsSync as existsSync10 } from "node:fs";
1157
1157
  import { join as join12, dirname as dirname8 } from "node:path";
1158
1158
  import { execFileSync as execFileSync3, spawn } from "node:child_process";
1159
- import { mkdirSync as mkdirSync6, readdirSync as readdirSync6, readFileSync as readFileSync9, realpathSync as realpathSync5, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
1160
- import { basename as basename7, dirname as dirname9, isAbsolute as isAbsolute8, join as join13, relative as relative3, resolve as resolve10 } from "node:path";
1161
- import { existsSync as existsSync13, readdirSync as readdirSync9, readFileSync as readFileSync12 } from "node:fs";
1162
- import { basename as basename11, isAbsolute as isAbsolute10, join as join17, relative as relative6, resolve as resolve14, sep as sep5 } from "node:path";
1159
+ import { mkdirSync as mkdirSync6, readdirSync as readdirSync7, readFileSync as readFileSync9, realpathSync as realpathSync5, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
1160
+ import { basename as basename7, dirname as dirname9, isAbsolute as isAbsolute8, join as join13, relative as relative3, resolve as resolve11 } from "node:path";
1161
+ import { existsSync as existsSync13, readdirSync as readdirSync10, readFileSync as readFileSync12 } from "node:fs";
1162
+ import { basename as basename11, isAbsolute as isAbsolute10, join as join17, relative as relative6, resolve as resolve15, sep as sep5 } from "node:path";
1163
1163
  import { existsSync as existsSync14 } from "node:fs";
1164
1164
  import { join as join18 } from "node:path";
1165
1165
  var SEVERITY_ORDER = ["critical", "high", "medium", "low", "nit"];
@@ -1702,6 +1702,7 @@ var REQUIRED_FIELDS = [
1702
1702
  var REVIEW_SEAT_ROLES = ["qc-specialist", "qc-specialist-2", "qc-specialist-3", "code-reviewer", "qa-engineer"];
1703
1703
  var BUDGET_LABELS = ["Budget (review / QC seats)", "Budget"];
1704
1704
  var RETURN_SHAPE_LABELS = ["Return shape (review / QC seats)", "Return shape"];
1705
+ var TASK_BUDGET_LABELS = ["Task budget (implement / ops rounds)", "Task budget"];
1705
1706
  function violation2(severity, code, message, fix) {
1706
1707
  return { ok: false, severity, code, message, fix };
1707
1708
  }
@@ -1729,6 +1730,8 @@ function parseAssignmentFields(assignmentText) {
1729
1730
  fields.budget = value;
1730
1731
  else if (RETURN_SHAPE_LABELS.includes(label))
1731
1732
  fields.returnShape = value;
1733
+ else if (TASK_BUDGET_LABELS.includes(label))
1734
+ fields.taskBudget = value;
1732
1735
  }
1733
1736
  return fields;
1734
1737
  }
@@ -1843,6 +1846,12 @@ function validateAssignmentFields(assignmentText, opts = {}) {
1843
1846
  violations.push(violation2("high", field.code, `${subject} must declare a round ${field.label} — ${missing}`, field.fix));
1844
1847
  }
1845
1848
  }
1849
+ if (!reviewSeat && !auditRound) {
1850
+ const missing = describeAbsence(fields.taskBudget);
1851
+ if (missing !== undefined) {
1852
+ violations.push(violation2("high", "assignment.field.task-budget-missing", `implement/ops round "${role}" must declare a Task budget — ${missing}`, `add "**Task budget (implement / ops rounds)**: <one implementer round closing the task's declared Files list and verification gates> — capacity contract spec § A1/A2"`));
1853
+ }
1854
+ }
1846
1855
  if (writable) {
1847
1856
  const workingPresent = fields.workingBranch !== undefined && fields.workingBranch !== "";
1848
1857
  const policyPresent = fields.branchPolicy !== undefined && fields.branchPolicy !== "";
@@ -1963,6 +1972,8 @@ var WORKFLOW_SNAPSHOT_FILE = "snapshot.json";
1963
1972
  var WORKFLOW_LIFECYCLE_STATUSES = ["running", "paused", "completed", "failed", "stopped"];
1964
1973
  var WORKFLOW_TERMINAL_STATUSES = ["completed", "failed", "stopped"];
1965
1974
  var WORKFLOW_LIFECYCLE_TYPES = ["plan", "iteration"];
1975
+ var WORKFLOW_DELIVERY_KINDS = ["development", "verification/report-only"];
1976
+ var WORKFLOW_COMPOUND_OUTCOMES = ["created", "updated", "skipped"];
1966
1977
  function violation3(severity, code, message, fix) {
1967
1978
  return { ok: false, severity, code, message, fix };
1968
1979
  }
@@ -1978,6 +1989,61 @@ function validateWorktreePathValue(violations, value, field) {
1978
1989
  violations.push(violation3("high", "workflow.snapshot.invalid-integration-worktree-path", `${field} must be a non-empty absolute path — got ${JSON.stringify(value)}`, "record the absolute integration checkout path (integration_worktree_path)"));
1979
1990
  }
1980
1991
  }
1992
+ function deliveryEvidenceViolations(value, what) {
1993
+ const violations = [];
1994
+ const invalid2 = (message) => {
1995
+ violations.push(violation3("medium", "workflow.snapshot.invalid-delivery-evidence", `${what}: ${message}`));
1996
+ };
1997
+ if (!isPlainObject2(value)) {
1998
+ invalid2("must be an object");
1999
+ return violations;
2000
+ }
2001
+ const members = ["compound", "pr", "merge", "completion"];
2002
+ const unknownMembers = Object.keys(value).filter((key) => !members.includes(key));
2003
+ if (unknownMembers.length > 0)
2004
+ invalid2(`unknown member(s) ${unknownMembers.join(", ")} — expected ${members.join(" | ")}`);
2005
+ const compound = value.compound;
2006
+ if (compound !== undefined) {
2007
+ if (!isPlainObject2(compound))
2008
+ invalid2("compound must be an object");
2009
+ else {
2010
+ const unknown = Object.keys(compound).filter((key) => key !== "outcome" && key !== "reason");
2011
+ if (unknown.length > 0)
2012
+ invalid2(`compound has unknown key(s) ${unknown.join(", ")}`);
2013
+ if (typeof compound.outcome !== "string" || !WORKFLOW_COMPOUND_OUTCOMES.includes(compound.outcome)) {
2014
+ invalid2(`compound.outcome must be one of ${WORKFLOW_COMPOUND_OUTCOMES.join(" | ")} — got ${JSON.stringify(compound.outcome)}`);
2015
+ } else if (compound.outcome === "skipped" && (typeof compound.reason !== "string" || compound.reason.trim() === "")) {
2016
+ invalid2("compound reason is required when the disposition outcome is 'skipped' (contract §4c)");
2017
+ } else if (compound.reason !== undefined && (typeof compound.reason !== "string" || compound.reason.trim() === "")) {
2018
+ invalid2("compound.reason must be a non-empty string when given");
2019
+ }
2020
+ }
2021
+ }
2022
+ const stringMembers = {
2023
+ pr: ["repo", "head", "target"],
2024
+ merge: ["provider", "evidence"],
2025
+ completion: ["policy", "evidence"]
2026
+ };
2027
+ for (const member of ["pr", "merge", "completion"]) {
2028
+ const block = value[member];
2029
+ if (block === undefined)
2030
+ continue;
2031
+ if (!isPlainObject2(block)) {
2032
+ invalid2(`${member} must be an object`);
2033
+ continue;
2034
+ }
2035
+ const fields = stringMembers[member];
2036
+ const unknown = Object.keys(block).filter((key) => !fields.includes(key));
2037
+ if (unknown.length > 0)
2038
+ invalid2(`${member} has unknown key(s) ${unknown.join(", ")}`);
2039
+ for (const field of fields) {
2040
+ if (typeof block[field] !== "string" || block[field].trim() === "") {
2041
+ invalid2(`${member}.${field} must be a non-empty string`);
2042
+ }
2043
+ }
2044
+ }
2045
+ return violations;
2046
+ }
1981
2047
  function validateWorkflowSnapshot(doc) {
1982
2048
  const violations = [];
1983
2049
  if (!isPlainObject2(doc)) {
@@ -2043,7 +2109,7 @@ function validateWorkflowSnapshot(doc) {
2043
2109
  if (!isPlainObject2(doc.branch)) {
2044
2110
  violations.push(violation3("medium", "workflow.snapshot.invalid-branch", "branch must be an object"));
2045
2111
  } else {
2046
- for (const key of ["base", "integration", "target"]) {
2112
+ for (const key of ["base", "source", "integration", "target"]) {
2047
2113
  if (doc.branch[key] !== undefined && (typeof doc.branch[key] !== "string" || doc.branch[key].trim() === "")) {
2048
2114
  violations.push(violation3("medium", "workflow.snapshot.invalid-branch", `branch.${key} must be a non-empty string`));
2049
2115
  }
@@ -2069,6 +2135,20 @@ function validateWorkflowSnapshot(doc) {
2069
2135
  if (doc.compass_ref !== undefined) {
2070
2136
  validateNonEmptyString2(violations, doc.compass_ref, "compass_ref", "workflow.snapshot.missing-compass-ref", "workflow.snapshot.invalid-compass-ref");
2071
2137
  }
2138
+ if (doc.delivery_kind !== undefined) {
2139
+ if (typeof doc.delivery_kind !== "string" || !WORKFLOW_DELIVERY_KINDS.includes(doc.delivery_kind)) {
2140
+ violations.push(violation3("medium", "workflow.snapshot.invalid-delivery-kind", `delivery_kind must be one of ${WORKFLOW_DELIVERY_KINDS.join(" | ")} — got ${JSON.stringify(doc.delivery_kind)}`));
2141
+ }
2142
+ }
2143
+ if (doc.project !== undefined) {
2144
+ validateNonEmptyString2(violations, doc.project, "project", "workflow.snapshot.missing-project", "workflow.snapshot.invalid-project");
2145
+ }
2146
+ if (doc.completion_policy !== undefined) {
2147
+ validateNonEmptyString2(violations, doc.completion_policy, "completion_policy", "workflow.snapshot.missing-completion-policy", "workflow.snapshot.invalid-completion-policy");
2148
+ }
2149
+ if (doc.delivery !== undefined) {
2150
+ violations.push(...deliveryEvidenceViolations(doc.delivery, "delivery"));
2151
+ }
2072
2152
  const terminal = typeof doc.status === "string" && WORKFLOW_TERMINAL_STATUSES.includes(doc.status);
2073
2153
  if (terminal) {
2074
2154
  if (doc.ended_at === undefined) {
@@ -2283,7 +2363,7 @@ function validateStatusV2(docOrPath, opts = {}) {
2283
2363
  if (typeof docOrPath === "string") {
2284
2364
  try {
2285
2365
  doc = readJson(docOrPath);
2286
- harnessDir = dirname5(resolve6(docOrPath));
2366
+ harnessDir = dirname5(resolve7(docOrPath));
2287
2367
  } catch (error) {
2288
2368
  return {
2289
2369
  ok: false,
@@ -2391,7 +2471,7 @@ function resolveCompassEnforcement(harnessDir) {
2391
2471
  return { hard: false, source: "none" };
2392
2472
  let entries;
2393
2473
  try {
2394
- entries = readdirSync2(iterationsDir, { withFileTypes: true });
2474
+ entries = readdirSync3(iterationsDir, { withFileTypes: true });
2395
2475
  } catch {
2396
2476
  return { hard: false, source: "none" };
2397
2477
  }
@@ -2418,7 +2498,7 @@ function resolveCompassEnforcement(harnessDir) {
2418
2498
  return { hard: false, source: "none" };
2419
2499
  }
2420
2500
  function resolveMstarcEnforcement(harnessDir) {
2421
- const dir = resolve6(harnessDir);
2501
+ const dir = resolve7(harnessDir);
2422
2502
  const rc = loadMstarc(dir, dirname5(dir));
2423
2503
  const value = rc?.config.enforcement;
2424
2504
  if (value === "hard")
@@ -2806,14 +2886,14 @@ function findingsCleanupGate(register, planId, opts) {
2806
2886
  return { ok: violations.length === 0, violations };
2807
2887
  }
2808
2888
  function resolveHarnessDir(startDir = process.cwd(), opts = {}) {
2809
- const start = resolve8(startDir);
2889
+ const start = resolve9(startDir);
2810
2890
  const explicit = opts.harnessDir ?? process.env.MSTAR_HARNESS_DIR;
2811
2891
  if (explicit)
2812
- return resolve8(start, explicit);
2813
- const boundary = resolve8(start, opts.workspaceRoot ?? defaultWorkspaceRoot(start));
2892
+ return resolve9(start, explicit);
2893
+ const boundary = resolve9(start, opts.workspaceRoot ?? defaultWorkspaceRoot(start));
2814
2894
  const rc = loadMstarc(start, boundary);
2815
2895
  if (rc !== null && rc.config.harnessDir)
2816
- return resolve8(rc.dir, rc.config.harnessDir);
2896
+ return resolve9(rc.dir, rc.config.harnessDir);
2817
2897
  let dir = start;
2818
2898
  for (;; ) {
2819
2899
  if (!isAtOrBelow2(dir, boundary))
@@ -2844,7 +2924,7 @@ function defaultWorkspaceRoot(startDir) {
2844
2924
  if (segment && segment !== ".")
2845
2925
  boundary = dirname6(boundary);
2846
2926
  }
2847
- return resolve8(boundary);
2927
+ return resolve9(boundary);
2848
2928
  } catch {}
2849
2929
  return startDir;
2850
2930
  }
@@ -2853,10 +2933,10 @@ function isAtOrBelow2(dir, root) {
2853
2933
  return rel === "" || !rel.startsWith("..") && !isAbsolute6(rel);
2854
2934
  }
2855
2935
  function mstarcDirOverride(harnessDir, key) {
2856
- const dir = resolve8(harnessDir);
2936
+ const dir = resolve9(harnessDir);
2857
2937
  const rc = loadMstarc(dir, dirname6(dir));
2858
2938
  const declared = rc?.config[key];
2859
- return declared ? resolve8(rc.dir, declared) : null;
2939
+ return declared ? resolve9(rc.dir, declared) : null;
2860
2940
  }
2861
2941
  function assertSafePathComponent(value, what) {
2862
2942
  if (value === "" || value === "." || value === ".." || !/^[A-Za-z0-9._-]+$/.test(value)) {
@@ -2864,7 +2944,7 @@ function assertSafePathComponent(value, what) {
2864
2944
  }
2865
2945
  }
2866
2946
  function canonicalizeNearestExisting(path) {
2867
- const abs = resolve8(path);
2947
+ const abs = resolve9(path);
2868
2948
  let dir = abs;
2869
2949
  const tail = [];
2870
2950
  for (;; ) {
@@ -2884,7 +2964,7 @@ function canonicalizeNearestExisting(path) {
2884
2964
  }
2885
2965
  function resolveSddDir(harnessDir, planId) {
2886
2966
  assertSafePathComponent(planId, "planId");
2887
- const base = resolve8(harnessDir);
2967
+ const base = resolve9(harnessDir);
2888
2968
  const declared = mstarcDirOverride(base, "sddDir");
2889
2969
  const sddBase = declared !== null ? declared : join10(base, "sdd");
2890
2970
  return join10(sddBase, planId);
@@ -2893,15 +2973,15 @@ function resolveIterationDir(harnessDir) {
2893
2973
  const declared = mstarcDirOverride(harnessDir, "iterationDir");
2894
2974
  if (declared !== null)
2895
2975
  return declared;
2896
- return join10(resolve8(harnessDir), "iterations");
2976
+ return join10(resolve9(harnessDir), "iterations");
2897
2977
  }
2898
2978
  function resolveHarnessSubdir(startDir, opts, key, fallback) {
2899
2979
  const harness = resolveHarnessDir(startDir, opts);
2900
2980
  if (harness === null) {
2901
- throw new Error(`harness dir not found from ${resolve8(startDir)} — cannot resolve the ${fallback} dir (run \`mstar harness scaffold\`, pass opts.harnessDir, or set MSTAR_HARNESS_DIR)`);
2981
+ throw new Error(`harness dir not found from ${resolve9(startDir)} — cannot resolve the ${fallback} dir (run \`mstar harness scaffold\`, pass opts.harnessDir, or set MSTAR_HARNESS_DIR)`);
2902
2982
  }
2903
2983
  const declared = mstarcDirOverride(harness, key);
2904
- return declared !== null ? declared : join10(resolve8(harness), fallback);
2984
+ return declared !== null ? declared : join10(resolve9(harness), fallback);
2905
2985
  }
2906
2986
  function resolveWorkflowDir(startDir = process.cwd(), opts = {}) {
2907
2987
  return resolveHarnessSubdir(startDir, opts, "workflowDir", "workflows");
@@ -3080,7 +3160,7 @@ function l1PreDispatchCheck(input, opts = {}) {
3080
3160
  const violations = [];
3081
3161
  const checkoutCache = new Map;
3082
3162
  const checkout = (path) => {
3083
- const key = resolve9(path);
3163
+ const key = resolve10(path);
3084
3164
  if (!checkoutCache.has(key))
3085
3165
  checkoutCache.set(key, probeCheckout(path, opts));
3086
3166
  return checkoutCache.get(key);
@@ -3131,7 +3211,7 @@ function l1PreDispatchCheck(input, opts = {}) {
3131
3211
  }
3132
3212
  }
3133
3213
  const identityViolation = (aPath, bPath, code, describe, fix) => {
3134
- if (resolve9(aPath) === resolve9(bPath)) {
3214
+ if (resolve10(aPath) === resolve10(bPath)) {
3135
3215
  return violation8("critical", code, `${describe} — the same checkout (normalized path equality) is not isolation`, fix);
3136
3216
  }
3137
3217
  if (!existsSync9(aPath) || !existsSync9(bPath))
@@ -3192,7 +3272,7 @@ function l2PreDispatchCheck(input, opts = {}) {
3192
3272
  violations.push(violation8("high", "worktree.l2.track-path-relative", `track ${index + 1} worktreePath "${track.worktreePath}" is not an absolute path — L2 tracks MUST use absolute worktree checkout paths (consistent with the lease validator's absolute worktree_path enforcement)`, `use an absolute path for track ${index + 1} (e.g. /Users/<you>/worktrees/<branch>)`));
3193
3273
  return;
3194
3274
  }
3195
- const normalized = resolve9(track.worktreePath);
3275
+ const normalized = resolve10(track.worktreePath);
3196
3276
  if (seenPaths.has(normalized)) {
3197
3277
  violations.push(violation8("high", "worktree.l2.track-path-collision", `duplicate worktreePath "${track.worktreePath}" across parallel tracks — L2 parallel-writable isolation requires a distinct absolute Worktree path per track (N parallel invokes ≠ isolation)`, "give every parallel track its own git worktree checkout"));
3198
3278
  return;
@@ -3374,7 +3454,7 @@ function hasWorkflowSnapshot(harnessDir) {
3374
3454
  if (!isDirectory2(workflowsDir))
3375
3455
  return false;
3376
3456
  try {
3377
- for (const entry of readdirSync6(workflowsDir, { withFileTypes: true })) {
3457
+ for (const entry of readdirSync7(workflowsDir, { withFileTypes: true })) {
3378
3458
  if (entry.isDirectory() && isFile2(join13(workflowsDir, entry.name, "snapshot.json")))
3379
3459
  return true;
3380
3460
  }
@@ -3384,9 +3464,9 @@ function hasWorkflowSnapshot(harnessDir) {
3384
3464
  return false;
3385
3465
  }
3386
3466
  function checkoutRootNearestExisting(dir, boundary) {
3387
- const stop = resolve10(boundary);
3388
- const startInside = isInside(resolve10(dir), stop);
3389
- let current = resolve10(dir);
3467
+ const stop = resolve11(boundary);
3468
+ const startInside = isInside(resolve11(dir), stop);
3469
+ let current = resolve11(dir);
3390
3470
  for (;; ) {
3391
3471
  const probed = probeCheckoutRoot(current);
3392
3472
  if (probed !== null)
@@ -3440,12 +3520,12 @@ function sddWorkspace(planId, opts = {}) {
3440
3520
  const harnessOverride = opts.harnessDir ?? (process.env.MSTAR_HARNESS_DIR || undefined);
3441
3521
  let harnessDir;
3442
3522
  if (harnessOverride) {
3443
- harnessDir = resolve10(root, harnessOverride);
3523
+ harnessDir = resolve11(root, harnessOverride);
3444
3524
  } else {
3445
3525
  const rc = findMstarc(root, root);
3446
3526
  const rcHarnessDir = rc !== null ? parseMstarc(readFileSync9(rc, "utf8")).harnessDir : undefined;
3447
3527
  if (rcHarnessDir) {
3448
- harnessDir = resolve10(rc !== null ? dirname9(rc) : root, rcHarnessDir);
3528
+ harnessDir = resolve11(rc !== null ? dirname9(rc) : root, rcHarnessDir);
3449
3529
  } else {
3450
3530
  const probed = probeHarnessWithStatus(root);
3451
3531
  if (probed) {
@@ -3477,7 +3557,7 @@ function taskBrief(planFile, taskN, outFile, opts = {}) {
3477
3557
  const bound = opts.context;
3478
3558
  const observedCwd = opts.cwd ?? process.cwd();
3479
3559
  if (bound) {
3480
- const inputPlan = canonicalizeNearestExisting(resolve10(observedCwd, planFile));
3560
+ const inputPlan = canonicalizeNearestExisting(resolve11(observedCwd, planFile));
3481
3561
  if (inputPlan !== canonicalizeNearestExisting(bound.planFile)) {
3482
3562
  throwGateFail([
3483
3563
  contextViolation("high", "sdd.context.plan-file-mismatch", `plan file "${planFile}" does not match the bound context plan file "${bound.planFile}" — ` + "bound mode extracts only the resolved context's plan; refused before any read or write")
@@ -3493,7 +3573,7 @@ function taskBrief(planFile, taskN, outFile, opts = {}) {
3493
3573
  let out;
3494
3574
  let mkdirAfterGate = null;
3495
3575
  if (outFile) {
3496
- out = bound ? resolve10(observedCwd, outFile) : outFile;
3576
+ out = bound ? resolve11(observedCwd, outFile) : outFile;
3497
3577
  } else if (bound) {
3498
3578
  out = join13(bound.sddDir, `task-${taskN}-brief.md`);
3499
3579
  mkdirAfterGate = bound.sddDir;
@@ -3536,7 +3616,7 @@ function taskBrief(planFile, taskN, outFile, opts = {}) {
3536
3616
  if (printed.length === 0) {
3537
3617
  throw new SddScriptError(`task ${taskN} not found in ${planFile} (no heading matching Task ${taskN})`, 3);
3538
3618
  }
3539
- return bound ? resolve10(observedCwd, out) : out;
3619
+ return bound ? resolve11(observedCwd, out) : out;
3540
3620
  }
3541
3621
  function isInside(child, ancestor) {
3542
3622
  const rel = relative3(ancestor, child);
@@ -3574,11 +3654,11 @@ function checkSddAction(context, action) {
3574
3654
  const featureReal = canonicalDir(context.featureCwd);
3575
3655
  const canonicalSddDir = canonicalizeNearestExisting(context.sddDir);
3576
3656
  const canonicalPlanFile = canonicalizeNearestExisting(context.planFile);
3577
- const cwdResolved = resolve10(action.cwd);
3657
+ const cwdResolved = resolve11(action.cwd);
3578
3658
  const checkTarget = (baseDir, target, kind) => {
3579
3659
  if (featureReal === null)
3580
3660
  return;
3581
- const targetAbs = resolve10(baseDir, target);
3661
+ const targetAbs = resolve11(baseDir, target);
3582
3662
  const canonical = canonicalizeNearestExisting(targetAbs);
3583
3663
  if (!isInside(canonical, featureReal)) {
3584
3664
  const declaredPrefix = targetAbs === featureReal || targetAbs.startsWith(`${featureReal}/`);
@@ -3606,10 +3686,10 @@ function checkSddAction(context, action) {
3606
3686
  add("sdd.context.target-missing", "artifact checks require the destination target");
3607
3687
  return { ok: false, violations };
3608
3688
  }
3609
- const targetAbs = resolve10(cwdResolved, action.target);
3689
+ const targetAbs = resolve11(cwdResolved, action.target);
3610
3690
  const canonical = canonicalizeNearestExisting(targetAbs);
3611
3691
  if (!isInside(canonical, canonicalSddDir) && canonical !== canonicalPlanFile) {
3612
- const rawSddDir = resolve10(context.sddDir);
3692
+ const rawSddDir = resolve11(context.sddDir);
3613
3693
  const declaredPrefix = targetAbs === rawSddDir || targetAbs.startsWith(`${rawSddDir}/`) || targetAbs === canonicalSddDir || targetAbs.startsWith(`${canonicalSddDir}/`) || targetAbs === canonicalPlanFile;
3614
3694
  if (declaredPrefix) {
3615
3695
  add("sdd.context.artifact-symlink-escape", `artifact target "${targetAbs}" canonicalizes to "${canonical}", outside the plan's control sddDir — symlink escape refused before write`);
@@ -4361,7 +4441,7 @@ function referenceExists(repoRoot, docText) {
4361
4441
  const dir = stack.pop();
4362
4442
  let entries;
4363
4443
  try {
4364
- entries = readdirSync9(dir, { withFileTypes: true });
4444
+ entries = readdirSync10(dir, { withFileTypes: true });
4365
4445
  } catch {
4366
4446
  continue;
4367
4447
  }
@@ -4382,7 +4462,7 @@ function referenceExists(repoRoot, docText) {
4382
4462
  for (const { ref, isSymbol, module } of refs) {
4383
4463
  if (!isSymbol || module === undefined) {
4384
4464
  const candidate = ref.replace(LINE_SUFFIX_RE, "").replace(ANCHOR_RE, "");
4385
- if (existsSync13(resolve14(repoRoot, candidate))) {
4465
+ if (existsSync13(resolve15(repoRoot, candidate))) {
4386
4466
  checked++;
4387
4467
  } else {
4388
4468
  violations.push(violation11("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"));
@@ -4402,7 +4482,7 @@ function collectKnowledgeDocs(dir) {
4402
4482
  const current = stack.pop();
4403
4483
  let entries;
4404
4484
  try {
4405
- entries = readdirSync9(current, { withFileTypes: true });
4485
+ entries = readdirSync10(current, { withFileTypes: true });
4406
4486
  } catch {
4407
4487
  continue;
4408
4488
  }
@@ -4457,9 +4537,9 @@ function isFileLikeRoot(root) {
4457
4537
  return /^[^.]*\.[A-Za-z0-9]{1,10}$/.test(basename11(root));
4458
4538
  }
4459
4539
  function scopeGuard(path, allowedRoots) {
4460
- const resolved = resolve14(path);
4540
+ const resolved = resolve15(path);
4461
4541
  for (const root of allowedRoots) {
4462
- const r = resolve14(root);
4542
+ const r = resolve15(root);
4463
4543
  if (isFileLikeRoot(r)) {
4464
4544
  if (resolved === r)
4465
4545
  return { ok: true, violations: [] };
@@ -5056,7 +5136,7 @@ function skillLocalConfig(config) {
5056
5136
  }
5057
5137
 
5058
5138
  // src/gates/catalog.ts
5059
- import { existsSync as existsSync15, readFileSync as readFileSync10, readdirSync as readdirSync4, realpathSync as realpathSync6 } from "node:fs";
5139
+ import { existsSync as existsSync15, readFileSync as readFileSync10, readdirSync as readdirSync5, realpathSync as realpathSync6 } from "node:fs";
5060
5140
  import { basename as basename6, isAbsolute as isAbsolute9, join as join19, relative as relative7, sep as sep3 } from "node:path";
5061
5141
  import { createUserMessage } from "@deepseek-ai/dsh-llm";
5062
5142
 
@@ -5066,7 +5146,7 @@ import { join as join14 } from "node:path";
5066
5146
 
5067
5147
  // src/gates/dispatch.ts
5068
5148
  import { existsSync as existsSync7 } from "node:fs";
5069
- import { basename as basename3, join as join8, resolve as resolve7 } from "node:path";
5149
+ import { basename as basename3, join as join8, resolve as resolve8 } from "node:path";
5070
5150
 
5071
5151
  // src/gates/workflow-selection.ts
5072
5152
  import { existsSync as existsSync3, readdirSync, realpathSync, statSync as statSync2 } from "node:fs";
@@ -5570,7 +5650,7 @@ function leaseGateViolations(harnessDir, exec, writable, prompt, hint) {
5570
5650
  const wt = worktree === undefined ? undefined : firstToken(worktree);
5571
5651
  if (isNaValue(wt)) {
5572
5652
  violations.push(leaseViolation("lease.dispatch.worktree-mismatch", "Assignment declares no Worktree path — cannot confirm this dispatch matches execution_lease.worktree_path", "add the absolute Worktree path to the Assignment (must equal the lease worktree_path)"));
5573
- } else if (resolve7(wt) !== resolve7(String(lease.worktree_path ?? ""))) {
5653
+ } else if (resolve8(wt) !== resolve8(String(lease.worktree_path ?? ""))) {
5574
5654
  violations.push(leaseViolation("lease.dispatch.worktree-mismatch", `Assignment Worktree path "${wt}" differs from execution_lease.worktree_path "${String(lease.worktree_path)}"`, "align the Assignment with the lease worktree path (or update the lease)"));
5575
5655
  }
5576
5656
  const forms = parseAssignmentBranchForms(header);
@@ -5839,10 +5919,16 @@ function assignmentTextFromFields(fields) {
5839
5919
  lines.push(`**Delegation**: ${fields.delegation}`);
5840
5920
  if (fields.taskCategory !== undefined)
5841
5921
  lines.push(`**Task category**: ${fields.taskCategory}`);
5922
+ if (fields.taskBudget !== undefined)
5923
+ lines.push(`**Task budget (implement / ops rounds)**: ${fields.taskBudget}`);
5842
5924
  if (fields.workingBranch !== undefined)
5843
5925
  lines.push(`**Working branch**: ${fields.workingBranch}`);
5844
5926
  if (fields.branchPolicy !== undefined)
5845
5927
  lines.push(`**Branch policy**: ${fields.branchPolicy}`);
5928
+ if (fields.budget !== undefined)
5929
+ lines.push(`**Budget (review / QC seats)**: ${fields.budget}`);
5930
+ if (fields.returnShape !== undefined)
5931
+ lines.push(`**Return shape (review / QC seats)**: ${fields.returnShape}`);
5846
5932
  return lines.join(`
5847
5933
  `);
5848
5934
  }
@@ -7428,7 +7514,7 @@ function projectRollupSource(harnessDir, residuals) {
7428
7514
  if (existsSync15(projectsDir)) {
7429
7515
  let entries;
7430
7516
  try {
7431
- entries = readdirSync4(projectsDir, { withFileTypes: true });
7517
+ entries = readdirSync5(projectsDir, { withFileTypes: true });
7432
7518
  } catch {
7433
7519
  entries = [];
7434
7520
  }
@@ -7505,7 +7591,7 @@ function projectRegisters(harnessDir) {
7505
7591
  return [];
7506
7592
  let entries;
7507
7593
  try {
7508
- entries = readdirSync4(projectsDir, { withFileTypes: true });
7594
+ entries = readdirSync5(projectsDir, { withFileTypes: true });
7509
7595
  } catch {
7510
7596
  return [];
7511
7597
  }
@@ -7994,11 +8080,11 @@ function installEngineStatusEndpoint(ctx, options) {
7994
8080
  }
7995
8081
 
7996
8082
  // src/gates/status.ts
7997
- import { existsSync as existsSync17, readdirSync as readdirSync7 } from "node:fs";
7998
- import { basename as basename8, join as join21, relative as relative9, resolve as resolve11 } from "node:path";
8083
+ import { existsSync as existsSync17, readdirSync as readdirSync8 } from "node:fs";
8084
+ import { basename as basename8, join as join21, relative as relative9, resolve as resolve12 } from "node:path";
7999
8085
  var LOGGER_NAME = "mstar/status-gate";
8000
8086
  function harnessDocKindOfTarget(harnessDir, targetPath) {
8001
- const resolved = resolve11(targetPath);
8087
+ const resolved = resolve12(targetPath);
8002
8088
  const name = basename8(resolved);
8003
8089
  if (name !== STATUS_FILE && name !== WORKFLOW_SNAPSHOT_FILE && name !== PROJECT_REGISTER_FILE)
8004
8090
  return null;
@@ -8068,7 +8154,7 @@ function projectRegisterDocs(harnessDir) {
8068
8154
  const projectsDir = resolveProjectDir(harnessDir, { harnessDir });
8069
8155
  let entries;
8070
8156
  try {
8071
- entries = readdirSync7(projectsDir, { withFileTypes: true });
8157
+ entries = readdirSync8(projectsDir, { withFileTypes: true });
8072
8158
  } catch {
8073
8159
  return [];
8074
8160
  }
@@ -8151,7 +8237,7 @@ async function editIntentListener(ctx, resolver, config, adapter, target, actor,
8151
8237
 
8152
8238
  // src/gates/skill-lint.ts
8153
8239
  import { existsSync as existsSync18, readFileSync as readFileSync13 } from "node:fs";
8154
- import { basename as basename9, dirname as dirname12, resolve as resolve13, sep as sep6 } from "node:path";
8240
+ import { basename as basename9, dirname as dirname12, resolve as resolve14, sep as sep6 } from "node:path";
8155
8241
  var SKILL_LINT_LOGGER = "mstar/skill-lint";
8156
8242
 
8157
8243
  class SkillLintVetoError extends Error {
@@ -8192,7 +8278,7 @@ function lintSkillDoc(doc, options = {}) {
8192
8278
  return violations.length === 0 ? { ok: true, violations } : { ok: false, violations };
8193
8279
  }
8194
8280
  function lintSkillWrite(doc, options) {
8195
- const skillId = basename9(dirname12(resolve13(options.target)));
8281
+ const skillId = basename9(dirname12(resolve14(options.target)));
8196
8282
  const result = lintSkillDoc(doc, { skillId });
8197
8283
  if (options.hard && !result.ok) {
8198
8284
  throw new SkillLintVetoError(options.target, result.violations);
@@ -8207,8 +8293,8 @@ function skillRootsOf(config) {
8207
8293
  function isSkillTarget(roots, target) {
8208
8294
  if (basename9(target.displayPath) !== "SKILL.md")
8209
8295
  return false;
8210
- const resolvedPath = resolve13(target.displayPath);
8211
- return roots.some((root) => resolvedPath.startsWith(resolve13(root) + sep6));
8296
+ const resolvedPath = resolve14(target.displayPath);
8297
+ return roots.some((root) => resolvedPath.startsWith(resolve14(root) + sep6));
8212
8298
  }
8213
8299
  function skillNameOf(target) {
8214
8300
  return basename9(dirname12(target.displayPath));
@@ -8223,7 +8309,7 @@ function gateSkillIntent(ctx, harnessDir, config, target) {
8223
8309
  return;
8224
8310
  if (!isSkillTarget(roots, target))
8225
8311
  return;
8226
- const skillPath = resolve13(target.displayPath);
8312
+ const skillPath = resolve14(target.displayPath);
8227
8313
  if (!existsSync18(skillPath))
8228
8314
  return;
8229
8315
  let doc;
@@ -8275,8 +8361,8 @@ async function skillWriteIntentListener(ctx, resolver, config, target, actor, ne
8275
8361
  }
8276
8362
 
8277
8363
  // src/gates/seams.ts
8278
- import { existsSync as existsSync19, readFileSync as readFileSync15, readdirSync as readdirSync10 } from "node:fs";
8279
- import { basename as basename10, dirname as dirname13, join as join22, resolve as resolve15, sep as sep8 } from "node:path";
8364
+ import { existsSync as existsSync19, readFileSync as readFileSync15, readdirSync as readdirSync11 } from "node:fs";
8365
+ import { basename as basename10, dirname as dirname13, join as join22, resolve as resolve16, sep as sep8 } from "node:path";
8280
8366
 
8281
8367
  // ../engine/dist/audit.js
8282
8368
  import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
@@ -8486,7 +8572,7 @@ function isMarkdownDoc(path) {
8486
8572
  function isAuditPlanTarget(path) {
8487
8573
  if (!isMarkdownDoc(path))
8488
8574
  return false;
8489
- const segments = resolve15(path).split(sep8);
8575
+ const segments = resolve16(path).split(sep8);
8490
8576
  for (let i = 0;i < segments.length; i++) {
8491
8577
  if (segments[i] !== "plans")
8492
8578
  continue;
@@ -8497,7 +8583,7 @@ function isAuditPlanTarget(path) {
8497
8583
  return false;
8498
8584
  }
8499
8585
  function isRolesTarget(path) {
8500
- const segments = resolve15(path).split(sep8);
8586
+ const segments = resolve16(path).split(sep8);
8501
8587
  const idx = segments.indexOf("mstar-roles");
8502
8588
  if (idx === -1)
8503
8589
  return false;
@@ -8507,14 +8593,14 @@ function isRolesTarget(path) {
8507
8593
  return rest[0] === "SKILL.md" || rest[0] === "references" && rest[rest.length - 1].endsWith(".md");
8508
8594
  }
8509
8595
  function rolesDirOf(path) {
8510
- const segments = resolve15(path).split(sep8);
8596
+ const segments = resolve16(path).split(sep8);
8511
8597
  const idx = segments.indexOf("mstar-roles");
8512
8598
  if (idx === -1)
8513
8599
  return dirname13(path);
8514
8600
  return idx === 0 ? sep8 : join22(sep8, ...segments.slice(1, idx + 1));
8515
8601
  }
8516
8602
  function isSeamTarget(seam, harnessDir, target) {
8517
- const path = resolve15(target.displayPath);
8603
+ const path = resolve16(target.displayPath);
8518
8604
  switch (seam) {
8519
8605
  case "design-md": {
8520
8606
  const base = basename10(path);
@@ -8525,7 +8611,7 @@ function isSeamTarget(seam, harnessDir, target) {
8525
8611
  case "compound": {
8526
8612
  if (harnessDir === null)
8527
8613
  return false;
8528
- return path.startsWith(resolve15(join22(harnessDir, "knowledge")) + sep8) && isMarkdownDoc(path);
8614
+ return path.startsWith(resolve16(join22(harnessDir, "knowledge")) + sep8) && isMarkdownDoc(path);
8529
8615
  }
8530
8616
  case "roles":
8531
8617
  return isRolesTarget(path);
@@ -8567,7 +8653,7 @@ function validateCompoundDoc(doc, _path, harnessDir) {
8567
8653
  function validateRolesState(rolesDir, skillsRoot = dirname13(rolesDir)) {
8568
8654
  const violations = [...validateRoleMapping(rolesDir).violations];
8569
8655
  const skillTexts = {};
8570
- for (const entry of readdirSync10(skillsRoot, { withFileTypes: true })) {
8656
+ for (const entry of readdirSync11(skillsRoot, { withFileTypes: true })) {
8571
8657
  if (!entry.isDirectory() || !entry.name.startsWith("mstar-"))
8572
8658
  continue;
8573
8659
  const skillFile = join22(skillsRoot, entry.name, "SKILL.md");
@@ -8604,7 +8690,7 @@ function gateSeamIntent(ctx, harnessDir, config, seam, target) {
8604
8690
  try {
8605
8691
  if (!isSeamTarget(seam, harnessDir, target))
8606
8692
  return;
8607
- const path = resolve15(target.displayPath);
8693
+ const path = resolve16(target.displayPath);
8608
8694
  if (!existsSync19(path))
8609
8695
  return;
8610
8696
  let doc;
@@ -8676,7 +8762,7 @@ function lintRolesWrite(doc, options) {
8676
8762
 
8677
8763
  // src/gates/tools.ts
8678
8764
  import { existsSync as existsSync20, readFileSync as readFileSync16 } from "node:fs";
8679
- import { join as join23, resolve as resolve17 } from "node:path";
8765
+ import { join as join23, resolve as resolve18 } from "node:path";
8680
8766
  import { defineTool } from "@deepseek-ai/dsh-tools";
8681
8767
  var ITERATION_VIOLATION_SCHEMA = {
8682
8768
  type: "object",
@@ -8896,7 +8982,7 @@ function registerSeamTools(ctx, resolver) {
8896
8982
  presentCall: (args) => ({ card: "generic", title: "Validate DESIGN.md", kind: "other", rawInput: args.dir }),
8897
8983
  isConcurrencySafe: () => false,
8898
8984
  async execute(args) {
8899
- const abs = resolve17(args.dir);
8985
+ const abs = resolve18(args.dir);
8900
8986
  const lightPath = join23(abs, "DESIGN.md");
8901
8987
  if (!existsSync20(lightPath))
8902
8988
  throw new Error(`design file not found: ${lightPath}`);
@@ -8950,7 +9036,7 @@ function registerSeamTools(ctx, resolver) {
8950
9036
  presentCall: (args) => ({ card: "generic", title: "Validate audit plan", kind: "other", rawInput: args.plan_path }),
8951
9037
  isConcurrencySafe: () => false,
8952
9038
  async execute(args) {
8953
- const abs = resolve17(args.plan_path);
9039
+ const abs = resolve18(args.plan_path);
8954
9040
  if (!existsSync20(abs))
8955
9041
  throw new Error(`plan file not found: ${abs}`);
8956
9042
  const text = readFileSync16(abs, "utf8");
@@ -8990,17 +9076,17 @@ function registerSeamTools(ctx, resolver) {
8990
9076
  presentCall: (args) => ({ card: "generic", title: "Validate knowledge doc", kind: "other", rawInput: args.doc_path }),
8991
9077
  isConcurrencySafe: () => false,
8992
9078
  async execute(args, exec) {
8993
- const abs = resolve17(args.doc_path);
9079
+ const abs = resolve18(args.doc_path);
8994
9080
  if (!existsSync20(abs))
8995
9081
  throw new Error(`knowledge doc not found: ${abs}`);
8996
9082
  const text = readFileSync16(abs, "utf8");
8997
9083
  const base = validateCompoundDoc(text, abs, args.repo_root !== undefined ? null : resolver.forAgent(exec.agent));
8998
9084
  const violations = [...base.violations];
8999
9085
  if (args.repo_root !== undefined) {
9000
- violations.push(...referenceExists(resolve17(args.repo_root), text).violations);
9086
+ violations.push(...referenceExists(resolve18(args.repo_root), text).violations);
9001
9087
  }
9002
9088
  if (args.knowledge_dir !== undefined) {
9003
- const knowledgeDir = resolve17(args.knowledge_dir);
9089
+ const knowledgeDir = resolve18(args.knowledge_dir);
9004
9090
  violations.push(...assertIndexRows(knowledgeDir).violations);
9005
9091
  violations.push(...scopeGuard(abs, [knowledgeDir]).violations);
9006
9092
  }
@@ -9035,10 +9121,10 @@ function registerSeamTools(ctx, resolver) {
9035
9121
  presentCall: (args) => ({ card: "generic", title: "Validate roles mapping", kind: "other", rawInput: args.roles_dir }),
9036
9122
  isConcurrencySafe: () => false,
9037
9123
  async execute(args) {
9038
- const rolesDir = resolve17(args.roles_dir);
9124
+ const rolesDir = resolve18(args.roles_dir);
9039
9125
  if (!existsSync20(join23(rolesDir, "SKILL.md")))
9040
9126
  throw new Error(`roles dir not found: ${rolesDir}`);
9041
- const result = validateRolesState(rolesDir, args.skills_root !== undefined ? resolve17(args.skills_root) : undefined);
9127
+ const result = validateRolesState(rolesDir, args.skills_root !== undefined ? resolve18(args.skills_root) : undefined);
9042
9128
  return { ok: result.ok, violations: result.violations.map(iterationViolationView) };
9043
9129
  }
9044
9130
  }));
@@ -9188,8 +9274,8 @@ class DshHostAdapter extends Service3 {
9188
9274
  }
9189
9275
 
9190
9276
  // src/gates/agent-personas.ts
9191
- import { readFileSync as readFileSync17, readdirSync as readdirSync12, statSync as statSync8 } from "node:fs";
9192
- import { join as join25, resolve as resolve18, sep as sep9 } from "node:path";
9277
+ import { readFileSync as readFileSync17, readdirSync as readdirSync13, statSync as statSync8 } from "node:fs";
9278
+ import { join as join25, resolve as resolve19, sep as sep9 } from "node:path";
9193
9279
  var ROLE_ID_PATTERN = /^[a-z0-9-]{1,32}$/;
9194
9280
  var defaultCache = new Map;
9195
9281
  function personaFor(roleId, lookup, warn) {
@@ -9206,7 +9292,7 @@ function personaFor(roleId, lookup, warn) {
9206
9292
  function subagentRoleIds(agentsDir) {
9207
9293
  let names;
9208
9294
  try {
9209
- names = readdirSync12(agentsDir);
9295
+ names = readdirSync13(agentsDir);
9210
9296
  } catch {
9211
9297
  return [];
9212
9298
  }
@@ -9230,8 +9316,8 @@ function subagentRoleIds(agentsDir) {
9230
9316
  function defaultFromMirror(agentsDir, roleId, warn) {
9231
9317
  if (!ROLE_ID_PATTERN.test(roleId))
9232
9318
  return;
9233
- const root = resolve18(agentsDir);
9234
- const file = resolve18(agentsDir, `${roleId}.md`);
9319
+ const root = resolve19(agentsDir);
9320
+ const file = resolve19(agentsDir, `${roleId}.md`);
9235
9321
  if (!file.startsWith(root + sep9))
9236
9322
  return;
9237
9323
  let stat;
@@ -9881,7 +9967,7 @@ function registerWorkflowLedger(ctx, resolver, workflowAskCache) {
9881
9967
  }
9882
9968
 
9883
9969
  // src/gates/goal-bridge.ts
9884
- import { existsSync as existsSync22, readdirSync as readdirSync13 } from "node:fs";
9970
+ import { existsSync as existsSync22, readdirSync as readdirSync14 } from "node:fs";
9885
9971
  import { join as join27 } from "node:path";
9886
9972
  var GOAL_BRIDGE_LOGGER = "mstar/goal-bridge";
9887
9973
  var GOAL_CHANGE_EVENT_TYPE = "goal/change";
@@ -9904,7 +9990,7 @@ function errorMessage4(error) {
9904
9990
  function projectRegisterPointer(harnessDir) {
9905
9991
  const projectsDir = resolveProjectDir(harnessDir, { harnessDir });
9906
9992
  try {
9907
- for (const entry of readdirSync13(projectsDir, { withFileTypes: true })) {
9993
+ for (const entry of readdirSync14(projectsDir, { withFileTypes: true })) {
9908
9994
  if (!entry.isDirectory())
9909
9995
  continue;
9910
9996
  const registerPath = join27(projectsDir, entry.name, PROJECT_REGISTER_FILE);
@@ -10598,7 +10684,7 @@ function registerMstarCommands(ctx) {
10598
10684
  if (dir === undefined)
10599
10685
  return;
10600
10686
  ctx.inject(["commands"], (commandsCtx) => {
10601
- for (const file of readdirSync14(dir).sort()) {
10687
+ for (const file of readdirSync15(dir).sort()) {
10602
10688
  if (!file.endsWith(".md"))
10603
10689
  continue;
10604
10690
  const parsed = parseCommandMarkdown(readFileSync19(join29(dir, file), "utf8"));