@mstar-harness/dsh 3.6.3 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +4 -6
  2. package/README.zh.md +3 -3
  3. package/dist/client/panel/PanelView.d.ts +8 -11
  4. package/dist/client/panel/TabNav.d.ts +2 -2
  5. package/dist/client/panel/graph/event-log.d.ts +5 -9
  6. package/dist/client/panel/graph/project-graph.d.ts +53 -72
  7. package/dist/client/panel/graph/schema.d.ts +31 -37
  8. package/dist/client/panel/locale.d.ts +19 -19
  9. package/dist/client/panel/pages/AgentCanvasPage.d.ts +40 -58
  10. package/dist/client/panel/pages/EventLogPage.d.ts +6 -6
  11. package/dist/client/panel/pages/IterationInfoSection.d.ts +9 -11
  12. package/dist/client/panel/pages/IterationTaskPage.d.ts +3 -3
  13. package/dist/client/panel/plan-sort.d.ts +3 -6
  14. package/dist/client/panel/state-section.d.ts +1 -1
  15. package/dist/client/panel/zones/Legend.d.ts +2 -2
  16. package/dist/client/panel/zones/ProjectRollup.d.ts +1 -2
  17. package/dist/client/panel/zones/TaskBoard.d.ts +1 -2
  18. package/dist/gates/_shared.d.ts +7 -10
  19. package/dist/gates/adapter.d.ts +6 -9
  20. package/dist/gates/agent-flow.d.ts +49 -59
  21. package/dist/gates/agent-personas.d.ts +1 -2
  22. package/dist/gates/catalog.d.ts +2 -5
  23. package/dist/gates/dispatch.d.ts +9 -11
  24. package/dist/gates/fallbacks-advisory.d.ts +2 -3
  25. package/dist/gates/fallbacks-probe.d.ts +2 -2
  26. package/dist/gates/fallbacks-seeds.d.ts +1 -1
  27. package/dist/gates/fallbacks-structural.d.ts +1 -1
  28. package/dist/gates/goal-bridge.d.ts +6 -9
  29. package/dist/gates/role-persona.d.ts +2 -3
  30. package/dist/gates/skill-lint.d.ts +19 -2
  31. package/dist/gates/system-prompt.d.ts +7 -11
  32. package/dist/gates/tools.d.ts +1 -1
  33. package/dist/gates/workflow-ledger.d.ts +21 -28
  34. package/dist/gates/workflow-policy.d.ts +15 -19
  35. package/dist/gates/workflow-selection.d.ts +3 -3
  36. package/dist/index.js +215 -33
  37. package/dist/types.d.ts +4 -7
  38. package/harness-commands/iteration-drive.md +6 -6
  39. package/harness-commands/iteration-loop.md +7 -7
  40. package/harness-commands/iteration-start.md +8 -8
  41. package/harness-skills/mstar-coding-behavior/SKILL.md +3 -20
  42. package/harness-skills/mstar-dispatch-gates/SKILL.md +7 -13
  43. package/harness-skills/mstar-dispatch-gates/references/leaf-executor-checklist.md +1 -1
  44. package/harness-skills/mstar-harness-core/SKILL.md +9 -53
  45. package/harness-skills/mstar-host/references/zcode.md +1 -0
  46. package/harness-skills/mstar-iteration/SKILL.md +32 -318
  47. package/harness-skills/mstar-iteration/references/command-shared-invariants.md +1 -1
  48. package/harness-skills/mstar-iteration/references/phase-1-prepare.md +155 -0
  49. package/harness-skills/mstar-iteration/references/phase-2-worktree-lease.md +113 -3
  50. package/harness-skills/mstar-iteration/references/phase5-helper-discovery.md +1 -1
  51. package/harness-skills/mstar-roles/SKILL.md +14 -12
  52. package/harness-skills/mstar-roles/references/_shared/leaf-executor-core.md +5 -6
  53. package/harness-skills/mstar-roles/references/architect.md +1 -1
  54. package/harness-skills/mstar-roles/references/code-reviewer.md +11 -1
  55. package/harness-skills/mstar-roles/references/frontend-dev.md +1 -1
  56. package/harness-skills/mstar-roles/references/fullstack-dev-shared.md +1 -1
  57. package/harness-skills/mstar-roles/references/ops-engineer.md +1 -1
  58. package/harness-skills/mstar-roles/references/product-manager.md +1 -1
  59. package/harness-skills/mstar-roles/references/project-manager/dispatch-and-assignment.md +4 -0
  60. package/harness-skills/mstar-roles/references/project-manager.md +6 -4
  61. package/harness-skills/mstar-roles/references/prompt-engineer.md +1 -1
  62. package/harness-skills/mstar-roles/references/qa-engineer.md +1 -1
  63. package/harness-skills/mstar-roles/references/qc-specialist-shared.md +1 -1
  64. package/harness-skills/mstar-roles/references/writing-specialist.md +1 -1
  65. package/harness-skills/mstar-sdd/references/file-handoffs.md +40 -7
  66. package/harness-skills/mstar-sdd/references/implementer-continuation-prompt.md +9 -0
  67. package/harness-skills/mstar-sdd/references/implementer-prompt.md +9 -0
  68. package/harness-skills/mstar-sdd/references/task-reviewer-prompt.md +7 -0
  69. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1149,11 +1149,11 @@ import { dirname as dirname4, join as join7, resolve as resolve5, sep } from "no
1149
1149
  import { execFileSync as execFileSync2 } from "node:child_process";
1150
1150
  import { existsSync as existsSync7 } from "node:fs";
1151
1151
  import { isAbsolute as isAbsolute5, resolve as resolve8 } from "node:path";
1152
- import { execFileSync as execFileSync3 } from "node:child_process";
1152
+ import { execFileSync as execFileSync3, spawn } from "node:child_process";
1153
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, resolve as resolve9 } from "node:path";
1154
+ import { basename as basename4, dirname as dirname6, isAbsolute as isAbsolute6, join as join10, relative as relative3, resolve as resolve9 } from "node:path";
1155
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 relative4, resolve as resolve12, sep as sep4 } from "node:path";
1156
+ import { basename as basename6, isAbsolute as isAbsolute8, join as join13, relative as relative5, resolve as resolve12, sep as sep4 } from "node:path";
1157
1157
  import { existsSync as existsSync10 } from "node:fs";
1158
1158
  import { join as join14 } from "node:path";
1159
1159
  var SEVERITY_ORDER = ["critical", "high", "medium", "low", "nit"];
@@ -2467,6 +2467,25 @@ function assertSafePathComponent(value, what) {
2467
2467
  throw new Error(`${what} must be a single safe path component ([A-Za-z0-9._-]+; not "", ".", "..", or containing "/" or "\\") — got ${JSON.stringify(value)}`);
2468
2468
  }
2469
2469
  }
