@mstar-harness/dsh 3.7.0 → 3.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1122,8 +1122,8 @@ var require_lib2 = __commonJS(function(exports, module) {
1122
1122
  });
1123
1123
 
1124
1124
  // src/index.ts
1125
- import { existsSync as existsSync21, readFileSync as readFileSync18, readdirSync as readdirSync14 } from "node:fs";
1126
- import { join as join23 } from "node:path";
1125
+ import { existsSync as existsSync22, readFileSync as readFileSync18, readdirSync as readdirSync14 } from "node:fs";
1126
+ import { join as join24 } from "node:path";
1127
1127
  import { fileURLToPath as fileURLToPath3 } from "node:url";
1128
1128
  import {
1129
1129
  apply as applySkillLocal,
@@ -1147,15 +1147,15 @@ import { AsyncLocalStorage } from "node:async_hooks";
1147
1147
  import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync as readdirSync3, realpathSync } from "node:fs";
1148
1148
  import { dirname as dirname4, join as join7, resolve as resolve5, sep } from "node:path";
1149
1149
  import { execFileSync as execFileSync2 } from "node:child_process";
1150
- import { existsSync as existsSync7 } from "node:fs";
1151
- import { isAbsolute as isAbsolute5, resolve as resolve8 } from "node:path";
1150
+ import { existsSync as existsSync7, realpathSync as realpathSync3 } from "node:fs";
1151
+ import { isAbsolute as isAbsolute5, join as join10, resolve as resolve8 } from "node:path";
1152
1152
  import { execFileSync as execFileSync3, spawn } from "node:child_process";
