dsh-gate-agent 0.1.5 → 0.1.7

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/lib/index.js CHANGED
@@ -82,7 +82,7 @@ notePaths \u662F [{path,class,lifecycle}] \u6570\u7EC4\uFF1Bpath \u63A5\u53D7 .a
82
82
  \u7ED9 worker \u5DE5\u4F5C\u9879\u3001Note\u3001\u56FA\u5B9A\u70B9\u548C\u8BC4\u5BA1\u65B9\u6CD5\uFF1B\u4E0D\u8981\u5728 review worker prompt \u4E2D\u9644\u5E26\u9879\u76EE\u73AF\u5883\u9A8C\u8BC1\uFF08package.json\u3001Node \u7248\u672C\u3001git \u72B6\u6001\u3001\u6587\u4EF6\u5B58\u5728\u6027\u3001\u521D\u59CB\u5316 smoke \u7ED3\u679C\uFF09\u3002
83
83
  \u5B8C\u6210\u540E\u8C03 gate_record({node:'plan-review',findings,reviewAxes,workerSessionIds,requiresDiscussion})\u3002
84
84
  reviewAxes \u5FC5\u987B\u5305\u542B standards\u3001spec\u3001architecture \u4E09\u8F74\u3002
85
- \u9700\u8981\u7528\u6237\u51B3\u5B9A\uFF1A\u8FDB\u5165 blocked\uFF0C\u7B49\u5F85 /gate-resume\uFF1B\u4ECD\u6709 findings\uFF1A\u5148 gate_record \u672C\u8F6E plan-review\uFF0C\u786E\u8BA4 node \u5DF2\u53D8\u4E3A plan-revise\uFF0C\u518D\u590D\u7528\u5DF2\u52A0\u8F7D\u7684 gate-planning\uFF0C\u53EA\u5E26 findings \u548C Note \u8DEF\u5F84\u6D3E revise\uFF0C\u518D review\u3002
85
+ \u9700\u8981\u7528\u6237\u51B3\u5B9A\uFF1A\u8FDB\u5165 blocked\uFF0C\u7B49\u5F85 /gate-resume\uFF1B\u4ECD\u6709 findings\uFF1A\u5148 gate_record \u672C\u8F6E plan-review\uFF0Cgate \u4F1A\u56DE\u5230 plan\uFF1B\u4FEE\u8BA2\u5B8C\u6210\u540E\u8BB0\u5F55 plan\uFF0C\u518D review\u3002
86
86
 
87
87
  ## Step 3 \u2014 \u56DE\u5230 Discuss
88
88
  review \u4E3A\u7A7A\u65F6\u56DE\u5230 discuss\uFF0CplanReady=true\u3002
@@ -97,34 +97,20 @@ worker \u4E0D\u52A0\u8F7D gate \u6280\u80FD\u3002
97
97
 
98
98
  ## Step 2 \u2014 Implementation Review
99
99
  \u4E3B agent \u9996\u6B21\u8FDB\u5165 code-review \u65F6\u52A0\u8F7D\u6280\u80FD gate-code-review\uFF1B\u82E5\u672C\u4F1A\u8BDD\u5DF2\u52A0\u8F7D\u4E14\u5185\u5BB9\u4ECD\u5728\u4E0A\u6587\uFF0C\u540E\u7EED review \u8F6E\u6B21\u76F4\u63A5\u590D\u7528\uFF0C\u4E0D\u8981\u91CD\u590D\u8C03\u7528 skill\u3002\u8BFB\u53D6\u8BE5\u6280\u80FD\u7684 assets/worker-briefs/gate-implement-review.md \u5199 review \u4EFB\u52A1\uFF0C\u6309\u6539\u52A8\u89C4\u6A21\u81EA\u884C\u51B3\u5B9A\u6D3E\u4E00\u4E2A\u6216\u591A\u4E2A\u53EA\u8BFB review worker\uFF0C\u8986\u76D6 Standards \u4E0E Spec \u4E24\u8F74\u3002
100
- \u5B8C\u6210\u540E\u8C03 gate_record({node:'code-review', findings, reviewAxes, workerSessionIds})\uFF1B\u6709 findings \u65F6\u5148\u8BB0\u5F55\uFF0C\u786E\u8BA4 node \u5DF2\u53D8\u4E3A implement-revise\uFF0C\u518D\u6D3E revise worker\u3002
100
+ \u5B8C\u6210\u540E\u8C03 gate_record({node:'code-review', findings, reviewAxes, workerSessionIds})\uFF1B\u6709 findings \u65F6\u5148\u8BB0\u5F55\uFF0Cgate \u4F1A\u56DE\u5230 implement\uFF1B\u4FEE\u8BA2\u5B8C\u6210\u540E\u8BB0\u5F55 implement\uFF0C\u518D review\u3002
101
101
  \u5BA1\u67E5\u8981\u6C42\u6EE1\u8DB3\u540E\u7EE7\u7EED Step 3\uFF0C\u65E0\u9700\u518D\u6B21\u6388\u6743\u3002
102
102
  \u5B9E\u73B0\u4E2D\u53D1\u73B0\u8303\u56F4\u5916\u95EE\u9898\u3001\u5408\u540C\u53D8\u5316\u6216\u9700\u8981\u91CD\u65B0\u8BA8\u8BBA\u65F6\uFF0Cworker \u505C\u6B62\u5E76\u8FD4\u56DE receipt\uFF1B\u4E3B agent \u5411\u7528\u6237\u8BF4\u660E\uFF0C\u4F7F\u7528 gate_record \u7684 requiresDiscussion \u6216\u63D0\u793A\u7528\u6237\u6267\u884C /gate-return-discuss\u3002\u4E0D\u8981\u505C\u5728 implement \u91CC\u7EE7\u7EED\u6269\u5927\u8303\u56F4\u3002
103
103
 
104
104
  ## Step 3 \u2014 Verify
105
105
  \u4E3B agent \u9996\u6B21\u8FDB\u5165 verify \u65F6\u52A0\u8F7D\u6280\u80FD gate-verify\uFF1B\u82E5\u672C\u4F1A\u8BDD\u5DF2\u52A0\u8F7D\u4E14\u5185\u5BB9\u4ECD\u5728\u4E0A\u6587\uFF0C\u76F4\u63A5\u590D\u7528\uFF0C\u4E0D\u8981\u91CD\u590D\u8C03\u7528 skill\u3002\u8BFB\u53D6\u8BE5\u6280\u80FD\u7684 assets/worker-briefs/gate-verify.md \u5199 verify \u4EFB\u52A1\uFF0C\u6D3E verify worker \u5B8C\u6210\u6700\u7EC8\u9A8C\u6536\u3002
106
106
  \u5B8C\u6210\u540E\u8C03 gate_record({node:'verify', verification, workerSessionIds})\uFF1Bverification.toolResults \u5FC5\u987B\u662F verify worker session log \u4E2D\u771F\u5B9E tool/result \u7684 call_... id\uFF0Cevidence \u662F workspace \u5185\u7684\u666E\u901A\u6587\u4EF6\u3002
107
- \u53EA\u6709\u6700\u7EC8 PASS \u624D\u5B8C\u6210\u4EA4\u4ED8\uFF1BFAIL \u56DE\u5230 implement-revise\u3002
107
+ \u53EA\u6709\u6700\u7EC8 PASS \u624D\u5B8C\u6210\u4EA4\u4ED8\uFF1BFAIL \u56DE\u5230 implement\u3002
108
108
  \u72B6\u6001\u66F4\u65B0\u9075\u5FAA\u9879\u76EE\u767B\u8BB0\u7684\u5DE5\u4F5C\u9879\u4E0E\u51B3\u7B56\u8BB0\u5F55\u751F\u547D\u5468\u671F\u3002
109
109
 
110
110
  ## Step 4 \u2014 Note lifecycle
111
111
  Verify PASS \u540E\u8FDB\u5165 note-lifecycle\uFF0C\u4E0D\u5F97\u76F4\u63A5 complete\u3002
112
112
  \u4E3B agent \u8C03 gate_note_finalize\uFF0C\u518D\u8C03 gate_note_verify\uFF1B\u901A\u8FC7\u540E gate_record({node:'note-lifecycle'})\u3002
113
113
  mechanical \u5DE5\u4F5C\u9879\u81EA\u52A8\u8DF3\u8FC7\uFF1B\u8DE8\u4F1A\u8BDD journal \u53EA\u62A5\u544A\u4E0D\u6062\u590D\uFF1Barchived manifest \u53EA\u7531\u7528\u6237\u6267\u884C /gate-note-seal\u3002note-lifecycle \u5B8C\u6210\u540E\u5EFA\u8BAE\u63D0\u4EA4\u672C\u6B21\u5B9E\u73B0\u4E0E Note\uFF1Bgate \u4E0D\u81EA\u52A8\u6267\u884C git add/commit\u3002`;
114
- var FIX_BUG_ORCHESTRATION = `## /gate-fix-bug \u7F16\u6392
115
- \u4E3B agent \u8BFB\u53D6 gate-fix-bug\uFF1B\u4E3B agent \u53EA\u6C47\u603B\uFF0C\u4E0D\u81EA\u884C\u4FEE\u590D\u3002
116
-
117
- ## Step 1 \u2014 Fix
118
- \u4E3B agent \u9996\u6B21\u8FDB\u5165 fix-bug \u65F6\u8BFB\u53D6/\u52A0\u8F7D gate-fix-bug\uFF1B\u5DF2\u52A0\u8F7D\u5219\u590D\u7528\uFF0C\u4E0D\u8981\u91CD\u590D\u8C03\u7528 skill\u3002\u8BFB\u53D6 gate-fix-bug \u6280\u80FD\u7684 assets/worker-briefs/gate-fix-bug.md\uFF0C\u6D3E fix worker\u3002fix worker \u4F7F\u7528 gate-fix-bug \u6267\u884C Process 1-9\uFF1A\u590D\u73B0\u3001\u56DE\u5F52\u8986\u76D6\u3001\u6839\u56E0\u3001\u6700\u5C0F\u4FEE\u590D\u3001\u539F\u590D\u73B0\u4E0E\u76F8\u5173\u6D4B\u8BD5\u3002\u5B8C\u6210\u540E\u8FD4\u56DE\u4FEE\u590D receipt\uFF1B\u4E0D\u8981\u81EA\u884C\u5B8C\u6210 Step 10-12\uFF0C\u4E5F\u4E0D\u8981\u63D0\u4EA4\u3002
119
-
120
- ## Step 2 \u2014 Independent review
121
- \u4E3B agent \u9996\u6B21\u8FDB\u5165 review \u65F6\u52A0\u8F7D gate-code-review\uFF1B\u5DF2\u52A0\u8F7D\u5219\u590D\u7528\uFF0C\u4E0D\u8981\u91CD\u590D\u8C03\u7528 skill\u3002\u63D0\u70BC\u4E24\u8F74\u8BC4\u5BA1\u8981\u6C42\uFF0C\u518D\u8BFB\u53D6 gate-fix-bug \u6280\u80FD\u7684 assets/worker-briefs/fix-bug-review.md\uFF0C\u6D3E\u4E00\u4E2A\u72EC\u7ACB review worker\uFF1B\u4FEE\u590D\u57FA\u7EBF\u3001\u9009\u5B9A\u5931\u8D25\u3001\u5408\u540C\u5F15\u7528\u548C\u5B8C\u6574 diff \u5199\u8FDB\u7B80\u62A5\u3002review \u53EA\u62A5 findings\u3002
122
-
123
- ## Step 3 \u2014 Resolve
124
- \u628A material in-scope findings \u4EA4\u56DE fix worker\uFF08send_message \u6216\u65B0 worker\uFF09\uFF0C\u5B8C\u6210 gate-fix-bug Step 11-12\uFF0C\u91CD\u8DD1\u539F\u590D\u73B0\u548C\u76F8\u5173\u6D4B\u8BD5\uFF1B\u91CD\u590D Step 2-3 \u76F4\u5230\u6CA1\u6709 material findings\u3002
125
-
126
- ## Step 4 \u2014 Record
127
- \u5B8C\u6210\u540E\u8C03 gate_record({node:'fix-bug', workerSessionIds})\uFF0CworkerSessionIds \u5305\u542B fix \u4E0E review worker\uFF1Bgate \u4E0D\u518D\u81EA\u52A8\u63D0\u4EA4\u3002`;
128
114
  var DOCS_ORCHESTRATION = `## /gate-docs \u7F16\u6392
129
115
  \u8303\u56F4\u7531\u6A21\u578B\u6309\u9879\u76EE\u5B9E\u9645\u6587\u6863\u9700\u8981\u5224\u65AD\u3002