2470
+ function canonicalizeNearestExisting(path) {
2471
+ const abs = resolve7(path);
2472
+ let dir = abs;
2473
+ const tail = [];
2474
+ for (;; ) {
2475
+ if (existsSync6(dir)) {
2476
+ try {
2477
+ return join9(realpathSync2(dir), ...tail);
2478
+ } catch {
2479
+ return abs;
2480
+ }
2481
+ }
2482
+ const parent = dirname5(dir);
2483
+ if (parent === dir)
2484
+ return abs;
2485
+ tail.unshift(basename3(dir));
2486
+ dir = parent;
2487
+ }
2488
+ }
2470
2489
  function resolveSddDir(harnessDir, planId) {
2471
2490
  assertSafePathComponent(planId, "planId");
2472
2491
  const base = resolve7(harnessDir);
@@ -2626,6 +2645,16 @@ function l2PreDispatchCheck(input, opts = {}) {
2626
2645
  });
2627
2646
  return gate(violations);
2628
2647
  }
2648
+ function assertBranchAlignment(worktreePath, expectedBranch, opts = {}) {
2649
+ const violations = [];
2650
+ const probe = probeBranch(worktreePath, opts);
2651
+ if ("error" in probe) {
2652
+ violations.push(violation7("high", "worktree.branch-probe-failed", `cannot probe branch at "${worktreePath}": ${probe.error}`, "verify the path is a git worktree checkout on the expected branch (not detached)"));
2653
+ } else if (probe.branch !== expectedBranch) {
2654
+ violations.push(violation7("high", "worktree.branch-mismatch", `worktree "${worktreePath}" is on branch "${probe.branch}", expected "${expectedBranch}" (Assignment Working branch)`, `checkout ${expectedBranch} in that worktree`));
2655
+ }
2656
+ return gate(violations);
2657
+ }
2629
2658
  class SddScriptError extends Error {
2630
2659
  exitCode;
2631
2660
  constructor(message, exitCode) {
@@ -2763,6 +2792,16 @@ function taskBrief(planFile, taskN, outFile, opts = {}) {
2763
2792
  if (!planFile || !Number.isInteger(taskN) || taskN < 1) {
2764
2793
  throw new SddScriptError("usage: mstar sdd task-brief PLAN_FILE TASK_NUMBER [OUTFILE]", 2);
2765
2794
  }
2795
+ const bound = opts.context;
2796
+ const observedCwd = opts.cwd ?? process.cwd();
2797
+ if (bound) {
2798
+ const inputPlan = canonicalizeNearestExisting(resolve9(observedCwd, planFile));
2799
+ if (inputPlan !== canonicalizeNearestExisting(bound.planFile)) {
2800
+ throwGateFail([
2801
+ contextViolation("high", "sdd.context.plan-file-mismatch", `plan file "${planFile}" does not match the bound context plan file "${bound.planFile}" — ` + "bound mode extracts only the resolved context's plan; refused before any read or write")
2802
+ ]);
2803
+ }
2804
+ }
2766
2805
  let content;
2767
2806
  try {
2768
2807
  content = readFileSync7(planFile, "utf8");
@@ -2770,8 +2809,12 @@ function taskBrief(planFile, taskN, outFile, opts = {}) {
2770
2809
  throw new SddScriptError(`no such plan file: ${planFile}`, 2);
2771
2810
  }
2772
2811
  let out;
2812
+ let mkdirAfterGate = null;
2773
2813
  if (outFile) {
2774
- out = outFile;
2814
+ out = bound ? resolve9(observedCwd, outFile) : outFile;
2815
+ } else if (bound) {
2816
+ out = join10(bound.sddDir, `task-${taskN}-brief.md`);
2817
+ mkdirAfterGate = bound.sddDir;
2775
2818
  } else {
2776
2819
  const sddDir = opts.sddDir ?? process.env.SDD_DIR;
2777
2820
  if (!sddDir) {
@@ -2780,6 +2823,13 @@ function taskBrief(planFile, taskN, outFile, opts = {}) {
2780
2823
  mkdirSync6(sddDir, { recursive: true });
2781
2824
  out = join10(sddDir, `task-${taskN}-brief.md`);
2782
2825
  }
2826
+ if (bound) {
2827
+ const gate2 = checkSddAction(bound, { kind: "artifact", cwd: observedCwd, target: out });
2828
+ if (!gate2.ok)
2829
+ throwGateFail(gate2.violations);
2830
+ if (mkdirAfterGate !== null)
2831
+ mkdirSync6(mkdirAfterGate, { recursive: true });
2832
+ }
2783
2833
  const records = content.endsWith(`
2784
2834
  `) ? content.split(`
2785
2835
  `).slice(0, -1) : content.split(`
@@ -2804,7 +2854,98 @@ function taskBrief(planFile, taskN, outFile, opts = {}) {
2804
2854
  if (printed.length === 0) {
2805
2855
  throw new SddScriptError(`task ${taskN} not found in ${planFile} (no heading matching Task ${taskN})`, 3);
2806
2856
  }
2807
- return out;
2857
+ return bound ? resolve9(observedCwd, out) : out;
2858
+ }
2859
+ function isInside(child, ancestor) {
2860
+ const rel = relative3(ancestor, child);
2861
+ return rel === "" || !rel.startsWith("..") && !isAbsolute6(rel);
2862
+ }
2863
+ function canonicalDir(path) {
2864
+ try {
2865
+ return statSync4(path).isDirectory() ? realpathSync3(path) : null;
2866
+ } catch {
2867
+ return null;
2868
+ }
2869
+ }
2870
+ function contextViolation(severity, code, message, fix) {
2871
+ return { ok: false, severity, code, message, fix };
2872
+ }
2873
+ function throwGateFail(violations) {
2874
+ const detail = violations.map((v) => `${v.code}: ${v.message}${v.fix ? ` (fix: ${v.fix})` : ""}`).join(`
2875
+ `);
2876
+ throw new SddScriptError(`SDD execution context rejected:
2877
+ ${detail}`, 1);
2878
+ }
2879
+ function checkSddAction(context, action) {
2880
+ const violations = [];
2881
+ const add = (code, message, fix) => {
2882
+ violations.push(contextViolation("high", code, message, fix));
2883
+ };
2884
+ if (action.kind !== "source" && action.kind !== "artifact" && action.kind !== "launch") {
2885
+ add("sdd.context.kind-unknown", `unknown action kind ${JSON.stringify(action.kind)} — expected "source" | "artifact" | "launch"`);
2886
+ return { ok: false, violations };
2887
+ }
2888
+ if (typeof action.cwd !== "string" || action.cwd.trim() === "") {
2889
+ add("sdd.context.cwd-missing", "action.cwd (the observed invocation cwd) is required — never an Assignment echo");
2890
+ return { ok: false, violations };
2891
+ }
2892
+ const featureReal = canonicalDir(context.featureCwd);
2893
+ const canonicalSddDir = canonicalizeNearestExisting(context.sddDir);
2894
+ const canonicalPlanFile = canonicalizeNearestExisting(context.planFile);
2895
+ const cwdResolved = resolve9(action.cwd);
2896
+ const checkTarget = (baseDir, target, kind) => {
2897
+ if (featureReal === null)
2898
+ return;
2899
+ const targetAbs = resolve9(baseDir, target);
2900
+ const canonical = canonicalizeNearestExisting(targetAbs);
2901
+ if (!isInside(canonical, featureReal)) {
2902
+ const declaredPrefix = targetAbs === featureReal || targetAbs.startsWith(`${featureReal}/`);
2903
+ if (declaredPrefix) {
2904
+ add("sdd.context.target-symlink-escape", `${kind} target "${target}" canonicalizes to "${canonical}", outside the feature worktree — symlink escape refused before mutation`);
2905
+ } else {
2906
+ add(`sdd.context.${kind}-target-outside-feature`, `${kind} target "${target}" resolves to "${targetAbs}", outside the feature worktree "${featureReal}" — refused before mutation`);
2907
+ }
2908
+ }
2909
+ };
2910
+ if (action.kind === "source") {
2911
+ const cwdReal = canonicalDir(cwdResolved);
2912
+ if (cwdReal === null) {
2913
+ add("sdd.context.cwd-missing", `observed source cwd "${action.cwd}" does not exist or is not a directory`);
2914
+ return { ok: false, violations };
2915
+ }
2916
+ if (featureReal === null || !isInside(cwdReal, featureReal)) {
2917
+ add("sdd.context.source-cwd-outside-feature", `observed source cwd "${cwdReal}" is outside the feature worktree "${context.featureCwd}" — a declared-correct context does not make a wrong-checkout write safe (A3)`, `run the source action from inside ${context.featureCwd}`);
2918
+ return { ok: false, violations };
2919
+ }
2920
+ if (action.target !== undefined)
2921
+ checkTarget(cwdReal, action.target, "source");
2922
+ } else if (action.kind === "artifact") {
2923
+ if (typeof action.target !== "string" || action.target.trim() === "") {
2924
+ add("sdd.context.target-missing", "artifact checks require the destination target");
2925
+ return { ok: false, violations };
2926
+ }
2927
+ const targetAbs = resolve9(cwdResolved, action.target);
2928
+ const canonical = canonicalizeNearestExisting(targetAbs);
2929
+ if (!isInside(canonical, canonicalSddDir) && canonical !== canonicalPlanFile) {
2930
+ const rawSddDir = resolve9(context.sddDir);
2931
+ const declaredPrefix = targetAbs === rawSddDir || targetAbs.startsWith(`${rawSddDir}/`) || targetAbs === canonicalSddDir || targetAbs.startsWith(`${canonicalSddDir}/`) || targetAbs === canonicalPlanFile;
2932
+ if (declaredPrefix) {
2933
+ add("sdd.context.artifact-symlink-escape", `artifact target "${targetAbs}" canonicalizes to "${canonical}", outside the plan's control sddDir — symlink escape refused before write`);
2934
+ } else {
2935
+ add("sdd.context.artifact-outside-plan", `artifact target "${targetAbs}" is outside the plan's control sddDir "${context.sddDir}" and is not the declared planFile "${context.planFile}" — legitimate control artifact edits stay inside the plan's artifacts; arbitrary control source edits are not allowed (A3)`);
2936
+ }
2937
+ }
2938
+ } else {
2939
+ if (featureReal === null) {
2940
+ add("sdd.context.launch-cwd-missing", `feature worktree "${context.featureCwd}" does not exist or is not a directory — cannot bind the child's starting cwd`);
2941
+ } else {
2942
+ violations.push(...assertBranchAlignment(featureReal, context.workingBranch).violations);
2943
+ }
2944
+ if (action.target !== undefined && action.target.trim() !== "" && featureReal !== null) {
2945
+ checkTarget(featureReal, action.target, "launch");
2946
+ }
2947
+ }
2948
+ return { ok: violations.length === 0, violations };
2808
2949
  }
2809
2950
  function violation8(severity, code, message, fix) {
2810
2951
  return { ok: false, severity, code, message, fix };
@@ -3590,7 +3731,7 @@ function collectKnowledgeDocs(dir) {
3590
3731
  if (entry.isDirectory()) {
3591
3732
  stack.push(full);
3592
3733
  } else if (entry.name.endsWith(".md") && entry.name !== "README.md" && entry.name !== "index.md") {
3593
- docs.push(relative4(dir, full).split(sep4).join("/"));
3734
+ docs.push(relative5(dir, full).split(sep4).join("/"));
3594
3735
  }
3595
3736
  }
3596
3737
  }
@@ -3847,6 +3988,14 @@ function validateRoleMapping(rolesDir, options = {}) {
3847
3988
  return { ok: violations.length === 0, violations };
3848
3989
  }
3849
3990
  var LOAD_ORDER_HEADING_RE = /^#{1,6}\s+[^\r\n]*\b(?:load[\s-]*order|first\s+action)\b[^\r\n]*$/i;
3991
+ var HUB_BOOTSTRAP_ASSERTIONS = [
3992
+ { marker: "identity-first", why: "identity boundary before any skill list" },
3993
+ { marker: "skill presets", why: "Assignment Skill presets decision field" },
3994
+ { marker: "none", why: "explicit none => identity only, no optional topic preset" },
3995
+ { marker: "standard", why: "omitted on a substantive round => standard preset" },
3996
+ { marker: "role-owned", why: "role-owned methods / evidence obligations load regardless of preset" },
3997
+ { marker: "unknown preset", why: "unknown preset / missing identity => Needs Context / Blocked, never infer PM" }
3998
+ ];
3850
3999
  function extractLoadOrderSection(text) {
3851
4000
  const lines = text.split(/\r?\n/);
3852
4001
  let start = -1;
@@ -3880,11 +4029,22 @@ function lintLoadOrder(skillTexts) {
3880
4029
  continue;
3881
4030
  const section = extractLoadOrderSection(text);
3882
4031
  if (section === null) {
3883
- violations.push(violation12("medium", "roles.loadorder.section.missing", `skill "${name}" has no Load Order / First action section — every mstar-* topic skill must declare its first read (mstar-harness-core § 加载约定; mstar-roles § Load Order (Required))`, `add a "## Load Order" section naming mstar-harness-core as the first read`));
4032
+ violations.push(violation12("medium", "roles.loadorder.section.missing", `skill "${name}" has no Load Order / First action section — every mstar-* topic skill must declare its first read (mstar-harness-core § 加载契约; mstar-roles § Load Order = single load-selection authority)`, `add a "## Load Order" section: topics name mstar-harness-core first; mstar-roles declares the Skill presets decision matrix`));
4033
+ continue;
4034
+ }
4035
+ if (name === "mstar-roles") {
4036
+ const lower = section.toLowerCase();
4037
+ const missing = HUB_BOOTSTRAP_ASSERTIONS.filter((a) => !lower.includes(a.marker.toLowerCase()));
4038
+ if (missing.length > 0) {
4039
+ violations.push(violation12("medium", "roles.loadorder.hub.bootstrap.missing", `skill "${name}" Load Order section is missing the hub bootstrap decision matrix: ${missing.map((m) => `"${m.marker}" (${m.why})`).join("; ")} (mstar-roles § Load Order = single load-selection authority)`, "declare identity-first, the Skill presets none/standard decision, role-owned methods, and the unknown-preset / missing-identity refusal in the Load Order section"));
4040
+ }
4041
+ if (!section.includes("mstar-harness-core")) {
4042
+ violations.push(violation12("medium", "roles.loadorder.core.missing", `skill "${name}" Load Order section does not point at mstar-harness-core — the hub bootstrap is exempt from core-first, but core remains the lifecycle/authorization conflict authority and global entry whenever loaded`, "keep the conditional mstar-harness-core pointer (global entry / conflict authority) in the Load Order section"));
4043
+ }
3884
4044
  continue;
3885
4045
  }
3886
4046
  if (!section.includes("mstar-harness-core")) {
3887
- violations.push(violation12("medium", "roles.loadorder.core.missing", `skill "${name}" Load Order section does not declare mstar-harness-core as its first dependency (mstar-harness-core § 加载约定: 凡 mstar-*(name ≠ mstar-harness-core)假定读者已 Read 本 skill)`, "name mstar-harness-core first in the Load Order section"));
4047
+ violations.push(violation12("medium", "roles.loadorder.core.missing", `skill "${name}" Load Order section does not declare mstar-harness-core as its first dependency (mstar-harness-core § 加载契约: directly-invoked topics keep core as first dependency; the mstar-roles hub bootstrap is the only exception)`, "name mstar-harness-core first in the Load Order section"));
3888
4048
  }
3889
4049
  }
3890
4050
  return { ok: violations.length === 0, violations };
@@ -3920,6 +4080,17 @@ var FIVE_QUESTION_SECTIONS = [
3920
4080
  { key: "evidence", label: "Evidence", question: "what a correct result looks like (success criteria / evidence)" },
3921
4081
  { key: "references", label: "References", question: "additional resources to open when the main path is not enough" }
3922
4082
  ];
4083
+ function stripFrontmatter(text) {
4084
+ const lines = text.replace(/^\uFEFF/, "").split(/\r?\n/);
4085
+ if (lines.length === 0 || lines[0].trim() !== "---")
4086
+ return text;
4087
+ for (let i = 1;i < lines.length; i++) {
4088
+ if (lines[i].trim() === "---")
4089
+ return lines.slice(i + 1).join(`
4090
+ `);
4091
+ }
4092
+ return text;
4093
+ }
3923
4094
  var HEADING_RE = /^#{1,6}\s+[^\r\n]+$/;
3924
4095
  function collectHeadings(bodyText) {
3925
4096
  const headings = [];
@@ -3935,6 +4106,16 @@ function collectHeadings(bodyText) {
3935
4106
  }
3936
4107
  return headings;
3937
4108
  }
4109
+ function classifySkillLint(skillId) {
4110
+ const id = skillId ?? "";
4111
+ if (id === "mstar-harness-core")
4112
+ return { kind: "core", mode: null };
4113
+ if (id === "mstar-skill-authoring")
4114
+ return { kind: "authoring", mode: "authoring" };
4115
+ if (id.startsWith("mstar-"))
4116
+ return { kind: "runtime", mode: "runtime" };
4117
+ return { kind: "authoring", mode: "authoring" };
4118
+ }
3938
4119
  var RUNTIME_HEADING_ALIASES = {
3939
4120
  workflow: ["process", "playbook"],
3940
4121
  "decision-rules": [
@@ -4176,7 +4357,7 @@ import { basename as basename2, join as join5, resolve as resolve6 } from "node:
4176
4357
 
4177
4358
  // src/gates/workflow-selection.ts
4178
4359
  import { existsSync as existsSync5, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
4179
- import { dirname as dirname7, join as join3, relative as relative3 } from "node:path";
4360
+ import { dirname as dirname7, join as join3, relative as relative4 } from "node:path";
4180
4361
  var TERMINAL_STATUS_CACHE_MAX = 64;
4181
4362
  var terminalStatusCache = new Map;
4182
4363
  function terminalStatusOf(snapshotPath) {
@@ -4298,7 +4479,7 @@ function resolveReadWorkflow(harnessDir) {
4298
4479
  if (verdict === undefined || !verdict.terminal)
4299
4480
  continue;
4300
4481
  if (best === undefined || verdict.mtimeMs > best.mtimeMs) {
4301
- best = { workflowId: entry.name, dir: join3(relative3(harnessDir, workflowsDir), entry.name), mtimeMs: verdict.mtimeMs };
4482
+ best = { workflowId: entry.name, dir: join3(relative4(harnessDir, workflowsDir), entry.name), mtimeMs: verdict.mtimeMs };
4302
4483
  }
4303
4484
  }
4304
4485
  for (const cachedPath of terminalStatusCache.keys()) {
@@ -5923,14 +6104,14 @@ function agentDigestKey(agent, cwd) {
5923
6104
 
5924
6105
  // src/gates/status.ts
5925
6106
  import { existsSync as existsSync14, readdirSync as readdirSync7 } from "node:fs";
5926
- import { basename as basename5, join as join11, relative as relative5, resolve as resolve10 } from "node:path";
6107
+ import { basename as basename5, join as join11, relative as relative6, resolve as resolve10 } from "node:path";
5927
6108
  var LOGGER_NAME = "mstar/status-gate";
5928
6109
  function harnessDocKindOfTarget(harnessDir, targetPath) {
5929
6110
  const resolved = resolve10(targetPath);
5930
6111
  const name = basename5(resolved);
5931
6112
  if (name !== STATUS_FILE && name !== WORKFLOW_SNAPSHOT_FILE && name !== PROJECT_REGISTER_FILE)
5932
6113
  return null;
5933
- const rel = relative5(harnessDir, resolved);
6114
+ const rel = relative6(harnessDir, resolved);
5934
6115
  if (name === STATUS_FILE && rel === STATUS_FILE)
5935
6116
  return "status";
5936
6117
  let workflowDir;
@@ -5942,9 +6123,9 @@ function harnessDocKindOfTarget(harnessDir, targetPath) {
5942
6123
  workflowDir = join11(harnessDir, "workflows");
5943
6124
  projectDir = join11(harnessDir, "projects");
5944
6125
  }
5945
- if (name === WORKFLOW_SNAPSHOT_FILE && /^[^/]+\/snapshot\.json$/.test(relative5(workflowDir, resolved)))
6126
+ if (name === WORKFLOW_SNAPSHOT_FILE && /^[^/]+\/snapshot\.json$/.test(relative6(workflowDir, resolved)))
5946
6127
  return "snapshot";
5947
- if (name === PROJECT_REGISTER_FILE && /^[^/]+\/residuals\.json$/.test(relative5(projectDir, resolved)))
6128
+ if (name === PROJECT_REGISTER_FILE && /^[^/]+\/residuals\.json$/.test(relative6(projectDir, resolved)))
5948
6129
  return "register";
5949
6130
  return null;
5950
6131
  }
@@ -6093,17 +6274,6 @@ ${violations.map(formatViolation).join(`
6093
6274
  this.violations = violations;
6094
6275
  }
6095
6276
  }
6096
- function stripFrontmatter(text) {
6097
- const lines = text.replace(/^\uFEFF/, "").split(/\r?\n/);
6098
- if (lines.length === 0 || lines[0].trim() !== "---")
6099
- return text;
6100
- for (let i = 1;i < lines.length; i++) {
6101
- if (lines[i].trim() === "---")
6102
- return lines.slice(i + 1).join(`
6103
- `);
6104
- }
6105
- return text;
6106
- }
6107
6277
  var EPHEMERAL_CODES = {
6108
6278
  "task-artifact": "skill.ephemeral.task-artifact",
6109
6279
  "sdd-deeplink": "skill.ephemeral.sdd-deeplink"
@@ -6116,19 +6286,23 @@ function ephemeralViolation(citation) {
6116
6286
  message: `ephemeral citation \`${citation.match}\` on line ${citation.line} — durable skill text must reference in-repo artifacts only (knowledge conventions/skill-content-porting-discipline.md §3)`
6117
6287
  };
6118
6288
  }
6119
- function lintSkillDoc(doc) {
6289
+ function lintSkillDoc(doc, options = {}) {
6120
6290
  const violations = [];
6121
6291
  const frontmatter = lintSkillFrontmatter(doc);
6122
6292
  if (!frontmatter.ok)
6123
6293
  violations.push(...frontmatter.violations);
6124
- const body = lintFiveQuestion(stripFrontmatter(doc));
6125
- if (!body.ok)
6126
- violations.push(...body.violations);
6294
+ const profile = classifySkillLint(options.skillId);
6295
+ if (profile.mode !== null) {
6296
+ const body = lintFiveQuestion(stripFrontmatter(doc), profile.mode);
6297
+ if (!body.ok)
6298
+ violations.push(...body.violations);
6299
+ }
6127
6300
  violations.push(...findEphemeralCitations(doc).map(ephemeralViolation));
6128
6301
  return violations.length === 0 ? { ok: true, violations } : { ok: false, violations };
6129
6302
  }
6130
6303
  function lintSkillWrite(doc, options) {
6131
- const result = lintSkillDoc(doc);
6304
+ const skillId = basename7(dirname9(resolve13(options.target)));
6305
+ const result = lintSkillDoc(doc, { skillId });
6132
6306
  if (options.hard && !result.ok) {
6133
6307
  throw new SkillLintVetoError(options.target, result.violations);
6134
6308
  }
@@ -6176,7 +6350,7 @@ function gateSkillIntent(ctx, harnessDir, config, target) {
6176
6350
  });
6177
6351
  return;
6178
6352
  }
6179
- const result = lintSkillDoc(doc);
6353
+ const result = lintSkillDoc(doc, { skillId: basename7(dirname9(skillPath)) });
6180
6354
  if (result.ok)
6181
6355
  return;
6182
6356
  const hard = resolveSeamHard(harnessDir, config);
@@ -8368,9 +8542,17 @@ function packagedCommandsDir() {
8368
8542
  return;
8369
8543
  }
8370
8544
  }
8545
+ var FRONTMATTER_FIELD_RE = /^[ \t]*:[ \t]*(.+)$/;
8371
8546
  function commandFrontmatterField(frontmatter, label) {
8372
- const match = new RegExp(`^${label}[ \\t]*:[ \\t]*(.+)$`, "m").exec(frontmatter);
8373
- return match?.[1]?.trim();
8547
+ for (const line of frontmatter.split(`
8548
+ `)) {
8549
+ if (!line.startsWith(label))
8550
+ continue;
8551
+ const match = FRONTMATTER_FIELD_RE.exec(line.slice(label.length));
8552
+ if (match)
8553
+ return match[1].trim();
8554
+ }
8555
+ return;
8374
8556
  }
8375
8557
  function unquote2(value) {
8376
8558
  return value.length >= 2 && value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value;
package/dist/types.d.ts CHANGED
@@ -108,8 +108,7 @@ export interface HarnessPlanView {
108
108
  readonly doneAt: string | null;
109
109
  /**
110
110
  * The `status.json` plan row `metadata.iteration_refs` (array of iteration
111
- * ids the plan is registered under). ALWAYS-present array (plan
112
- * `20260813-panel-quick-fixes` Task 2): a missing/non-array value projects
111
+ * ids the plan is registered under). ALWAYS-present array: a missing/non-array value projects
113
112
  * to `[]` — the empty default, never an omitted field (lossless JSON).
114
113
  */
115
114
  readonly iterationRefs: string[];
@@ -204,8 +203,7 @@ export interface MstarHarnessState {
204
203
  * projected loose (`string`) like `HarnessPlanView.status`. ALWAYS-present
205
204
  * nullable scalar (lossless JSON, never omitted): missing/empty → `null`;
206
205
  * `null` on selection error (no snapshot read). Added for the slim
207
- * `mstar:engine-status` digest (plan `20260820-dsh-engine-status-slim`).
208
- */
206
+ * `mstar:engine-status` digest. */
209
207
  readonly workflowType: string | null;
210
208
  /**
211
209
  * The selected workflow snapshot's top-level lifecycle `status`
@@ -269,8 +267,7 @@ export interface MstarHarnessState {
269
267
  }
270
268
  /**
271
269
  * One agent-flow ledger event in the catalog view. Optional fields (dispatch/
272
- * settle + the W-B2 `workflow-*` kinds — plan `20260815-dsh-workflow-ledger`
273
- * Task 2) are OMITTED (never `undefined`-valued properties — `Session.append`
270
+ * settle + the W-B2 `workflow-*` kinds — plan ) are OMITTED (never `undefined`-valued properties — `Session.append`
274
271
  * rejects non-lossless JSON) using the `iterationViolationView` omit pattern.
275
272
  */
276
273
  export interface AgentFlowEventView {
@@ -292,7 +289,7 @@ export interface AgentFlowEventView {
292
289
  /** Settle duration in ms (settle events only, when recorded). */
293
290
  readonly durationMs?: number | null;
294
291
  /**
295
- * Settle rows only (plan `20260811-panel-f4-timeliness` Task 1): true when
292
+ * Settle rows only : true when
296
293
  * the settle carries the PAIRED dispatch's identity (`role`/`planId`/
297
294
  * `taskId` — same fields + semantics as the dispatch event) — the client
298
295
  * pairs exactly on that identity. ABSENT on unpaired (legacy) settles →
@@ -7,7 +7,7 @@ input: "[no args]"
7
7
 
8
8
  # Drive Iteration
9
9
 
10
- Drive the active Morning Star iteration forward. **Boot loads skills; this command sequences Phase 2 → 3 → 4 → 5.** Phase gate SSOT → **`mstar-iteration`** §2–§5;本 command 仅补充 **可选第三方 helper skill 发现**(Phase 5),不反向写入 `mstar-*`。
10
+ Drive the active Morning Star iteration forward. **Boot loads skills; this command sequences Phase 2 → 3 → 4 → 5.** Phase route + gate SSOT → **`mstar-iteration`** Phase route map + **Phase transition gates** table(§2 detail → `references/phase-2-worktree-lease.md`;§3 → `references/phase-3-iteration-close.md`;§4–§5 → `references/phase-4-5-pr-delivery.md`);本 command 仅补充 **可选第三方 helper skill 发现**(Phase 5),不反向写入 `mstar-*`。
11
11
 
12
12
  ## Phase flow(禁止跳步)
13
13
 
@@ -21,25 +21,25 @@ Phase 2–5 共享内容(PM invariants、assignment preflight、session todos
21
21
 
22
22
  ## Boot
23
23
 
24
- 按 **`mstar-iteration`** Load order 加载(`mstar-harness-core` → `mstar-roles` → `references/project-manager.md` → `mstar-iteration` § Phase 2–5 + `command-shared-invariants.md` → `mstar-compound` → `mstar-dispatch-gates` + host reference → **`mstar-sdd`**(first implement dispatch 前)→ `mstar-review-qc`(first QC 前)→ `mstar-artifacts` / `mstar-conventions` / `mstar-branch-worktree` → **`mstar-iteration/references/phase-2-worktree-lease.md`**)。完整 load list → **`mstar-roles`**。
24
+ 按 **`mstar-iteration`** Load order 加载(`mstar-harness-core` → `mstar-roles` → `references/project-manager.md` → `mstar-iteration`(按当前 Phase 查 route map,只加载一行 detail)+ `command-shared-invariants.md` → `mstar-compound` → `mstar-dispatch-gates` + host reference → **`mstar-sdd`**(first implement dispatch 前)→ `mstar-review-qc`(first QC 前)→ `mstar-artifacts` / `mstar-conventions` / `mstar-branch-worktree` → **`mstar-iteration/references/phase-2-worktree-lease.md`**)。完整 load list → **`mstar-roles`**。
25
25
 
26
26
  ## Phase 2: Autonomous Execute
27
27
 
28
- Execute **`mstar-iteration` § Phase 2** exactly(§2.0 五道闸 → §2.1 session todos → §2.2 backlog → §2.3 integration branch + control worktree → §2.4 per-plan loop(lease-gated;SDD per-task;QC tri N=3 + QA;serial merge)→ §2.5 dispatch-first → §2.6 push 纪律)。全部 plan `Done` → **STOP** → 打印 `## Phase 3: iteration-close`。
28
+ Execute **`mstar-iteration/references/phase-2-worktree-lease.md`** §2.0–§2.5 exactly(§2.0 五道闸 → §2.1 session todos → §2.2 backlog → §2.3 integration branch + control worktree → §2.4 per-plan loop(lease-gated;SDD per-task;QC tri N=3 + QA;serial merge)→ §2.5 dispatch-first;§2.6 push 纪律 → main skill `## 2.6`)。全部 plan `Done` → **STOP** → 打印 `## Phase 3: iteration-close`。
29
29
 
30
30
  **Assignment preflight**:每次 implement/QC/QA 派发前按 **`mstar-iteration/references/command-shared-invariants.md`** 执行。
31
31
 
32
32
  ## Phase 3: iteration-close
33
33
 
34
- 当 **every** plan 为 `Done`:**STOP** per-plan loop → 打印 **`## Phase 3: iteration-close`** → execute **`mstar-iteration` § Phase 3**(→ **`references/phase-3-iteration-close.md`** §3.0→§3.5;§3.1 entry checklist HARD GATE;§3.2 compound + package promotion;§3.4 `status: completed` + `end_date`)→ §3.5 exit 全 `[x]` 后打印 **`## Phase 4: Create PR`**。
34
+ 当 **every** plan 为 `Done`:**STOP** per-plan loop → 打印 **`## Phase 3: iteration-close`** → execute **`mstar-iteration/references/phase-3-iteration-close.md`** §3.0→§3.5(§3.1 entry checklist HARD GATE;§3.2 compound + package promotion;§3.4 `status: completed` + `end_date`)→ §3.5 exit 全 `[x]` 后打印 **`## Phase 4: Create PR`**。
35
35
 
36
36
  ## Phase 4: Create PR
37
37
 
38
- Execute **`mstar-iteration` § Phase 4**(→ **`references/phase-4-5-pr-delivery.md`**):打印 `## Phase 4: Create PR` → resolve `metadata.target_branch`(缺失 → **STOP**,never default `main`/`master`)→ 创建 PR `spec_integration_branch` → `target_branch` → 记录 PR URL + number → 勾掉 `phase-4-create-pr` → **Immediately** 打印 **`## Phase 5: PR merge-ready`**(**禁止**在此停止或汇报 Done)。
38
+ Execute **`mstar-iteration/references/phase-4-5-pr-delivery.md`** §4:打印 `## Phase 4: Create PR` → resolve `metadata.target_branch`(缺失 → **STOP**,never default `main`/`master`)→ 创建 PR `spec_integration_branch` → `target_branch` → 记录 PR URL + number → 勾掉 `phase-4-create-pr` → **Immediately** 打印 **`## Phase 5: PR merge-ready`**(**禁止**在此停止或汇报 Done)。
39
39
 
40
40
  ## Phase 5: PR merge-ready(babysit loop)
41
41
 
42
- Execute **`mstar-iteration` § Phase 5**(→ **`references/phase-4-5-pr-delivery.md`** §5.0–§5.2;**§5.1a push cadence HARD**)。**§5.5 exit checklist 全 `[x]` = 本 command Done.**
42
+ Execute **`mstar-iteration/references/phase-4-5-pr-delivery.md`** §5.0–§5.2(**§5.1a push cadence HARD**)。**§5.5 exit checklist 全 `[x]` = 本 command Done.**
43
43
 
44
44
  本 command **叠加**可选 helper skill 发现(**non-`mstar-*`**;不写入 `mstar-*` load order)→ **`mstar-iteration/references/phase5-helper-discovery.md`**(babysit / `*-babysit` / greploop / fallback 路径清单;first readable `SKILL.md` wins)。Loop + review fix hygiene + exit checklist → §5.1–§5.2(同上 reference)。
45
45
 
@@ -16,7 +16,7 @@ Run a **full** Morning Star iteration with minimal human intervention. **Done =
16
16
  | `iteration-drive` | Phase 2→5 re-entry / resume on an already locked iteration |
17
17
  | **`iteration-loop`** | Phase 1→5 end-to-end; **autonomous** direction lock |
18
18
 
19
- Phase gate SSOT → **`mstar-iteration`** §1–§5. This command is a **consumer**; it does not redefine skill semantics.
19
+ Phase route + gate SSOT → **`mstar-iteration`** **Phase route map** + **Phase transition gates** table. This command is a **consumer**; it does not redefine skill semantics.
20
20
 
21
21
  ## Args(最多 2 个)
22
22
 
@@ -29,7 +29,7 @@ Phase gate SSOT → **`mstar-iteration`** §1–§5. This command is a **consume
29
29
  | `direction` | Iteration direction / feedback constraint (free text) | Code-first research → **auto-lock recommended** |
30
30
  | `scale` | `S` \| `M` \| `L` \| `XL` | **`M`** |
31
31
 
32
- **Scale budget**(写入 compass;约束 **业务** plan 数量)→ **`mstar-iteration`** §1.2 + `references/autonomous-direction-lock.md`:
32
+ **Scale budget**(写入 compass;约束 **业务** plan 数量)→ **`mstar-iteration/references/phase-1-prepare.md`** §1.2 + `references/autonomous-direction-lock.md`:
33
33
 
34
34
  - **S** → 1 business plan
35
35
  - **M** → 2–3 business plans
@@ -52,7 +52,7 @@ Execute **`mstar-iteration` §2.6**(Continuous execution SSOT)+ **`mstar-ite
52
52
 
53
53
  ## Boot
54
54
 
55
- 按 **`mstar-iteration`** Load order 加载(`mstar-harness-core` → `mstar-roles` → `references/project-manager.md` → `mstar-iteration` § Phase 1–5 + `command-shared-invariants.md` → `mstar-dispatch-gates` → `mstar-phase-gates` → `mstar-conventions` / `mstar-artifacts` → `mstar-host` → `mstar-compound`(Phase 3 前)→ **`mstar-sdd`**(first implement 前)→ `mstar-review-qc`(first QC 前)→ `mstar-branch-worktree` → **`mstar-iteration/references/phase-2-worktree-lease.md`**)。完整 load list → **`mstar-roles`**。
55
+ 按 **`mstar-iteration`** Load order 加载(`mstar-harness-core` → `mstar-roles` → `references/project-manager.md` → `mstar-iteration`(按当前 Phase 查 route map,只加载一行 detail)+ `command-shared-invariants.md` → `mstar-dispatch-gates` → `mstar-phase-gates` → `mstar-conventions` / `mstar-artifacts` → `mstar-host` → `mstar-compound`(Phase 3 前)→ **`mstar-sdd`**(first implement 前)→ `mstar-review-qc`(first QC 前)→ `mstar-branch-worktree` → **`mstar-iteration/references/phase-2-worktree-lease.md`**)。完整 load list → **`mstar-roles`**。
56
56
 
57
57
  **Session todos(loop 专属;Phase 2–5 共享 rows → `command-shared-invariants.md`)**:
58
58
 
@@ -62,7 +62,7 @@ Execute **`mstar-iteration` §2.6**(Continuous execution SSOT)+ **`mstar-ite
62
62
 
63
63
  ## Phase 1: Autonomous start
64
64
 
65
- Execute **`mstar-iteration` § Phase 1**(**autonomous** direction lock + scale budget + branch resolve SSOT → `references/autonomous-direction-lock.md`):
65
+ Execute **`mstar-iteration/references/phase-1-prepare.md`**(§1.1–§1.6;**autonomous** direction lock + scale budget + branch resolve SSOT → `references/autonomous-direction-lock.md`):
66
66
 
67
67
  ### 1–4. Research → Explore → Lock → Write
68
68
 
@@ -70,7 +70,7 @@ Survey structured harness dirs(`{HARNESS_DIR}/status.json`、`{ITERATION_DIR}/
70
70
 
71
71
  ### 5. Review & Edit Chain(HARD GATE)
72
72
 
73
- Execute **`mstar-iteration` §1.6**:`product-manager` → `architect` → `writing-specialist` 顺序 invoke(**禁止** `{KNOWLEDGE_DIR}/` 新增;corpus hygiene)→ PM lock。**Assignment preflight** per **`command-shared-invariants.md`**。
73
+ Execute **`mstar-iteration/references/phase-1-prepare.md` §1.6**:`product-manager` → `architect` → `writing-specialist` 顺序 invoke(**禁止** `{KNOWLEDGE_DIR}/` 新增;corpus hygiene)→ PM lock。**Assignment preflight** per **`command-shared-invariants.md`**。
74
74
 
75
75
  **Pre-commit checklist**(print before §6;all `[x]`):
76
76
 
@@ -84,7 +84,7 @@ Execute **`mstar-iteration` §1.6**:`product-manager` → `architect` → `wri
84
84
 
85
85
  ### 6. Integration Branch
86
86
 
87
- Per **`mstar-iteration` §2.3**(create from `iteration_base_branch`;register branch fields;commit docs;push)。**STOP** if base/target missing。**Immediately** print `## Phase 2: Autonomous Execute` → continue(勾掉 `phase-1-autonomous-start`)。
87
+ Per **`mstar-iteration/references/phase-2-worktree-lease.md` §2.3**(create from `iteration_base_branch`;register branch fields;commit docs;push)。**STOP** if base/target missing。**Immediately** print `## Phase 2: Autonomous Execute` → continue(勾掉 `phase-1-autonomous-start`)。
88
88
 
89
89
  ---
90
90
 
@@ -92,7 +92,7 @@ Per **`mstar-iteration` §2.3**(create from `iteration_base_branch`;register
92
92
 
93
93
  Delegate to **`iteration-drive`**(Phase 2 → §2、Phase 3 → §3 + `references/phase-3-iteration-close.md`、Phase 4/5 → §4–§5 + `references/phase-4-5-pr-delivery.md`、Phase 5 helper discovery → `phase5-helper-discovery.md`)。**Assignment preflight** per **`command-shared-invariants.md`**。
94
94
 
95
- **Loop 特有**:Phase 5 push cadence(HARD)→ **`mstar-iteration` §5.1a**;exit checklist → §5.2(`references/phase-4-5-pr-delivery.md`)。
95
+ **Loop 特有**:Phase 5 push cadence(HARD)→ **`mstar-iteration/references/phase-4-5-pr-delivery.md`** §5.1a;exit checklist → §5.2(同 reference)。
96
96
 
97
97
  **Then** report: iteration id, locked direction + scale, plans completed, compound summary, PR link, merge-ready evidence。
98
98
 
@@ -30,7 +30,7 @@ Start a new Morning Star harness iteration. **Phase 1 is not complete until the
30
30
  |-----------------|------------------------|
31
31
  | 自己 Edit compass/plans/specs 冒充 product-manager / architect / writing-specialist 的审查编辑 | §5.1 → §5.2 → §5.3 **顺序**各 **1 次 invoke**;上一角色返回后再派发下一角色 |
32
32
  | 只写 `## Assignment` 或 checklist 就声称 review chain 完成 | **几条角色 ⇒ 几条 invoke**;零 invoke = `dispatch incomplete`(`mstar-dispatch-gates`) |
33
- | §5 完成前 commit / 创建 integration 分支 | 5.4 PM lock 在 subagent 返回且磁盘产物已修订之后(`mstar-iteration` §1.6) |
33
+ | §5 完成前 commit / 创建 integration 分支 | 5.4 PM lock 在 subagent 返回且磁盘产物已修订之后(`mstar-iteration/references/phase-1-prepare.md` §1.6) |
34
34
 
35
35
  派发细则 → **`mstar-dispatch-gates`**(specialist review-and-edit dispatch)+ **`mstar-host`**(宿主 invoke 能力)。**不得**在 PM 线程加载其他 role reference 代劳。
36
36
 
@@ -49,7 +49,7 @@ Start a new Morning Star harness iteration. **Phase 1 is not complete until the
49
49
 
50
50
  ## 0. Boot
51
51
 
52
- 按 **`mstar-iteration`** Load order 加载(`mstar-harness-core` → `mstar-roles` → `references/project-manager.md` → `mstar-iteration` § Phase 1 + `mstar-phase-gates` + `mstar-dispatch-gates` + `mstar-conventions/artifacts` + `mstar-host` → active host reference)。Cursor Plan mode 另读 **`cursor-plan-mode-bridge.md`**(`mstar-iteration` Phase 1 in Plan mode)。完整 load list → **`mstar-roles`**。
52
+ 按 **`mstar-iteration`** Load order 加载(`mstar-harness-core` → `mstar-roles` → `references/project-manager.md` → `mstar-iteration`(route map:start → **`references/phase-1-prepare.md`**)+ `mstar-phase-gates` + `mstar-dispatch-gates` + `mstar-conventions/artifacts` + `mstar-host` → active host reference)。Cursor Plan mode 另读 **`cursor-plan-mode-bridge.md`**(`mstar-iteration` Phase 1 in Plan mode)。完整 load list → **`mstar-roles`**。
53
53
 
54
54
  **若 Cursor Plan mode 活跃 → 进入 §P;否则继续 §1。**
55
55
 
@@ -76,17 +76,17 @@ Scope **2–4** candidates targeting **product completeness**(default to defer
76
76
 
77
77
  > **非 Plan 路径**。Cursor Plan mode 用 §P feedback loop + deferred grill(主路径不是 grill)。
78
78
 
79
- **Direction lock mode: `interactive`**(`mstar-iteration` §1.2 默认;本命令不使用 `autonomous`)。This command bundles a **non-`mstar-*`** skill at `skills/grill-me/SKILL.md` — **only this command step** references it.
79
+ **Direction lock mode: `interactive`**(`mstar-iteration/references/phase-1-prepare.md` §1.2 默认;本命令不使用 `autonomous`)。This command bundles a **non-`mstar-*`** skill at `skills/grill-me/SKILL.md` — **only this command step** references it.
80
80
 
81
- **Before this step:** Read `skills/grill-me/SKILL.md`. Run **grill-me** to stress-test candidate directions with the user: walk through trade-offs, converge on a **single iteration direction** with shared understanding, document locked direction + success criteria + non-goals。**If `direction` arg given** — seed grill-me with it (still interactive; the hint does **not** skip grill-me)。Confirm delivery branch policy(`iteration_base_branch` / `target_branch`)per **`mstar-iteration` §1.2** — **Do not default to `main`/`master` just because those names exist.**
81
+ **Before this step:** Read `skills/grill-me/SKILL.md`. Run **grill-me** to stress-test candidate directions with the user: walk through trade-offs, converge on a **single iteration direction** with shared understanding, document locked direction + success criteria + non-goals。**If `direction` arg given** — seed grill-me with it (still interactive; the hint does **not** skip grill-me)。Confirm delivery branch policy(`iteration_base_branch` / `target_branch`)per **`mstar-iteration/references/phase-1-prepare.md` §1.2** — **Do not default to `main`/`master` just because those names exist.**
82
82
 
83
83
  ## 4. Write Compass & Plans
84
84
 
85
- Produce harness artifacts per **`mstar-iteration` §1.3–§1.5**(template: `mstar-iteration/references/iteration-compass-template.md`):compass(frontmatter **must** include `iteration_base_branch`、`target_branch`、`status: active`)、plans、`status.json` 登记(§1.5)、`{ITERATION_DIR}/README.md` 索引(一行 = 一次迭代)、package dirs(`{ITERATION_DIR}/<iteration-id>/{guides,specs}/`)。
85
+ Produce harness artifacts per **`mstar-iteration/references/phase-1-prepare.md` §1.3–§1.5**(template: `mstar-iteration/references/iteration-compass-template.md`):compass(frontmatter **must** include `iteration_base_branch`、`target_branch`、`status: active`)、plans、`status.json` 登记(§1.5)、`{ITERATION_DIR}/README.md` 索引(一行 = 一次迭代)、package dirs(`{ITERATION_DIR}/<iteration-id>/{guides,specs}/`)。
86
86
 
87
87
  ## 5. Review & Edit Chain(HARD GATE — do not commit before this)
88
88
 
89
- Execute **`mstar-iteration` §1.6**(SSOT):顺序 `product-manager` → `architect` → `writing-specialist` → PM lock(**禁止**并行三 roles;OpenCode plain role id — `mstar-host/references/opencode.md`);**禁止** `{KNOWLEDGE_DIR}/` 新增;writing-specialist corpus hygiene(`iteration-artifact-boundaries.md` + `iteration-corpus-hygiene.md`)。Tool rule → **`mstar-dispatch-gates`** specialist review-and-edit(每 role 1 invoke,等磁盘修订返回)。Exception: user explicitly waives subagent dispatch ("PM-only review").
89
+ Execute **`mstar-iteration/references/phase-1-prepare.md` §1.6**(SSOT):顺序 `product-manager` → `architect` → `writing-specialist` → PM lock(**禁止**并行三 roles;OpenCode plain role id — `mstar-host/references/opencode.md`);**禁止** `{KNOWLEDGE_DIR}/` 新增;writing-specialist corpus hygiene(`iteration-artifact-boundaries.md` + `iteration-corpus-hygiene.md`)。Tool rule → **`mstar-dispatch-gates`** specialist review-and-edit(每 role 1 invoke,等磁盘修订返回)。Exception: user explicitly waives subagent dispatch ("PM-only review").
90
90
 
91
91
  **Assignment preflight**:每次 invoke 前按 **`mstar-iteration/references/command-shared-invariants.md`** 执行(warn-only + `enforcement: hard` fail-fast;bin 缺失静默跳过)。
92
92
 
@@ -109,13 +109,13 @@ PM must print this block before §6; all `[ ]` must be `[x]`:
109
109
 
110
110
  ## 6. Integration Branch
111
111
 
112
- Per **`mstar-iteration` §2.3**:create `spec_integration_branch` from `iteration_base_branch`(`git fetch` → `git checkout -b <spec_integration_branch> <iteration_base_branch>`);register `iteration_base_branch` / `spec_integration_branch` / `target_branch` in compass frontmatter **and** `status.json` metadata;commit docs;push。**STOP** if `iteration_base_branch` / `target_branch` missing — never default `main`/`master`.
112
+ Per **`mstar-iteration/references/phase-2-worktree-lease.md` §2.3**:create `spec_integration_branch` from `iteration_base_branch`(`git fetch` → `git checkout -b <spec_integration_branch> <iteration_base_branch>`);register `iteration_base_branch` / `spec_integration_branch` / `target_branch` in compass frontmatter **and** `status.json` metadata;commit docs;push。**STOP** if `iteration_base_branch` / `target_branch` missing — never default `main`/`master`.
113
113
 
114
114
  ---
115
115
 
116
116
  ## 7. Phase 2–5(auto-continue)
117
117
 
118
- **`pause` arg → command ends here**(Phase 1 locked + integration pushed;run `/iteration-drive` later)。**Default(no `pause`)→ auto-continue**:execute **`iteration-drive`**(Phase 2 → **`mstar-iteration` §2**;Phase 3 → §3 + `references/phase-3-iteration-close.md`;Phase 4/5 → §4–§5 + `references/phase-4-5-pr-delivery.md`;Phase 5 helper discovery → `phase5-helper-discovery.md`)。Shared invariants / preflight / STOP → **`mstar-iteration/references/command-shared-invariants.md`**。
118
+ **`pause` arg → command ends here**(Phase 1 locked + integration pushed;run `/iteration-drive` later)。**Default(no `pause`)→ auto-continue**:execute **`iteration-drive`**(Phase 2 → **`mstar-iteration/references/phase-2-worktree-lease.md`**;Phase 3 → `references/phase-3-iteration-close.md`;Phase 4/5 → `references/phase-4-5-pr-delivery.md`;Phase 5 helper discovery → `phase5-helper-discovery.md`)。Shared invariants / preflight / STOP → **`mstar-iteration/references/command-shared-invariants.md`**。
119
119
 
120
120
  **Done = Phase 5 §5.5 exit checklist 全 `[x]`**(同 `iteration-drive`)。**Then** report: iteration id, direction lock summary, plans completed, compound summary, PR link, merge-ready evidence(CI snapshot + review resolution + Greptile if applicable)。
121
121