@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/README.i18n.yaml +2 -2
- package/README.md +4 -2
- package/README.zh.md +4 -2
- package/dist/gates/_shared.d.ts +18 -7
- package/dist/gates/fallbacks-advisory.d.ts +53 -15
- package/dist/gates/role-persona.d.ts +121 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +268 -161
- package/harness-skills/mstar-harness-core/SKILL.md +8 -1
- package/harness-skills/mstar-host/references/omp.md +2 -2
- package/harness-skills/mstar-host/references/zcode.md +7 -1
- package/package.json +1 -1
- package/harness-agents/project-manager.md +0 -30
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
|
|
1126
|
-
import { join as
|
|
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
|
|
1154
|
-
import { basename as basename4, dirname as dirname6, isAbsolute as isAbsolute6, join as
|
|
1155
|
-
import { existsSync as
|
|
1156
|
-
import { basename as
|
|
1157
|
-
import { existsSync as
|
|
1158
|
-
import { join as
|
|
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 !== ""
|
|
2599
|
-
|
|
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(
|
|
2695
|
-
return
|
|
2696
|
-
if (isFile2(
|
|
2697
|
-
return
|
|
2698
|
-
if (hasWorkflowSnapshot(
|
|
2699
|
-
return
|
|
2700
|
-
if (hasWorkflowSnapshot(
|
|
2701
|
-
return
|
|
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 =
|
|
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(
|
|
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 :
|
|
2729
|
-
const common = isAbsolute6(commonRaw) ? 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 =
|
|
2734
|
-
const cmAbs =
|
|
2735
|
-
return
|
|
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 =
|
|
2786
|
+
root = realpathSync4(controlRoot);
|
|
2753
2787
|
} else {
|
|
2754
2788
|
const topLevel = gitOut(cwd, ["rev-parse", "--show-toplevel"]);
|
|
2755
|
-
root =
|
|
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(
|
|
2777
|
-
harnessDir =
|
|
2778
|
-
} else if (isDirectory2(
|
|
2779
|
-
harnessDir =
|
|
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 =
|
|
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(
|
|
2821
|
+
writeFileSync4(join11(sddDir, ".gitignore"), `*
|
|
2788
2822
|
`);
|
|
2789
|
-
return
|
|
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 =
|
|
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 =
|
|
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() ?
|
|
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(
|
|
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 (
|
|
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 =
|
|
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(
|
|
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 =
|
|
3751
|
-
if (!
|
|
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(
|
|
3809
|
+
return /^[^.]*\.[A-Za-z0-9]{1,10}$/.test(basename7(root));
|
|
3776
3810
|
}
|
|
3777
3811
|
function scopeGuard(path, allowedRoots) {
|
|
3778
|
-
const resolved =
|
|
3812
|
+
const resolved = resolve13(path);
|
|
3779
3813
|
for (const root of allowedRoots) {
|
|
3780
|
-
const r =
|
|
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 (!
|
|
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 ${
|
|
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
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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
|
|
6107
|
-
import { basename as basename5, join as
|
|
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 =
|
|
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 =
|
|
6124
|
-
projectDir =
|
|
6157
|
+
workflowDir = join12(harnessDir, "workflows");
|
|
6158
|
+
projectDir = join12(harnessDir, "projects");
|
|
6125
6159
|
}
|
|
6126
|
-
if (name === WORKFLOW_SNAPSHOT_FILE && /^[^/]+\/snapshot\.json$/.test(
|
|
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(
|
|
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 =
|
|
6189
|
-
if (!
|
|
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
|
|
6263
|
-
import { basename as
|
|
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 =
|
|
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 (
|
|
6351
|
+
if (basename8(target.displayPath) !== "SKILL.md")
|
|
6318
6352
|
return false;
|
|
6319
|
-
const resolvedPath =
|
|
6320
|
-
return roots.some((root) => resolvedPath.startsWith(
|
|
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
|
|
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 =
|
|
6336
|
-
if (!
|
|
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:
|
|
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
|
|
6388
|
-
import { basename as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 :
|
|
6655
|
+
return idx === 0 ? sep3 : join14(sep3, ...segments.slice(1, idx + 1));
|
|
6622
6656
|
}
|
|
6623
6657
|
function isSeamTarget(seam, harnessDir, target) {
|
|
6624
|
-
const path =
|
|
6658
|
+
const path = resolve14(target.displayPath);
|
|
6625
6659
|
switch (seam) {
|
|
6626
6660
|
case "design-md": {
|
|
6627
|
-
const base =
|
|
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(
|
|
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 =
|
|
6653
|
-
const sibling =
|
|
6654
|
-
if (
|
|
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 =
|
|
6681
|
-
if (!
|
|
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 =
|
|
6715
|
-
if (!
|
|
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(`${
|
|
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(`${
|
|
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
|
|
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 (!
|
|
6985
|
+
if (!existsSync18(args.snapshot_path))
|
|
6952
6986
|
throw new Error(`workflow snapshot not found: ${args.snapshot_path}`);
|
|
6953
|
-
if (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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
|
|
7157
|
-
import { join as
|
|
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 (!
|
|
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 =
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
7805
|
-
import { join as
|
|
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 =
|
|
7833
|
-
if (
|
|
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
|
|
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 (!
|
|
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 =
|
|
7860
|
-
if (!
|
|
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
|
|
8041
|
-
import { join as
|
|
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 =
|
|
8058
|
-
if (!
|
|
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 =
|
|
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
|
-
|
|
8255
|
-
|
|
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
|
|
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(
|
|
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((
|
|
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
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
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
|
});
|