130
116
  \u5B8C\u6210\u540E\u8C03 gate_record({node:'docs'}) \u56DE\u5230 discuss\u3002`;
@@ -133,21 +119,18 @@ Verify \u5DF2 PASS\uFF1B\u5F53\u524D\u4E0D\u6D3E worker\uFF0C\u4E5F\u4E0D\u5199\
133
119
  \u6309\u987A\u5E8F\u6267\u884C\uFF1Agate_note_finalize \u2192 gate_note_verify \u2192 gate_record({node:'note-lifecycle'})\u3002
134
120
  finalize/verify \u5931\u8D25\u7559\u5728\u672C\u8282\u70B9\u4FEE\u590D\uFF1Barchived manifest \u7F3A\u5931\u65F6\u63D0\u793A\u7528\u6237\u6267\u884C /gate-note-seal\u3002
135
121
  \u53EA\u6709 noteVerified=true \u624D\u80FD gate_record \u5B8C\u6210\uFF1Bmechanical \u5DE5\u4F5C\u9879\u53EF\u8DF3\u8FC7 finalize\u3002\u5B8C\u6210\u540E\u5EFA\u8BAE\u63D0\u4EA4\u672C\u6B21\u5B9E\u73B0\u4E0E Note\uFF1Bgate \u4E0D\u81EA\u52A8 git add/commit\u3002\u5B8C\u6210\u540E\u68C0\u67E5\u672C\u6B21\u65B0 Note \u662F\u5426\u5B8C\u5168\u53D6\u4EE3\u4E86\u67D0\u7BC7 implemented Note\uFF1A\u6709\u72EC\u7ACB\u53C2\u8003\u4EF7\u503C\u5C31\u5728\u6700\u7EC8\u6C47\u62A5\u4E2D\u7ED9\u51FA\u5F52\u6863\u5019\u9009\u548C\u76EE\u6807\u547D\u4EE4\uFF0C\u6CA1\u6709\u72EC\u7ACB\u4EF7\u503C\u5219\u5EFA\u8BAE\u5220\u9664\uFF1B\u4E0D\u8981\u81EA\u52A8\u5F52\u6863\u3002`;
136
- var GATE_RECORD_NODES = ["plan", "plan-review", "proposal-review", "plan-revise", "implement", "code-review", "implement-revise", "verify", "verify-standalone", "note-lifecycle", "docs", "code-review-standalone", "fix-bug"];
122
+ var GATE_RECORD_NODES = ["plan", "plan-review", "proposal-review", "implement", "code-review", "verify", "verify-standalone", "note-lifecycle", "docs", "code-review-standalone"];
137
123
  var NODE_INFO = {
138
124
  plan: { variant: "plan", method: "`gate-planning` + `gate-write-agent-notes`" },
139
125
  "plan-review": { variant: "plan", method: "`gate-plan-review`" },
140
- "plan-revise": { variant: "plan", method: "`gate-planning` + `gate-write-agent-notes`" },
141
126
  "proposal-review": { variant: "reviewing-proposal", method: "`gate-plan-review`\uFF08\u4E09\u8F74\uFF09" },
142
127
  implement: { variant: "implement", method: "`gate-implement`" },
143
- "implement-revise": { variant: "implement", method: "`gate-implement`" },
144
128
  "code-review": { variant: "implement", method: "`gate-code-review` (one skill, both axes)" },
145
129
  "code-review-standalone": { variant: "reviewing-code", method: "`gate-code-review` (one skill, both axes)" },
146
130
  verify: { variant: "implement", method: "`gate-verify`" },
147
131
  "verify-standalone": { variant: "reviewing-verify", method: "\u65E0" },
148
132
  "note-lifecycle": { variant: "note-lifecycle", method: "`gate-write-agent-notes`\uFF08lifecycle \u5DE5\u5177\uFF0C\u4E0D\u662F worker\uFF09" },
149
- docs: { variant: "docs", method: "\u65E0" },
150
- "fix-bug": { variant: "fix-bug", method: "`gate-fix-bug`" }
133
+ docs: { variant: "docs", method: "\u65E0" }
151
134
  };
152
135
  var NODE_METHODS = Object.fromEntries(Object.entries(NODE_INFO).map(([node, info]) => [node, info.method]));
153
136
  var WORKER_NODES = new Set(GATE_RECORD_NODES.filter((node) => node !== "docs" && node !== "note-lifecycle"));
@@ -155,7 +138,7 @@ var DISPATCH_RULE = `## \u6280\u80FD\u52A0\u8F7D\u89C4\u5219
155
138
  - \u672C\u4F1A\u8BDD\u5DF2\u7ECF\u901A\u8FC7 skill \u5DE5\u5177\u52A0\u8F7D\u8FC7\u7684\u6280\u80FD\uFF0C\u5185\u5BB9\u4ECD\u5728\u4E0A\u6587\u65F6\u76F4\u63A5\u590D\u7528\uFF0C\u4E0D\u8981\u91CD\u590D\u8C03\u7528 skill\u3002
156
139
  - \u53EA\u6709\u4EE5\u4E0B\u60C5\u51B5\u624D\u91CD\u65B0\u52A0\u8F7D\uFF1A\u672C\u4F1A\u8BDD\u9996\u6B21\u8FDB\u5165\u8BE5\u6280\u80FD\uFF1Bcompaction \u540E\u5185\u5BB9\u5DF2\u4E0D\u5728\u4E0A\u4E0B\u6587\uFF1B\u6280\u80FD\u6587\u4EF6/\u7248\u672C\u53D1\u751F\u53D8\u5316\uFF1B\u7528\u6237\u660E\u786E\u8981\u6C42\u5237\u65B0\u3002
157
140
  - gate_record / gate_status \u8FD4\u56DE\u65B0\u7684 procedure \u53EA\u4EE3\u8868 node\u3001\u8F6E\u6B21\u6216 findings \u53D8\u5316\uFF0C\u4E0D\u4EE3\u8868\u8981\u91CD\u65B0\u52A0\u8F7D\u6280\u80FD\u3002
158
- - \u591A\u8F6E review/revise \u590D\u7528\u540C\u4E00\u4EFD\u6280\u80FD\u5185\u5BB9\uFF1B\u628A\u65B0\u7684 findings\u3001\u6587\u4EF6\u8303\u56F4\u548C\u8981\u6C42\u4F20\u7ED9 worker\uFF0C\u4E0D\u8981\u91CD\u65B0\u52A0\u8F7D\u6280\u80FD\u3002`;
141
+ - \u591A\u8F6E review/\u4FEE\u8BA2\u590D\u7528\u540C\u4E00\u4EFD\u6280\u80FD\u5185\u5BB9\uFF1B\u628A\u65B0\u7684 findings\u3001\u6587\u4EF6\u8303\u56F4\u548C\u8981\u6C42\u4EA4\u7ED9\u5B9E\u9645\u6267\u884C\u8005\uFF0C\u4E0D\u8981\u91CD\u65B0\u52A0\u8F7D\u6280\u80FD\u3002`;
159
142
  var REVIEWING_CODE_PROCEDURE = `## /gate-implement-review \u7F16\u6392
160
143
  \u4E3B agent \u9996\u6B21\u8FDB\u5165\u65F6\u52A0\u8F7D gate-code-review\uFF1B\u5DF2\u52A0\u8F7D\u5219\u590D\u7528\uFF0C\u4E0D\u8981\u91CD\u590D\u8C03\u7528 skill\u3002\u6D3E\u53EA\u8BFB review worker \u8986\u76D6 Standards \u4E0E Spec \u4E24\u8F74\uFF1B\u5B8C\u6210\u540E gate_record({node:'code-review-standalone', findings, reviewAxes, workerSessionIds}) \u56DE discuss\u3002`;
161
144
  var REVIEWING_PROPOSAL_PROCEDURE = `## /gate-propose-review \u7F16\u6392
@@ -173,18 +156,17 @@ var PLAN_STEP_2 = stepSection(PLAN_ORCHESTRATION, "## Step 2", "## Step 3");
173
156
  var IMPLEMENT_STEP_1 = stepSection(IMPLEMENT_ORCHESTRATION, "## Step 1", "## Step 2");
174
157
  var IMPLEMENT_STEP_2 = stepSection(IMPLEMENT_ORCHESTRATION, "## Step 2", "## Step 3");
175
158
  var IMPLEMENT_STEP_3 = stepSection(IMPLEMENT_ORCHESTRATION, "## Step 3", "## Step 4");