1153
- import { mkdirSync as mkdirSync6, readdirSync as readdirSync6, readFileSync as readFileSync7, realpathSync as realpathSync3, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
1154
- import { basename as basename4, dirname as dirname6, isAbsolute as isAbsolute6, join as join10, relative as relative3, resolve as resolve9 } from "node:path";
1155
- import { existsSync as existsSync9, readdirSync as readdirSync9, readFileSync as readFileSync10 } from "node:fs";
1156
- import { basename as basename6, isAbsolute as isAbsolute8, join as join13, relative as relative5, resolve as resolve12, sep as sep4 } from "node:path";
1157
- import { existsSync as existsSync10 } from "node:fs";
1158
- import { join as join14 } from "node:path";
1153
+ import { mkdirSync as mkdirSync6, readdirSync as readdirSync6, readFileSync as readFileSync7, realpathSync as realpathSync4, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
1154
+ import { basename as basename4, dirname as dirname6, isAbsolute as isAbsolute6, join as join11, relative as relative3, resolve as resolve9 } from "node:path";
1155
+ import { existsSync as existsSync10, readdirSync as readdirSync9, readFileSync as readFileSync10 } from "node:fs";
1156
+ import { basename as basename7, isAbsolute as isAbsolute8, join as join15, relative as relative6, resolve as resolve13, sep as sep4 } from "node:path";
1157
+ import { existsSync as existsSync11 } from "node:fs";
1158
+ import { join as join16 } from "node:path";
1159
1159
  var SEVERITY_ORDER = ["critical", "high", "medium", "low", "nit"];
1160
1160
  function applyEnforcement(gate, opts) {
1161
1161
  return { ...gate, hardBlocked: opts.hard && gate.violations.length > 0 };
@@ -2583,6 +2583,28 @@ function probeBranch(worktreePath, opts) {
2583
2583
  return { error: detail };
2584
2584
  }
2585
2585
  }
2586
+ function probeCheckout(worktreePath, opts) {
2587
+ const timeout = opts.timeoutMs ?? probeTimeoutMs();
2588
+ try {
2589
+ const stdout = execFileSync2(opts.gitPath ?? "git", ["-C", worktreePath, "rev-parse", "--git-dir"], {
2590
+ encoding: "utf8",
2591
+ stdio: ["ignore", "pipe", "pipe"],
2592
+ timeout
2593
+ });
2594
+ const raw = stdout.trim();
2595
+ if (raw === "")
2596
+ return { error: `no git dir reported at "${worktreePath}"` };
2597
+ const abs = isAbsolute5(raw) ? raw : join10(worktreePath, raw);
2598
+ return { gitDir: realpathSync3(abs) };
2599
+ } catch (err) {
2600
+ const e = err;
2601
+ if (e.killed === true || e.signal !== undefined) {
2602
+ return { error: `git probe timed out after ${timeout}ms (killed by ${e.signal ?? "SIGTERM"})` };
2603
+ }
2604
+ const detail = (e.stderr !== undefined ? e.stderr.toString().trim() : "") || e.message || "git probe failed";
2605
+ return { error: detail };
2606
+ }
2607
+ }
2586
2608
  function l1PreDispatchCheck(input, opts = {}) {
2587
2609
  const violations = [];
2588
2610
  const { controlWorktreePath, leaseWorktreePath, leaseWorkingBranch, planId } = input;
@@ -2595,8 +2617,20 @@ function l1PreDispatchCheck(input, opts = {}) {
2595
2617
  if (leaseWorkingBranch.trim() === "") {
2596
2618
  violations.push(violation7("high", "worktree.l1.lease-branch-missing", `execution_lease.working_branch is empty for plan "${planId}"`, "record the lease working_branch before dispatch"));
2597
2619
  }
2598
- if (controlWorktreePath !== "" && leaseWorktreePath !== "" && resolve8(controlWorktreePath) === resolve8(leaseWorktreePath)) {
2599
- violations.push(violation7("critical", "worktree.l1.lease-equals-control", `execution_lease.worktree_path "${leaseWorktreePath}" equals metadata.control_worktree_path — the feature worktree MUST differ from the control worktree (L1 isolation; product edits never land in the control checkout)`, "use a distinct feature worktree for the plan (git worktree add <path> <branch>) and update the lease"));
2620
+ if (controlWorktreePath !== "" && leaseWorktreePath !== "") {
2621
+ if (resolve8(controlWorktreePath) === resolve8(leaseWorktreePath)) {
2622
+ violations.push(violation7("critical", "worktree.l1.lease-equals-control", `execution_lease.worktree_path "${leaseWorktreePath}" equals metadata.control_worktree_path — the feature worktree MUST differ from the control worktree (L1 isolation; product edits never land in the control checkout)`, "use a distinct feature worktree for the plan (git worktree add <path> <branch>) and update the lease"));
2623
+ } else if (existsSync7(leaseWorktreePath)) {
2624
+ const controlProbe = probeCheckout(controlWorktreePath, opts);
2625
+ const leaseProbe = probeCheckout(leaseWorktreePath, opts);
2626
+ if ("error" in controlProbe) {
2627
+ violations.push(violation7("high", "worktree.l1.checkout-probe-failed", `cannot establish the lease worktree "${leaseWorktreePath}" is a distinct Git checkout from the control worktree "${controlWorktreePath}" for plan "${planId}": ${controlProbe.error}`, "verify the control worktree path is a git checkout (integration-branch checkout)"));
2628
+ } else if ("error" in leaseProbe) {
2629
+ violations.push(violation7("high", "worktree.l1.checkout-probe-failed", `cannot establish the lease worktree "${leaseWorktreePath}" is a distinct Git checkout from the control worktree "${controlWorktreePath}" for plan "${planId}": ${leaseProbe.error}`, "verify the lease worktree path is a git checkout (git worktree add <path> <branch>)"));
2630
+ } else if (controlProbe.gitDir === leaseProbe.gitDir) {
2631
+ violations.push(violation7("critical", "worktree.l1.lease-equals-control", `execution_lease.worktree_path "${leaseWorktreePath}" is the same Git checkout as metadata.control_worktree_path "${controlWorktreePath}" — a plain subdirectory or symlink alias of the control checkout is not isolation; the feature worktree MUST be a distinct checkout`, "use a distinct feature worktree for the plan (git worktree add <path> <branch>) and update the lease"));
2632
+ }
2633
+ }
2600
2634
  }
2601
2635
  if (leaseWorktreePath !== "" && !existsSync7(leaseWorktreePath)) {
2602
2636
  violations.push(violation7("high", "worktree.l1.feature-missing", `feature worktree directory "${leaseWorktreePath}" does not exist for plan "${planId}"`, `create it before dispatch: git worktree add ${leaseWorktreePath} <working-branch>`));
@@ -2691,14 +2725,14 @@ function gitOut(cwd, args) {
2691
2725
  }
2692
2726
  }
2693
2727
  function probeHarnessWithStatus(root) {
2694
- if (isFile2(join10(root, ".mstar", "status.json")))
2695
- return join10(root, ".mstar");
2696
- if (isFile2(join10(root, ".agents", "status.json")))
2697
- return join10(root, ".agents");
2698
- if (hasWorkflowSnapshot(join10(root, ".mstar")))
2699
- return join10(root, ".mstar");
2700
- if (hasWorkflowSnapshot(join10(root, ".agents")))
2701
- return join10(root, ".agents");
2728
+ if (isFile2(join11(root, ".mstar", "status.json")))
2729
+ return join11(root, ".mstar");
2730
+ if (isFile2(join11(root, ".agents", "status.json")))
2731
+ return join11(root, ".agents");
2732
+ if (hasWorkflowSnapshot(join11(root, ".mstar")))
2733
+ return join11(root, ".mstar");
2734
+ if (hasWorkflowSnapshot(join11(root, ".agents")))
2735
+ return join11(root, ".agents");
2702
2736
  return null;
2703
2737
  }
2704
2738
  function hasWorkflowSnapshot(harnessDir) {
@@ -2706,13 +2740,13 @@ function hasWorkflowSnapshot(harnessDir) {
2706
2740
  try {
2707
2741
  workflowsDir = resolveWorkflowDir(harnessDir, { harnessDir });
2708
2742
  } catch {
2709
- workflowsDir = join10(harnessDir, "workflows");
2743
+ workflowsDir = join11(harnessDir, "workflows");
2710
2744
  }
2711
2745
  if (!isDirectory2(workflowsDir))
2712
2746
  return false;
2713
2747
  try {
2714
2748
  for (const entry of readdirSync6(workflowsDir, { withFileTypes: true })) {
2715
- if (entry.isDirectory() && isFile2(join10(workflowsDir, entry.name, "snapshot.json")))
2749
+ if (entry.isDirectory() && isFile2(join11(workflowsDir, entry.name, "snapshot.json")))
2716
2750
  return true;
2717
2751
  }
2718
2752
  } catch {
@@ -2725,14 +2759,14 @@ function isLinkedWorktree(root) {
2725
2759
  const commonRaw = gitOut(root, ["rev-parse", "--git-common-dir"]);
2726
2760
  if (gitDirRaw === null || commonRaw === null)
2727
2761
  return false;
2728
- const gitDir = isAbsolute6(gitDirRaw) ? gitDirRaw : join10(root, gitDirRaw);
2729
- const common = isAbsolute6(commonRaw) ? commonRaw : join10(root, commonRaw);
2762
+ const gitDir = isAbsolute6(gitDirRaw) ? gitDirRaw : join11(root, gitDirRaw);
2763
+ const common = isAbsolute6(commonRaw) ? commonRaw : join11(root, commonRaw);
2730
2764
  if (gitDir.includes("/.git/worktrees/") || gitDir.includes("/worktrees/"))
2731
2765
  return true;
2732
2766
  try {
2733
- const gdParent = realpathSync3(dirname6(gitDir));
2734
- const cmAbs = realpathSync3(common);
2735
- return join10(gdParent, basename4(gitDir)) !== cmAbs && gitDir !== cmAbs;
2767
+ const gdParent = realpathSync4(dirname6(gitDir));
2768
+ const cmAbs = realpathSync4(common);
2769
+ return join11(gdParent, basename4(gitDir)) !== cmAbs && gitDir !== cmAbs;
2736
2770
  } catch {
2737
2771
  return false;
2738
2772
  }
@@ -2749,10 +2783,10 @@ function sddWorkspace(planId, opts = {}) {
2749
2783
  if (!isDirectory2(controlRoot)) {
2750
2784
  throw new SddScriptError(`mstar sdd workspace: CONTROL_ROOT / MSTAR_CONTROL_ROOT is not a directory: ${controlRoot}`, 1);
2751
2785
  }
2752
- root = realpathSync3(controlRoot);
2786
+ root = realpathSync4(controlRoot);
2753
2787
  } else {
2754
2788
  const topLevel = gitOut(cwd, ["rev-parse", "--show-toplevel"]);
2755
- root = realpathSync3(topLevel ?? cwd);
2789
+ root = realpathSync4(topLevel ?? cwd);
2756
2790
  }
2757
2791
  if (!controlRoot && isLinkedWorktree(root)) {
2758
2792
  throw new SddScriptError(`mstar sdd workspace: linked worktree at ${root} has no {HARNESS_DIR}/status.json (default gitignore).
@@ -2773,20 +2807,20 @@ function sddWorkspace(planId, opts = {}) {
2773
2807
  const probed = probeHarnessWithStatus(root);
2774
2808
  if (probed) {
2775
2809
  harnessDir = probed;
2776
- } else if (isDirectory2(join10(root, ".mstar"))) {
2777
- harnessDir = join10(root, ".mstar");
2778
- } else if (isDirectory2(join10(root, ".agents"))) {
2779
- harnessDir = join10(root, ".agents");
2810
+ } else if (isDirectory2(join11(root, ".mstar"))) {
2811
+ harnessDir = join11(root, ".mstar");
2812
+ } else if (isDirectory2(join11(root, ".agents"))) {
2813
+ harnessDir = join11(root, ".agents");
2780
2814
  } else {
2781
- harnessDir = join10(root, ".mstar");
2815
+ harnessDir = join11(root, ".mstar");
2782
2816
  }
2783
2817
  }
2784
2818
  }
2785
2819
  const sddDir = resolveSddDir(harnessDir, planId);
2786
2820
  mkdirSync6(sddDir, { recursive: true });
2787
- writeFileSync4(join10(sddDir, ".gitignore"), `*
2821
+ writeFileSync4(join11(sddDir, ".gitignore"), `*
2788
2822
  `);
2789
- return realpathSync3(sddDir);
2823
+ return realpathSync4(sddDir);
2790
2824
  }
2791
2825
  function taskBrief(planFile, taskN, outFile, opts = {}) {
2792
2826
  if (!planFile || !Number.isInteger(taskN) || taskN < 1) {
@@ -2813,7 +2847,7 @@ function taskBrief(planFile, taskN, outFile, opts = {}) {
2813
2847
  if (outFile) {
2814
2848
  out = bound ? resolve9(observedCwd, outFile) : outFile;
2815
2849
  } else if (bound) {
2816
- out = join10(bound.sddDir, `task-${taskN}-brief.md`);
2850
+ out = join11(bound.sddDir, `task-${taskN}-brief.md`);
2817
2851
  mkdirAfterGate = bound.sddDir;
2818
2852
  } else {
2819
2853
  const sddDir = opts.sddDir ?? process.env.SDD_DIR;
@@ -2821,7 +2855,7 @@ function taskBrief(planFile, taskN, outFile, opts = {}) {
2821
2855
  throw new SddScriptError("mstar sdd task-brief: set SDD_DIR or pass OUTFILE (run mstar sdd workspace PLAN_ID first)", 2);
2822
2856
  }
2823
2857
  mkdirSync6(sddDir, { recursive: true });
2824
- out = join10(sddDir, `task-${taskN}-brief.md`);
2858
+ out = join11(sddDir, `task-${taskN}-brief.md`);
2825
2859
  }
2826
2860
  if (bound) {
2827
2861
  const gate2 = checkSddAction(bound, { kind: "artifact", cwd: observedCwd, target: out });
@@ -2862,7 +2896,7 @@ function isInside(child, ancestor) {
2862
2896
  }
2863
2897
  function canonicalDir(path) {
2864
2898
  try {
2865
- return statSync4(path).isDirectory() ? realpathSync3(path) : null;
2899
+ return statSync4(path).isDirectory() ? realpathSync4(path) : null;
2866
2900
  } catch {
2867
2901
  return null;
2868
2902
  }
@@ -3688,7 +3722,7 @@ function referenceExists(repoRoot, docText) {
3688
3722
  break;
3689
3723
  if (entry.isDirectory()) {
3690
3724
  if (!WALK_SKIP_DIRS.has(entry.name))
3691
- stack.push(join13(dir, entry.name));
3725
+ stack.push(join15(dir, entry.name));
3692
3726
  } else if (!entry.isSymbolicLink()) {
3693
3727
  const base = entry.name.replace(/\.(?:ts|tsx|js|jsx|mjs|cjs)$/, "");
3694
3728
  if (moduleNames.has(base))
@@ -3700,7 +3734,7 @@ function referenceExists(repoRoot, docText) {
3700
3734
  for (const { ref, isSymbol, module } of refs) {
3701
3735
  if (!isSymbol || module === undefined) {
3702
3736
  const candidate = ref.replace(LINE_SUFFIX_RE, "").replace(ANCHOR_RE, "");
3703
- if (existsSync9(resolve12(repoRoot, candidate))) {
3737
+ if (existsSync10(resolve13(repoRoot, candidate))) {
3704
3738
  checked++;
3705
3739
  } else {
3706
3740
  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"));
@@ -3727,11 +3761,11 @@ function collectKnowledgeDocs(dir) {
3727
3761
  for (const entry of entries) {
3728
3762
  if (entry.isSymbolicLink())
3729
3763
  continue;
3730
- const full = join13(current, entry.name);
3764
+ const full = join15(current, entry.name);
3731
3765
  if (entry.isDirectory()) {
3732
3766
  stack.push(full);
3733
3767
  } else if (entry.name.endsWith(".md") && entry.name !== "README.md" && entry.name !== "index.md") {
3734
- docs.push(relative5(dir, full).split(sep4).join("/"));
3768
+ docs.push(relative6(dir, full).split(sep4).join("/"));
3735
3769
  }
3736
3770
  }
3737
3771
  }
@@ -3747,8 +3781,8 @@ function normalizeIndexRef(cell) {
3747
3781
  }
3748
3782
  function assertIndexRows(knowledgeDir) {
3749
3783
  const violations = [];
3750
- const readmePath = join13(knowledgeDir, "README.md");
3751
- if (!existsSync9(readmePath)) {
3784
+ const readmePath = join15(knowledgeDir, "README.md");
3785
+ if (!existsSync10(readmePath)) {
3752
3786
  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"));
3753
3787
  return { ok: false, violations };
3754
3788
  }
@@ -3772,12 +3806,12 @@ function assertIndexRows(knowledgeDir) {
3772
3806
  return { ok: violations.length === 0, violations };
3773
3807
  }
3774
3808
  function isFileLikeRoot(root) {
3775
- return /^[^.]*\.[A-Za-z0-9]{1,10}$/.test(basename6(root));
3809
+ return /^[^.]*\.[A-Za-z0-9]{1,10}$/.test(basename7(root));
3776
3810
  }
3777
3811
  function scopeGuard(path, allowedRoots) {
3778
- const resolved = resolve12(path);
3812
+ const resolved = resolve13(path);
3779
3813
  for (const root of allowedRoots) {
3780
- const r = resolve12(root);
3814
+ const r = resolve13(root);
3781
3815
  if (isFileLikeRoot(r)) {
3782
3816
  if (resolved === r)
3783
3817
  return { ok: true, violations: [] };
@@ -3935,8 +3969,8 @@ function validateRoleMapping(rolesDir, options = {}) {
3935
3969
  const violations = [];
3936
3970
  const referenceById = new Map(mapping.map((m) => [m.agentId, m.reference]));
3937
3971
  for (const { agentId, reference } of mapping) {
3938
- if (!existsSync10(join14(rolesDir, reference))) {
3939
- 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 ${join14(rolesDir, reference)} or fix the mapping row`));
3972
+ if (!existsSync11(join16(rolesDir, reference))) {
3973
+ 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 ${join16(rolesDir, reference)} or fix the mapping row`));
3940
3974
  }
3941
3975
  }
3942
3976
  for (const { family, memberIds } of families) {
@@ -4343,12 +4377,12 @@ function skillLocalConfig(config) {
4343
4377
  }
4344
4378
 
4345
4379
  // src/gates/catalog.ts
4346
- import { existsSync as existsSync13, readFileSync as readFileSync8, readdirSync as readdirSync4 } from "node:fs";
4380
+ import { existsSync as existsSync14, readFileSync as readFileSync8, readdirSync as readdirSync4 } from "node:fs";
4347
4381
  import { join as join8 } from "node:path";
4348
4382
  import { createUserMessage } from "@deepseek-ai/dsh-llm";
4349
4383
 
4350
4384
  // src/gates/agent-flow.ts
4351
- import { appendFileSync, closeSync, existsSync as existsSync11, mkdirSync as mkdirSync2, openSync, readFileSync as readFileSync5, readSync, renameSync as renameSync2, rmdirSync, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
4385
+ import { appendFileSync, closeSync, existsSync as existsSync12, mkdirSync as mkdirSync2, openSync, readFileSync as readFileSync5, readSync, renameSync as renameSync2, rmdirSync, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
4352
4386
  import { join as join6 } from "node:path";
4353
4387
 
4354
4388
  // src/gates/dispatch.ts
@@ -5496,7 +5530,7 @@ function ledgerContent(file, n) {
5496
5530
  }
5497
5531
  function readAgentFlow(workflowDir, limit) {
5498
5532
  const file = join6(workflowDir, AGENT_FLOW_FILE);
5499
- if (!existsSync11(file)) {
5533
+ if (!existsSync12(file)) {
5500
5534
  return { events: [], summary: [] };
5501
5535
  }
5502
5536
  const n = limit === undefined ? AGENT_FLOW_DEFAULT_LIMIT : Math.max(0, Math.floor(limit));
@@ -5751,7 +5785,7 @@ function harnessStateSource(harnessDir) {
5751
5785
  if (harnessDir === null)
5752
5786
  return null;
5753
5787
  const statusPath = join8(harnessDir, STATUS_FILE);
5754
- if (!existsSync13(statusPath))
5788
+ if (!existsSync14(statusPath))
5755
5789
  return null;
5756
5790
  try {
5757
5791
  const selection = resolveReadWorkflow(harnessDir);
@@ -5772,7 +5806,7 @@ function harnessStateSource(harnessDir) {
5772
5806
  }
5773
5807
  const snapshotPath = join8(harnessDir, selection.dir, WORKFLOW_SNAPSHOT_FILE);
5774
5808
  let snapshot;
5775
- if (!existsSync13(snapshotPath)) {
5809
+ if (!existsSync14(snapshotPath)) {
5776
5810
  return selectionErrorState({
5777
5811
  kind: "error",
5778
5812
  code: "workflow.selection.snapshot-unreadable",
@@ -5864,7 +5898,7 @@ function selectionErrorState(selection, rollup, harnessDir, compass) {
5864
5898
  function projectRollupSource(harnessDir, residuals) {
5865
5899
  const milestones = [];
5866
5900
  const projectsDir = resolveProjectDir(harnessDir, { harnessDir });
5867
- if (existsSync13(projectsDir)) {
5901
+ if (existsSync14(projectsDir)) {
5868
5902
  let entries;
5869
5903
  try {
5870
5904
  entries = readdirSync4(projectsDir, { withFileTypes: true });
@@ -5875,7 +5909,7 @@ function projectRollupSource(harnessDir, residuals) {
5875
5909
  if (!entry.isDirectory())
5876
5910
  continue;
5877
5911
  const roadmapPath = join8(projectsDir, entry.name, PROJECT_ROADMAP_FILE);
5878
- if (!existsSync13(roadmapPath))
5912
+ if (!existsSync14(roadmapPath))
5879
5913
  continue;
5880
5914
  try {
5881
5915
  const doc = parseCompassFrontmatterText(readFileSync8(roadmapPath, "utf8"), roadmapPath);
@@ -5940,7 +5974,7 @@ function residualRollup(harnessDir) {
5940
5974
  }
5941
5975
  function projectRegisters(harnessDir) {
5942
5976
  const projectsDir = resolveProjectDir(harnessDir, { harnessDir });
5943
- if (!existsSync13(projectsDir))
5977
+ if (!existsSync14(projectsDir))
5944
5978
  return [];
5945
5979
  let entries;
5946
5980
  try {
@@ -5953,7 +5987,7 @@ function projectRegisters(harnessDir) {
5953
5987
  if (!entry.isDirectory())
5954
5988
  continue;
5955
5989
  const registerPath = join8(projectsDir, entry.name, PROJECT_REGISTER_FILE);
5956
- if (!existsSync13(registerPath))
5990
+ if (!existsSync14(registerPath))
5957
5991
  continue;
5958
5992
  try {
5959
5993
  registers.push({ projectId: entry.name, doc: readJson(registerPath) });
@@ -5965,7 +5999,7 @@ function projectRegisters(harnessDir) {
5965
5999
  }
5966
6000
  function knowledgeDigest(harnessDir) {
5967
6001
  const indexPath = join8(harnessDir, "knowledge", "README.md");
5968
- if (!existsSync13(indexPath))
6002
+ if (!existsSync14(indexPath))
5969
6003
  return null;
5970
6004
  try {
5971
6005
  const categories = new Set;
@@ -6010,7 +6044,7 @@ function compassDirection(compassPath) {
6010
6044
  }
6011
6045
  function steeringCompassPath(harnessDir) {
6012
6046
  const iterationsDir = resolveIterationDir(harnessDir);
6013
- if (!existsSync13(iterationsDir))
6047
+ if (!existsSync14(iterationsDir))
6014
6048
  return;
6015
6049
  let entries;
6016
6050
  try {
@@ -6022,7 +6056,7 @@ function steeringCompassPath(harnessDir) {
6022
6056
  if (!entry.isDirectory())
6023
6057
  continue;
6024
6058
  const compassPath = join8(iterationsDir, entry.name, "delivery-compass.md");
6025
- if (!existsSync13(compassPath))
6059
+ if (!existsSync14(compassPath))
6026
6060
  continue;
6027
6061
  let content;
6028
6062
  try {
@@ -6041,7 +6075,7 @@ function iterationGateSource(harnessDir) {
6041
6075
  if (harnessDir === null)
6042
6076
  return;
6043
6077
  const statusPath = join8(harnessDir, STATUS_FILE);
6044
- if (!existsSync13(statusPath))
6078
+ if (!existsSync14(statusPath))
6045
6079
  return;
6046
6080
  const compass = steeringCompassPath(harnessDir);
6047
6081
  if (compass === undefined)
@@ -6103,15 +6137,15 @@ function agentDigestKey(agent, cwd) {
6103
6137
  }
6104
6138
 
6105
6139
  // src/gates/status.ts
6106
- import { existsSync as existsSync14, readdirSync as readdirSync7 } from "node:fs";
6107
- import { basename as basename5, join as join11, relative as relative6, resolve as resolve10 } from "node:path";
6140
+ import { existsSync as existsSync15, readdirSync as readdirSync7 } from "node:fs";
6141
+ import { basename as basename5, join as join12, relative as relative7, resolve as resolve10 } from "node:path";
6108
6142
  var LOGGER_NAME = "mstar/status-gate";
6109
6143
  function harnessDocKindOfTarget(harnessDir, targetPath) {
6110
6144
  const resolved = resolve10(targetPath);
6111
6145
  const name = basename5(resolved);
6112
6146
  if (name !== STATUS_FILE && name !== WORKFLOW_SNAPSHOT_FILE && name !== PROJECT_REGISTER_FILE)
6113
6147
  return null;
6114
- const rel = relative6(harnessDir, resolved);
6148
+ const rel = relative7(harnessDir, resolved);
6115
6149
  if (name === STATUS_FILE && rel === STATUS_FILE)
6116
6150
  return "status";
6117
6151
  let workflowDir;
@@ -6120,12 +6154,12 @@ function harnessDocKindOfTarget(harnessDir, targetPath) {
6120
6154
  workflowDir = resolveWorkflowDir(harnessDir, { harnessDir });
6121
6155
  projectDir = resolveProjectDir(harnessDir, { harnessDir });
6122
6156
  } catch {
6123
- workflowDir = join11(harnessDir, "workflows");
6124
- projectDir = join11(harnessDir, "projects");
6157
+ workflowDir = join12(harnessDir, "workflows");
6158
+ projectDir = join12(harnessDir, "projects");
6125
6159
  }
6126
- if (name === WORKFLOW_SNAPSHOT_FILE && /^[^/]+\/snapshot\.json$/.test(relative6(workflowDir, resolved)))
6160
+ if (name === WORKFLOW_SNAPSHOT_FILE && /^[^/]+\/snapshot\.json$/.test(relative7(workflowDir, resolved)))
6127
6161
  return "snapshot";
6128
- if (name === PROJECT_REGISTER_FILE && /^[^/]+\/residuals\.json$/.test(relative6(projectDir, resolved)))
6162
+ if (name === PROJECT_REGISTER_FILE && /^[^/]+\/residuals\.json$/.test(relative7(projectDir, resolved)))
6129
6163
  return "register";
6130
6164
  return null;
6131
6165
  }
@@ -6185,8 +6219,8 @@ function projectRegisterDocs(harnessDir) {
6185
6219
  for (const entry of entries) {
6186
6220
  if (!entry.isDirectory())
6187
6221
  continue;
6188
- const registerPath = join11(projectsDir, entry.name, PROJECT_REGISTER_FILE);
6189
- if (!existsSync14(registerPath))
6222
+ const registerPath = join12(projectsDir, entry.name, PROJECT_REGISTER_FILE);
6223
+ if (!existsSync15(registerPath))
6190
6224
  continue;
6191
6225
  try {
6192
6226
  registers.push({ projectId: entry.name, doc: readJson(registerPath) });
@@ -6259,8 +6293,8 @@ async function editIntentListener(ctx, resolver, config, adapter, target, actor,
6259
6293
  }
6260
6294
 
6261
6295
  // src/gates/skill-lint.ts
6262
- import { existsSync as existsSync15, readFileSync as readFileSync11 } from "node:fs";
6263
- import { basename as basename7, dirname as dirname9, resolve as resolve13, sep as sep2 } from "node:path";
6296
+ import { existsSync as existsSync16, readFileSync as readFileSync11 } from "node:fs";
6297
+ import { basename as basename8, dirname as dirname9, resolve as resolve12, sep as sep2 } from "node:path";
6264
6298
  var SKILL_LINT_LOGGER = "mstar/skill-lint";
6265
6299
 
6266
6300
  class SkillLintVetoError extends Error {
@@ -6301,7 +6335,7 @@ function lintSkillDoc(doc, options = {}) {
6301
6335
  return violations.length === 0 ? { ok: true, violations } : { ok: false, violations };
6302
6336
  }
6303
6337
  function lintSkillWrite(doc, options) {
6304
- const skillId = basename7(dirname9(resolve13(options.target)));
6338
+ const skillId = basename8(dirname9(resolve12(options.target)));
6305
6339
  const result = lintSkillDoc(doc, { skillId });
6306
6340
  if (options.hard && !result.ok) {
6307
6341
  throw new SkillLintVetoError(options.target, result.violations);
@@ -6314,13 +6348,13 @@ function skillRootsOf(config) {
6314
6348
  return roots.map((root) => root.trim()).filter((root) => root !== "");
6315
6349
  }
6316
6350
  function isSkillTarget(roots, target) {
6317
- if (basename7(target.displayPath) !== "SKILL.md")
6351
+ if (basename8(target.displayPath) !== "SKILL.md")
6318
6352
  return false;
6319
- const resolvedPath = resolve13(target.displayPath);
6320
- return roots.some((root) => resolvedPath.startsWith(resolve13(root) + sep2));
6353
+ const resolvedPath = resolve12(target.displayPath);
6354
+ return roots.some((root) => resolvedPath.startsWith(resolve12(root) + sep2));
6321
6355
  }
6322
6356
  function skillNameOf(target) {
6323
- return basename7(dirname9(target.displayPath));
6357
+ return basename8(dirname9(target.displayPath));
6324
6358
  }
6325
6359
  function skillCanonicalForm(target) {
6326
6360
  return resolveSkillRoot("dsh", { skill: skillNameOf(target), rel: "SKILL.md" });
@@ -6332,8 +6366,8 @@ function gateSkillIntent(ctx, harnessDir, config, target) {
6332
6366
  return;
6333
6367
  if (!isSkillTarget(roots, target))
6334
6368
  return;
6335
- const skillPath = resolve13(target.displayPath);
6336
- if (!existsSync15(skillPath))
6369
+ const skillPath = resolve12(target.displayPath);
6370
+ if (!existsSync16(skillPath))
6337
6371
  return;
6338
6372
  let doc;
6339
6373
  try {
@@ -6350,7 +6384,7 @@ function gateSkillIntent(ctx, harnessDir, config, target) {
6350
6384
  });
6351
6385
  return;
6352
6386
  }
6353
- const result = lintSkillDoc(doc, { skillId: basename7(dirname9(skillPath)) });
6387
+ const result = lintSkillDoc(doc, { skillId: basename8(dirname9(skillPath)) });
6354
6388
  if (result.ok)
6355
6389
  return;
6356
6390
  const hard = resolveSeamHard(harnessDir, config);
@@ -6384,8 +6418,8 @@ async function skillWriteIntentListener(ctx, resolver, config, target, actor, ne
6384
6418
  }
6385
6419
 
6386
6420
  // src/gates/seams.ts
6387
- import { existsSync as existsSync16, readFileSync as readFileSync13, readdirSync as readdirSync10 } from "node:fs";
6388
- import { basename as basename8, dirname as dirname10, join as join15, resolve as resolve15, sep as sep3 } from "node:path";
6421
+ import { existsSync as existsSync17, readFileSync as readFileSync13, readdirSync as readdirSync10 } from "node:fs";
6422
+ import { basename as basename10, dirname as dirname10, join as join14, resolve as resolve14, sep as sep3 } from "node:path";
6389
6423
 
6390
6424
  // ../engine/dist/audit.js
6391
6425
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
@@ -6584,7 +6618,7 @@ var SEAM_LOGGERS = {
6584
6618
  roles: "mstar/roles-lint"
6585
6619
  };
6586
6620
  function isIndexFile(path) {
6587
- const base = basename8(path);
6621
+ const base = basename10(path);
6588
6622
  return base === "README.md" || base === "index.md";
6589
6623
  }
6590
6624
  function isMarkdownDoc(path) {
@@ -6593,7 +6627,7 @@ function isMarkdownDoc(path) {
6593
6627
  function isAuditPlanTarget(path) {
6594
6628
  if (!isMarkdownDoc(path))
6595
6629
  return false;
6596
- const segments = resolve15(path).split(sep3);
6630
+ const segments = resolve14(path).split(sep3);
6597
6631
  for (let i = 0;i < segments.length; i++) {
6598
6632
  if (segments[i] !== "plans")
6599
6633
  continue;
@@ -6604,7 +6638,7 @@ function isAuditPlanTarget(path) {
6604
6638
  return false;
6605
6639
  }
6606
6640
  function isRolesTarget(path) {
6607
- const segments = resolve15(path).split(sep3);
6641
+ const segments = resolve14(path).split(sep3);
6608
6642
  const idx = segments.indexOf("mstar-roles");
6609
6643
  if (idx === -1)
6610
6644
  return false;
@@ -6614,17 +6648,17 @@ function isRolesTarget(path) {
6614
6648
  return rest[0] === "SKILL.md" || rest[0] === "references" && rest[rest.length - 1].endsWith(".md");
6615
6649
  }
6616
6650
  function rolesDirOf(path) {
6617
- const segments = resolve15(path).split(sep3);
6651
+ const segments = resolve14(path).split(sep3);
6618
6652
  const idx = segments.indexOf("mstar-roles");
6619
6653
  if (idx === -1)
6620
6654
  return dirname10(path);
6621
- return idx === 0 ? sep3 : join15(sep3, ...segments.slice(1, idx + 1));
6655
+ return idx === 0 ? sep3 : join14(sep3, ...segments.slice(1, idx + 1));
6622
6656
  }
6623
6657
  function isSeamTarget(seam, harnessDir, target) {
6624
- const path = resolve15(target.displayPath);
6658
+ const path = resolve14(target.displayPath);
6625
6659
  switch (seam) {
6626
6660
  case "design-md": {
6627
- const base = basename8(path);
6661
+ const base = basename10(path);
6628
6662
  return base === "DESIGN.md" || base === "DESIGN.dark.md";
6629
6663
  }
6630
6664
  case "audit":
@@ -6632,7 +6666,7 @@ function isSeamTarget(seam, harnessDir, target) {
6632
6666
  case "compound": {
6633
6667
  if (harnessDir === null)
6634
6668
  return false;
6635
- return path.startsWith(resolve15(join15(harnessDir, "knowledge")) + sep3) && isMarkdownDoc(path);
6669
+ return path.startsWith(resolve14(join14(harnessDir, "knowledge")) + sep3) && isMarkdownDoc(path);
6636
6670
  }
6637
6671
  case "roles":
6638
6672
  return isRolesTarget(path);
@@ -6649,9 +6683,9 @@ function auditSecretsViolations(findings, file) {
6649
6683
  }
6650
6684
  function validateDesignDoc(doc, path) {
6651
6685
  const violations = [...validateDesignTokenFrontmatter(doc).violations];
6652
- const isDark = basename8(path) === "DESIGN.dark.md";
6653
- const sibling = join15(dirname10(path), isDark ? "DESIGN.md" : "DESIGN.dark.md");
6654
- if (existsSync16(sibling)) {
6686
+ const isDark = basename10(path) === "DESIGN.dark.md";
6687
+ const sibling = join14(dirname10(path), isDark ? "DESIGN.md" : "DESIGN.dark.md");
6688
+ if (existsSync17(sibling)) {
6655
6689
  const light = isDark ? readFileSync13(sibling, "utf8") : doc;
6656
6690
  const dark = isDark ? doc : readFileSync13(sibling, "utf8");
6657
6691
  violations.push(...assertLightDarkParity(light, dark).violations);
@@ -6677,8 +6711,8 @@ function validateRolesState(rolesDir, skillsRoot = dirname10(rolesDir)) {
6677
6711
  for (const entry of readdirSync10(skillsRoot, { withFileTypes: true })) {
6678
6712
  if (!entry.isDirectory() || !entry.name.startsWith("mstar-"))
6679
6713
  continue;
6680
- const skillFile = join15(skillsRoot, entry.name, "SKILL.md");
6681
- if (!existsSync16(skillFile))
6714
+ const skillFile = join14(skillsRoot, entry.name, "SKILL.md");
6715
+ if (!existsSync17(skillFile))
6682
6716
  continue;
6683
6717
  try {
6684
6718
  skillTexts[entry.name] = readFileSync13(skillFile, "utf8");
@@ -6711,8 +6745,8 @@ function gateSeamIntent(ctx, harnessDir, config, seam, target) {
6711
6745
  try {
6712
6746
  if (!isSeamTarget(seam, harnessDir, target))
6713
6747
  return;
6714
- const path = resolve15(target.displayPath);
6715
- if (!existsSync16(path))
6748
+ const path = resolve14(target.displayPath);
6749
+ if (!existsSync17(path))
6716
6750
  return;
6717
6751
  let doc;
6718
6752
  try {
@@ -6728,12 +6762,12 @@ function gateSeamIntent(ctx, harnessDir, config, seam, target) {
6728
6762
  const hard = resolveSeamHard(harnessDir, config);
6729
6763
  const verdict = applyEnforcement(result, { hard });
6730
6764
  if (verdict.hardBlocked) {
6731
- 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):
6765
+ logger.error(`${basename10(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):
6732
6766
  ${verdict.violations.map(formatViolation).join(`
6733
6767
  `)}`);
6734
6768
  emitSeamAdvisory(ctx, seam, target.displayPath, verdict, hard, { repair: true });
6735
6769
  } else {
6736
- logger.warn(`${basename8(path)} write to ${target.displayPath} (advisory):
6770
+ logger.warn(`${basename10(path)} write to ${target.displayPath} (advisory):
6737
6771
  ${verdict.violations.map(formatViolation).join(`
6738
6772
  `)}`);
6739
6773
  emitSeamAdvisory(ctx, seam, target.displayPath, verdict, hard);
@@ -6782,7 +6816,7 @@ function lintRolesWrite(doc, options) {
6782
6816
  }
6783
6817
 
6784
6818
  // src/gates/tools.ts
6785
- import { existsSync as existsSync17, readFileSync as readFileSync14 } from "node:fs";
6819
+ import { existsSync as existsSync18, readFileSync as readFileSync14 } from "node:fs";
6786
6820
  import { join as join17, resolve as resolve16 } from "node:path";
6787
6821
  import { defineTool } from "@deepseek-ai/dsh-tools";
6788
6822
  var ITERATION_VIOLATION_SCHEMA = {
@@ -6948,9 +6982,9 @@ function registerSddIterationTools(ctx, resolver) {
6948
6982
  presentResult: (_args, _result) => ({ card: "generic", title: "Iteration gate evaluation" }),
6949
6983
  isConcurrencySafe: () => false,
6950
6984
  async execute(args) {
6951
- if (!existsSync17(args.snapshot_path))
6985
+ if (!existsSync18(args.snapshot_path))
6952
6986
  throw new Error(`workflow snapshot not found: ${args.snapshot_path}`);
6953
- if (!existsSync17(args.compass_path))
6987
+ if (!existsSync18(args.compass_path))
6954
6988
  throw new Error(`compass file not found: ${args.compass_path}`);
6955
6989
  const snapshotDoc = readJson(args.snapshot_path);
6956
6990
  const compassDoc = parseCompassFrontmatter(args.compass_path);
@@ -7005,7 +7039,7 @@ function registerSeamTools(ctx, resolver) {
7005
7039
  async execute(args) {
7006
7040
  const abs = resolve16(args.dir);
7007
7041
  const lightPath = join17(abs, "DESIGN.md");
7008
- if (!existsSync17(lightPath))
7042
+ if (!existsSync18(lightPath))
7009
7043
  throw new Error(`design file not found: ${lightPath}`);
7010
7044
  const light = readFileSync14(lightPath, "utf8");
7011
7045
  const result = validateDesignDoc(light, lightPath);
@@ -7058,7 +7092,7 @@ function registerSeamTools(ctx, resolver) {
7058
7092
  isConcurrencySafe: () => false,
7059
7093
  async execute(args) {
7060
7094
  const abs = resolve16(args.plan_path);
7061
- if (!existsSync17(abs))
7095
+ if (!existsSync18(abs))
7062
7096
  throw new Error(`plan file not found: ${abs}`);
7063
7097
  const text = readFileSync14(abs, "utf8");
7064
7098
  const result = validateAuditDoc(text, abs);
@@ -7098,7 +7132,7 @@ function registerSeamTools(ctx, resolver) {
7098
7132
  isConcurrencySafe: () => false,
7099
7133
  async execute(args, exec) {
7100
7134
  const abs = resolve16(args.doc_path);
7101
- if (!existsSync17(abs))
7135
+ if (!existsSync18(abs))
7102
7136
  throw new Error(`knowledge doc not found: ${abs}`);
7103
7137
  const text = readFileSync14(abs, "utf8");
7104
7138
  const base = validateCompoundDoc(text, abs, args.repo_root !== undefined ? null : resolver.forAgent(exec.agent));
@@ -7143,7 +7177,7 @@ function registerSeamTools(ctx, resolver) {
7143
7177
  isConcurrencySafe: () => false,
7144
7178
  async execute(args) {
7145
7179
  const rolesDir = resolve16(args.roles_dir);
7146
- if (!existsSync17(join17(rolesDir, "SKILL.md")))
7180
+ if (!existsSync18(join17(rolesDir, "SKILL.md")))
7147
7181
  throw new Error(`roles dir not found: ${rolesDir}`);
7148
7182
  const result = validateRolesState(rolesDir, args.skills_root !== undefined ? resolve16(args.skills_root) : undefined);
7149
7183
  return { ok: result.ok, violations: result.violations.map(iterationViolationView) };
@@ -7153,8 +7187,8 @@ function registerSeamTools(ctx, resolver) {
7153
7187
  }
7154
7188
 
7155
7189
  // src/gates/adapter.ts
7156
- import { existsSync as existsSync18 } from "node:fs";
7157
- import { join as join18 } from "node:path";
7190
+ import { existsSync as existsSync19 } from "node:fs";
7191
+ import { join as join19 } from "node:path";
7158
7192
  import { Service as Service2 } from "@deepseek-ai/cordis";
7159
7193
  var HOST_LOGGER = "mstar/host-adapter";
7160
7194
  function mergeLeasesMatch(left, right) {
@@ -7190,7 +7224,7 @@ class DshHostAdapter extends Service2 {
7190
7224
  this.logSink(level, msg);
7191
7225
  }
7192
7226
  statusGate(path, kind, harnessDir) {
7193
- if (!existsSync18(path))
7227
+ if (!existsSync19(path))
7194
7228
  return { ok: true, violations: [] };
7195
7229
  return validateStatusDoc(path, kind, harnessDir);
7196
7230
  }
@@ -7245,7 +7279,7 @@ class DshHostAdapter extends Service2 {
7245
7279
  if (harnessDir !== null) {
7246
7280
  const selection = resolveActiveWorkflow(harnessDir);
7247
7281
  if (selection.kind === "active") {
7248
- const snapshotPath = join18(harnessDir, selection.dir, WORKFLOW_SNAPSHOT_FILE);
7282
+ const snapshotPath = join19(harnessDir, selection.dir, WORKFLOW_SNAPSHOT_FILE);
7249
7283
  try {
7250
7284
  const snapshot = readJson(snapshotPath);
7251
7285
  const stored = snapshot?.integration_merge_lease;
@@ -7272,7 +7306,7 @@ class DshHostAdapter extends Service2 {
7272
7306
 
7273
7307
  // src/gates/agent-personas.ts
7274
7308
  import { readFileSync as readFileSync15, readdirSync as readdirSync12, statSync as statSync7 } from "node:fs";
7275
- import { join as join19, resolve as resolve17, sep as sep5 } from "node:path";
7309
+ import { join as join20, resolve as resolve17, sep as sep5 } from "node:path";
7276
7310
  var ROLE_ID_PATTERN = /^[a-z0-9-]{1,32}$/;
7277
7311
  var defaultCache = new Map;
7278
7312
  function personaFor(roleId, lookup, warn) {
@@ -7300,7 +7334,7 @@ function subagentRoleIds(agentsDir) {
7300
7334
  const roleId = name.slice(0, -3);
7301
7335
  let content;
7302
7336
  try {
7303
- content = readFileSync15(join19(agentsDir, name), "utf8");
7337
+ content = readFileSync15(join20(agentsDir, name), "utf8");
7304
7338
  } catch {
7305
7339
  continue;
7306
7340
  }
@@ -7411,6 +7445,8 @@ function unquote(value) {
7411
7445
  // src/gates/role-persona.ts
7412
7446
  var ROLE_PERSONA_LOGGER = "mstar/role-persona";
7413
7447
  var SUBAGENTS_SERVICE = "subagents";
7448
+ var PERSONA_SEAM_EVENT = "internal/get";
7449
+ var ROLE_PERSONA_WRAPPER_BRAND = Symbol("mstar.role-persona.wrapper");
7414
7450
  var rolePersonaLogSink = () => {};
7415
7451
  function setRolePersonaLogger(sink) {
7416
7452
  const prior = rolePersonaLogSink;
@@ -7428,7 +7464,7 @@ function setRolePersonaAgentsDir(dir) {
7428
7464
  var wrapperCache = new WeakMap;
7429
7465
  function registerRolePersonaChannel(ctx, config) {
7430
7466
  const rolePersonas = config.rolePersonas;
7431
- ctx.on("internal/get", (_readCtx, name, _error, next) => {
7467
+ ctx.on(PERSONA_SEAM_EVENT, (_readCtx, name, _error, next) => {
7432
7468
  const value = next();
7433
7469
  if (name !== SUBAGENTS_SERVICE)
7434
7470
  return value;
@@ -7440,6 +7476,47 @@ function registerRolePersonaChannel(ctx, config) {
7440
7476
  }
7441
7477
  });
7442
7478
  }
7479
+ var SEAM_WARN = `role persona channel not installed — cordis '${PERSONA_SEAM_EVENT}' seam missing or unrecognized (rolePersonas will not be merged into subagent starts)`;
7480
+ function evaluateSeamProbe({ dispatched, readError, value }) {
7481
+ if (!dispatched)
7482
+ return { ok: false, reason: "seam-absent" };
7483
+ if (readError !== undefined)
7484
+ return { ok: true, reason: "service-absent" };
7485
+ if (typeof value === "object" && value !== null && value[ROLE_PERSONA_WRAPPER_BRAND] === true) {
7486
+ return { ok: true };
7487
+ }
7488
+ return { ok: false, reason: "wrap-skipped" };
7489
+ }
7490
+ function probeRolePersonaSeam(ctx) {
7491
+ try {
7492
+ let dispatched = false;
7493
+ let readError;
7494
+ let value;
7495
+ const disposeCanary = ctx.on(PERSONA_SEAM_EVENT, (_readCtx, _name, _error, next) => {
7496
+ dispatched = true;
7497
+ return next();
7498
+ });
7499
+ try {
7500
+ value = ctx.subagents;
7501
+ } catch (error) {
7502
+ readError = error;
7503
+ } finally {
7504
+ disposeCanary();
7505
+ }
7506
+ const result = evaluateSeamProbe({ dispatched, readError, value });
7507
+ if (!result.ok) {
7508
+ log2("warn", `${SEAM_WARN} (reason: ${result.reason})`);
7509
+ } else if (result.reason === "service-absent") {
7510
+ log2("debug", `role persona seam probe: 'subagents' unresolved at apply (the apply ctx does not resolve it — cordis resolves the service in dispatch scopes, where reads are intercepted per read)`);
7511
+ }
7512
+ return result;
7513
+ } catch (error) {
7514
+ try {
7515
+ log2("debug", `role persona seam probe failed internally — fail-open (observation only): ${errorMessage2(error)}`);
7516
+ } catch {}
7517
+ return { ok: true };
7518
+ }
7519
+ }
7443
7520
  function wrapSubagentsService(value, rolePersonas) {
7444
7521
  if (typeof value !== "object" || value === null)
7445
7522
  return value;
@@ -7450,6 +7527,7 @@ function wrapSubagentsService(value, rolePersonas) {
7450
7527
  if (cached !== undefined && cached.rolePersonas === rolePersonas)
7451
7528
  return cached.wrapper;
7452
7529
  const wrapper = Object.create(value);
7530
+ Object.defineProperty(wrapper, ROLE_PERSONA_WRAPPER_BRAND, { value: true, enumerable: false });
7453
7531
  wrapper.start = (name, request) => {
7454
7532
  let merged = request;
7455
7533
  try {
@@ -7518,7 +7596,7 @@ function log2(level, message) {
7518
7596
 
7519
7597
  // src/gates/workflow-ledger.ts
7520
7598
  import { readFileSync as readFileSync16, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
7521
- import { join as join20 } from "node:path";
7599
+ import { join as join21 } from "node:path";
7522
7600
  var WORKFLOW_LEDGER_LOGGER = "mstar/workflow-ledger";
7523
7601
  var TOOL_WORKFLOW_RUN_START = "tool-workflow/run-start";
7524
7602
  var TOOL_WORKFLOW_AGENT_START = "tool-workflow/agent-start";
@@ -7562,7 +7640,7 @@ function loadWatermark(workflowDir, fresh = false) {
7562
7640
  return cached;
7563
7641
  const watermark = new Map;
7564
7642
  try {
7565
- const raw = readFileSync16(join20(workflowDir, WORKFLOW_LEDGER_WATERMARK_FILE), "utf8");
7643
+ const raw = readFileSync16(join21(workflowDir, WORKFLOW_LEDGER_WATERMARK_FILE), "utf8");
7566
7644
  const record = asRecord(JSON.parse(raw));
7567
7645
  const cursors = asRecord(record?.cursors);
7568
7646
  if (cursors !== undefined) {
@@ -7585,7 +7663,7 @@ function loadWatermark(workflowDir, fresh = false) {
7585
7663
  }
7586
7664
  function saveWatermark(workflowDir, watermark) {
7587
7665
  try {
7588
- const file = join20(workflowDir, WORKFLOW_LEDGER_WATERMARK_FILE);
7666
+ const file = join21(workflowDir, WORKFLOW_LEDGER_WATERMARK_FILE);
7589
7667
  const tmp = `${file}.tmp`;
7590
7668
  writeFileSync5(tmp, JSON.stringify({ v: 1, cursors: Object.fromEntries(watermark) }));
7591
7669
  renameSync3(tmp, file);
@@ -7801,8 +7879,8 @@ function registerWorkflowLedger(ctx, resolver, workflowAskCache) {
7801
7879
  }
7802
7880
 
7803
7881
  // src/gates/goal-bridge.ts
7804
- import { existsSync as existsSync19, readFileSync as readFileSync17, readdirSync as readdirSync13 } from "node:fs";
7805
- import { join as join21 } from "node:path";
7882
+ import { existsSync as existsSync20, readFileSync as readFileSync17, readdirSync as readdirSync13 } from "node:fs";
7883
+ import { join as join22 } from "node:path";
7806
7884
  var GOAL_BRIDGE_LOGGER = "mstar/goal-bridge";
7807
7885
  var DEFAULT_MAX_GOAL_ROUNDS = 256;
7808
7886
  var FLOW_SEQUENCE = "iteration-start → per-plan cycles → iteration-close → PR delivery → merge-ready";
@@ -7829,12 +7907,12 @@ function projectRegisterPointer(harnessDir) {
7829
7907
  for (const entry of readdirSync13(projectsDir, { withFileTypes: true })) {
7830
7908
  if (!entry.isDirectory())
7831
7909
  continue;
7832
- const registerPath = join21(projectsDir, entry.name, PROJECT_REGISTER_FILE);
7833
- if (existsSync19(registerPath))
7910
+ const registerPath = join22(projectsDir, entry.name, PROJECT_REGISTER_FILE);
7911
+ if (existsSync20(registerPath))
7834
7912
  return registerPath;
7835
7913
  }
7836
7914
  } catch {}
7837
- return join21(projectsDir, _DEFAULT_PROJECT, PROJECT_REGISTER_FILE);
7915
+ return join22(projectsDir, _DEFAULT_PROJECT, PROJECT_REGISTER_FILE);
7838
7916
  }
7839
7917
  function isRootLikeAgent(agent) {
7840
7918
  const header = agent?.session?.header;
@@ -7845,7 +7923,7 @@ function iterationGoalObjective(iterationId) {
7845
7923
  }
7846
7924
  function steeringCompass(harnessDir) {
7847
7925
  const iterationsDir = resolveIterationDir(harnessDir);
7848
- if (!existsSync19(iterationsDir))
7926
+ if (!existsSync20(iterationsDir))
7849
7927
  return;
7850
7928
  let entries;
7851
7929
  try {
@@ -7856,8 +7934,8 @@ function steeringCompass(harnessDir) {
7856
7934
  for (const entry of entries) {
7857
7935
  if (!entry.isDirectory())
7858
7936
  continue;
7859
- const compassPath = join21(iterationsDir, entry.name, "delivery-compass.md");
7860
- if (!existsSync19(compassPath))
7937
+ const compassPath = join22(iterationsDir, entry.name, "delivery-compass.md");
7938
+ if (!existsSync20(compassPath))
7861
7939
  continue;
7862
7940
  let content;
7863
7941
  try {
@@ -8037,8 +8115,8 @@ function registerGoalBridge(ctx, resolver, config) {
8037
8115
  }
8038
8116
 
8039
8117
  // src/gates/plan-mode-bridge.ts
8040
- import { existsSync as existsSync20 } from "node:fs";
8041
- import { join as join22 } from "node:path";
8118
+ import { existsSync as existsSync21 } from "node:fs";
8119
+ import { join as join23 } from "node:path";
8042
8120
  var PLAN_MODE_BRIDGE_LOGGER = "mstar/plan-mode-bridge";
8043
8121
  var PLAN_STATUS_TODO = "Todo";
8044
8122
  var planModeBridgeLogSink = () => {};
@@ -8054,13 +8132,13 @@ function errorMessage5(error) {
8054
8132
  return error instanceof Error ? error.message : String(error);
8055
8133
  }
8056
8134
  function hasPrepareWindow(harnessDir) {
8057
- const statusPath = join22(harnessDir, STATUS_FILE);
8058
- if (!existsSync20(statusPath))
8135
+ const statusPath = join23(harnessDir, STATUS_FILE);
8136
+ if (!existsSync21(statusPath))
8059
8137
  return false;
8060
8138
  const selection = resolveReadWorkflow(harnessDir);
8061
8139
  if (selection.kind === "error")
8062
8140
  return false;
8063
- const snapshotPath = join22(harnessDir, selection.dir, WORKFLOW_SNAPSHOT_FILE);
8141
+ const snapshotPath = join23(harnessDir, selection.dir, WORKFLOW_SNAPSHOT_FILE);
8064
8142
  let doc;
8065
8143
  try {
8066
8144
  doc = readJson(snapshotPath);
@@ -8231,6 +8309,10 @@ function setAdvisoryLogger(sink) {
8231
8309
  return prior;
8232
8310
  }
8233
8311
  var ADVISORY_ID_LIST_CAP = 20;
8312
+ var advisoryAbortWarned = false;
8313
+ function resetAdvisoryAbortWarn() {
8314
+ advisoryAbortWarned = false;
8315
+ }
8234
8316
  function capIdList(items) {
8235
8317
  if (items.length <= ADVISORY_ID_LIST_CAP)
8236
8318
  return items.join(", ");
@@ -8239,11 +8321,11 @@ function capIdList(items) {
8239
8321
  async function runFallbacksAdvisory(ctx, agentsDir) {
8240
8322
  try {
8241
8323
  if (!fallbacksMounted(ctx))
8242
- return false;
8324
+ return { ran: false, converged: false };
8243
8325
  const config = readRowConfig(ctx);
8244
8326
  if (config === undefined) {
8245
8327
  log6("debug", "fallbacks row config unreadable (absent or non-object) — adoption advisory skipped");
8246
- return true;
8328
+ return { ran: true, converged: true };
8247
8329
  }
8248
8330
  const service = fallbacksService(ctx);
8249
8331
  if (service !== undefined) {
@@ -8251,8 +8333,11 @@ async function runFallbacksAdvisory(ctx, agentsDir) {
8251
8333
  }
8252
8334
  return runStructuralAdvisory(config, agentsDir);
8253
8335
  } catch (error) {
8254
- log6("warn", `fallbacks adoption advisory aborted (degraded — warn-only, deployment config untouched): ${errorMessage7(error)}`);
8255
- return true;
8336
+ if (!advisoryAbortWarned) {
8337
+ advisoryAbortWarned = true;
8338
+ log6("warn", `fallbacks adoption advisory aborted (degraded — warn-only, deployment config untouched): ${errorMessage7(error)}`);
8339
+ }
8340
+ return { ran: true, converged: false };
8256
8341
  }
8257
8342
  }
8258
8343
  async function runSeedsAdvisory(service, config, agentsDir) {
@@ -8262,12 +8347,12 @@ async function runSeedsAdvisory(service, config, agentsDir) {
8262
8347
  }
8263
8348
  if (agentsDir === undefined) {
8264
8349
  log6("debug", "harness-agents mirror absent — fallbacks adoption taxonomy check skipped (config-only advisory)");
8265
- return true;
8350
+ return { ran: true, converged: true };
8266
8351
  }
8267
8352
  const mstarIds = subagentRoleIds(agentsDir);
8268
8353
  if (mstarIds.length === 0) {
8269
8354
  log6("debug", "harness-agents mirror has no subagent-mode shells — fallbacks adoption taxonomy check skipped");
8270
- return true;
8355
+ return { ran: true, converged: true };
8271
8356
  }
8272
8357
  const seedsLog = (_level, message) => log6("debug", message);
8273
8358
  const view = await declareMstarSeeds(service, { agentsDir, log: seedsLog });
@@ -8276,26 +8361,26 @@ async function runSeedsAdvisory(service, config, agentsDir) {
8276
8361
  readback = service.getEffectiveRoles();
8277
8362
  } catch (error) {
8278
8363
  log6("warn", `fallbacks effective-state readback failed — adoption state unavailable: ${errorMessage7(error)}`);
8279
- return true;
8364
+ return { ran: true, converged: true };
8280
8365
  }
8281
8366
  reportEffectiveState(mstarIds, readback);
8282
8367
  reportDeclareOutcome(view);
8283
- return true;
8368
+ return { ran: true, converged: true };
8284
8369
  }
8285
8370
  function runStructuralAdvisory(config, agentsDir) {
8286
8371
  if (agentsDir === undefined) {
8287
8372
  log6("debug", "harness-agents mirror absent — fallbacks adoption taxonomy check skipped (config-only advisory)");
8288
- return true;
8373
+ return { ran: true, converged: true };
8289
8374
  }
8290
8375
  const mstarIds = subagentRoleIds(agentsDir);
8291
8376
  if (mstarIds.length === 0) {
8292
8377
  log6("debug", "harness-agents mirror has no subagent-mode shells — fallbacks adoption taxonomy check skipped");
8293
- return true;
8378
+ return { ran: true, converged: true };
8294
8379
  }
8295
8380
  const list = readRolesList(config);
8296
8381
  if (list === undefined) {
8297
8382
  log6("debug", "fallbacks roles block not structurally readable (roles.list absent or non-array) — adoption advisory skipped");
8298
- return true;
8383
+ return { ran: true, converged: true };
8299
8384
  }
8300
8385
  const declared = new Map;
8301
8386
  for (let index = 0;index < list.length; index++) {
@@ -8320,7 +8405,7 @@ function runStructuralAdvisory(config, agentsDir) {
8320
8405
  if (emptyPersona.length > 0) {
8321
8406
  log6("warn", `fallbacks roles.list declares roles with an empty persona: ${capIdList(emptyPersona)} — declare a persona (or remove the role)`);
8322
8407
  }
8323
- return true;
8408
+ return { ran: true, converged: true };
8324
8409
  }
8325
8410
  function reportEffectiveState(mstarIds, readback) {
8326
8411
  const byId = new Map;
@@ -8537,7 +8622,7 @@ var inject = ["loader"];
8537
8622
  function packagedCommandsDir() {
8538
8623
  try {
8539
8624
  const dir = fileURLToPath3(new URL("../harness-commands", import.meta.url));
8540
- return existsSync21(dir) ? dir : undefined;
8625
+ return existsSync22(dir) ? dir : undefined;
8541
8626
  } catch {
8542
8627
  return;
8543
8628
  }
@@ -8593,7 +8678,7 @@ function registerMstarCommands(ctx) {
8593
8678
  for (const file of readdirSync14(dir).sort()) {
8594
8679
  if (!file.endsWith(".md"))
8595
8680
  continue;
8596
- const parsed = parseCommandMarkdown(readFileSync18(join23(dir, file), "utf8"));
8681
+ const parsed = parseCommandMarkdown(readFileSync18(join24(dir, file), "utf8"));
8597
8682
  if (parsed === undefined)
8598
8683
  continue;
8599
8684
  commandsCtx.commands.register({
@@ -8659,6 +8744,7 @@ function apply(ctx, config) {
8659
8744
  else
8660
8745
  logger.warn(message);
8661
8746
  });
8747
+ resetAdvisoryAbortWarn();
8662
8748
  let advisoryPassed = false;
8663
8749
  let advisoryPassInFlight = false;
8664
8750
  let advisoryGeneration = 0;
@@ -8667,8 +8753,8 @@ function apply(ctx, config) {
8667
8753
  return;
8668
8754
  advisoryPassInFlight = true;
8669
8755
  const generation = advisoryGeneration;
8670
- runFallbacksAdvisory(ctx, packagedAgentsDir()).then((ran) => {
8671
- if (ran && generation === advisoryGeneration)
8756
+ runFallbacksAdvisory(ctx, packagedAgentsDir()).then((report) => {
8757
+ if (report.ran && report.converged && generation === advisoryGeneration)
8672
8758
  advisoryPassed = true;
8673
8759
  }).finally(() => {
8674
8760
  advisoryPassInFlight = false;
@@ -8682,23 +8768,43 @@ function apply(ctx, config) {
8682
8768
  const service = fallbacksService(serviceCtx);
8683
8769
  if (service === undefined)
8684
8770
  return;
8685
- declareMstarSeeds(service, {
8686
- agentsDir: packagedAgentsDir(),
8687
- log: (level, message) => {
8688
- const logger = ctx.logger(SEEDS_LOGGER);
8689
- if (level === "warn")
8690
- logger.warn(message);
8691
- else if (level === "error")
8692
- logger.error(message);
8693
- else
8694
- logger.debug(message);
8695
- }
8696
- }).catch((error) => {
8697
- ctx.logger(SEEDS_LOGGER).error(`mstar seeds declaration failed (contained — fallbacks taxonomy unchanged): ${error instanceof Error ? error.message : String(error)}`);
8698
- });
8771
+ let disposed = false;
8772
+ const retryTimers = [];
8773
+ const declareAttempt = (attempt) => {
8774
+ declareMstarSeeds(service, {
8775
+ agentsDir: packagedAgentsDir(),
8776
+ log: (level, message) => {
8777
+ const logger = ctx.logger(SEEDS_LOGGER);
8778
+ if (level === "warn")
8779
+ logger.warn(message);
8780
+ else if (level === "error")
8781
+ logger.error(message);
8782
+ else
8783
+ logger.debug(message);
8784
+ }
8785
+ }).catch((error) => {
8786
+ if (disposed)
8787
+ return;
8788
+ const message = error instanceof Error ? error.message : String(error);
8789
+ if (attempt >= 3) {
8790
+ ctx.logger(SEEDS_LOGGER).error(`mstar seeds declaration failed (contained — fallbacks taxonomy unchanged): ${message}`);
8791
+ return;
8792
+ }
8793
+ ctx.logger(SEEDS_LOGGER).debug(`seeds declare attempt ${attempt}/3 failed: ${message}`);
8794
+ retryTimers.push(setTimeout(() => {
8795
+ if (!disposed)
8796
+ declareAttempt(attempt + 1);
8797
+ }, attempt === 1 ? 50 : 250));
8798
+ });
8799
+ };
8800
+ declareAttempt(1);
8699
8801
  return () => {
8802
+ disposed = true;
8803
+ for (const timer of retryTimers)
8804
+ clearTimeout(timer);
8700
8805
  advisoryPassed = false;
8701
8806
  advisoryGeneration += 1;
8807
+ resetAdvisoryAbortWarn();
8702
8808
  };
8703
8809
  });
8704
8810
  registerSettleListener(ctx, config, pairing);
@@ -8757,6 +8863,7 @@ function apply(ctx, config) {
8757
8863
  }
8758
8864
  ctx.on("tools/pre-execute", (exec, next) => preExecuteListener(ctx, resolver, config, adapter, exec, next), { prepend: true });
8759
8865
  registerRolePersonaChannel(ctx, config);
8866
+ probeRolePersonaSeam(ctx);
8760
8867
  ctx.events.on("subagent/start", () => {
8761
8868
  runAdvisoryPass();
8762
8869
  });