159
+ var PLAN_REVISION_PROCEDURE = `## Plan revision
160
+ \u4E0A\u4E00\u8F6E review findings \u5DF2\u8BB0\u5F55\uFF1B\u5F53\u524D node \u4E3A plan\u3002\u4FEE\u8BA2\u5B8C\u6210\u540E\u8C03\u7528 gate_record({node:'plan'}) \u56DE\u5230 plan-review\u3002`;
161
+ var IMPLEMENT_REVISION_PROCEDURE = `## Implement revision
162
+ \u4E0A\u4E00\u8F6E review/verify findings \u5DF2\u8BB0\u5F55\uFF1B\u5F53\u524D node \u4E3A implement\u3002\u4FEE\u8BA2\u5B8C\u6210\u540E\u8C03\u7528 gate_record({node:'implement'}) \u56DE\u5230 code-review\u3002`;
176
163
  var NODE_PROCEDURES = {
177
164
  plan: PLAN_STEP_1,
178
165
  "plan-review": PLAN_STEP_2,
179
- "plan-revise": `## Plan revise
180
- \u6839\u636E findings \u7528 gate_note_write \u66F4\u65B0 Note\uFF1B\u5B8C\u6210\u540E gate_record({node:'plan-revise'}) \u56DE\u5230 plan-review\uFF0C\u518D\u6309 plan-review procedure review\u3002`,
181
166
  implement: IMPLEMENT_STEP_1,
182
167
  "code-review": IMPLEMENT_STEP_2,
183
- "implement-revise": `## Implement revise
184
- \u4FEE\u590D findings\uFF1B\u91CD\u8DD1\u6D4B\u8BD5\uFF1B\u5B8C\u6210\u540E gate_record({node:'implement-revise'}) \u56DE\u5230 code-review\uFF0C\u518D\u6309 code-review procedure review\u3002`,
185
168
  verify: IMPLEMENT_STEP_3,
186
169
  "note-lifecycle": NOTE_LIFECYCLE_ORCHESTRATION,
187
- "fix-bug": FIX_BUG_ORCHESTRATION,
188
170
  "code-review-standalone": REVIEWING_CODE_PROCEDURE,
189
171
  "proposal-review": REVIEWING_PROPOSAL_PROCEDURE,
190
172
  "verify-standalone": REVIEWING_VERIFY_PROCEDURE
@@ -193,13 +175,10 @@ var METHODOLOGY_KEYS = [
193
175
  "discuss",
194
176
  "orchestrating/plan",
195
177
  "orchestrating/plan-review",
196
- "orchestrating/plan-revise",
197
178
  "orchestrating/implement",
198
179
  "orchestrating/code-review",
199
- "orchestrating/implement-revise",
200
180
  "orchestrating/verify",
201
181
  "orchestrating/note-lifecycle",
202
- "orchestrating/fix-bug",
203
182
  "docs",
204
183
  "reviewing/code-review-standalone",
205
184
  "reviewing/proposal-review",
@@ -209,6 +188,7 @@ var METHODOLOGY_KEYS = [
209
188
  "orchestrating",
210
189
  "reviewing"
211
190
  ];
191
+ var LEGACY_METHODOLOGY_KEYS = ["orchestrating/plan-revise", "orchestrating/implement-revise"];
212
192
  var METHODOLOGY_KEY_SET = new Set(METHODOLOGY_KEYS);
213
193
  function methodologyKeyFor(state) {
214
194
  if (state.phase === "orchestrating" || state.phase === "reviewing") {
@@ -222,23 +202,21 @@ var GATE_METHODOLOGY = `## Gate \u65B9\u6CD5\u8BBA
222
202
 
223
203
  ${DISCUSS_ORCHESTRATION}
224
204
 
225
- ## orchestrating/plan \xB7 orchestrating/plan-review \xB7 orchestrating/plan-revise
226
- \u628A\u8BA8\u8BBA\u5171\u8BC6\u3001\u65E2\u6709\u51B3\u7B56\u4E0E\u7528\u6237\u9700\u6C42\u6536\u655B\u6210\u53EF\u5B9E\u65BD\u8BA1\u5212\u4E0E proposed Note\uFF1B\u8BA1\u5212\u5FC5\u987B\u5199\u6E05\u8303\u56F4\u3001\u9A8C\u6536\u3001\u5907\u9009\u4E0E\u98CE\u9669\u3002Plan Review \u72EC\u7ACB\u5224\u65AD\uFF1Bfindings \u5148\u8BB0\u5F55\u518D revise\uFF1Breview \u901A\u8FC7\u540E\u56DE discuss\u3002\u4E0D\u8981\u5728\u89C4\u5212\u91CC\u5F00\u59CB\u5B9E\u73B0\u3002
205
+ ## orchestrating/plan \xB7 orchestrating/plan-review
206
+ \u628A\u8BA8\u8BBA\u5171\u8BC6\u3001\u65E2\u6709\u51B3\u7B56\u4E0E\u7528\u6237\u9700\u6C42\u6536\u655B\u6210\u53EF\u5B9E\u65BD\u8BA1\u5212\u4E0E proposed Note\uFF1B\u8BA1\u5212\u5FC5\u987B\u5199\u6E05\u8303\u56F4\u3001\u9A8C\u6536\u3001\u5907\u9009\u4E0E\u98CE\u9669\u3002Plan Review \u72EC\u7ACB\u5224\u65AD\uFF1Bfindings \u5148\u8BB0\u5F55\uFF0C\u4FEE\u8BA2\u540E\u518D review\uFF1Breview \u901A\u8FC7\u540E\u56DE discuss\u3002\u4E0D\u8981\u5728\u89C4\u5212\u91CC\u5F00\u59CB\u5B9E\u73B0\u3002
227
207
 
228
- ## orchestrating/implement \xB7 orchestrating/implement-revise
208
+ ## orchestrating/implement
229
209
  \u6309\u5DF2\u786E\u8BA4\u7684\u8BA1\u5212\u6216\u8BA8\u8BBA\u540E\u7684\u5B9E\u65BD\u8BF4\u660E\u5B9E\u65BD\u5E76\u5B8C\u6210\u6D4B\u8BD5\uFF1B\u5B9E\u73B0\u540E\u505A\u72EC\u7ACB review\uFF0C\u518D\u7528\u53EF\u6267\u884C\u8BC1\u636E verify\uFF1B\u6700\u540E\u5B8C\u6210 Note lifecycle\u3002\u4E0D\u6269\u5927\u8303\u56F4\uFF0C\u4E0D\u5728\u5B9E\u73B0\u4E2D\u91CD\u65B0\u89C4\u5212\u3002
230
210
 
231
211
  ## orchestrating/code-review
232
- \u72EC\u7ACB\u5224\u65AD\u6539\u52A8\u662F\u5426\u6EE1\u8DB3\u5408\u540C\u4E0E\u6807\u51C6\uFF1B\u53EA\u62A5 findings\uFF0C\u4E0D\u4FEE\u4EE3\u7801\u3001\u4E0D\u66FF\u4EE3 verify\uFF1Bfindings \u8BB0\u5F55\u540E\u518D\u8FDB\u5165 revise\u3002
212
+ \u72EC\u7ACB\u5224\u65AD\u6539\u52A8\u662F\u5426\u6EE1\u8DB3\u5408\u540C\u4E0E\u6807\u51C6\uFF1B\u53EA\u62A5 findings\uFF0C\u4E0D\u4FEE\u4EE3\u7801\u3001\u4E0D\u66FF\u4EE3 verify\uFF1Bfindings \u8BB0\u5F55\u540E\u518D\u8FDB\u884C\u4FEE\u8BA2\u3002
233
213
 
234
214
  ## orchestrating/verify
235
- \u7528\u53EF\u6267\u884C\u8BC1\u636E\u5224\u5B9A PASS/FAIL\uFF1B\u4E0D\u4FEE\u6539\u4EA7\u54C1/\u6D4B\u8BD5\u8BA9\u7ED3\u679C\u53D8\u7EFF\uFF1BFAIL \u56DE implement-revise\u3002
215
+ \u7528\u53EF\u6267\u884C\u8BC1\u636E\u5224\u5B9A PASS/FAIL\uFF1B\u4E0D\u4FEE\u6539\u4EA7\u54C1/\u6D4B\u8BD5\u8BA9\u7ED3\u679C\u53D8\u7EFF\uFF1BFAIL \u56DE implement\u3002
236
216
 
237
217
  ## orchestrating/note-lifecycle
238
218
  \u5B8C\u6210 Note \u7684 finalize \u4E0E\u6821\u9A8C\uFF1B\u4E0D\u5199\u4E1A\u52A1\u4EE3\u7801\uFF1B\u68C0\u67E5\u662F\u5426\u4EA7\u751F\u5F52\u6863\u5019\u9009\uFF1B\u5B8C\u6210\u540E\u56DE discuss\u3002
239
219
 
240
- ## orchestrating/fix-bug
241
- \u5BF9\u5DF2\u6388\u6743\u7684\u5B9E\u73B0\u7F3A\u9677\uFF1A\u590D\u73B0\u3001\u56DE\u5F52\u8986\u76D6\u3001\u6839\u56E0\u3001\u6700\u5C0F\u4FEE\u590D\u3001\u72EC\u7ACB review\uFF1B\u4E0D\u505A\u65B0\u529F\u80FD\u3001\u4E0D\u6269\u5927\u8303\u56F4\uFF1B\u5B8C\u6210\u540E\u56DE discuss\u3002
242
220
 
243
221
  ## docs
244
222
  \u6587\u6863\u6CBB\u7406\uFF1B\u4E0D\u6539\u53D8\u529F\u80FD\u884C\u4E3A\uFF1B\u8303\u56F4\u7531\u6A21\u578B\u6309\u9879\u76EE\u5B9E\u9645\u6587\u6863\u9700\u8981\u5224\u65AD\uFF1B\u5B8C\u6210\u540E\u56DE discuss\u3002
@@ -280,13 +258,17 @@ function procedureFor(state, { reviewLimit = DEFAULT_REVIEW_LIMIT } = {}) {
280
258
  text = "Gate \u5DF2\u5B8C\u6210\uFF1B\u65B0\u4EFB\u52A1\u9700\u8981\u91CD\u65B0\u6388\u6743\u3002";
281
259
  } else if (variant === "docs") {
282
260
  text = DOCS_ORCHESTRATION;
261
+ } else if (state.node === "plan" && state.revision !== null) {
262
+ text = PLAN_REVISION_PROCEDURE;
263
+ } else if (state.node === "implement" && state.revision !== null) {
264
+ text = IMPLEMENT_REVISION_PROCEDURE;
283
265
  } else {
284
266
  text = NODE_PROCEDURES[state.node ?? ""] ?? "";
285
267
  }
286
268
  if (text === "") {
287
269
  text = "\u5F53\u524D phase/node \u6CA1\u6709\u5339\u914D\u7684 procedure\uFF1B\u8C03\u7528 gate_status \u91CD\u65B0\u8BFB\u53D6\uFF1B\u82E5\u4ECD\u4E0D\u4E00\u81F4\uFF0C\u56DE discuss \u4FEE\u590D Gate \u72B6\u6001\u3002";
288
270
  }
289
- if (["plan", "implement", "fix-bug", "reviewing-code", "reviewing-proposal", "reviewing-verify"].includes(variant)) {
271
+ if (["plan", "implement", "reviewing-code", "reviewing-proposal", "reviewing-verify"].includes(variant)) {
290
272
  text = [text, DISPATCH_RULE].filter(Boolean).join("\n\n");
291
273
  }
292
274
  if (variant === "plan" || variant === "implement") {
@@ -323,7 +305,8 @@ function statusText(state, reviewLimit = DEFAULT_REVIEW_LIMIT, { includeRounds =
323
305
  `work\uFF1A${state.work}`,
324
306
  `blockReason\uFF1A${state.blockReason ?? "\u65E0"}`,
325
307
  `planReady\uFF1A${state.planReady ? "\u662F" : "\u5426"}`,
326
- ...includeRounds ? [`rounds\uFF1A${roundsText(state, reviewLimit)}`] : []
308
+ ...includeRounds ? [`rounds\uFF1A${roundsText(state, reviewLimit)}`] : [],
309
+ ...state.revision === null ? [] : [`revision\uFF1A${state.revision.from} \u540E / round ${state.revision.round} / findings ${state.revision.findings.length}`]
327
310
  ];
328
311
  if (state.notePaths?.length > 0 || isMechanicalDecision(state.noteDecision)) {
329
312
  lines.push(`notes\uFF1A${state.noteDecision ?? "\u65E0"} ${state.notePaths?.length ?? 0} \u7BC7\uFF0Cverified=${state.noteVerified === true ? "\u662F" : "\u5426"}`);
@@ -370,6 +353,7 @@ function defaultState() {
370
353
  work: "active",
371
354
  blockReason: null,
372
355
  rounds: { planReview: 0, codeReview: 0 },
356
+ revision: null,
373
357
  exhausted: { plan: false, code: false },
374
358
  planReady: false,
375
359
  verification: null,
@@ -387,15 +371,37 @@ function defaultState() {
387
371
  function textOrNull(value) {
388
372
  return typeof value === "string" ? value : null;
389
373
  }
374
+ function revisionOf(value) {
375
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
376
+ const source = value;
377
+ if (source.from !== "plan-review" && source.from !== "code-review" && source.from !== "verify") return null;
378
+ if (!Array.isArray(source.findings)) return null;
379
+ return {
380
+ from: source.from,
381
+ findings: source.findings.filter((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry)).map((entry) => ({ ...entry })),
382
+ round: Number(source.round) || 0
383
+ };
384
+ }
385
+ function legacyNode(node) {
386
+ if (node === "plan-revise") return "plan";
387
+ if (node === "implement-revise") return "implement";
388
+ return node;
389
+ }
390
390
  function normalizeState(value) {
391
391
  const base = defaultState();
392
392
  if (value === null || typeof value !== "object" || Array.isArray(value)) return base;
393
393
  const source = value;
394
394
  const phase = PHASES.includes(source.phase) ? source.phase : "discuss";
395
- const blockedFrom = source.blockedFrom !== null && typeof source.blockedFrom === "object" && !Array.isArray(source.blockedFrom) ? { phase: textOrNull(source.blockedFrom.phase), node: textOrNull(source.blockedFrom.node) } : null;
395
+ let node = legacyNode(textOrNull(source.node));
396
+ let revision = revisionOf(source.revision);
397
+ if (revision === null && source.node === "plan-revise") revision = { from: "plan-review", findings: [], round: Number(source.rounds?.planReview) || 0 };
398
+ if (revision === null && source.node === "implement-revise") revision = { from: "code-review", findings: [], round: Number(source.rounds?.codeReview) || 0 };
399
+ if (revision === null && source.blockedFrom?.node === "plan-revise") revision = { from: "plan-review", findings: [], round: Number(source.rounds?.planReview) || 0 };
400
+ if (revision === null && source.blockedFrom?.node === "implement-revise") revision = { from: "code-review", findings: [], round: Number(source.rounds?.codeReview) || 0 };
401
+ const blockedFrom = source.blockedFrom !== null && typeof source.blockedFrom === "object" && !Array.isArray(source.blockedFrom) ? { phase: textOrNull(source.blockedFrom.phase), node: legacyNode(textOrNull(source.blockedFrom.node)) } : null;
396
402
  return {
397
403
  phase,
398
- node: textOrNull(source.node),
404
+ node,
399
405
  task: textOrNull(source.task),
400
406
  work: textOrNull(source.work) ?? "active",
401
407
  blockReason: textOrNull(source.blockReason),
@@ -403,6 +409,7 @@ function normalizeState(value) {
403
409
  planReview: Number(source.rounds?.planReview) || 0,
404
410
  codeReview: Number(source.rounds?.codeReview) || 0
405
411
  },
412
+ revision,
406
413
  exhausted: {
407
414
  plan: source.exhausted?.plan === true,
408
415
  code: source.exhausted?.code === true
@@ -778,7 +785,8 @@ function applyCommandEvent(state, name, args) {
778
785
  noteDecision: null,
779
786
  noteSearch: null,
780
787
  noteVerified: false,
781
- noteFinalizeRecovery: []
788
+ noteFinalizeRecovery: [],
789
+ revision: null
782
790
  };
783
791
  case "gate-enter-implement":
784
792
  return {
@@ -791,18 +799,17 @@ function applyCommandEvent(state, name, args) {
791
799
  blockedFrom: null,
792
800
  verification: null,
793
801
  noteVerified: false,
794
- noteFinalizeRecovery: []
802
+ noteFinalizeRecovery: [],
803
+ revision: null
795
804
  };
796
- case "gate-fix-bug":
797
- return { ...state, phase: "orchestrating", task: text === "" ? state.task ?? "\u5F53\u524D\u4E0A\u4E0B\u6587\u4E2D\u7684\u7F3A\u9677" : text, node: "fix-bug", work: "active", blockReason: null, blockedFrom: null };
798
805
  case "gate-docs":
799
- return { ...state, phase: "docs", task: text, node: null, work: "active", blockReason: null, blockedFrom: null };
806
+ return { ...state, phase: "docs", task: text, node: null, work: "active", blockReason: null, blockedFrom: null, revision: null };
800
807
  case "gate-implement-review":
801
- return { ...state, phase: "reviewing", task: text, node: "code-review-standalone", work: "active", blockReason: null, blockedFrom: null };
808
+ return { ...state, phase: "reviewing", task: text, node: "code-review-standalone", work: "active", blockReason: null, blockedFrom: null, revision: null };
802
809
  case "gate-code-verify":
803
- return { ...state, phase: "reviewing", task: text, node: "verify-standalone", work: "active", blockReason: null, blockedFrom: null };
810
+ return { ...state, phase: "reviewing", task: text, node: "verify-standalone", work: "active", blockReason: null, blockedFrom: null, revision: null };
804
811
  case "gate-propose-review":
805
- return { ...state, phase: "reviewing", task: text, node: "proposal-review", work: "active", blockReason: null, blockedFrom: null };
812
+ return { ...state, phase: "reviewing", task: text, node: "proposal-review", work: "active", blockReason: null, blockedFrom: null, revision: null };
806
813
  case "gate-block":
807
814
  return {
808
815
  ...state,
@@ -822,7 +829,7 @@ function applyCommandEvent(state, name, args) {
822
829
  blockedFrom: null
823
830
  };
824
831
  case "gate-return-discuss":
825
- return { ...state, phase: "discuss", node: null, work: "active", blockReason: null, blockedFrom: null };
832
+ return { ...state, phase: "discuss", node: null, work: "active", blockReason: null, blockedFrom: null, revision: null };
826
833
  default:
827
834
  return state;
828
835
  }
@@ -1059,10 +1066,10 @@ function accessFor(state, worker) {
1059
1066
  repoWrite: "push"
1060
1067
  };
1061
1068
  }
1062
- if (state.node === "plan" || state.node === "plan-revise") {
1069
+ if (state.node === "plan") {
1063
1070
  return { read: true, write: "none", noteWrite: true, shell: "read", repoWrite: "none" };
1064
1071
  }
1065
- if (state.node === "implement" || state.node === "implement-revise" || state.node === "fix-bug") {
1072
+ if (state.node === "implement") {
1066
1073
  return { read: true, write: "workspace", noteWrite: false, shell: "write", repoWrite: "push" };
1067
1074
  }
1068
1075
  return { read: true, write: "none", noteWrite: false, shell: "read", repoWrite: "none" };
@@ -1152,8 +1159,8 @@ function workerProtocol(node) {
1152
1159
  return [
1153
1160
  "## Gate worker",
1154
1161
  "\u4F60\u662F gate \u4E3A\u8BE5\u8282\u70B9\u6D3E\u53D1\u7684 worker\u3002\u53EA\u6267\u884C\u8BE5\u8282\u70B9\uFF1B\u4E0D\u8981\u8C03\u7528 gate_record\uFF0C\u4E0D\u8981\u63A8\u8FDB gate\u3002",
1155
- node === "verify-standalone" ? "\u52A0\u8F7D\u4F7F\u7528 gate-user-verify \u5B8C\u6210\u9A8C\u6536\uFF0C\u5E76\u6309\u8BE5\u6280\u80FD Step 6 \u6C47\u62A5\u3002\u4EFB\u52A1\u4E0E\u6C47\u62A5\u6A21\u677F\u89C1\u8BE5\u6280\u80FD assets/worker-briefs/gate-code-verify.md\u3002\u4E0D\u4FEE\u6539\u4EA7\u54C1\u4EE3\u7801\u3001\u6D4B\u8BD5\u3001\u9700\u6C42\u6216\u8BBE\u8BA1\uFF1B\u53EF\u4EE5\u8FD0\u884C\u6D4B\u8BD5/\u547D\u4EE4\u4F5C\u4E3A\u8BC1\u636E\uFF0C\u4F46\u4E0D\u5F97\u4FEE\u6539\u3001\u653E\u5BBD\u6216\u91CD\u5199\u6D4B\u8BD5\uFF1B\u4E0D\u8981\u81EA\u884C\u63D0\u4EA4\u3002" : node === "fix-bug" ? "\u4E3B\u4EE3\u7406\u5DF2\u8BFB\u53D6 gate-fix-bug\uFF1B\u4F60\u6267\u884C gate-fix-bug \u7684 Process 1-9\uFF08\u590D\u73B0\u3001\u56DE\u5F52\u8986\u76D6\u3001\u6839\u56E0\u3001\u6700\u5C0F\u4FEE\u590D\u3001\u6D4B\u8BD5\uFF09\uFF0C\u8FD4\u56DE\u4FEE\u590D receipt\uFF1B\u4E0D\u8981\u81EA\u884C\u5B8C\u6210 Step 10-12\uFF0C\u4E0D\u8981\u63D0\u4EA4\u3002\u4E0D\u6539\u4EA7\u54C1\u5408\u540C\u3001\u4E0D\u6269\u5927\u8303\u56F4\u3002" : "\u4E3B\u4EE3\u7406\u5DF2\u7ECF\u52A0\u8F7D\u6240\u9700 gate \u6280\u80FD\uFF0C\u5E76\u628A\u5177\u4F53\u4EFB\u52A1\u4E0E\u76F8\u5173\u65B9\u6CD5\u8981\u6C42\u4EA4\u7ED9\u4F60\u3002\u4E0D\u8981\u81EA\u5DF1\u52A0\u8F7D gate \u6280\u80FD\u3002",
1156
- node === "plan" || node === "plan-revise" ? "\u7528 gate_note_write \u5728 .agents/notes/proposed \u4E0B\u521B\u5EFA\u6216\u66F4\u65B0 proposed Agent Note\uFF1B\u539F\u5730\u540C\u6B65\u65E2\u6709 implemented Note \u65F6\u8DEF\u5F84\u5199 implemented/<class>/...\uFF1Bplanning \u4E2D write/edit/apply_patch \u548C\u4ED3\u5E93\u5199\u88AB\u62D2\u7EDD\uFF0C\u53EA\u8BFB shell \u53EF\u7528\u3002" : ""
1162
+ node === "verify-standalone" ? "\u52A0\u8F7D\u4F7F\u7528 gate-user-verify \u5B8C\u6210\u9A8C\u6536\uFF0C\u5E76\u6309\u8BE5\u6280\u80FD Step 6 \u6C47\u62A5\u3002\u4EFB\u52A1\u4E0E\u6C47\u62A5\u6A21\u677F\u89C1\u8BE5\u6280\u80FD assets/worker-briefs/gate-code-verify.md\u3002\u4E0D\u4FEE\u6539\u4EA7\u54C1\u4EE3\u7801\u3001\u6D4B\u8BD5\u3001\u9700\u6C42\u6216\u8BBE\u8BA1\uFF1B\u53EF\u4EE5\u8FD0\u884C\u6D4B\u8BD5/\u547D\u4EE4\u4F5C\u4E3A\u8BC1\u636E\uFF0C\u4F46\u4E0D\u5F97\u4FEE\u6539\u3001\u653E\u5BBD\u6216\u91CD\u5199\u6D4B\u8BD5\uFF1B\u4E0D\u8981\u81EA\u884C\u63D0\u4EA4\u3002" : "\u4E3B\u4EE3\u7406\u5DF2\u7ECF\u52A0\u8F7D\u6240\u9700 gate \u6280\u80FD\uFF0C\u5E76\u628A\u5177\u4F53\u4EFB\u52A1\u4E0E\u76F8\u5173\u65B9\u6CD5\u8981\u6C42\u4EA4\u7ED9\u4F60\u3002\u4E0D\u8981\u81EA\u5DF1\u52A0\u8F7D gate \u6280\u80FD\u3002",
1163
+ node === "plan" ? "\u7528 gate_note_write \u5728 .agents/notes/proposed \u4E0B\u521B\u5EFA\u6216\u66F4\u65B0 proposed Agent Note\uFF1B\u539F\u5730\u540C\u6B65\u65E2\u6709 implemented Note \u65F6\u8DEF\u5F84\u5199 implemented/<class>/...\uFF1Bplanning \u4E2D write/edit/apply_patch \u548C\u4ED3\u5E93\u5199\u88AB\u62D2\u7EDD\uFF0C\u53EA\u8BFB shell \u53EF\u7528\u3002" : ""
1157
1164
  ].filter(Boolean).join("\n\n");
1158
1165
  }
1159
1166
  var REVIEW_NODES = /* @__PURE__ */ new Set(["plan-review", "proposal-review", "code-review", "code-review-standalone"]);
@@ -1170,9 +1177,11 @@ function reviewAxesError(args) {
1170
1177
  }
1171
1178
  return void 0;
1172
1179
  }
1173
- async function workerEvidenceError(ctx, root, args) {
1180
+ async function workerEvidenceError(ctx, root, args, state) {
1174
1181
  if (!WORKER_NODES.has(args.node)) return void 0;
1175
1182
  const ids = Array.isArray(args.workerSessionIds) ? [...new Set(args.workerSessionIds.filter((value) => typeof value === "string" && value !== ""))] : [];
1183
+ const revisionNode = args.node === "plan" && state?.revision?.from === "plan-review" || args.node === "implement" && (state?.revision?.from === "code-review" || state?.revision?.from === "verify");
1184
+ if (ids.length === 0 && revisionNode) return void 0;
1176
1185
  if (ids.length === 0) return { code: "worker-required", reason: "gate_record \u9700\u8981 workerSessionIds\uFF1B\u6CA1\u6709 worker \u4E0D\u80FD\u63A8\u8FDB\u3002" };
1177
1186
  const service = ctx.get("subagents");
1178
1187
  if (service === void 0 || typeof service.listDescendants !== "function") {
@@ -1291,7 +1300,7 @@ var GATE_FROZEN_REASON = "Gate \u5DF2\u51BB\u7ED3\uFF1A\u5148 /gate-resume";
1291
1300
  function fileWriteDenied(state, effective) {
1292
1301
  if (state.phase === "blocked") return GATE_FROZEN_REASON;
1293
1302
  if (!effective.worker && state.phase === "discuss") return DISCUSS_READ_ONLY;
1294
- if (effective.worker && (state.node === "plan" || state.node === "plan-revise")) return "planning worker \u53EA\u5141\u8BB8 gate_note_write\uFF1B\u4EA7\u54C1\u6587\u4EF6\u548C\u4ED3\u5E93\u5199\u88AB\u62D2\u7EDD\u3002";
1303
+ if (effective.worker && state.node === "plan") return "planning worker \u53EA\u5141\u8BB8 gate_note_write\uFF1B\u4EA7\u54C1\u6587\u4EF6\u548C\u4ED3\u5E93\u5199\u88AB\u62D2\u7EDD\u3002";
1295
1304
  if (effective.worker) return `\u5F53\u524D ${state.node ?? "worker"} worker \u4E0D\u5141\u8BB8\u5199\u6587\u4EF6\uFF1Breview/verify worker \u53EA\u8BFB\u3002`;
1296
1305
  return "\u5F53\u524D\u89D2\u8272\u4E0D\u5141\u8BB8\u5199\u6587\u4EF6";
1297
1306
  }
@@ -1365,7 +1374,7 @@ function installRestrictions(ctx, deps) {
1365
1374
  }
1366
1375
 
1367
1376
  // src/commands.ts
1368
- import path10 from "node:path";
1377
+ import path11 from "node:path";
1369
1378
 
1370
1379
  // src/notes/provision.ts
1371
1380
  import { copyFileSync, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
@@ -1503,7 +1512,7 @@ var BASE_ARTIFACT_POLICY = {
1503
1512
  }
1504
1513
  }
1505
1514
  };
1506
- var PHASES2 = new Set(METHODOLOGY_KEYS);
1515
+ var PHASES2 = /* @__PURE__ */ new Set([...METHODOLOGY_KEYS, ...LEGACY_METHODOLOGY_KEYS]);
1507
1516
  var RESERVED = [".agents/gate/artifact-policy.json", ".agents/notes/"];
1508
1517
  function normalizeArtifactPath(value) {
1509
1518
  return path9.posix.normalize(String(value).replaceAll("\\", "/").replace(/^\.\//u, ""));
@@ -1621,9 +1630,188 @@ function writeArtifact(root, requested, content) {
1621
1630
  return { relative: path9.relative(root, target).replaceAll("\\", "/") };
1622
1631
  }
1623
1632
 
1633
+ // src/init-manifest.ts
1634
+ import { createHash } from "node:crypto";
1635
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync5 } from "node:fs";
1636
+ import path10 from "node:path";
1637
+ var INIT_MANIFEST_PATH = ".agents/gate/init-manifest.json";
1638
+ var ARTIFACT_POLICY_PATH2 = ".agents/gate/artifact-policy.json";
1639
+ var AGENTS_BLOCK = /<!-- gate-notes:start -->[\s\S]*?<!-- gate-notes:end -->/u;
1640
+ function sha256Bytes(value) {
1641
+ return `sha256:${createHash("sha256").update(value).digest("hex")}`;
1642
+ }
1643
+ function sha256File(file) {
1644
+ try {
1645
+ return sha256Bytes(readFileSync4(file));
1646
+ } catch {
1647
+ return null;
1648
+ }
1649
+ }
1650
+ function packageVersion() {
1651
+ try {
1652
+ const pkg = JSON.parse(readFileSync4(path10.join(PACKAGE_ROOT, "package.json"), "utf8"));
1653
+ return typeof pkg.version === "string" ? pkg.version : "unknown";
1654
+ } catch {
1655
+ return "unknown";
1656
+ }
1657
+ }
1658
+ function currentAgentsBlock(root) {
1659
+ try {
1660
+ const text = readFileSync4(path10.join(root, "AGENTS.md"), "utf8");
1661
+ return AGENTS_BLOCK.exec(text)?.[0] ?? null;
1662
+ } catch {
1663
+ return null;
1664
+ }
1665
+ }
1666
+ function readManifest(root) {
1667
+ try {
1668
+ const value = JSON.parse(readFileSync4(path10.join(root, INIT_MANIFEST_PATH), "utf8"));
1669
+ if (value === null || typeof value !== "object" || value.version !== 1) return null;
1670
+ if (typeof value.createdAt !== "string" || typeof value.gateVersion !== "string") return null;
1671
+ if (value.immutable === null || typeof value.immutable !== "object" || Array.isArray(value.immutable)) return null;
1672
+ if (value.managed === null || typeof value.managed !== "object" || Array.isArray(value.managed)) return null;
1673
+ if (value.notes === null || typeof value.notes !== "object" || Array.isArray(value.notes)) return null;
1674
+ return value;
1675
+ } catch {
1676
+ return null;
1677
+ }
1678
+ }
1679
+ function immutablePaths() {
1680
+ return [
1681
+ ...NOTES_CI_SCRIPTS.map((name) => `.agents/gate/ci/${name}`),
1682
+ ".agents/gate/verify-notes.mjs"
1683
+ ];
1684
+ }
1685
+ function provisionInitManifest(root, packageScript) {
1686
+ const previous = readManifest(root);
1687
+ const createdAt = typeof previous?.createdAt === "string" ? previous.createdAt : (/* @__PURE__ */ new Date()).toISOString();
1688
+ const immutable = {};
1689
+ for (const relative of immutablePaths()) {
1690
+ const hash = sha256File(path10.join(root, relative));
1691
+ if (hash !== null) immutable[relative] = hash;
1692
+ }
1693
+ const policyFile = path10.join(root, ARTIFACT_POLICY_PATH2);
1694
+ const policyHash = sha256File(policyFile) ?? sha256Bytes("");
1695
+ const block = currentAgentsBlock(root);
1696
+ let pkgScript = null;
1697
+ try {
1698
+ const pkg = JSON.parse(readFileSync4(path10.join(root, "package.json"), "utf8"));
1699
+ pkgScript = typeof pkg.scripts?.["verify-notes"] === "string" ? pkg.scripts["verify-notes"] : null;
1700
+ } catch {
1701
+ }
1702
+ const manifest = {
1703
+ version: 1,
1704
+ gateVersion: packageVersion(),
1705
+ createdAt,
1706
+ immutable,
1707
+ managed: {
1708
+ artifactPolicy: { path: ARTIFACT_POLICY_PATH2, schemaVersion: 1, sha256: policyHash },
1709
+ agentsBlockHash: block === null ? null : sha256Bytes(block),
1710
+ packageScript: pkgScript ?? packageScript,
1711
+ workflow: ".github/workflows/verify-notes.yml"
1712
+ },
1713
+ notes: { path: ".agents/notes", lifecycles: ["proposed", "implemented", "rejected", "archived"] }
1714
+ };
1715
+ mkdirSync5(path10.dirname(path10.join(root, INIT_MANIFEST_PATH)), { recursive: true });
1716
+ writeFileSync5(path10.join(root, INIT_MANIFEST_PATH), `${JSON.stringify(manifest, null, 2)}
1717
+ `);
1718
+ return { path: INIT_MANIFEST_PATH, manifest, status: previous === null ? "created" : "updated" };
1719
+ }
1720
+ function verifyInit(root) {
1721
+ const manifest = readManifest(root);
1722
+ const issues = [];
1723
+ const immutable = [];
1724
+ for (const relative of immutablePaths()) {
1725
+ const actual = sha256File(path10.join(root, relative));
1726
+ const expected = manifest?.immutable?.[relative];
1727
+ if (actual === null) {
1728
+ immutable.push({ path: relative, status: manifest === null ? "unknown" : "missing" });
1729
+ if (manifest !== null) issues.push({ severity: "error", code: "immutable-missing", message: `${relative} \u7F3A\u5931` });
1730
+ } else if (manifest === null) {
1731
+ immutable.push({ path: relative, status: "unknown" });
1732
+ } else if (expected === void 0) {
1733
+ immutable.push({ path: relative, status: "missing" });
1734
+ issues.push({ severity: "error", code: "immutable-manifest-missing", message: `${relative} \u4E0D\u5728 init-manifest.immutable` });
1735
+ } else if (actual !== expected) {
1736
+ immutable.push({ path: relative, status: "modified" });
1737
+ issues.push({ severity: "error", code: "immutable-modified", message: `${relative} \u4E0E init-manifest \u4E0D\u4E00\u81F4` });
1738
+ } else {
1739
+ immutable.push({ path: relative, status: "ok" });
1740
+ }
1741
+ }
1742
+ const manifestExists = existsSync5(path10.join(root, INIT_MANIFEST_PATH));
1743
+ if (manifest === null) issues.push({ severity: "error", code: manifestExists ? "manifest-invalid" : "manifest-missing", message: manifestExists ? "init-manifest \u65E0\u6548\uFF1B\u91CD\u65B0\u8FD0\u884C /gate-init" : "init-manifest \u7F3A\u5931\uFF1B\u91CD\u65B0\u8FD0\u884C /gate-init" });
1744
+ let artifactPolicy = "missing";
1745
+ const policyFile = path10.join(root, ARTIFACT_POLICY_PATH2);
1746
+ if (existsSync5(policyFile)) {
1747
+ try {
1748
+ const parsed = parseArtifactPolicy(JSON.parse(readFileSync4(policyFile, "utf8")));
1749
+ if (parsed.policy === void 0) artifactPolicy = "invalid";
1750
+ else {
1751
+ const actualHash = sha256File(policyFile);
1752
+ artifactPolicy = manifest?.managed?.artifactPolicy?.sha256 !== void 0 && actualHash !== manifest.managed.artifactPolicy.sha256 ? "customized" : "ok";
1753
+ }
1754
+ } catch {
1755
+ artifactPolicy = "invalid";
1756
+ }
1757
+ }
1758
+ if (artifactPolicy === "missing") issues.push({ severity: "error", code: "artifact-policy-missing", message: "artifact-policy.json \u7F3A\u5931" });
1759
+ if (artifactPolicy === "invalid") issues.push({ severity: "error", code: "artifact-policy-invalid", message: "artifact-policy.json \u65E0\u6548" });
1760
+ const currentBlock = currentAgentsBlock(root);
1761
+ let agentsBlock = manifest === null ? "unknown" : "missing";
1762
+ if (currentBlock !== null && manifest !== null) {
1763
+ agentsBlock = manifest.managed?.agentsBlockHash !== null && manifest.managed?.agentsBlockHash !== void 0 && sha256Bytes(currentBlock) !== manifest.managed.agentsBlockHash ? "modified" : "ok";
1764
+ }
1765
+ if (agentsBlock === "missing") issues.push({ severity: "error", code: "agents-block-missing", message: "AGENTS.md \u7F3A\u5C11 gate managed block" });
1766
+ if (agentsBlock === "modified") issues.push({ severity: "warning", code: "agents-block-modified", message: "AGENTS.md managed block \u5DF2\u4FEE\u6539" });
1767
+ let packageScript = manifest === null ? "unknown" : "missing";
1768
+ let currentScript = null;
1769
+ try {
1770
+ const pkg = JSON.parse(readFileSync4(path10.join(root, "package.json"), "utf8"));
1771
+ currentScript = typeof pkg.scripts?.["verify-notes"] === "string" ? pkg.scripts["verify-notes"] : null;
1772
+ } catch {
1773
+ }
1774
+ if (currentScript === null) {
1775
+ packageScript = "missing";
1776
+ issues.push({ severity: "error", code: "package-script-missing", message: "package.json \u7F3A\u5C11 scripts.verify-notes" });
1777
+ } else if (manifest === null) {
1778
+ packageScript = "unknown";
1779
+ } else if (manifest.managed?.packageScript !== null && manifest.managed?.packageScript !== void 0 && currentScript !== manifest.managed.packageScript) {
1780
+ packageScript = "customized";
1781
+ issues.push({ severity: "warning", code: "package-script-customized", message: "scripts.verify-notes \u4E0E init \u65F6\u4E0D\u540C" });
1782
+ } else packageScript = "ok";
1783
+ const workflowPath = manifest?.managed?.workflow ?? ".github/workflows/verify-notes.yml";
1784
+ const workflow = existsSync5(path10.join(root, workflowPath)) ? "existing" : "missing";
1785
+ if (workflow === "missing") issues.push({ severity: "warning", code: "workflow-missing", message: `${workflowPath} \u7F3A\u5931` });
1786
+ let notes = "ok";
1787
+ for (const lifecycle of ["proposed", "implemented", "rejected", "archived"]) {
1788
+ if (!existsSync5(path10.join(root, ".agents", "notes", lifecycle))) {
1789
+ notes = "missing";
1790
+ issues.push({ severity: "error", code: "notes-missing", message: `.agents/notes/${lifecycle} \u7F3A\u5931` });
1791
+ }
1792
+ }
1793
+ const currentVersion = packageVersion();
1794
+ if (manifest !== null && manifest.gateVersion !== currentVersion) {
1795
+ issues.push({ severity: "warning", code: "stale-init", message: `init gateVersion=${manifest.gateVersion}\uFF0C\u5F53\u524D=${currentVersion}\uFF1B\u5EFA\u8BAE\u91CD\u65B0\u8FD0\u884C /gate-init` });
1796
+ }
1797
+ const ok = !issues.some((issue) => issue.severity === "error");
1798
+ const lines = [
1799
+ `init verify\uFF1A${ok ? "ok" : "FAILED"}`,
1800
+ `manifest\uFF1A${manifest === null ? "missing/invalid" : "ok"}`,
1801
+ `gateVersion\uFF1A${manifest?.gateVersion ?? "unknown"}\uFF08current ${currentVersion}\uFF09`,
1802
+ `artifact-policy\uFF1A${artifactPolicy}`,
1803
+ `agents block\uFF1A${agentsBlock}`,
1804
+ `package script\uFF1A${packageScript}`,
1805
+ `workflow\uFF1A${workflow}`,
1806
+ `notes\uFF1A${notes}`,
1807
+ ...issues.map((issue) => `${issue.severity}: ${issue.message}`)
1808
+ ];
1809
+ return { ok, manifest: manifest === null ? manifestExists ? "invalid" : "missing" : "ok", immutable, artifactPolicy, agentsBlock, packageScript, workflow, notes, issues, text: lines.join("\n") };
1810
+ }
1811
+
1624
1812
  // src/commands.ts
1625
1813
  import { execFileSync as execFileSync3 } from "node:child_process";
1626
- import { readFileSync as readFileSync4 } from "node:fs";
1814
+ import { readFileSync as readFileSync5 } from "node:fs";
1627
1815
 
1628
1816
  // src/command-catalog.ts
1629
1817
  var GATE_COMMANDS = [
@@ -1631,7 +1819,6 @@ var GATE_COMMANDS = [
1631
1819
  { name: "gate-enter-plan", description: "\u57FA\u4E8E\u8BA8\u8BBA\u5171\u8BC6\u3001\u65E2\u6709\u51B3\u7B56\u4E0E\u7528\u6237\u9700\u6C42\u8FDB\u5165 planning", hint: "<\u5177\u4F53\u5DE5\u4F5C\u4E8B\u9879\u6216\u4E0A\u4E0B\u6587\u8BED\u4E49>", when: "discuss/complete" },
1632
1820
  { name: "gate-enter-implement", description: "\u57FA\u4E8E\u5DF2\u786E\u8BA4\u8BA1\u5212\u6216\u8BA8\u8BBA\u540E\u7684\u5B9E\u65BD\u8BF4\u660E\u8FDB\u5165 implementation", hint: "<\u5177\u4F53\u5DE5\u4F5C\u4E8B\u9879\u6216\u4E0A\u4E0B\u6587\u8BED\u4E49>", when: "discuss/complete" },
1633
1821
  { name: "gate-prd", description: "\u5728 discuss \u4E2D\u6309\u7528\u6237\u8981\u6C42\u521B\u5EFA\u6216\u66F4\u65B0 PRD", hint: "[\u4E3B\u9898\u6216\u4E0A\u4E0B\u6587\u8BED\u4E49]", when: "discuss" },
1634
- { name: "gate-fix-bug", description: "\u4E3A\u5DF2\u6388\u6743\u7F3A\u9677\u6D3E\u53D1 fix worker\uFF0C\u57FA\u4E8E\u63CF\u8FF0\u6216\u5F53\u524D\u4E0A\u4E0B\u6587\u4FEE\u590D", hint: "<\u5177\u4F53\u5DE5\u4F5C\u4E8B\u9879\u6216\u4E0A\u4E0B\u6587\u8BED\u4E49>", when: "discuss/complete" },
1635
1822
  { name: "gate-docs", description: "\u8FDB\u5165\u6587\u6863\u6CBB\u7406\uFF0C\u6309\u9879\u76EE\u6587\u6863\u89C4\u8303\u5904\u7406", hint: "[\u6587\u6863\u8303\u56F4\u6216\u4E0A\u4E0B\u6587\u8BED\u4E49]", when: "discuss/complete" },
1636
1823
  { name: "gate-implement-review", description: "\u5BF9\u5F53\u524D\u6539\u52A8\u505A\u72EC\u7ACB\u53EA\u8BFB code review", hint: "<\u5177\u4F53\u5DE5\u4F5C\u4E8B\u9879\u6216\u4E0A\u4E0B\u6587\u8BED\u4E49>", when: "discuss/complete" },
1637
1824
  { name: "gate-code-verify", description: "\u5BF9\u5F53\u524D\u6539\u52A8\u505A\u72EC\u7ACB\u53EA\u8BFB\u9A8C\u6536\uFF08gate-user-verify\uFF09", hint: "<\u5177\u4F53\u5DE5\u4F5C\u4E8B\u9879\u6216\u4E0A\u4E0B\u6587\u8BED\u4E49>", when: "discuss/complete" },
@@ -1691,25 +1878,28 @@ function registerCommands(ctx, deps) {
1691
1878
  command2("gate-init", async (invocation) => {
1692
1879
  const workspace = workspaceBoundary(ctx, invocation.agent);
1693
1880
  if (workspace === void 0) return { kind: "error", text: "\u65E0\u6CD5\u786E\u5B9A\u5F53\u524D\u4F1A\u8BDD\u5DE5\u4F5C\u533A" };
1694
- const root = path10.resolve(workspace);
1881
+ const root = path11.resolve(workspace);
1695
1882
  let provisioned;
1696
1883
  let projectScripts;
1697
1884
  let projectCi;
1698
1885
  let projectGit;
1699
1886
  let artifactPolicy;
1887
+ let initManifest;
1700
1888
  try {
1701
1889
  provisioned = provisionNotes(root);
1702
1890
  artifactPolicy = provisionArtifactPolicy(root);
1703
1891
  projectCi = provisionCi(root);
1704
1892
  projectScripts = provisionProjectScripts(root);
1705
1893
  projectGit = provisionGit(root);
1894
+ initManifest = provisionInitManifest(root, projectScripts.command);
1706
1895
  } catch (error) {
1707
1896
  return { kind: "error", text: `notes \u521D\u59CB\u5316\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}` };
1708
1897
  }
1709
- wake(invocation, store.read(root, invocation.agent), `Gate \u5DF2\u521D\u59CB\u5316\uFF1A${root}\uFF08phase=discuss\uFF09\uFF0Cnotes \u5DF2\u521D\u59CB\u5316\u4E3A ${provisioned.notes}\uFF0Cartifact policy \u4E3A ${artifactPolicy.path}\uFF08${artifactPolicy.status}\uFF09\uFF0CAGENTS.md \u5DF2\u66F4\u65B0\uFF0Cverify-notes \u5DF2\u914D\u7F6E\u4E3A ${projectScripts.command}\uFF0CCI \u5DF2\u914D\u7F6E\u4E3A ${projectCi.workflow}\uFF0Cgit\uFF1A${projectGit.git}${projectGit.gitError === null ? "" : `\uFF08${projectGit.gitError}\uFF09`}\uFF0Cignore\uFF1A${projectGit.ignore}\u3002`, "gate-init");
1898
+ wake(invocation, store.read(root, invocation.agent), `Gate \u5DF2\u521D\u59CB\u5316\uFF1A${root}\uFF08phase=discuss\uFF09\uFF0Cnotes \u5DF2\u521D\u59CB\u5316\u4E3A ${provisioned.notes}\uFF0Cartifact policy \u4E3A ${artifactPolicy.path}\uFF08${artifactPolicy.status}\uFF09\uFF0Cinit manifest \u4E3A ${initManifest.path}\uFF08${initManifest.status}\uFF09\uFF0CAGENTS.md \u5DF2\u66F4\u65B0\uFF0Cverify-notes \u5DF2\u914D\u7F6E\u4E3A ${projectScripts.command}\uFF0CCI \u5DF2\u914D\u7F6E\u4E3A ${projectCi.workflow}\uFF0Cgit\uFF1A${projectGit.git}${projectGit.gitError === null ? "" : `\uFF08${projectGit.gitError}\uFF09`}\uFF0Cignore\uFF1A${projectGit.ignore}\u3002`, "gate-init");
1710
1899
  return { kind: "success", text: `Gate \u5DF2\u521D\u59CB\u5316\uFF1A${root}\uFF08phase=discuss\uFF09
1711
1900
  notes\uFF1A${provisioned.notes}
1712
1901
  artifact policy\uFF1A${artifactPolicy.path}\uFF08${artifactPolicy.status}\uFF09
1902
+ init manifest\uFF1A${initManifest.path}\uFF08${initManifest.status}\uFF09
1713
1903
  AGENTS\uFF1A${provisioned.agents}
1714
1904
  verify-notes\uFF1A${projectScripts.command}
1715
1905
  CI\uFF1A${projectCi.workflow}
@@ -1753,29 +1943,12 @@ ignore\uFF1A${projectGit.ignore}` };
1753
1943
  const topic = String(invocation.rawInput ?? "").trim() || "\u5F53\u524D\u8BA8\u8BBA";
1754
1944
  let skill = "";
1755
1945
  try {
1756
- skill = readFileSync4(path10.join(SKILLS, "gate-prd", "SKILL.md"), "utf8");
1946
+ skill = readFileSync5(path11.join(SKILLS, "gate-prd", "SKILL.md"), "utf8");
1757
1947
  } catch {
1758
1948
  }
1759
1949
  wake(invocation, state, ["\u8BF7\u6309 gate-prd \u6280\u80FD\u521B\u5EFA\u6216\u66F4\u65B0 PRD\u3002", "\u4E3B\u9898/\u4E0A\u4E0B\u6587\uFF1A" + topic, skill].filter(Boolean).join("\n\n"), "gate-prd");
1760
1950
  return { kind: "success", text: "\u5DF2\u8BF7\u6C42 PRD\uFF1A" + topic };
1761
1951
  });
1762
- command2("gate-fix-bug", async (invocation) => {
1763
- const brief = String(invocation.rawInput ?? "").trim();
1764
- const gate = resolveGate(ctx, invocation.agent);
1765
- const state = store.read(gate.root, invocation.agent);
1766
- if (state.phase !== "discuss" && state.phase !== "complete") return { kind: "error", text: `\u5F53\u524D phase \u662F ${state.phase}` };
1767
- if (state.work === "blocked" || state.blockReason !== null) return { kind: "error", text: `\u5F53\u524D\u88AB blocked\uFF1A${state.blockReason ?? "unknown"}\uFF1B\u5148 /gate-resume` };
1768
- const scope2 = brief === "" ? state.task ?? "\u5F53\u524D\u4E0A\u4E0B\u6587\u4E2D\u7684\u7F3A\u9677" : brief;
1769
- state.phase = "orchestrating";
1770
- state.node = "fix-bug";
1771
- state.task = scope2;
1772
- state.work = "active";
1773
- state.blockReason = null;
1774
- state.blockedFrom = null;
1775
- store.write(gate.root, invocation.agent, state);
1776
- wake(invocation, state, `Gate \u5DF2\u8FDB\u5165 fix-bug\uFF1A${scope2}\u3002`, "gate-fix-bug");
1777
- return { kind: "success", text: `\u8FDB\u5165 fix-bug\uFF1A${scope2}` };
1778
- });
1779
1952
  command2("gate-docs", async (invocation) => {
1780
1953
  const scope2 = String(invocation.rawInput ?? "").trim() || "\u6587\u6863\u6CBB\u7406";
1781
1954
  const gate = resolveGate(ctx, invocation.agent);
@@ -1783,6 +1956,7 @@ ignore\uFF1A${projectGit.ignore}` };
1783
1956
  if (state.phase !== "discuss" && state.phase !== "complete") return { kind: "error", text: `\u5F53\u524D phase \u662F ${state.phase}` };
1784
1957
  if (state.work === "blocked" || state.blockReason !== null) return { kind: "error", text: `\u5F53\u524D\u88AB blocked\uFF1A${state.blockReason ?? "unknown"}\uFF1B\u5148 /gate-resume` };
1785
1958
  state.phase = "docs";
1959
+ state.revision = null;
1786
1960
  state.task = scope2;
1787
1961
  state.work = "active";
1788
1962
  state.blockReason = null;
@@ -1802,6 +1976,7 @@ ignore\uFF1A${projectGit.ignore}` };
1802
1976
  state.phase = "reviewing";
1803
1977
  state.task = scope2;
1804
1978
  state.node = "code-review-standalone";
1979
+ state.revision = null;
1805
1980
  state.work = "active";
1806
1981
  state.blockReason = null;
1807
1982
  state.blockedFrom = null;
@@ -1819,6 +1994,7 @@ ignore\uFF1A${projectGit.ignore}` };
1819
1994
  state.phase = "reviewing";
1820
1995
  state.task = scope2;
1821
1996
  state.node = "verify-standalone";
1997
+ state.revision = null;
1822
1998
  state.work = "active";
1823
1999
  state.blockReason = null;
1824
2000
  state.blockedFrom = null;
@@ -1836,6 +2012,7 @@ ignore\uFF1A${projectGit.ignore}` };
1836
2012
  state.phase = "reviewing";
1837
2013
  state.task = scope2;
1838
2014
  state.node = "proposal-review";
2015
+ state.revision = null;
1839
2016
  state.work = "active";
1840
2017
  state.blockReason = null;
1841
2018
  state.blockedFrom = null;
@@ -1881,6 +2058,7 @@ ignore\uFF1A${projectGit.ignore}` };
1881
2058
  if (state.phase === "blocked") return { kind: "error", text: `\u5F53\u524D blocked\uFF1A${state.blockReason ?? "unknown"}\uFF1B\u5148 /gate-resume` };
1882
2059
  state.phase = "discuss";
1883
2060
  state.node = null;
2061
+ state.revision = null;
1884
2062
  state.work = "active";
1885
2063
  state.blockReason = null;
1886
2064
  state.blockedFrom = null;
@@ -1920,8 +2098,8 @@ ${JSON.stringify(check.results, null, 2)}` };
1920
2098
  const node = resolveNodeBinary();
1921
2099
  if (node === void 0) return { kind: "error", text: "notes-runtime-unavailable" };
1922
2100
  try {
1923
- const script = path10.join(NOTES_SKILL_DIR, "scripts", "archive-agent-note.ts");
1924
- const output = execFileSync3(node, [script, "--root", path10.join(gate.root, ".agents", "notes"), ...args], { cwd: gate.root, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
2101
+ const script = path11.join(NOTES_SKILL_DIR, "scripts", "archive-agent-note.ts");
2102
+ const output = execFileSync3(node, [script, "--root", path11.join(gate.root, ".agents", "notes"), ...args], { cwd: gate.root, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
1925
2103
  return { kind: "success", text: String(output).trim() || "Note \u5DF2\u5F52\u6863" };
1926
2104
  } catch (error) {
1927
2105
  return { kind: "error", text: String(error?.stderr ?? error?.message ?? error).trim() };
@@ -1932,11 +2110,11 @@ ${JSON.stringify(check.results, null, 2)}` };
1932
2110
  const raw = String(invocation.rawInput ?? "").trim();
1933
2111
  const args = raw === "" ? [] : raw.split(/\s+/u);
1934
2112
  const target = args[0] ?? "board.html";
1935
- const title = args[1] ?? `${path10.basename(gate.root)} \u51B3\u7B56\u770B\u677F`;
2113
+ const title = args[1] ?? `${path11.basename(gate.root)} \u51B3\u7B56\u770B\u677F`;
1936
2114
  const node = resolveNodeBinary();
1937
2115
  if (node === void 0) return { kind: "error", text: "notes-runtime-unavailable" };
1938
2116
  try {
1939
- const script = path10.join(NOTES_SKILL_DIR, "scripts", "build-board.ts");
2117
+ const script = path11.join(NOTES_SKILL_DIR, "scripts", "build-board.ts");
1940
2118
  const output = execFileSync3(node, [script, "--init", target, title], { cwd: gate.root, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
1941
2119
  return { kind: "success", text: String(output).trim() || `\u51B3\u7B56\u770B\u677F\u5DF2\u751F\u6210\uFF1A${target}` };
1942
2120
  } catch (error) {
@@ -1948,8 +2126,8 @@ ${JSON.stringify(check.results, null, 2)}` };
1948
2126
  const node = resolveNodeBinary();
1949
2127
  if (node === void 0) return { kind: "error", text: "notes-runtime-unavailable" };
1950
2128
  try {
1951
- const script = path10.join(NOTES_SKILL_DIR, "scripts", "verify-archived-agent-notes.ts");
1952
- const output = execFileSync3(node, [script, "--root", path10.join(gate.root, ".agents", "notes"), "--write"], { cwd: gate.root, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
2129
+ const script = path11.join(NOTES_SKILL_DIR, "scripts", "verify-archived-agent-notes.ts");
2130
+ const output = execFileSync3(node, [script, "--root", path11.join(gate.root, ".agents", "notes"), "--write"], { cwd: gate.root, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
1953
2131
  return { kind: "success", text: String(output).trim() || "archived manifest \u5DF2\u5199\u5165" };
1954
2132
  } catch (error) {
1955
2133
  return { kind: "error", text: String(error?.stderr ?? error?.message ?? error).trim() };
@@ -2017,13 +2195,13 @@ function registerStartPhase(ctx, deps) {
2017
2195
  }
2018
2196
 
2019
2197
  // src/tools/record.ts
2020
- import { createHash } from "node:crypto";
2021
- import { existsSync as existsSync5, lstatSync as lstatSync5, readFileSync as readFileSync5 } from "node:fs";
2198
+ import { createHash as createHash2 } from "node:crypto";
2199
+ import { existsSync as existsSync6, lstatSync as lstatSync5, readFileSync as readFileSync6 } from "node:fs";
2022
2200
  function registerRecord(ctx, deps) {
2023
2201
  const { store, reviewLimit, wake } = deps;
2024
2202
  ctx.tools.register({
2025
2203
  name: "gate_record",
2026
- description: "\u8BB0\u5F55 root agent \u6D3E\u53D1\u7684\u8282\u70B9 worker \u7ED3\u679C\u5E76\u63A8\u8FDB gate \u72B6\u6001\u3002worker \u8282\u70B9\u8981\u6C42 workerSessionIds\uFF1Breview \u8282\u70B9\u8981\u6C42\u4E24\u8F74\u7ED3\u679C\uFF1Bverify \u8981\u6C42 toolResults\u3002\u4EC5 root agent \u53EF\u8C03\u7528\u3002",
2204
+ description: "\u8BB0\u5F55 root agent \u6D3E\u53D1\u7684\u8282\u70B9 worker \u7ED3\u679C\u5E76\u63A8\u8FDB gate \u72B6\u6001\u3002\u9996\u6B21 plan/implement\u3001review\u3001verify \u7B49 worker \u8282\u70B9\u8981\u6C42 workerSessionIds\uFF1Bplan/implement \u4FEE\u8BA2\u53EF\u7701\u7565\uFF1Breview \u8282\u70B9\u8981\u6C42\u4E24\u8F74\u7ED3\u679C\uFF1Bverify \u8981\u6C42 toolResults\u3002\u4EC5 root agent \u53EF\u8C03\u7528\u3002",
2027
2205
  parameters: {
2028
2206
  type: "object",
2029
2207
  additionalProperties: false,
@@ -2079,6 +2257,7 @@ function registerRecord(ctx, deps) {
2079
2257
  if (args.node !== "docs") return fail({ code: "wrong-node", expected: "docs", got: args.node ?? null, reason: 'docs \u9636\u6BB5\u53EA\u80FD\u901A\u8FC7 gate_record({node:"docs"}) \u7ED3\u675F\u3002' });
2080
2258
  state.phase = "discuss";
2081
2259
  state.node = null;
2260
+ state.revision = null;
2082
2261
  state.work = "active";
2083
2262
  state.blockReason = null;
2084
2263
  state.blockedFrom = null;
@@ -2092,7 +2271,7 @@ function registerRecord(ctx, deps) {
2092
2271
  if (state.node !== args.node) return fail({ code: "wrong-node", expected: state.node ?? null, got: args.node ?? null, reason: `\u5F53\u524D\u8282\u70B9\u662F ${state.node ?? "\u65E0"}\uFF0C\u8BF7\u6C42\u7684 node \u662F ${args.node ?? "\u672A\u63D0\u4F9B"}\u3002` });
2093
2272
  const axesError = reviewAxesError(args);
2094
2273
  if (axesError !== void 0) return fail(axesError);
2095
- const workerError = await workerEvidenceError(ctx, root, args);
2274
+ const workerError = await workerEvidenceError(ctx, root, args, state);
2096
2275
  if (workerError !== void 0) return fail(workerError);
2097
2276
  const topFindings = Array.isArray(args.findings) ? args.findings : [];
2098
2277
  const axesFindings = REVIEW_NODES.has(args.node) ? [
@@ -2119,44 +2298,53 @@ function registerRecord(ctx, deps) {
2119
2298
  state.work = "active";
2120
2299
  state.blockReason = null;
2121
2300
  state.blockedFrom = null;
2301
+ state.revision = null;
2122
2302
  } else if (args.node === "code-review-standalone") {
2123
2303
  state.phase = "discuss";
2124
2304
  state.node = null;
2305
+ state.revision = null;
2125
2306
  state.work = "active";
2126
2307
  state.blockReason = null;
2127
2308
  } else if (args.node === "plan") {
2128
- if (typeof args.task !== "string" || args.task.trim() === "") {
2129
- return fail({ code: "task-required", reason: "node=plan \u5FC5\u987B\u643A\u5E26 task\uFF08\u5DE5\u4F5C\u9879\u7B80\u8FF0\uFF1Bmechanical \u7528 noteDecision \u8868\u793A\uFF09\u3002" });
2130
- }
2131
- const decision = args.noteDecision;
2132
- if (!isNoteDecision(decision)) {
2133
- return fail({ code: "note-decision-required", reason: "node=plan \u9700\u8981 noteDecision\uFF08new/update/in-place/mechanical\uFF09\u3002" });
2134
- }
2135
- const optionNotePaths = notePathsForDecision(args.notePaths, decision);
2136
- const noteError = validateNotePaths(gate.root, optionNotePaths, decision);
2137
- if (noteError !== void 0) return fail(noteError);
2138
- state.task = args.task.trim();
2139
- state.notePaths = isMechanicalDecision(decision) ? [] : optionNotePaths;
2140
- state.noteDecision = decision;
2141
- state.noteSearch = typeof args.noteSearch === "string" ? args.noteSearch : null;
2142
- state.noteVerified = isMechanicalDecision(decision);
2143
- state.node = "plan-review";
2144
- } else if (args.node === "plan-revise") {
2145
- if (args.noteDecision !== void 0 || args.notePaths !== void 0) {
2309
+ if (state.revision?.from === "plan-review") {
2146
2310
  const decision = args.noteDecision ?? state.noteDecision;
2311
+ if (args.noteDecision !== void 0 && !isNoteDecision(args.noteDecision)) {
2312
+ return fail({ code: "note-decision-required", reason: "plan \u4FEE\u8BA2\u7684 noteDecision \u5FC5\u987B\u662F new/update/in-place/mechanical\u3002" });
2313
+ }
2314
+ if (args.noteDecision !== void 0 || args.notePaths !== void 0) {
2315
+ if (!isNoteDecision(decision)) {
2316
+ return fail({ code: "note-decision-required", reason: "plan \u4FEE\u8BA2\u66F4\u65B0 notePaths \u9700\u8981\u5408\u6CD5 noteDecision\u3002" });
2317
+ }
2318
+ const requestedNotePaths = args.notePaths ?? state.notePaths;
2319
+ const optionNotePaths = notePathsForDecision(requestedNotePaths, decision);
2320
+ const noteError = validateNotePaths(gate.root, optionNotePaths, decision);
2321
+ if (noteError !== void 0) return fail(noteError);
2322
+ state.notePaths = isMechanicalDecision(decision) ? [] : optionNotePaths;
2323
+ state.noteDecision = decision;
2324
+ if (typeof args.noteSearch === "string") state.noteSearch = args.noteSearch;
2325
+ state.noteVerified = isMechanicalDecision(decision);
2326
+ }
2327
+ state.revision = null;
2328
+ state.node = "plan-review";
2329
+ } else {
2330
+ if (typeof args.task !== "string" || args.task.trim() === "") {
2331
+ return fail({ code: "task-required", reason: "node=plan \u5FC5\u987B\u643A\u5E26 task\uFF08\u5DE5\u4F5C\u9879\u7B80\u8FF0\uFF1Bmechanical \u7528 noteDecision \u8868\u793A\uFF09\u3002" });
2332
+ }
2333
+ const decision = args.noteDecision;
2147
2334
  if (!isNoteDecision(decision)) {
2148
- return fail({ code: "note-decision-required", reason: "plan-revise \u9700\u8981\u5408\u6CD5 noteDecision\u3002" });
2335
+ return fail({ code: "note-decision-required", reason: "node=plan \u9700\u8981 noteDecision\uFF08new/update/in-place/mechanical\uFF09\u3002" });
2149
2336
  }
2150
- const requestedNotePaths = args.notePaths ?? state.notePaths;
2151
- const optionNotePaths = notePathsForDecision(requestedNotePaths, decision);
2337
+ const optionNotePaths = notePathsForDecision(args.notePaths, decision);
2152
2338
  const noteError = validateNotePaths(gate.root, optionNotePaths, decision);
2153
2339
  if (noteError !== void 0) return fail(noteError);
2340
+ state.task = args.task.trim();
2154
2341
  state.notePaths = isMechanicalDecision(decision) ? [] : optionNotePaths;
2155
2342
  state.noteDecision = decision;
2156
- if (typeof args.noteSearch === "string") state.noteSearch = args.noteSearch;
2343
+ state.noteSearch = typeof args.noteSearch === "string" ? args.noteSearch : null;
2157
2344
  state.noteVerified = isMechanicalDecision(decision);
2345
+ state.revision = null;
2346
+ state.node = "plan-review";
2158
2347
  }
2159
- state.node = "plan-review";
2160
2348
  } else if (args.node === "plan-review") {
2161
2349
  state.rounds.planReview += 1;
2162
2350
  if (findings.length === 0) {
@@ -2165,6 +2353,7 @@ function registerRecord(ctx, deps) {
2165
2353
  state.planReady = true;
2166
2354
  state.work = "active";
2167
2355
  state.blockReason = null;
2356
+ state.revision = null;
2168
2357
  commitHint = "\u5EFA\u8BAE\u63D0\u4EA4 planning baseline\uFF08Note + \u8BA1\u5212\uFF09";
2169
2358
  } else if (state.rounds.planReview >= reviewLimit) {
2170
2359
  state.exhausted.plan = true;
@@ -2173,45 +2362,74 @@ function registerRecord(ctx, deps) {
2173
2362
  state.node = null;
2174
2363
  state.work = "blocked";
2175
2364
  state.blockReason = "plan-review-rounds-exhausted";
2176
- } else state.node = "plan-revise";
2177
- } else if (args.node === "implement") {
2178
- if (args.noteDecision !== void 0 && !isNoteDecision(args.noteDecision)) {
2179
- return fail({ code: "note-decision-required", reason: "implement \u7684 noteDecision \u5FC5\u987B\u662F new/update/in-place/mechanical\u3002" });
2180
- }
2181
- const decision = args.noteDecision ?? state.noteDecision;
2182
- if (decision !== null && !isNoteDecision(decision)) {
2183
- return fail({ code: "note-decision-required", reason: "implement \u7684 noteDecision \u5FC5\u987B\u662F new/update/in-place/mechanical\u3002" });
2184
- }
2185
- if (isMechanicalDecision(args.noteDecision)) {
2186
- state.noteDecision = MECHANICAL_DECISION;
2187
- state.notePaths = [];
2188
- state.noteVerified = true;
2189
- } else if (args.noteDecision === void 0 && isMechanicalDecision(state.noteDecision)) {
2365
+ state.revision = null;
2190
2366
  } else {
2191
- if (Array.isArray(args.notePaths)) {
2367
+ state.revision = { from: "plan-review", findings, round: state.rounds.planReview };
2368
+ state.node = "plan";
2369
+ }
2370
+ } else if (args.node === "implement") {
2371
+ if (state.revision?.from === "code-review" || state.revision?.from === "verify") {
2372
+ if (args.noteDecision !== void 0 && !isNoteDecision(args.noteDecision)) {
2373
+ return fail({ code: "note-decision-required", reason: "implement \u4FEE\u8BA2\u7684 noteDecision \u5FC5\u987B\u662F new/update/in-place/mechanical\u3002" });
2374
+ }
2375
+ if (args.notePaths !== void 0) {
2376
+ const decision = args.noteDecision ?? state.noteDecision;
2192
2377
  if (!isNoteDecision(decision)) {
2193
- return fail({ code: "note-decision-required", reason: "implement \u5199 notePaths \u9700\u8981\u5408\u6CD5 noteDecision\u3002" });
2378
+ return fail({ code: "note-decision-required", reason: "implement \u4FEE\u8BA2\u66F4\u65B0 notePaths \u9700\u8981\u5408\u6CD5 noteDecision\u3002" });
2194
2379
  }
2195
2380
  const nextNotePaths = normalizeNotePaths(args.notePaths);
2196
2381
  const noteError = validateNotePaths(gate.root, nextNotePaths, decision);
2197
2382
  if (noteError !== void 0) return fail(noteError);
2198
2383
  state.notePaths = nextNotePaths;
2384
+ state.noteDecision = decision;
2385
+ state.noteVerified = isMechanicalDecision(decision);
2386
+ }
2387
+ state.revision = null;
2388
+ state.node = "code-review";
2389
+ } else {
2390
+ if (args.noteDecision !== void 0 && !isNoteDecision(args.noteDecision)) {
2391
+ return fail({ code: "note-decision-required", reason: "implement \u7684 noteDecision \u5FC5\u987B\u662F new/update/in-place/mechanical\u3002" });
2199
2392
  }
2200
- if (isNoteDecision(args.noteDecision) && !isMechanicalDecision(args.noteDecision)) state.noteDecision = args.noteDecision;
2393
+ const decision = args.noteDecision ?? state.noteDecision;
2394
+ if (decision !== null && !isNoteDecision(decision)) {
2395
+ return fail({ code: "note-decision-required", reason: "implement \u7684 noteDecision \u5FC5\u987B\u662F new/update/in-place/mechanical\u3002" });
2396
+ }
2397
+ if (isMechanicalDecision(args.noteDecision)) {
2398
+ state.noteDecision = MECHANICAL_DECISION;
2399
+ state.notePaths = [];
2400
+ state.noteVerified = true;
2401
+ } else if (args.noteDecision === void 0 && isMechanicalDecision(state.noteDecision)) {
2402
+ } else {
2403
+ if (Array.isArray(args.notePaths)) {
2404
+ if (!isNoteDecision(decision)) {
2405
+ return fail({ code: "note-decision-required", reason: "implement \u5199 notePaths \u9700\u8981\u5408\u6CD5 noteDecision\u3002" });
2406
+ }
2407
+ const nextNotePaths = normalizeNotePaths(args.notePaths);
2408
+ const noteError = validateNotePaths(gate.root, nextNotePaths, decision);
2409
+ if (noteError !== void 0) return fail(noteError);
2410
+ state.notePaths = nextNotePaths;
2411
+ }
2412
+ if (isNoteDecision(args.noteDecision) && !isMechanicalDecision(args.noteDecision)) state.noteDecision = args.noteDecision;
2413
+ }
2414
+ state.revision = null;
2415
+ state.node = "code-review";
2201
2416
  }
2202
- state.node = "code-review";
2203
- } else if (args.node === "implement-revise") state.node = "code-review";
2204
- else if (args.node === "code-review") {
2417
+ } else if (args.node === "code-review") {
2205
2418
  state.rounds.codeReview += 1;
2206
- if (findings.length === 0) state.node = "verify";
2207
- else if (state.rounds.codeReview >= reviewLimit) {
2419
+ if (findings.length === 0) {
2420
+ state.node = "verify";
2421
+ state.revision = null;
2422
+ } else if (state.rounds.codeReview >= reviewLimit) {
2208
2423
  state.exhausted.code = true;
2209
2424
  state.blockedFrom = { phase: "discuss", node: null };
2210
2425
  state.phase = "blocked";
2211
2426
  state.node = null;
2212
2427
  state.work = "blocked";
2213
2428
  state.blockReason = "code-review-rounds-exhausted";
2214
- } else state.node = "implement-revise";
2429
+ } else {
2430
+ state.revision = { from: "code-review", findings, round: state.rounds.codeReview };
2431
+ state.node = "implement";
2432
+ }
2215
2433
  } else if (args.node === "verify" || args.node === "verify-standalone") {
2216
2434
  const verification = args.verification;
2217
2435
  const commands = Array.isArray(verification?.commands) ? verification.commands.filter((item) => typeof item === "string" && item.trim() !== "") : [];
@@ -2224,12 +2442,12 @@ function registerRecord(ctx, deps) {
2224
2442
  for (const item of evidence) {
2225
2443
  const target = classifyPath(gate.workspace, item);
2226
2444
  try {
2227
- if (target.outside || !existsSync5(target.absolute) || !lstatSync5(target.absolute).isFile()) {
2445
+ if (target.outside || !existsSync6(target.absolute) || !lstatSync5(target.absolute).isFile()) {
2228
2446
  invalidEvidence.push(item);
2229
2447
  continue;
2230
2448
  }
2231
- const bytes = readFileSync5(target.absolute);
2232
- records.push({ path: target.relative, size: bytes.length, sha256: createHash("sha256").update(bytes).digest("hex") });
2449
+ const bytes = readFileSync6(target.absolute);
2450
+ records.push({ path: target.relative, size: bytes.length, sha256: createHash2("sha256").update(bytes).digest("hex") });
2233
2451
  } catch {
2234
2452
  invalidEvidence.push(item);
2235
2453
  }
@@ -2248,14 +2466,17 @@ function registerRecord(ctx, deps) {
2248
2466
  };
2249
2467
  if (args.node === "verify-standalone") {
2250
2468
  state.phase = "discuss";
2469
+ state.revision = null;
2251
2470
  state.node = null;
2252
2471
  state.work = "active";
2253
2472
  state.blockReason = null;
2254
2473
  state.blockedFrom = null;
2255
2474
  } else if (verification.passed !== true) {
2256
- state.node = "implement-revise";
2475
+ state.revision = { from: "verify", findings: [], round: state.rounds.codeReview };
2476
+ state.node = "implement";
2257
2477
  state.noteVerified = false;
2258
2478
  } else if (isMechanicalDecision(state.noteDecision)) {
2479
+ state.revision = null;
2259
2480
  state.noteVerified = true;
2260
2481
  state.noteFinalized = true;
2261
2482
  commitHint = "\u5EFA\u8BAE\u63D0\u4EA4\u5B9E\u73B0";
@@ -2267,6 +2488,7 @@ function registerRecord(ctx, deps) {
2267
2488
  state.task = null;
2268
2489
  state.planReady = false;
2269
2490
  } else {
2491
+ state.revision = null;
2270
2492
  state.phase = "orchestrating";
2271
2493
  state.node = "note-lifecycle";
2272
2494
  state.work = "active";
@@ -2274,18 +2496,11 @@ function registerRecord(ctx, deps) {
2274
2496
  state.noteFinalized = false;
2275
2497
  state.noteFinalizeRecovery = [];
2276
2498
  }
2277
- } else if (args.node === "fix-bug") {
2278
- state.phase = "discuss";
2279
- state.node = null;
2280
- state.work = "active";
2281
- state.blockReason = null;
2282
- state.blockedFrom = null;
2283
- state.task = null;
2284
- state.planReady = false;
2285
2499
  } else if (args.node === "note-lifecycle") {
2286
2500
  if (state.noteVerified !== true) {
2287
2501
  return fail({ code: "note-lifecycle-incomplete", reason: "note-lifecycle \u9700\u8981\u5148 gate_note_finalize + gate_note_verify\u3002" });
2288
2502
  }
2503
+ state.revision = null;
2289
2504
  commitHint = "\u5EFA\u8BAE\u63D0\u4EA4\u672C\u6B21\u5B9E\u73B0\u4E0E Note";
2290
2505
  state.phase = "discuss";
2291
2506
  state.node = null;
@@ -2347,8 +2562,8 @@ function registerStatus(ctx, deps) {
2347
2562
  }
2348
2563
 
2349
2564
  // src/tools/notes.ts
2350
- import { existsSync as existsSync6, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5 } from "node:fs";
2351
- import path11 from "node:path";
2565
+ import { existsSync as existsSync7, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "node:fs";
2566
+ import path12 from "node:path";
2352
2567
  function registerNoteTools(ctx, deps) {
2353
2568
  const { store, reviewLimit, wake } = deps;
2354
2569
  ctx.tools.register({
@@ -2370,11 +2585,11 @@ function registerNoteTools(ctx, deps) {
2370
2585
  async execute(args, exec) {
2371
2586
  const gate = resolveGate(ctx, exec.agent);
2372
2587
  const effective = effectiveState(ctx, exec.agent, gate, store);
2373
- if (!effective.worker || !["plan", "plan-revise"].includes(effective.state.node ?? "")) {
2374
- return { ok: false, code: "planning-only", reason: "gate_note_write \u53EA\u5141\u8BB8 planning worker \u5728 plan/plan-revise \u8282\u70B9\u4F7F\u7528\u3002" };
2588
+ if (!effective.worker || effective.state.node !== "plan") {
2589
+ return { ok: false, code: "planning-only", reason: "gate_note_write \u53EA\u5141\u8BB8 planning worker \u5728 plan \u8282\u70B9\u4F7F\u7528\u3002" };
2375
2590
  }
2376
2591
  let relative = String(args.path ?? "").replaceAll("\\", "/").replace(/^\.?\//u, "");
2377
- if (relative === "" || relative.includes("..") || path11.isAbsolute(relative) || !relative.endsWith(".md")) {
2592
+ if (relative === "" || relative.includes("..") || path12.isAbsolute(relative) || !relative.endsWith(".md")) {
2378
2593
  return { ok: false, code: "invalid-path" };
2379
2594
  }
2380
2595
  let lifecycle = "proposed";
@@ -2386,16 +2601,16 @@ function registerNoteTools(ctx, deps) {
2386
2601
  if (!/^(?:feature|bug-fix|simplification|architecture|process|testing)\/\d{4}-\d{2}-\d{2}-.+\.md$/u.test(relative)) {
2387
2602
  return { ok: false, code: "invalid-path", reason: "\u9700\u8981 <class>/yyyy-mm-dd-topic.md\uFF0C\u6216 proposed|implemented/<class>/...\u3002" };
2388
2603
  }
2389
- const base = path11.join(gate.root, ".agents", "notes", String(lifecycle));
2390
- const absolute = path11.resolve(base, relative);
2604
+ const base = path12.join(gate.root, ".agents", "notes", String(lifecycle));
2605
+ const absolute = path12.resolve(base, relative);
2391
2606
  if (!isInside(base, absolute)) return { ok: false, code: "invalid-path" };
2392
2607
  if (pathHasSymlink(base, absolute)) return { ok: false, code: "invalid-path" };
2393
- if (lifecycle === "implemented" && !existsSync6(absolute)) {
2608
+ if (lifecycle === "implemented" && !existsSync7(absolute)) {
2394
2609
  return { ok: false, code: "implemented-must-exist", reason: "implemented Note \u53EA\u80FD\u539F\u5730\u7F16\u8F91\uFF0C\u4E0D\u80FD\u65B0\u5EFA\u3002" };
2395
2610
  }
2396
- mkdirSync5(path11.dirname(absolute), { recursive: true });
2397
- writeFileSync5(absolute, String(args.content ?? ""));
2398
- return { ok: true, path: path11.relative(gate.root, absolute).replaceAll("\\", "/"), lifecycle };
2611
+ mkdirSync6(path12.dirname(absolute), { recursive: true });
2612
+ writeFileSync6(absolute, String(args.content ?? ""));
2613
+ return { ok: true, path: path12.relative(gate.root, absolute).replaceAll("\\", "/"), lifecycle };
2399
2614
  }
2400
2615
  });
2401
2616
  ctx.tools.register({
@@ -2418,7 +2633,7 @@ function registerNoteTools(ctx, deps) {
2418
2633
  if (!check.ok) return { ...check, state: normalizeState(state) };
2419
2634
  if (state.node === "note-lifecycle") {
2420
2635
  if (state.noteFinalized !== true) return { ok: false, code: "note-lifecycle-incomplete", reason: "\u5148\u8C03\u7528 gate_note_finalize\u3002", state: normalizeState(state) };
2421
- const implemented = state.notePaths.length > 0 && state.notePaths.every((entry) => entry.lifecycle === "implemented" && existsSync6(path11.join(gate.root, entry.path)));
2636
+ const implemented = state.notePaths.length > 0 && state.notePaths.every((entry) => entry.lifecycle === "implemented" && existsSync7(path12.join(gate.root, entry.path)));
2422
2637
  if (!implemented) return { ok: false, code: "note-lifecycle-incomplete", reason: "notePaths \u5C1A\u672A\u5168\u90E8\u8FDB\u5165 implemented\u3002", results: check.results, state: normalizeState(state) };
2423
2638
  state.noteVerified = true;
2424
2639
  store.write(gate.root, exec.agent, state);
@@ -2466,9 +2681,9 @@ function registerNoteTools(ctx, deps) {
2466
2681
  const recovered = recoverFinalize(gate.root, sessionId);
2467
2682
  for (const entry of state.notePaths) {
2468
2683
  if (entry.lifecycle !== "proposed") continue;
2469
- const source = path11.join(gate.root, entry.path);
2684
+ const source = path12.join(gate.root, entry.path);
2470
2685
  const targetRelative = entry.path.replaceAll("\\", "/").replace(".agents/notes/proposed/", ".agents/notes/implemented/");
2471
- if (!existsSync6(source) && existsSync6(path11.join(gate.root, targetRelative))) {
2686
+ if (!existsSync7(source) && existsSync7(path12.join(gate.root, targetRelative))) {
2472
2687
  entry.path = targetRelative;
2473
2688
  entry.lifecycle = "implemented";
2474
2689
  recovered.push("adopted-target");
@@ -2511,7 +2726,8 @@ var GATE_TOOLS = [
2511
2726
  { name: "gate_note_finalize", summary: "\u628A proposed Note \u79FB\u5230 implemented \u5E76\u66F4\u65B0\u5934\u5757\uFF1Broot-only\u3002" },
2512
2727
  { name: "gate_help", summary: "\u5217\u51FA gate \u547D\u4EE4\u3001\u5DE5\u5177\u548C\u5F53\u524D phase/node\uFF1B\u53EA\u8BFB\uFF0Croot-only\u3002" },
2513
2728
  { name: "gate_artifact_write", summary: "\u6309 artifact policy \u5199\u767D\u540D\u5355\u6587\u4EF6\uFF1B\u4E0D\u8D70\u666E\u901A workspace write\u3002" },
2514
- { name: "gate_research_dispatch", summary: "root-only \u5728 discuss/plan \u6D3E research worker\uFF1Bworker \u53EA\u5199 research artifact\u3002" }
2729
+ { name: "gate_research_dispatch", summary: "root-only \u5728 discuss/plan \u6D3E research worker\uFF1Bworker \u53EA\u5199 research artifact\u3002" },
2730
+ { name: "gate_init_verify", summary: "root-only \u53EA\u8BFB\u6821\u9A8C init-manifest\u3001\u751F\u6210\u7269 hash\u3001policy \u4E0E init \u7ED3\u6784\u3002" }
2515
2731
  ];
2516
2732
 
2517
2733
  // src/tools/help.ts
@@ -2679,6 +2895,27 @@ function registerResearchDispatch(ctx, deps) {
2679
2895
  });
2680
2896
  }
2681
2897
 
2898
+ // src/tools/init-verify.ts
2899
+ function registerInitVerify(ctx, _deps) {
2900
+ ctx.tools.register({
2901
+ name: "gate_init_verify",
2902
+ description: "root-only \u53EA\u8BFB\u6821\u9A8C /gate-init \u4EA7\u7269\uFF1Ainit-manifest\u3001immutable hash\u3001artifact policy\u3001AGENTS managed block\u3001verify-notes script\u3001workflow\u3001notes \u76EE\u5F55\u3002",
2903
+ parameters: { type: "object", additionalProperties: false, properties: {} },
2904
+ output: {
2905
+ schema: { type: "object", additionalProperties: true },
2906
+ render: (_args, value) => [{ type: "text", text: typeof value?.text === "string" ? value.text : JSON.stringify(value) }]
2907
+ },
2908
+ async execute(_args, exec) {
2909
+ if (rootAgentOf(ctx, exec.agent)?.id !== exec.agent?.id) {
2910
+ return { ok: false, code: "root-only", reason: "gate_init_verify \u53EA\u80FD\u7531 root agent \u8C03\u7528\u3002" };
2911
+ }
2912
+ const gate = resolveGate(ctx, exec.agent);
2913
+ if (gate.root === void 0) return { ok: false, code: "state-unavailable", reason: "\u65E0\u6CD5\u786E\u5B9A\u5DE5\u4F5C\u533A\u3002" };
2914
+ return verifyInit(gate.root);
2915
+ }
2916
+ });
2917
+ }
2918
+
2682
2919
  // src/tools/index.ts
2683
2920
  function registerTools(ctx, deps) {
2684
2921
  registerStartPhase(ctx, deps);
@@ -2688,6 +2925,7 @@ function registerTools(ctx, deps) {
2688
2925
  registerHelp(ctx, deps);
2689
2926
  registerArtifactTools(ctx, deps);
2690
2927
  registerResearchDispatch(ctx, deps);
2928
+ registerInitVerify(ctx, deps);
2691
2929
  }
2692
2930
 
2693
2931
  // src/index.ts
@@ -2707,7 +2945,6 @@ export {
2707
2945
  Config,
2708
2946
  DISCUSS_ORCHESTRATION,
2709
2947
  DOCS_ORCHESTRATION,
2710
- FIX_BUG_ORCHESTRATION,
2711
2948
  GATE_RECORD_NODES,
2712
2949
  IMPLEMENT_ORCHESTRATION,
2713
2950
  NODE_METHODS,