mancode 0.5.4 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  assertActivationRollbackManifestTransition,
9
9
  assertClaimTransition,
10
10
  assertConfigPolicyConsistency,
11
+ assertExecutableImplementationScope,
11
12
  assertHandoffTransition,
12
13
  assertKnownKeys,
13
14
  assertOperationJournalTransition,
@@ -17,6 +18,7 @@ import {
17
18
  assertRecord,
18
19
  assertRepairUsesOriginalAuthorization,
19
20
  assertRequirementsLedgerTransition,
21
+ assertRequirementsScopeConsistent,
20
22
  assertReviewLedgerAgainstContext,
21
23
  assertReviewLedgerTransition,
22
24
  assertSafeSharedRelativePath,
@@ -49,6 +51,7 @@ import {
49
51
  formatTaskRef,
50
52
  gitRefWorkflowRepairJournalPath,
51
53
  handoffDirectory,
54
+ implementationScopeIsExecutable,
52
55
  isUlid,
53
56
  listGitRefWorkflowRepairJournalSummaries,
54
57
  listUnfinishedGitRefWorkflowRepairs,
@@ -111,7 +114,7 @@ import {
111
114
  workflowMetadataDigest,
112
115
  writeOperationReservation,
113
116
  writeProjectFacts
114
- } from "./chunk-VHZI2WKD.js";
117
+ } from "./chunk-YWHFHZ4A.js";
115
118
  import {
116
119
  DEFAULT_MANCODE_END_MARKER,
117
120
  DEFAULT_MANCODE_START_MARKER,
@@ -136,7 +139,7 @@ import {
136
139
  stageV3AdapterUpgradeFiles,
137
140
  v3AdapterTargetPath,
138
141
  v3AdapterVersionsFromStatuses
139
- } from "./chunk-PQDAFZYS.js";
142
+ } from "./chunk-AWOIP2LC.js";
140
143
 
141
144
  // src/cli.ts
142
145
  import { Option, program } from "commander";
@@ -1154,6 +1157,11 @@ var OPERATION_DEFINITIONS = {
1154
1157
  expectedRevisionPrefixes: ["claim:"],
1155
1158
  requiredLockPrefixes: ["claim:"]
1156
1159
  }),
1160
+ write(
1161
+ "mark-review-verification-stale",
1162
+ ["review:", "verification:", "task:"],
1163
+ ["task:"]
1164
+ ),
1157
1165
  write("update-metadata-scope", ["task:"], ["task:"]),
1158
1166
  write("activate-successor-claims", ["task:"], ["task:"], {
1159
1167
  expectedRevisionPrefixes: ["claim:"],
@@ -5694,11 +5702,13 @@ function parseRequirementsLedger2(raw, options = {}) {
5694
5702
  "requirements need at least one required acceptance criterion"
5695
5703
  );
5696
5704
  }
5705
+ const confirmedScope = normalizeStrings(value.confirmedScope);
5706
+ const excludedScope = normalizeStrings(value.excludedScope);
5697
5707
  return {
5698
5708
  version: 1,
5699
5709
  goal: value.goal.trim(),
5700
- confirmedScope: normalizeStrings(value.confirmedScope),
5701
- excludedScope: normalizeStrings(value.excludedScope),
5710
+ confirmedScope,
5711
+ excludedScope,
5702
5712
  technicalDecisions: normalizeStrings(value.technicalDecisions),
5703
5713
  defaults: normalizeStrings(value.defaults),
5704
5714
  blockingUnknowns: normalizeStrings(value.blockingUnknowns),
@@ -5706,6 +5716,12 @@ function parseRequirementsLedger2(raw, options = {}) {
5706
5716
  acceptanceCriteria
5707
5717
  };
5708
5718
  }
5719
+ function assertRequirementsScopeConsistent2(ledger) {
5720
+ const confirmed = new Set(ledger.confirmedScope);
5721
+ if (ledger.excludedScope.some((item) => confirmed.has(item))) {
5722
+ throw new Error("requirements scope cannot be both confirmed and excluded");
5723
+ }
5724
+ }
5709
5725
  function requirementsAreReady2(ledger) {
5710
5726
  return ledger.blockingUnknowns.length === 0;
5711
5727
  }
@@ -9622,7 +9638,7 @@ async function activateLegacyMigration(input) {
9622
9638
  if (session === null || session.status !== "active") {
9623
9639
  throw new Error("MANCODE_SESSION_NOT_FOUND");
9624
9640
  }
9625
- const store = new (await import("./store-EEWJJANB.js")).V3ContextStore(root);
9641
+ const store = new (await import("./store-DREAZNIX.js")).V3ContextStore(root);
9626
9642
  const project = await store.readProjectSnapshot();
9627
9643
  const stage = await readMigrationStage(root, input.stageId);
9628
9644
  if (stage.state !== "staged" || stage.revision !== input.expectedStageRevision) {
@@ -9885,7 +9901,7 @@ async function activateLegacyMigration(input) {
9885
9901
  for (const action of payload.actions.filter(
9886
9902
  (action2) => action2.kind === "v3_adapter_file"
9887
9903
  )) {
9888
- const { applyV3AdapterFilePlan: applyV3AdapterFilePlan2 } = await import("./v3-adapter-NEN5F32W.js");
9904
+ const { applyV3AdapterFilePlan: applyV3AdapterFilePlan2 } = await import("./v3-adapter-TCEFETAG.js");
9889
9905
  await applyV3AdapterFilePlan2(root, action);
9890
9906
  }
9891
9907
  journal = await completeActivationStep(
@@ -13741,7 +13757,7 @@ async function upgradeV3Adapters(input) {
13741
13757
  if (unfinished.length > 0) {
13742
13758
  throw new Error("MANCODE_ADAPTER_UPGRADE_OPERATION_PENDING");
13743
13759
  }
13744
- const actualVersions = await import("./v3-adapter-NEN5F32W.js").then(
13760
+ const actualVersions = await import("./v3-adapter-TCEFETAG.js").then(
13745
13761
  ({ inspectV3AdapterVersions: inspectV3AdapterVersions2 }) => inspectV3AdapterVersions2(
13746
13762
  root,
13747
13763
  managedAdapterNames(project.manifest.managedAdapters)
@@ -14332,7 +14348,7 @@ import path26 from "path";
14332
14348
  var SCOUT_AGENT = {
14333
14349
  name: "scout",
14334
14350
  description: "Investigates the codebase for mancode /man workflows. Finds similar implementations, reusable modules, files to change, and risks. Does not write code.",
14335
- tools: ["Read", "Grep", "Glob", "Bash"],
14351
+ tools: ["Read", "Grep", "Glob"],
14336
14352
  body: `\u4F60\u662F mancode \u6559\u7EC3\u7EC4\u7684 Scout\uFF08\u7403\u63A2\uFF09\u3002
14337
14353
 
14338
14354
  \u4F60\u7684\u804C\u8D23\uFF1A\u8C03\u7814\u4EE3\u7801\u5E93\uFF0C\u4E3A Head Coach \u51C6\u5907\u6218\u672F\u4FE1\u606F\u3002
@@ -14343,6 +14359,8 @@ var SCOUT_AGENT = {
14343
14359
  - \u53EA\u5217\u5BF9\u5B9E\u65BD\u6709\u7528\u7684\u4FE1\u606F
14344
14360
  - \u627E\u5230\u98CE\u9669\u70B9\u8981\u6807\u6CE8\uFF08\u26A0\uFE0F\uFF09
14345
14361
  - \u4E0D\u786E\u5B9A\u7684\u8981\u660E\u8BF4\uFF0C\u4E0D\u731C
14362
+ - \u4E3B\u52A8\u6838\u9A8C\u7528\u6237\u524D\u63D0\uFF0C\u5E76\u4ECE\u7AEF\u5230\u7AEF\u7528\u6237\u76EE\u6807\u3001\u5E38\u89C1\u9886\u57DF\u5931\u8D25\u8DEF\u5F84\u548C\u8FB9\u754C\u6761\u4EF6\u5BFB\u627E\u4F1A\u6539\u53D8\u65B9\u6848\u7684\u76F2\u70B9\uFF1B\u6700\u591A\u4FDD\u7559 3 \u4E2A\u6700\u9AD8\u5F71\u54CD\u9879\u3002\u4ED3\u5E93\u4E8B\u5B9E\u5FC5\u987B\u6709\u8BC1\u636E\uFF1B\u65E0\u6CD5\u5728\u4ED3\u5E93\u6838\u9A8C\u7684\u884C\u4E1A\u5224\u65AD\u5FC5\u987B\u6807\u4E3A domain_hypothesis\uFF0C\u53EA\u80FD\u5F62\u6210\u805A\u7126\u95EE\u9898\uFF0C\u4E0D\u80FD\u5199\u6210\u4E8B\u5B9E
14363
+ - \u53D1\u73B0\u53EA\u63D0\u4F9B\u8BC1\u636E\u548C\u5EFA\u8BAE\u6743\uFF0C\u4E0D\u4EA7\u751F\u4FEE\u6539\u6743\uFF1B\u4E0D\u628A\u5EFA\u8BAE\u5199\u6210\u5DF2\u786E\u8BA4\u8303\u56F4\u6216\u6280\u672F\u51B3\u7B56
14346
14364
  - \u5B58\u5728 \`.mancode/shared/context/glossary.json\` \u65F6\uFF0C\u62A5\u544A\u4F18\u5148\u4F7F\u7528\u5176\u4E2D\u672F\u8BED\uFF1B\u53D1\u73B0\u65B0\u7684\u9AD8\u9891\u9886\u57DF\u8BCD\u53EF\u5728\u62A5\u544A\u4E2D\u5217\u4E3A\u5EFA\u8BAE\u8BCD\u6761\uFF08\u4EC5\u5EFA\u8BAE\uFF0C\u4E0D\u5199\u5165\u672F\u8BED\u8868\uFF09
14347
14365
  - \u5F15\u7528\u6587\u4EF6\u7528 \`path:line\` \u683C\u5F0F\uFF0C\u8BA9 Head Coach \u4E00\u79D2\u8DF3\u8FC7\u53BB
14348
14366
 
@@ -14408,6 +14426,16 @@ var SCOUT_AGENT = {
14408
14426
  - Transport/platform: <\u5F71\u54CD\u6216 no change>
14409
14427
  - Migration/rollback: <\u9700\u8981\u7684\u8BC1\u636E\u6216 no change>
14410
14428
 
14429
+ ## Decision-impact Findings
14430
+ - Finding ID: F-1\uFF08\u540E\u7EED\u4F9D\u6B21 F-2\u3001F-3\uFF1B\u6700\u591A\u4E09\u9879\uFF09
14431
+ - Type: premise | scope | technical | risk | acceptance
14432
+ - Status: repository_fact | domain_hypothesis
14433
+ - Finding: <\u4E0E\u7528\u6237\u524D\u63D0\u51B2\u7A81\u7684\u4E8B\u5B9E\u3001\u5173\u952E\u76F2\u70B9\u6216\u53EF\u884C\u7684\u8303\u56F4\u5EFA\u8BAE\uFF1B\u6CA1\u6709\u5219\u5199 none>
14434
+ - Evidence/Basis: \`<repository test/file:line/caller-provided output\uFF0C\u6216\u660E\u786E\u6807\u6CE8\u7684\u9886\u57DF\u63A8\u7406\u4F9D\u636E>\`
14435
+ - Class: blocking | recommendable | defaultable
14436
+ - Impact: <\u4F1A\u6539\u53D8\u7684\u76EE\u6807\u3001\u8303\u56F4\u3001\u884C\u4E3A\u3001\u9A8C\u6536\u3001\u67B6\u6784\u3001\u6570\u636E\u3001\u517C\u5BB9\u6027\u3001\u5B89\u5168\u6216 owner>
14437
+ - Recommendation: <\u4E00\u4E2A\u6700\u5C0F\u3001\u76F4\u63A5\u7684\u5EFA\u8BAE\uFF1B\u4E0D\u66FF\u7528\u6237\u786E\u8BA4>
14438
+
14411
14439
  ## \u76F8\u4F3C\u5B9E\u73B0
14412
14440
  - \`<detected-source-root>/<relevant-file>:<line>\` \u2014 \u7B80\u8FF0\u53EF\u590D\u7528\u7684\u903B\u8F91
14413
14441
 
@@ -14443,8 +14471,8 @@ trigger: <\u88AB\u65B0\u8BC1\u636E\u63A8\u7FFB\u6216\u8D85\u51FA\u5F53\u524D req
14443
14471
 
14444
14472
  - \u7528 Grep / Glob \u627E\u4EE3\u7801\uFF0C\u4E0D\u8981 cat \u6574\u4E2A\u6587\u4EF6
14445
14473
  - \u7528 Read \u770B file:line \u9644\u8FD1\u7684\u4E0A\u4E0B\u6587
14446
- - \u7528 Bash \u8DD1 \`git log --oneline -5\` \u4E86\u89E3\u6700\u8FD1\u6539\u52A8
14447
- - **\u4E0D\u8981** Edit / Write \u2014 \u90A3\u662F Head Coach \u7684\u6D3B
14474
+ - \u53EA\u5F15\u7528\u5F53\u524D\u53EA\u8BFB\u5DE5\u5177\u80FD\u591F\u6838\u9A8C\u7684\u8BC1\u636E\uFF1B\u9700\u8981\u8FD0\u884C\u547D\u4EE4\u65F6\uFF0C\u628A\u547D\u4EE4\u5217\u4E3A\u4EA4\u7ED9\u8C03\u7528\u65B9\u7684\u9A8C\u8BC1\u5EFA\u8BAE\uFF0C\u4E0D\u81EA\u884C\u6267\u884C
14475
+ - **\u4E0D\u8981** Edit / Write / Bash \u2014 \u90A3\u662F\u6267\u884C\u9636\u6BB5\u7684\u6D3B
14448
14476
 
14449
14477
  \u6536\u5230\u4EFB\u52A1\u540E\u7ACB\u5373\u5F00\u59CB\u8C03\u7814\u3002\u62A5\u544A\u5B8C\u6574\u5373\u53EF\uFF0C\u4E0D\u9700\u8981\u7B49\u7528\u6237\u786E\u8BA4\u3002`
14450
14478
  };
@@ -14468,7 +14496,11 @@ var PLAN_COACH_AGENT = {
14468
14496
 
14469
14497
  ## \u8F93\u5165\u5C31\u7EEA\u68C0\u67E5
14470
14498
 
14471
- \u5148\u8BFB\u53D6 \`requirements.json\`\uFF0C\u4EE5\u5176\u4E2D\u7684 confirmedScope\u3001excludedScope\u3001technicalDecisions\u3001defaults\u3001blockingUnknowns\u3001coverage \u548C acceptanceCriteria \u4E3A\u6743\u5A01\u8F93\u5165\uFF1B\`requirements.md\` \u53EA\u7528\u4E8E\u9605\u8BFB\u3002\u9010\u9879\u68C0\u67E5 platform\u3001core_scope\u3001technical_stack\u3001data_and_persistence\u3001performance\u3001compatibility\u3001security \u7684\u72B6\u6001\u548C\u7406\u7531\u662F\u5426\u4E0E\u4E8B\u5B9E\u4E00\u81F4\u3002\u68C0\u67E5\u9700\u6C42\u662F\u5426\u8986\u76D6\u4EFB\u52A1\u5B9E\u9645\u9002\u7528\u7684\u7528\u6237\u76EE\u6807\u3001\u6838\u5FC3\u6D41\u7A0B\u3001\u9996\u671F\u8303\u56F4\u3001\u6392\u9664\u9879\u3001\u6280\u672F\u4E0E\u8FD0\u884C\u7EA6\u675F\u3001\u6570\u636E/\u72B6\u6001/\u96C6\u6210\u3001\u5173\u952E\u6027\u80FD/\u517C\u5BB9\u6027/\u5B89\u5168\u8981\u6C42\u548C\u9A8C\u6536\u6807\u51C6\u3002blockingUnknowns \u975E\u7A7A\u3001coverage \u7528\u65E0\u6839\u636E\u7684 not_applicable \u63A9\u76D6\u51B3\u7B56\u3001\u6838\u5FC3\u884C\u4E3A\u7F3A\u5C11\u9A8C\u6536 ID\uFF0C\u6216\u6587\u6863\u4E0E\u7ED3\u6784\u5316\u8F93\u5165\u77DB\u76FE\u65F6\u5FC5\u987B\u8FD4\u56DE NEEDS_CLARIFICATION\u3002
14499
+ \u5148\u8BFB\u53D6 \`requirements.json\`\u3002V3 \u4EE5 \`functionalScope.inScope\`\u3001\`functionalScope.outOfScope\`\u3001\`technicalDecisions\`\u3001\`defaults\`\u3001\`blockingUnknowns\`\u3001\`coverage\` \u548C \`acceptanceCriteria\` \u4E3A\u6743\u5A01\u8F93\u5165\uFF1Blegacy \u8F93\u5165\u4E2D\u7684\u8BED\u4E49\u5BF9\u5E94\u5B57\u6BB5\u662F \`confirmedScope\` \u4E0E \`excludedScope\`\uFF1B\`requirements.md\` \u53EA\u7528\u4E8E\u9605\u8BFB\u3002\u9010\u9879\u68C0\u67E5 platform\u3001core_scope\u3001technical_stack\u3001data_and_persistence\u3001performance\u3001compatibility\u3001security \u7684\u72B6\u6001\u548C\u7406\u7531\u662F\u5426\u4E0E\u4E8B\u5B9E\u4E00\u81F4\u3002\u68C0\u67E5\u9700\u6C42\u662F\u5426\u8986\u76D6\u4EFB\u52A1\u5B9E\u9645\u9002\u7528\u7684\u7528\u6237\u76EE\u6807\u3001\u6838\u5FC3\u6D41\u7A0B\u3001\u9996\u671F\u8303\u56F4\u3001\u6392\u9664\u9879\u3001\u6280\u672F\u4E0E\u8FD0\u884C\u7EA6\u675F\u3001\u6570\u636E/\u72B6\u6001/\u96C6\u6210\u3001\u5173\u952E\u6027\u80FD/\u517C\u5BB9\u6027/\u5B89\u5168\u8981\u6C42\u548C\u9A8C\u6536\u6807\u51C6\u3002blockingUnknowns \u975E\u7A7A\u3001coverage \u7528\u65E0\u6839\u636E\u7684 not_applicable \u63A9\u76D6\u51B3\u7B56\u3001\u6838\u5FC3\u884C\u4E3A\u7F3A\u5C11\u9A8C\u6536 ID\uFF0C\u6216\u6587\u6863\u4E0E\u7ED3\u6784\u5316\u8F93\u5165\u77DB\u76FE\u65F6\u5FC5\u987B\u8FD4\u56DE NEEDS_CLARIFICATION\u3002
14500
+
14501
+ \u9010\u9879\u6838\u5BF9 Scout \u7684 F-1\u2026F-3 \u662F\u5426\u5DF2\u6709\u6309\u7C7B\u578B\u5904\u7F6E\uFF1A\`repository_fact\` \u53EF\u4EE5\u7EA0\u6B63\u9519\u8BEF\u524D\u63D0\uFF1B\`domain_hypothesis\` \u5FC5\u987B\u5148\u8F6C\u6210\u805A\u7126\u95EE\u9898\uFF0C\u4E0D\u80FD\u5F53\u6210\u5DF2\u786E\u8BA4\u4E8B\u5B9E\u3002blocking \u5199\u5165 \`blockingUnknowns\`\uFF1B\u7528\u6237\u63A5\u53D7\u7684\u8303\u56F4\u6216\u884C\u4E3A finding \u5199\u5165 \`confirmedScope\`\uFF08V3 \u4E3A \`functionalScope.inScope\`\uFF09\u5E76\u8865\u4E0A\u5339\u914D\u7684\u9A8C\u6536 \`acceptanceCriteria\`\uFF1B\u7528\u6237\u63A5\u53D7\u7684\u6280\u672F\u9009\u62E9\u5199\u5165 \`technicalDecisions\`\uFF1B\u4F4E\u5F71\u54CD\u3001\u53EF\u9006\u7684\u5B9E\u73B0\u7EC6\u8282\u624D\u5199\u5165 \`defaults\`\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u6392\u9664\u7684\u884C\u4E3A\u5199\u5165 \`excludedScope\`\uFF08V3 \u4E3A \`functionalScope.outOfScope\`\uFF09\u3002\u672A\u63A5\u53D7\u7684\u5EFA\u8BAE\u4ECD\u7136\u6CA1\u6709\u6267\u884C\u6743\uFF0C\u4F46\u4E0D\u5F97\u81EA\u52A8\u585E\u5165 excludedScope\uFF0C\u66F4\u4E0D\u80FD\u590D\u5236\u8FDB\u6240\u6709\u5B57\u6BB5\u3002\u9519\u8BEF\u524D\u63D0\u6216\u98CE\u9669\u82E5\u4F1A\u6539\u53D8\u8BA1\u5212\uFF0C\u5FC5\u987B\u5148\u4F5C\u4E3A blocking \u6F84\u6E05\uFF0C\u518D\u6309\u6700\u7EC8\u8BED\u4E49\u843D\u5165\u4E0A\u8FF0\u552F\u4E00\u5408\u9002\u4F4D\u7F6E\u3002\u53D1\u73B0\u53EA\u4EA7\u751F\u5EFA\u8BAE\u6743\uFF0Cconfirmed requirements \u624D\u4EA7\u751F\u884C\u4E3A\u6388\u6743\u3002
14502
+
14503
+ \u8BA1\u5212\u8FD8\u5FC5\u987B\u8BFB\u53D6\u6216\u63D0\u51FA\u4E00\u4EFD\u7528\u6237\u53EF\u89C1\u7684 \`implementationScope\`\uFF08repo-relative \`include\`\u3001\`exclude\`\u3001\`modules\`\uFF09\uFF0C\u4F5C\u4E3A\u6587\u4EF6\u6539\u52A8\u4E0A\u9650\u3002\u5B83\u4E0D\u80FD\u7531 Scout \u5EFA\u8BAE\u81EA\u52A8\u751F\u6210\u6388\u6743\uFF0C\u4E5F\u4E0D\u80FD\u7528\u6A21\u5757\u6807\u7B7E\u4EE3\u66FF\u975E\u7A7A include\uFF1B\u5B83\u4E0E\u884C\u4E3A\u9700\u6C42\u5171\u540C\u7EA6\u675F\u6267\u884C\u3002
14472
14504
 
14473
14505
  \u540C\u65F6\u6267\u884C\u65B9\u6848\u5B8C\u6574\u6027\u68C0\u67E5\uFF1A
14474
14506
 
@@ -14476,6 +14508,7 @@ var PLAN_COACH_AGENT = {
14476
14508
  2. \u6BCF\u4E2A\u65B9\u6848\u5FC5\u987B\u8BF4\u660E\u590D\u6742\u5EA6\u7531\u8C01\u627F\u62C5\u4EE5\u53CA\u53EF\u89C2\u5BDF\u6210\u672C\uFF0C\u627F\u62C5\u8005\u53EF\u4EE5\u662F\u5B9E\u73B0\u4EE3\u7801\u3001\u8FC1\u79FB\u3001\u8FD0\u884C\u7EF4\u62A4\u3001\u7528\u6237\u64CD\u4F5C\u3001\u517C\u5BB9\u5C42\u6216\u6D4B\u8BD5\uFF1B\u4E0D\u80FD\u53EA\u5199\u201C\u66F4\u7B80\u5355\u201D\u3002
14477
14509
  3. \u5FC5\u987B\u7ED9\u51FA\u552F\u4E00 recommendation\uFF0C\u5E76\u8BF4\u660E\u62D2\u7EDD\u5176\u4ED6\u65B9\u5411\u7684\u4E3B\u8981\u7406\u7531\uFF1B\u4E0D\u80FD\u628A\u591A\u4E2A\u672A\u51B3\u65B9\u5411\u539F\u6837\u4EA4\u7ED9\u7528\u6237\u3002
14478
14510
  4. \u7B80\u5355\u4EFB\u52A1\u6CA1\u6709\u771F\u5B9E\u66FF\u4EE3\u65B9\u6848\u65F6\u53EA\u5217\u4E00\u4E2A\u660E\u663E\u53EF\u884C\u65B9\u5411\uFF0C\u5E76\u89E3\u91CA\u4E3A\u4EC0\u4E48\u4E0D\u5B58\u5728\u771F\u5B9E\u66FF\u4EE3\uFF1B\u4E0D\u5F97\u5236\u9020\u4F2A\u9009\u9879\u3002\u8FD9\u4E2A\u5355\u4E00\u65B9\u5411\u4ECD\u5FC5\u987B\u6210\u4E3A recommendation \u5E76\u6709 stop conditions\u3002
14511
+ 5. \u6BCF\u4E2A\u5B9E\u65BD\u6B65\u9AA4\u5FC5\u987B\u6620\u5C04\u5230\u5DF2\u786E\u8BA4\u8303\u56F4\u6216\u9A8C\u6536 ID\u3002\u4F18\u5148\u590D\u7528\u73B0\u6709\u5B9E\u73B0\u548C\u4F9D\u8D56\uFF0C\u9009\u62E9\u80FD\u6EE1\u8DB3\u9A8C\u6536\u7684\u6700\u5C0F\u76F4\u63A5\u65B9\u6848\uFF1B\u4E0D\u4E3A\u5355\u6B21\u7528\u9014\u589E\u52A0\u62BD\u8C61\u3001\u53EF\u914D\u7F6E\u6027\u3001\u76F8\u90BB\u6E05\u7406\u6216\u63A8\u6D4B\u6027\u9632\u5FA1\u3002
14479
14512
 
14480
14513
  Scout \u82E5\u7ED9\u51FA\u4E24\u4E2A\u540C\u7B49\u5019\u9009 semantic owner\u3001\u65E0\u6CD5\u786E\u5B9A authority/writer\uFF0C\u6216 evidence \u4E0E confirmed requirements \u51B2\u7A81\uFF0C\u4E0D\u80FD\u81EA\u884C\u9009\u4E00\u4E2A\u7EE7\u7EED\u3002
14481
14514
 
@@ -14509,6 +14542,10 @@ stop_conditions: <conditions that invalidate this plan>
14509
14542
  ## \u6A21\u5757\u7D22\u5F15
14510
14543
  ## \u6280\u672F\u4E0E\u4EA4\u4ED8\u7EA6\u675F\uFF08\u4EC5\u65B0\u9879\u76EE\u6216\u6280\u672F\u9009\u62E9\u672A\u5B9A\u65F6\uFF09
14511
14544
  - \u5DF2\u786E\u8BA4\u65B9\u6848\u3001\u9009\u62E9\u7406\u7531\u548C\u53D6\u820D\uFF1B\u5C1A\u672A\u786E\u8BA4\u4F1A\u6539\u53D8\u67B6\u6784\u7684\u6280\u672F\u9009\u62E9\u65F6\u8FD4\u56DE NEEDS_CLARIFICATION\uFF1B\u5DF2\u6709\u9879\u76EE\u5199\u201C\u6CBF\u7528\u68C0\u6D4B\u5230\u7684\u9879\u76EE\u7EA6\u5B9A\u201D
14545
+ ## \u6267\u884C\u8FB9\u754C\uFF08implementationScope\uFF09
14546
+ - include\uFF1A<\u5141\u8BB8\u4FEE\u6539\u7684 repo-relative \u8DEF\u5F84/glob>
14547
+ - exclude\uFF1A<\u5373\u4F7F\u5339\u914D include \u4E5F\u4E0D\u5F97\u4FEE\u6539\u7684\u8DEF\u5F84/glob>
14548
+ - modules\uFF1A<\u8BED\u4E49\u5F52\u5C5E\u6807\u7B7E\uFF1B\u4E0D\u5355\u72EC\u6388\u6743\u6587\u4EF6\u5199\u5165>
14512
14549
  ## \u6A21\u5757\uFF1A<\u540D\u79F0>
14513
14550
  ### \u6539\u52A8\u6587\u4EF6 / \u65B0\u5EFA\u6587\u4EF6
14514
14551
  ### \u590D\u7528\u8D44\u6E90\uFF08\u5F15\u7528 scout-report.md \u884C\u53F7\uFF09
@@ -14764,6 +14801,7 @@ var FILM_ANALYST_OFFENSE_AGENT = {
14764
14801
  - \u6700\u540E\u7ED9\u8BC4\u5206\uFF081-10\uFF09+ \u901A\u8FC7 / \u4E0D\u901A\u8FC7
14765
14802
  - \u53EA\u5BA1\u67E5\u672C\u6B21 diff\u3001\u7528\u6237\u9700\u6C42\u548C\u76F4\u63A5\u53D7\u5F71\u54CD\u8DEF\u5F84\uFF1B\u6700\u591A 3 \u4E2A\u65B0\u95EE\u9898
14766
14803
  - \u6BCF\u4E2A\u95EE\u9898\u5FC5\u987B\u5305\u542B\u6539\u52A8\u884C\u3001\u53EF\u6838\u67E5\u8BC1\u636E\u548C\u7528\u6237\u5F71\u54CD\u3002\u6CA1\u6709\u8BC1\u636E\u7684 checklist \u9879\u4E0D\u8F93\u51FA
14804
+ - \u5148\u505A\u6388\u6743\u4E00\u81F4\u6027\u5BA1\u67E5\uFF1AV3 \u5BF9\u7167 requirements \u7684 \`functionalScope.inScope\` / \`functionalScope.outOfScope\`\u3001\`technicalDecisions\`\u3001\`defaults\` \u548C \`acceptanceCriteria\`\uFF1Blegacy \u5BF9\u7167\u8BED\u4E49\u7B49\u4EF7\u7684 \`confirmedScope\` / \`excludedScope\`\u3002\u540C\u65F6\u8BFB\u53D6 Context Pack \u7684 \`activeTask.implementationScope\`\uFF0C\u9010\u4E2A\u68C0\u67E5\u5B9E\u9645\u6539\u52A8\u8DEF\u5F84\u662F\u5426\u843D\u5728 include \u4E14\u4E0D\u5339\u914D exclude\uFF1Bmodules \u53EA\u662F\u5F52\u5C5E\u6807\u7B7E\uFF0C\u4E0D\u5355\u72EC\u6388\u6743\u6587\u4EF6\u5199\u5165\u3002\u4EFB\u4F55\u672A\u7ECF\u6388\u6743\u3001\u89E6\u78B0\u884C\u4E3A\u6392\u9664\u9879\u3001\u8D85\u51FA\u6587\u4EF6\u8FB9\u754C\u6216\u65E0\u6CD5\u8FFD\u6EAF\u5230\u9A8C\u6536\u7684\u6539\u52A8\u4E00\u5F8B\u8BB0\u4E3A \u{1F534} scope blocker
14767
14805
 
14768
14806
  ## \u4F60\u4E0D\u5199\u4EE3\u7801
14769
14807
 
@@ -14773,6 +14811,7 @@ var FILM_ANALYST_OFFENSE_AGENT = {
14773
14811
 
14774
14812
  | \u7EF4\u5EA6 | \u68C0\u67E5\u4EC0\u4E48 |
14775
14813
  |---|---|
14814
+ | **\u6388\u6743\u4E00\u81F4\u6027** | \u6BCF\u4E00\u5904\u6539\u52A8\u80FD\u5426\u540C\u65F6\u8FFD\u6EAF\u5230\u5DF2\u786E\u8BA4\u884C\u4E3A/\u9A8C\u6536 ID\uFF0C\u5E76\u4F4D\u4E8E implementationScope \u6587\u4EF6\u8FB9\u754C\u5185\uFF1B\u662F\u5426\u5B9E\u73B0\u4E86\u88AB\u62D2\u7EDD\u3001\u5EF6\u671F\u6216\u672A\u8BA8\u8BBA\u7684\u5EFA\u8BAE |
14776
14815
  | **\u53EF\u8BFB\u6027** | \u547D\u540D\u6E05\u6670\u3001\u7ED3\u6784\u5408\u7406\u3001\u6CE8\u91CA\u6070\u5F53\uFF08\u53EA\u5728 WHY \u975E\u663E\u7136\u65F6\uFF09 |
14777
14816
  | **\u53EF\u7EF4\u62A4\u6027** | \u6A21\u5757\u8FB9\u754C\u3001\u8026\u5408\u5EA6\u3001\u6269\u5C55\u6027 |
14778
14817
  | **\u98CE\u683C\u4E00\u81F4\u6027** | \u662F\u5426\u5339\u914D\u9879\u76EE\u5DF2\u6709\u98CE\u683C\uFF08\u5373\u4F7F\u4F60\u4E0D\u8BA4\u540C\uFF09 |
@@ -15321,11 +15360,11 @@ trigger: <\u5177\u4F53\u4E8B\u5B9E>
15321
15360
  // src/templates/skills/principles.ts
15322
15361
  var CORE_CODING_PRINCIPLES = `## \u94C1\u5F8B\uFF08\u6C38\u4E0D\u8FDD\u53CD\uFF09
15323
15362
 
15324
- 1. **\u4E0D\u505A\u65E0\u5173\u4FEE\u6539** \u2014 \u53EA\u6539 plan \u8303\u56F4\u5185\u7684
15325
- 2. **\u5148\u9A8C\u8BC1\u518D\u58F0\u79F0\u5B8C\u6210** \u2014 build/lint/test \u5FC5\u987B\u5B9E\u9645\u8DD1
15363
+ 1. **\u4E0D\u505A\u65E0\u5173\u4FEE\u6539** \u2014 \u53EA\u6539\u7528\u6237\u5DF2\u786E\u8BA4\u7684 plan \u4E0E implementationScope\uFF1B\u6BCF\u4E00\u5904\u6539\u52A8\u90FD\u80FD\u8FFD\u6EAF\u5230\u8303\u56F4\u6216\u9A8C\u6536
15364
+ 2. **\u5148\u9A8C\u8BC1\u518D\u58F0\u79F0\u5B8C\u6210** \u2014 \u5F00\u5DE5\u524D\u5199\u660E\u5B9E\u8D28\u5047\u8BBE\u548C\u53EF\u9A8C\u8BC1\u6210\u529F\u6807\u51C6\uFF1Bbuild/lint/test \u5FC5\u987B\u5B9E\u9645\u8DD1
15326
15365
  3. **\u5931\u8D25\u4E24\u6B21\u5FC5\u987B\u505C\u4E0B** \u2014 \u4E0D\u76F2\u8BD5
15327
15366
  4. **\u4E0D\u53EF\u9006\u64CD\u4F5C\u5148\u95EE** \u2014 \u5220\u9664\u3001force push\u3001worktree \u5408\u5E76
15328
- 5. **\u53EA\u89E3\u51B3\u88AB\u95EE\u5230\u7684\u95EE\u9898** \u2014 \u4E0D\u52A0\u63A8\u6D4B\u6027\u529F\u80FD`;
15367
+ 5. **\u53EA\u89E3\u51B3\u88AB\u95EE\u5230\u7684\u95EE\u9898** \u2014 \u4F18\u5148\u590D\u7528\u73B0\u6709\u5B9E\u73B0\uFF0C\u9009\u62E9\u6EE1\u8DB3\u9A8C\u6536\u7684\u6700\u5C0F\u76F4\u63A5\u6539\u52A8\uFF1B\u4E0D\u52A0\u63A8\u6D4B\u6027\u529F\u80FD\u3001\u4E00\u6B21\u6027\u62BD\u8C61\u3001\u65E0\u5173\u6E05\u7406\u6216\u591A\u4F59\u914D\u7F6E`;
15329
15368
 
15330
15369
  // src/templates/skills/man.ts
15331
15370
  var MAN_SKILL = {
@@ -15345,7 +15384,7 @@ var MAN_SKILL = {
15345
15384
 
15346
15385
  ### Step 1: Scout \u8C03\u7814
15347
15386
 
15348
- \u5148\u8BFB \`.mancode/shared/context/glossary.json\`\uFF08\u82E5\u5B58\u5728\uFF09\uFF0C\u8C03\u7814\u3001\u62A5\u544A\u4E0E\u540E\u7EED\u6C9F\u901A\u4F18\u5148\u4F7F\u7528\u5176\u4E2D\u5DF2\u786E\u8BA4\u672F\u8BED\u3002\u8C03\u7528 \`scout\`\uFF0C\u5199 \`scout-report.md\`\u3002\u62A5\u544A\u5FC5\u987B\u5305\u542B\u201C**\u4E0D\u786E\u5B9A\u7684\u5730\u65B9**\u201D\uFF0C\u5E76\u6309\u53EF\u9A8C\u8BC1\u4E8B\u5B9E\u8865\u5145 Current Behavior Evidence\u3001Candidate Semantic Owner\u3001Source of Truth\u3001Historical / Compatibility Impact\uFF1B\u5B57\u6BB5\u4E0D\u76F8\u5173\u6216\u65E0\u6CD5\u9A8C\u8BC1\u65F6\u53EF\u4EE5\u7701\u7565\uFF0C\u4E0D\u80FD\u7F16\u9020\u3002Current Behavior Evidence \u81F3\u5C11\u6709\u4E00\u4E2A\u53EF\u590D\u73B0\u89C2\u5BDF\u548C\u4ED3\u5E93\u8DEF\u5F84\u3001\u6D4B\u8BD5\u6216\u547D\u4EE4\u8BC1\u636E\uFF1Bowner \u5199\u7F6E\u4FE1\u5EA6\u4E0E\u51B2\u7A81\uFF1Bsource of truth \u533A\u5206 authority \u548C derived copy\uFF1B\u517C\u5BB9\u5F71\u54CD\u8986\u76D6\u65E7 workflow\u3001legacy fixture\u3001transport\u3001\u8FC1\u79FB\u548C rollback\u3002\u8FD0\u884C \`mancode workflow update <taskId> --step 2\`\u3002
15387
+ \u5148\u8BFB \`.mancode/shared/context/glossary.json\`\uFF08\u82E5\u5B58\u5728\uFF09\uFF0C\u8C03\u7814\u3001\u62A5\u544A\u4E0E\u540E\u7EED\u6C9F\u901A\u4F18\u5148\u4F7F\u7528\u5176\u4E2D\u5DF2\u786E\u8BA4\u672F\u8BED\u3002\u8C03\u7528\u53EA\u8BFB \`scout\`\uFF0C\u5199 \`scout-report.md\`\u3002\u62A5\u544A\u5FC5\u987B\u5305\u542B\u201C**\u4E0D\u786E\u5B9A\u7684\u5730\u65B9**\u201D\u548C\u6700\u591A 3 \u4E2A\u4F1A\u6539\u53D8\u51B3\u7B56\u7684 Decision-impact Findings\uFF1B\u4F7F\u7528\u7A33\u5B9A ID F-1\u2026F-3\uFF0C\u6807\u6CE8 Type\uFF1Apremise / scope / technical / risk / acceptance\uFF0C\u5E76\u533A\u5206 repository_fact \u4E0E domain_hypothesis\u3002\u524D\u8005\u5FC5\u987B\u6709\u4ED3\u5E93\u8BC1\u636E\uFF1B\u540E\u8005\u53EA\u6839\u636E\u7AEF\u5230\u7AEF\u76EE\u6807\u548C\u5E38\u89C1\u9886\u57DF\u5931\u8D25/\u8FB9\u754C\u8DEF\u5F84\u63D0\u51FA\u805A\u7126\u95EE\u9898\uFF0C\u4E0D\u80FD\u5199\u6210\u4E8B\u5B9E\u3002\u6309\u53EF\u9A8C\u8BC1\u4E8B\u5B9E\u8865\u5145 Current Behavior Evidence\u3001Candidate Semantic Owner\u3001Source of Truth\u3001Historical / Compatibility Impact\uFF1B\u5B57\u6BB5\u4E0D\u76F8\u5173\u6216\u65E0\u6CD5\u9A8C\u8BC1\u65F6\u53EF\u4EE5\u7701\u7565\uFF0C\u4E0D\u80FD\u7F16\u9020\u3002Current Behavior Evidence \u81F3\u5C11\u6709\u4E00\u4E2A\u53EF\u590D\u73B0\u89C2\u5BDF\u548C\u4ED3\u5E93\u8DEF\u5F84\u3001\u6D4B\u8BD5\u6216\u8C03\u7528\u65B9\u63D0\u4F9B\u7684\u547D\u4EE4\u8BC1\u636E\uFF1Bowner \u5199\u7F6E\u4FE1\u5EA6\u4E0E\u51B2\u7A81\uFF1Bsource of truth \u533A\u5206 authority \u548C derived copy\uFF1B\u517C\u5BB9\u5F71\u54CD\u8986\u76D6\u65E7 workflow\u3001legacy fixture\u3001transport\u3001\u8FC1\u79FB\u548C rollback\u3002\u4E3B\u52A8\u6838\u9A8C\u7528\u6237\u524D\u63D0\u5E76\u6307\u51FA\u5173\u952E\u76F2\u70B9\uFF0C\u4F46\u53D1\u73B0\u53EA\u4EA7\u751F\u5EFA\u8BAE\u6743\uFF0C\u4E0D\u4EA7\u751F\u6267\u884C\u6743\u3002\u8FD0\u884C \`mancode workflow update <taskId> --step 2\`\u3002
15349
15388
 
15350
15389
  ### Step 2: \u9700\u6C42\u6F84\u6E05
15351
15390
 
@@ -15356,6 +15395,8 @@ var MAN_SKILL = {
15356
15395
  - **recommendable**\uFF1A\u6709\u5408\u9002\u65B9\u6848\u65F6\u76F4\u63A5\u7ED9 2\u20133 \u4E2A\u65B9\u6848\u3001\u4F18\u7F3A\u70B9\u548C\u660E\u786E\u63A8\u8350\uFF0C\u8BA9\u7528\u6237\u63A5\u53D7\u6216\u8C03\u6574\uFF1B\u4E0D\u8981\u53EA\u628A\u9009\u62E9\u9898\u629B\u7ED9\u7528\u6237\u3002
15357
15396
  - **defaultable**\uFF1A\u547D\u540D\u3001\u5FAE\u5C0F\u6837\u5F0F\u7B49\u4F4E\u5F71\u54CD\u7EC6\u8282\uFF0C\u53EF\u91C7\u7528\u9ED8\u8BA4\u503C\uFF0C\u4F46\u5199\u660E\u9ED8\u8BA4\u503C\u548C\u7406\u7531\u3002
15358
15397
 
15398
+ \u4E3A\u6BCF\u4E2A F-1\u2026F-3 \u660E\u786E\u4E14\u6309\u7C7B\u578B\u5904\u7F6E\uFF1Ablocking \u5199\u5165 \`blockingUnknowns\`\uFF1B\u7528\u6237\u63A5\u53D7\u7684\u8303\u56F4\u6216\u884C\u4E3A\u5199\u5165 \`confirmedScope\` \u5E76\u8865\u4E0A\u76F8\u5E94 \`acceptanceCriteria\`\uFF1B\u7528\u6237\u63A5\u53D7\u7684\u6280\u672F\u9009\u62E9\u5199\u5165 \`technicalDecisions\`\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u6392\u9664\u7684\u884C\u4E3A\u5199\u5165 \`excludedScope\`\uFF1B\`defaults\` \u53EA\u80FD\u63CF\u8FF0\u5DF2\u786E\u8BA4\u8303\u56F4\u5185\u4F4E\u5F71\u54CD\u3001\u53EF\u9006\u4E14\u7B26\u5408\u4ED3\u5E93\u7EA6\u5B9A\u7684\u5B9E\u73B0\u7EC6\u8282\uFF0C\u4E0D\u80FD\u6269\u5927\u8303\u56F4\u3002\u672A\u63A5\u53D7\u7684\u5EFA\u8BAE\u4ECD\u65E0\u6267\u884C\u6743\uFF0C\u4F46\u4E0D\u5F97\u81EA\u52A8\u585E\u5165 \`excludedScope\`\uFF0C\u4E5F\u4E0D\u5F97\u590D\u5236\u8FDB\u6240\u6709\u5B57\u6BB5\u3002
15399
+
15359
15400
  \u6309\u4EFB\u52A1\u5B9E\u9645\u9002\u7528\u8303\u56F4\u68C0\u67E5\uFF1A\u7528\u6237\u76EE\u6807\u4E0E\u5E73\u53F0\u3001\u6838\u5FC3\u6D41\u7A0B\u3001\u9996\u671F\u8303\u56F4\u3001\u6392\u9664\u9879\u3001\u6280\u672F\u4E0E\u8FD0\u884C\u7EA6\u675F\u3001\u6570\u636E/\u72B6\u6001/\u96C6\u6210\u3001\u6027\u80FD/\u517C\u5BB9\u6027/\u5B89\u5168\u3001\u53EF\u9A8C\u8BC1\u5B8C\u6210\u6807\u51C6\u3002\u8FDE\u7EED\u6F84\u6E05\u6CA1\u6709\u51CF\u5C11 blocking \u9879\u65F6\uFF0C\u4E0D\u6563\u95EE\uFF1B\u8BA9\u7528\u6237\u9009\u62E9\u7F29\u5C0F\u9996\u671F\u8303\u56F4\u3001\u63A5\u53D7\u5217\u660E\u7684\u63A8\u8350\u9ED8\u8BA4\u503C\u6216\u6682\u505C\u3002
15360
15401
 
15361
15402
  \u628A\u7ED3\u8BBA\u5199\u5165\u7ED3\u6784\u5316\u9700\u6C42\u8F93\u5165\uFF0C\u81F3\u5C11\u5305\u542B \`goal\`\u3001\u975E\u7A7A \`confirmedScope\`\u3001\`excludedScope\`\u3001\`technicalDecisions\`\u3001\`defaults\`\u3001\`blockingUnknowns\`\u3001\`coverage\` \u548C \`acceptanceCriteria\`\u3002coverage \u5FC5\u987B\u9010\u9879\u8BF4\u660E platform\u3001core_scope\u3001technical_stack\u3001data_and_persistence\u3001performance\u3001compatibility\u3001security \u662F \`confirmed\`\u3001\`defaulted\` \u6216\u5E26\u7406\u7531\u7684 \`not_applicable\`\uFF0C\u4E0D\u80FD\u7528\u7A7A\u6570\u7EC4\u5047\u88C5\u5DF2\u7ECF\u8003\u8651\u3002\u6BCF\u4E2A\u6838\u5FC3\u7528\u6237\u884C\u4E3A\u5FC5\u987B\u6709\u7A33\u5B9A\u9A8C\u6536 ID\uFF08\`AC-1\` \u7B49\uFF09\u3001\u63CF\u8FF0\u3001\`required\` \u548C\u9A8C\u8BC1\u65B9\u5F0F \`automated\` / \`manual\` / \`hybrid\`\uFF1B\u81F3\u5C11\u4E00\u4E2A\u9A8C\u6536\u9879\u5FC5\u9700\u3002\u8FD0\u884C \`mancode workflow requirements <taskId> finalize --file <requirements-input.json>\`\uFF0C\u7531 CLI \u6821\u9A8C\u5E76\u751F\u6210\u6743\u5A01 \`requirements.json\` \u4E0E \`requirements.md\`\uFF0C\u4E0D\u8981\u624B\u5DE5\u5236\u9020\u4E24\u4EFD\u53EF\u80FD\u51B2\u7A81\u7684\u7ED3\u8BBA\u3002\u65E0\u987B\u63D0\u95EE\u65F6\u53EF\u628A \`clarification\` \u8BB0\u5165\u7D2F\u8BA1 skippedSteps\uFF0C\u4F46\u4E0D\u80FD\u8DF3\u8FC7\u9700\u6C42\u6458\u8981\u4E0E\u5C31\u7EEA\u5224\u65AD\u3002\u4ECD\u6709 blocking \u9879\u65F6\u505C\u5728 Step 2\uFF1B\u53EA\u6709 CLI \u8FD4\u56DE ready \u624D\u8FD0\u884C \`mancode workflow update <taskId> --step 3\`\u3002
@@ -15366,7 +15407,7 @@ var MAN_SKILL = {
15366
15407
 
15367
15408
  Plan Coach \u5FC5\u987B\u8BC1\u660E\u6240\u6709\u9009\u9879\u89E3\u51B3\u540C\u4E00\u4E2A goal\u3001\u9A8C\u6536\u8FB9\u754C\u548C scope\uFF1B\u9010\u9879\u5199\u660E complexity bearer \u53CA\u53EF\u89C2\u5BDF\u6210\u672C\uFF1B\u7ED9\u51FA\u4E14\u53EA\u7ED9\u51FA\u4E00\u4E2A recommendation\u3001\u62D2\u7EDD\u5176\u4ED6\u65B9\u5411\u7684\u4E3B\u8981\u7406\u7531\u548C stop conditions\u3002\u7B80\u5355\u4EFB\u52A1\u6CA1\u6709\u771F\u5B9E\u66FF\u4EE3\u65F6\u53EA\u5217\u4E00\u4E2A\u65B9\u5411\u5E76\u8BF4\u660E\u539F\u56E0\uFF0C\u4E0D\u5236\u9020\u4F2A\u9009\u9879\u3002\u4E24\u4E2A\u540C\u7B49 owner \u5019\u9009\u6216 authority writer \u672A\u51B3\u65F6\u8FD4\u56DE \`NEEDS_CLARIFICATION\`\u3002
15368
15409
 
15369
- \u8BA1\u5212\u5FC5\u987B\u542B\u9700\u6C42\u6458\u8981\u3001\u4EFB\u52A1\u5206\u7EA7\u3001\u6280\u672F\u9009\u62E9\u53CA\u7406\u7531\u3001\u6A21\u5757\u7D22\u5F15\u3001\u590D\u7528\u8D44\u6E90\u4E0E scout \u884C\u53F7\u3001\u6838\u5FC3\u884C\u4E3A\u3001\u6700\u5C0F\u7B56\u7565\u3001\u4E0D\u505A\u4EC0\u4E48\u3001\u6B65\u9AA4\u3001\u98CE\u9669/\u56DE\u9000\u3001\u5B8C\u6210\u5B9A\u4E49\u3001\u771F\u5B9E\u9A8C\u8BC1\u4E0E smoke test\u3001\u9884\u4F30\u548C\u975E\u963B\u585E\u9ED8\u8BA4\u503C\u3002\u5165\u53E3/\u6D41\u7A0B\u8DE8\u5E73\u53F0\u4E0D\u4E00\u81F4\u3001owner/source of truth \u4E0D\u6E05\u3001\u72B6\u6001\u6216 contract \u8BED\u4E49\u53D8\u5316\u3001\u8DE8 workflow/child/team/transport\uFF0C\u6216\u8FC1\u79FB/\u517C\u5BB9\u5F71\u54CD\u8D85\u8FC7\u4E00\u4E2A\u7248\u672C\u65F6\uFF0C\u5728 \`plan.md\` \u5185\u52A0\u5165\u53EF\u9009 Domain Matrix\uFF0C\u5217\u51FA Domain\u3001\u5F53\u524D\u884C\u4E3A/\u8BC1\u636E\u3001\u5019\u9009 owner\u3001source of truth\u3001contract/state \u5F71\u54CD\u3001compatibility/history\u3001validation \u548C rollback/stop\uFF1B\u5B83\u4E0D\u662F\u65B0\u7684 authority\u3002\u9996\u6B21\u8BA1\u5212\u5199\u5165\u6210\u529F\u540E\u8FD0\u884C \`mancode workflow update <taskId> --step 4\`\uFF1B\u91CD\u5199\u8BA1\u5212\u65F6\u4FDD\u6301 Step 4\uFF0C\u8FD0\u884C \`--plan-version <\u5F53\u524D\u7248\u672C+1>\`\uFF0C\u4E0D\u5F97\u76F4\u63A5\u7F16\u8F91 planVersion\u3002
15410
+ \u8BA1\u5212\u5FC5\u987B\u542B\u9700\u6C42\u6458\u8981\u3001\u4EFB\u52A1\u5206\u7EA7\u3001\u6280\u672F\u9009\u62E9\u53CA\u7406\u7531\u3001\u6A21\u5757\u7D22\u5F15\u3001\u590D\u7528\u8D44\u6E90\u4E0E scout \u884C\u53F7\u3001\u6838\u5FC3\u884C\u4E3A\u3001\u6700\u5C0F\u7B56\u7565\u3001\u4E0D\u505A\u4EC0\u4E48\u3001\u6B65\u9AA4\u3001\u98CE\u9669/\u56DE\u9000\u3001\u5B8C\u6210\u5B9A\u4E49\u3001\u771F\u5B9E\u9A8C\u8BC1\u4E0E smoke test\u3001\u9884\u4F30\u548C\u975E\u963B\u585E\u9ED8\u8BA4\u503C\uFF0C\u8FD8\u8981\u6709\u7528\u6237\u53EF\u89C1\u7684 \`implementationScope\`\uFF1Arepo-relative \`include\`\u3001\`exclude\`\u3001\`modules\`\u3002include \u662F\u6587\u4EF6\u5199\u5165\u4E0A\u9650\u4E14\u5FC5\u987B\u975E\u7A7A\uFF0Cexclude \u4F18\u5148\uFF0Cmodules \u53EA\u63CF\u8FF0\u5F52\u5C5E\u3001\u4E0D\u5355\u72EC\u6388\u6743\u3002\u6BCF\u4E2A\u5B9E\u65BD\u6B65\u9AA4\u5FC5\u987B\u6620\u5C04\u5230\u5DF2\u786E\u8BA4\u8303\u56F4\u6216\u9A8C\u6536 ID\uFF1B\u4F18\u5148\u590D\u7528\u5DF2\u6709\u4EE3\u7801\u548C\u4F9D\u8D56\uFF0C\u9009\u62E9\u80FD\u6EE1\u8DB3\u9A8C\u6536\u7684\u6700\u5C0F\u3001\u76F4\u63A5\u3001\u53EF\u9A8C\u8BC1\u65B9\u6848\uFF0C\u4E0D\u4E3A\u5355\u6B21\u7528\u9014\u65B0\u589E\u62BD\u8C61\u3001\u53EF\u914D\u7F6E\u6027\u6216\u63A8\u6D4B\u6027\u9632\u5FA1\u3002\u5165\u53E3/\u6D41\u7A0B\u8DE8\u5E73\u53F0\u4E0D\u4E00\u81F4\u3001owner/source of truth \u4E0D\u6E05\u3001\u72B6\u6001\u6216 contract \u8BED\u4E49\u53D8\u5316\u3001\u8DE8 workflow/child/team/transport\uFF0C\u6216\u8FC1\u79FB/\u517C\u5BB9\u5F71\u54CD\u8D85\u8FC7\u4E00\u4E2A\u7248\u672C\u65F6\uFF0C\u5728 \`plan.md\` \u5185\u52A0\u5165\u53EF\u9009 Domain Matrix\uFF0C\u5217\u51FA Domain\u3001\u5F53\u524D\u884C\u4E3A/\u8BC1\u636E\u3001\u5019\u9009 owner\u3001source of truth\u3001contract/state \u5F71\u54CD\u3001compatibility/history\u3001validation \u548C rollback/stop\uFF1B\u5B83\u4E0D\u662F\u65B0\u7684 authority\u3002\u9996\u6B21\u8BA1\u5212\u4E0E\u8FB9\u754C\u901A\u8FC7 CLI \u4E00\u8D77\u5199\u5165\u540E\u8FD0\u884C \`mancode workflow update <taskId> --step 4\`\uFF1B\u517C\u5BB9\u65E7\u5165\u53E3\u91CD\u5199\u8BA1\u5212\u65F6\u4FDD\u6301 Step 4\uFF0C\u4F7F\u7528 \`--plan-version <\u5F53\u524D\u7248\u672C+1>\`\uFF0C\u5E76\u8BA9\u65E7\u5BA1\u67E5/\u9A8C\u8BC1\u5931\u6548\uFF0C\u4E0D\u5F97\u76F4\u63A5\u7F16\u8F91 planVersion\u3002
15370
15411
 
15371
15412
  ### Step 4: \u8BA1\u5212\u5173\u5361
15372
15413
 
@@ -15388,7 +15429,9 @@ Plan Coach \u5FC5\u987B\u8BC1\u660E\u6240\u6709\u9009\u9879\u89E3\u51B3\u540C\u4
15388
15429
 
15389
15430
  ### Step 5: \u5B9E\u65BD
15390
15431
 
15391
- \u8C03\u7528 \`head-coach\` \u6309\u786E\u8BA4\u8BA1\u5212\u5B9E\u65BD\u3002\u591A\u6587\u4EF6\u3001\u65B0\u6A21\u5757\u6216\u9AD8\u98CE\u9669\u4EFB\u52A1\u53EF\u5EFA\u8BAE worktree\uFF0C\u5FC5\u987B\u5148\u83B7\u7528\u6237\u540C\u610F\u3002\u5B9E\u65BD\u5B8C\u6210\u540E\u901A\u8FC7 CLI \u66F4\u65B0\u81F3 Step 6\u3002
15432
+ \u8C03\u7528 \`head-coach\` \u6309\u786E\u8BA4\u8BA1\u5212\u5B9E\u65BD\u3002\u5148\u660E\u786E\u4ECD\u5B58\u5728\u7684\u5B9E\u8D28\u5047\u8BBE\u548C\u53EF\u9A8C\u8BC1\u6210\u529F\u6807\u51C6\uFF1B\u6BCF\u4E00\u5904\u6539\u52A8\u90FD\u5FC5\u987B\u8FFD\u6EAF\u5230\u5DF2\u786E\u8BA4\u8303\u56F4\u3001\u6280\u672F\u51B3\u7B56\u6216\u9A8C\u6536 ID\u3002\u53EA\u6539\u4E3A\u6EE1\u8DB3\u8BA1\u5212\u6240\u5FC5\u9700\u7684\u6587\u4EF6\uFF0C\u4E0D\u987A\u624B\u91CD\u6784\u3001\u683C\u5F0F\u5316\u3001\u6E05\u7406\u76F8\u90BB\u4EE3\u7801\u6216\u589E\u52A0\u672A\u8BF7\u6C42\u529F\u80FD\u3002\u591A\u6587\u4EF6\u3001\u65B0\u6A21\u5757\u6216\u9AD8\u98CE\u9669\u4EFB\u52A1\u53EF\u5EFA\u8BAE worktree\uFF0C\u5FC5\u987B\u5148\u83B7\u7528\u6237\u540C\u610F\u3002\u5B9E\u65BD\u5B8C\u6210\u540E\u901A\u8FC7 CLI \u66F4\u65B0\u81F3 Step 6\u3002
15433
+
15434
+ \u82E5\u5347\u7EA7\u524D\u5DF2\u7ECF\u8FDB\u5165\u6267\u884C\u9636\u6BB5\u7684\u672C\u5730 Man \u4EFB\u52A1\u7F3A\u5C11\u53EF\u6267\u884C \`implementationScope\`\uFF0C\u5B8C\u6210\u95E8\u4ECD\u4F1A\u62D2\u7EDD\u3002\u5148\u5411\u7528\u6237\u5C55\u793A\u5B8C\u6574\u8FB9\u754C\u5E76\u7B49\u5F85\u660E\u786E\u786E\u8BA4\uFF0C\u518D\u4F7F\u7528\u5185\u5BB9\u5B8C\u5168\u4E0D\u53D8\u7684\u5F53\u524D plan \u548C \`--scope-file\` \u91CD\u65B0\u6267\u884C plan revise\u3002\u8FD9\u4E2A\u517C\u5BB9\u8865\u7ED1\u53EA\u5141\u8BB8\u9012\u589E plan authority \u5E76\u4F7F\u65E7 review/verification \u5931\u6548\uFF1B\u4E0D\u5F97\u4FEE\u6539 plan\u3001\u884C\u4E3A\u3001\u9A8C\u6536\u6216\u5DF2\u7ECF\u53EF\u6267\u884C\u7684\u8FB9\u754C\u3002
15392
15435
 
15393
15436
  ### Step 6: \u81EA\u6D4B\u3001\u8BCA\u65AD\u4E0E\u56DE\u5F52
15394
15437
 
@@ -15400,7 +15443,7 @@ Plan Coach \u5FC5\u987B\u8BC1\u660E\u6240\u6709\u9009\u9879\u89E3\u51B3\u540C\u4
15400
15443
 
15401
15444
  ### Step 7: Film #1 \u4EE3\u7801\u8D28\u91CF\u5BA1\u67E5\u4E0E\u4FEE\u590D
15402
15445
 
15403
- \u672A\u8DF3\u8FC7 review \u65F6\u8C03\u7528 \`film-analyst-offense\`\uFF0C\u53EA\u5BA1\u67E5\u672C\u6B21 diff \u7684\u884C\u4E3A\u6B63\u786E\u6027\u3001\u590D\u7528\u3001\u590D\u6742\u5EA6\u548C\u6D4B\u8BD5\uFF0C\u5199 \`film-report-1.md\`\u3002\u6BCF\u6761 finding \u5FC5\u987B\u5F15\u7528\u6539\u52A8\u884C\u3001\u7ED9\u51FA\u8BC1\u636E\u548C\u7528\u6237\u5F71\u54CD\uFF1B\u6700\u591A 3 \u4E2A\u65B0 finding\u3002\u7528\u7A33\u5B9A ID\uFF08\u5982 Q1\uFF09\u6807\u8BB0 \u{1F534} blocker\uFF0C\u5E76\u8FD0\u884C \`mancode workflow review <taskId> complete --review-domain quality --report film-report-1.md --blockers Q1,Q2\`\uFF1B\u6CA1\u6709 blocker \u65F6\u4F20\u7A7A\u5B57\u7B26\u4E32\u3002\u6B64\u65F6\u4E0D\u4FEE\u590D\uFF0C\u5148\u5B8C\u6210\u6240\u9700\u5BA1\u67E5\u9886\u57DF\uFF0C\u518D\u66F4\u65B0\u81F3 Step 8\u3002
15446
+ \u672A\u8DF3\u8FC7 review \u65F6\u8C03\u7528 \`film-analyst-offense\`\uFF0C\u5148\u628A\u5B9E\u9645 diff \u5BF9\u7167 \`confirmedScope\`\u3001\`excludedScope\`\u3001\`technicalDecisions\`\u3001\`acceptanceCriteria\` \u548C \`implementationScope\` \u505A\u6388\u6743\u4E00\u81F4\u6027\u5BA1\u67E5\uFF0C\u518D\u68C0\u67E5\u884C\u4E3A\u6B63\u786E\u6027\u3001\u590D\u7528\u3001\u590D\u6742\u5EA6\u548C\u6D4B\u8BD5\uFF0C\u5199 \`film-report-1.md\`\u3002\u5B9E\u73B0\u88AB\u62D2\u7EDD\u3001\u5EF6\u671F\u3001\u672A\u8BA8\u8BBA\u3001\u65E0\u6CD5\u8FFD\u6EAF\u5230\u5DF2\u786E\u8BA4\u884C\u4E3A\uFF0C\u6216\u6539\u52A8\u8DEF\u5F84\u843D\u5728 include \u5916 / \u5339\u914D exclude \u7684\u5185\u5BB9\u4E00\u5F8B\u4F5C\u4E3A \u{1F534} scope blocker\u3002\u6BCF\u6761 finding \u5FC5\u987B\u5F15\u7528\u6539\u52A8\u884C\u3001\u7ED9\u51FA\u8BC1\u636E\u548C\u7528\u6237\u5F71\u54CD\uFF1B\u6700\u591A 3 \u4E2A\u65B0 finding\u3002\u7528\u7A33\u5B9A ID\uFF08\u5982 Q1\uFF09\u6807\u8BB0 \u{1F534} blocker\uFF0C\u5E76\u8FD0\u884C \`mancode workflow review <taskId> complete --review-domain quality --report film-report-1.md --blockers Q1,Q2\`\uFF1B\u6CA1\u6709 blocker \u65F6\u4F20\u7A7A\u5B57\u7B26\u4E32\u3002\u6B64\u65F6\u4E0D\u4FEE\u590D\uFF0C\u5148\u5B8C\u6210\u6240\u9700\u5BA1\u67E5\u9886\u57DF\uFF0C\u518D\u66F4\u65B0\u81F3 Step 8\u3002
15404
15447
 
15405
15448
  ### Step 8: Film #2 \u5B89\u5168\u4E0E\u8FB9\u754C\u5BA1\u67E5
15406
15449
 
@@ -15734,16 +15777,18 @@ var MANTEAM_SKILL = {
15734
15777
 
15735
15778
  \u6309 \`/man\` \u7684 9 \u6B65\u6D41\u7A0B\u6267\u884C\uFF08\u542B\u6F84\u6E05\u3001\u8BA1\u5212\u5173\u5361\u548C\u589E\u5F3A\u6536\u5C3E\uFF09\uFF0C\u4F46\u6BCF\u4E00\u6B65\u589E\u52A0\u56E2\u961F\u7EA6\u675F\uFF1A
15736
15779
 
15737
- 1. Scout Report\uFF1A\u5FC5\u987B\u5217\u51FA\u5171\u4EAB\u6587\u4EF6\u3001\u8FD1\u671F\u76F8\u5173\u63D0\u4EA4\u3001\u6F5C\u5728\u51B2\u7A81\u6587\u4EF6\uFF0C\u5E76\u6309\u4E8B\u5B9E\u8865\u5145 Current Behavior Evidence\u3001Candidate Semantic Owner\u3001Source of Truth\u3001Historical / Compatibility Impact\uFF1Bauthority \u4E0E Markdown/adapter \u7B49 derived copy \u5FC5\u987B\u533A\u5206\u3002
15738
- 2. \u6F84\u6E05\uFF1A\u6CBF\u7528 /man \u7684\u9700\u6C42\u5C31\u7EEA\u95E8\u69DB\uFF0C\u4E0D\u8BBE\u56FA\u5B9A\u8F6E\u6570\u6216\u6BCF\u6279\u95EE\u9898\u6570\u91CF\uFF1B\u95EE\u51FA\u6240\u6709\u4F1A\u6539\u53D8\u51B3\u7B56\u4E14\u65E0\u6CD5\u4ECE\u9879\u76EE\u4E8B\u5B9E\u67E5\u6E05\u7684\u7591\u95EE\uFF0C\u4E0D\u91CD\u590D\u5DF2\u786E\u8BA4\u5185\u5BB9\u3002\u6709\u5408\u9002\u65B9\u6848\u65F6\u76F4\u63A5\u7ED9\u51FA\u9009\u9879\u3001\u4F18\u7F3A\u70B9\u548C\u660E\u786E\u63A8\u8350\u3002\u901A\u8FC7 \`workflow requirements ... finalize\` \u56FA\u5316\u4E03\u4E2A coverage \u7EF4\u5EA6\u3001\u7ED3\u6784\u5316\u9700\u6C42\u548C\u5E26\u9A8C\u8BC1\u65B9\u5F0F\u7684\u9A8C\u6536 ID\uFF0C\u53EA\u6709 CLI \u5224\u5B9A ready \u624D\u8FDB\u5165\u8BA1\u5212\u3002
15739
- 3. Game Plan\uFF1APlan Coach \u5148\u505A\u8F93\u5165\u5C31\u7EEA\u68C0\u67E5\uFF1B\u6240\u6709\u9009\u9879\u5FC5\u987B\u89E3\u51B3\u540C\u4E00\u76EE\u6807\u548C\u9A8C\u6536\u8FB9\u754C\uFF0C\u5199\u660E complexity bearer\uFF0C\u53EA\u4FDD\u7559\u4E00\u4E2A recommendation \u548C stop conditions\uFF1B\u7B80\u5355\u4EFB\u52A1\u53EF\u4EE5\u53EA\u6709\u4E00\u4E2A\u771F\u5B9E\u65B9\u5411\u3002\u8BA1\u5212\u91CC\u5FC5\u987B\u5305\u542B\u53D8\u66F4\u8FB9\u754C\u3001\u6280\u672F\u9009\u62E9\u7406\u7531\u3001\u517C\u5BB9\u6027\u98CE\u9669\u3001\u56DE\u6EDA\u65B9\u5F0F\uFF1B\u9AD8\u98CE\u9669\u6216\u8DE8 team/transport/owner/authority \u7684\u4EFB\u52A1\u5728 plan.md \u5185\u52A0\u5165\u975E\u6743\u5A01 Domain Matrix\u3002\u7981\u6B62\u63D0\u524D\u4FEE\u6539\u4E1A\u52A1\u6587\u4EF6\u6216\u56E2\u961F memory\u3002
15780
+ 1. Scout Report\uFF1A\u5FC5\u987B\u5217\u51FA\u5171\u4EAB\u6587\u4EF6\u3001\u8FD1\u671F\u76F8\u5173\u63D0\u4EA4\u3001\u6F5C\u5728\u51B2\u7A81\u6587\u4EF6\uFF0C\u5E76\u6309\u4E8B\u5B9E\u8865\u5145 Current Behavior Evidence\u3001Candidate Semantic Owner\u3001Source of Truth\u3001Historical / Compatibility Impact\uFF1Bauthority \u4E0E Markdown/adapter \u7B49 derived copy \u5FC5\u987B\u533A\u5206\u3002\u6700\u591A\u4FDD\u7559\u4E09\u4E2A\u4F1A\u6539\u53D8\u51B3\u7B56\u7684 finding\uFF0C\u4F7F\u7528\u7A33\u5B9A ID F-1\u2026F-3 \u548C Type\uFF1Apremise / scope / technical / risk / acceptance\u3002
15781
+ 2. \u6F84\u6E05\uFF1A\u6CBF\u7528 /man \u7684\u9700\u6C42\u5C31\u7EEA\u95E8\u69DB\uFF0C\u4E0D\u8BBE\u56FA\u5B9A\u8F6E\u6570\u6216\u6BCF\u6279\u95EE\u9898\u6570\u91CF\uFF1B\u95EE\u51FA\u6240\u6709\u4F1A\u6539\u53D8\u51B3\u7B56\u4E14\u65E0\u6CD5\u4ECE\u9879\u76EE\u4E8B\u5B9E\u67E5\u6E05\u7684\u7591\u95EE\uFF0C\u4E0D\u91CD\u590D\u5DF2\u786E\u8BA4\u5185\u5BB9\u3002\u6709\u5408\u9002\u65B9\u6848\u65F6\u76F4\u63A5\u7ED9\u51FA\u9009\u9879\u3001\u4F18\u7F3A\u70B9\u548C\u660E\u786E\u63A8\u8350\u3002\u53D1\u73B0\u53EA\u4EA7\u751F\u5EFA\u8BAE\u6743\uFF0C\u4E0D\u4EA7\u751F\u6267\u884C\u6743\uFF1A\u63A5\u53D7\u7684\u8303\u56F4\u6216\u884C\u4E3A\u8FDB\u5165 confirmedScope \u548C\u5339\u914D\u7684 acceptanceCriteria\uFF1B\u63A5\u53D7\u7684\u6280\u672F\u9009\u62E9\u8FDB\u5165 technicalDecisions\uFF1B\u53EA\u6709\u660E\u786E\u6392\u9664\u7684\u884C\u4E3A\u8FDB\u5165 excludedScope\uFF1B\u672A\u63A5\u53D7\u7684\u5EFA\u8BAE\u4ECD\u65E0\u6267\u884C\u6743\uFF0C\u4F46\u4E0D\u5F97\u81EA\u52A8\u585E\u5165 excludedScope\uFF1B\u4F4E\u5F71\u54CD\u53EF\u9006\u9ED8\u8BA4\u503C\u8FDB\u5165 defaults \u4E14\u4E0D\u5F97\u6269\u5F20\u8303\u56F4\u3002\u901A\u8FC7 \`workflow requirements ... finalize\` \u56FA\u5316\u4E03\u4E2A coverage \u7EF4\u5EA6\u3001\u7ED3\u6784\u5316\u9700\u6C42\u548C\u5E26\u9A8C\u8BC1\u65B9\u5F0F\u7684\u9A8C\u6536 ID\uFF0C\u53EA\u6709 CLI \u5224\u5B9A ready \u624D\u8FDB\u5165\u8BA1\u5212\u3002
15782
+ 3. Game Plan\uFF1APlan Coach \u5148\u505A\u8F93\u5165\u5C31\u7EEA\u68C0\u67E5\uFF1B\u6240\u6709\u9009\u9879\u5FC5\u987B\u89E3\u51B3\u540C\u4E00\u76EE\u6807\u548C\u9A8C\u6536\u8FB9\u754C\uFF0C\u5199\u660E complexity bearer\uFF0C\u53EA\u4FDD\u7559\u4E00\u4E2A recommendation \u548C stop conditions\uFF1B\u7B80\u5355\u4EFB\u52A1\u53EF\u4EE5\u53EA\u6709\u4E00\u4E2A\u771F\u5B9E\u65B9\u5411\u3002\u8BA1\u5212\u91CC\u5FC5\u987B\u5305\u542B\u7528\u6237\u53EF\u89C1\u7684 \`implementationScope\`\uFF08repo-relative include/exclude/modules\uFF09\u3001\u6280\u672F\u9009\u62E9\u7406\u7531\u3001\u517C\u5BB9\u6027\u98CE\u9669\u3001\u56DE\u6EDA\u65B9\u5F0F\uFF1Binclude \u662F\u6587\u4EF6\u5199\u5165\u4E0A\u9650\uFF0Cmodules \u4E0D\u5355\u72EC\u6388\u6743\u3002\u9AD8\u98CE\u9669\u6216\u8DE8 team/transport/owner/authority \u7684\u4EFB\u52A1\u5728 plan.md \u5185\u52A0\u5165\u975E\u6743\u5A01 Domain Matrix\u3002\u7981\u6B62\u63D0\u524D\u4FEE\u6539\u4E1A\u52A1\u6587\u4EF6\u6216\u56E2\u961F memory\u3002
15740
15783
  4. \u8BA1\u5212\u5173\u5361\uFF1A\u7528\u6237\u53EF\u53EA\u4FDD\u7559\u8BA1\u5212\u3001\u7EE7\u7EED\u5B8C\u6574\u56E2\u961F\u6267\u884C\u3001\u660E\u786E\u4EA4\u7ED9 solo \u8F7B\u91CF\u6267\u884C\u6216\u91CD\u5199\u8BA1\u5212\uFF1BActive Plans \u6309 taskId \u66F4\u65B0\u3002\u56E2\u961F\u5171\u4EAB\u6587\u4EF6\u6216\u4EA4\u63A5\u98CE\u9669\u5B58\u5728\u65F6\u63A8\u8350\u5B8C\u6574\u56E2\u961F\u6267\u884C\u3002
15741
15784
  5. \u5B9E\u65BD\uFF1A\u6539\u52A8\u524D\u518D\u6B21\u68C0\u67E5 \`git status --short\`\uFF0C\u907F\u514D\u8E29\u7528\u6237\u6216\u961F\u53CB\u6539\u52A8\u3002
15742
15785
  6. Self-test\uFF1A\u5728 Step 6 \u521D\u59CB\u5316 verification ledger\uFF0C\u628A\u6BCF\u4E2A required \u9A8C\u6536 ID \u7684\u81EA\u52A8\u3001\u4EBA\u5DE5\u6216 hybrid \u7ED3\u679C\u548C\u8BC1\u636E\u901A\u8FC7 CLI \u8BB0\u5F55\uFF1B\u81EA\u52A8\u7ED3\u679C\u5305\u542B\u547D\u4EE4\u4E0E\u9000\u51FA\u7801\uFF0C\u672A\u5168\u90E8\u901A\u8FC7\u4E0D\u5F97\u8FDB\u5165 review\u3002\u4F18\u5148\u8DD1\u9879\u76EE\u5DF2\u6709\u9A8C\u8BC1\u547D\u4EE4\uFF1B\u5931\u8D25\u4E24\u6B21\u505C\u4E0B\u8BCA\u65AD\u6839\u56E0\u3002\u9700\u8981\u4EBA\u5DE5\u9A8C\u8BC1\u65F6\u6807\u8BB0 require-manual \u5E76\u7B49\u5F85\u7528\u6237\u660E\u786E\u786E\u8BA4\uFF0C\u4E0D\u5F97\u81EA\u52A8\u6062\u590D\u3002remediation \u540E\u5728 Step 9 \u91CD\u65B0\u767B\u8BB0\u5168\u90E8\u9A8C\u6536\u3002
15743
- 7. Review scope + Film #1\uFF1A\u57FA\u4E8E\u5B9E\u9645 diff \u5199 \`review-scope.md\`\uFF0C\u7528 \`workflow review ... init\` \u9009\u62E9 targeted \u6216 full\uFF1B\u91CD\u70B9\u5BA1\u67E5\u884C\u4E3A\u3001\u53EF\u7EF4\u62A4\u6027\u3001\u56E2\u961F\u98CE\u683C\u4E0E\u6D4B\u8BD5\uFF0Cfinding \u5FC5\u987B\u6709\u8BC1\u636E\u548C\u7A33\u5B9A ID\u3002
15786
+ 7. Review scope + Film #1\uFF1A\u57FA\u4E8E\u5B9E\u9645 diff \u5199 \`review-scope.md\`\uFF0C\u7528 \`workflow review ... init\` \u9009\u62E9 targeted \u6216 full\uFF1B\u5148\u68C0\u67E5\u6BCF\u4E00\u5904\u6539\u52A8\u662F\u5426\u80FD\u8FFD\u6EAF\u5230\u5DF2\u786E\u8BA4\u8303\u56F4\u4E14\u540C\u65F6\u4F4D\u4E8E \`implementationScope\` include \u5185\u3001\u4E0D\u5339\u914D exclude\uFF0C\u672A\u7ECF\u6388\u6743\u7684\u6539\u52A8\u4F5C\u4E3A blocker\uFF0C\u518D\u5BA1\u67E5\u884C\u4E3A\u3001\u53EF\u7EF4\u62A4\u6027\u3001\u56E2\u961F\u98CE\u683C\u4E0E\u6D4B\u8BD5\uFF1Bfinding \u5FC5\u987B\u6709\u8BC1\u636E\u548C\u7A33\u5B9A ID\u3002
15744
15787
  8. Film #2\uFF1A\u4EC5 full \u6267\u884C\uFF0C\u5148\u8BFB Film #1 \u62A5\u544A\u5E76\u53BB\u91CD\uFF0C\u53EA\u5BA1\u67E5\u8FB9\u754C\u3001\u5B89\u5168\u3001\u6027\u80FD\u3001\u5E76\u53D1\u548C\u517C\u5BB9\u6027\u3002targeted \u7684\u7B2C\u4E8C\u5BA1\u662F\u4E0D\u9002\u7528\uFF0C\u4E0D\u80FD\u8BB0\u4E3A skipped\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8981\u6C42\u624D\u53EF\u8DF3\u8FC7\u5168\u90E8 review\uFF0C\u5E76\u5199\u5165 \`review\` \u548C\u6B8B\u4F59\u98CE\u9669\u3002
15745
15788
  9. Post-game\uFF1A\u6C47\u603B blocker\uFF0C\u53EA\u505A\u4E00\u8F6E\u4FEE\u590D\u5E76\u7528 \`workflow review ... remediate\` \u8BB0\u5F55\uFF1B\u590D\u9A8C\u540E\u5199 summary \u4E0E hand-off\u3002\u9A8C\u8BC1\u5931\u8D25\u3001\u5BA1\u67E5\u4E0D\u5B8C\u6574\u6216\u4ECD\u6709 blocker \u65F6\u6807\u8BB0 blocked\uFF0C\u4E0D\u5F97\u6807 completed\u3002
15746
15789
 
15790
+ \u5B9E\u65BD\u671F\u95F4\u82E5\u53EA\u9700\u8C03\u6574\u6587\u4EF6\u8FB9\u754C\u3001\u4E0D\u6539\u53D8\u5DF2\u786E\u8BA4\u884C\u4E3A\u6216\u9A8C\u6536\uFF0C\u5148\u5411\u7528\u6237\u5C55\u793A\u5B8C\u6574\u65B0\u8FB9\u754C\u5E76\u53D6\u5F97\u660E\u786E\u540C\u610F\uFF0C\u518D\u901A\u8FC7\u4E13\u7528 \`workflow scope change\` mutation \u66F4\u65B0\uFF1B\u5B83\u5FC5\u987B\u9012\u589E plan authority\u3001\u4F7F\u65E7 review/verification \u5931\u6548\u5E76\u91CD\u7B7E\u517C\u5BB9 claim\u3002\u884C\u4E3A\u6216\u9A8C\u6536\u53D8\u5316\u4ECD\u8D70 reframe\uFF0C\u4E0D\u80FD\u7528 scope change \u7ED5\u8FC7\u9700\u6C42\u786E\u8BA4\u3002
15791
+
15747
15792
  \u5B9E\u65BD\u4E2D\u65B0\u8BC1\u636E\u82E5\u63A8\u7FFB\u5DF2\u786E\u8BA4\u7684\u76EE\u6807\u3001owner\u3001source of truth \u6216\u9A8C\u6536\uFF0C\u5165\u53E3/\u6D41\u7A0B\u4F1A\u4EA7\u751F\u4E0D\u540C\u8BED\u4E49\uFF0Cstatus/contract/policy/transition \u542B\u4E49\u8981\u53D8\uFF0C\u53D1\u73B0 stale adapter\u3001writer \u4E0D\u517C\u5BB9\u3001\u672A\u5B8C\u6210 operation\u3001active child/open handoff/active solo assignment\uFF0C\u6216\u53D8\u5316\u8D85\u51FA requirements/plan scope\uFF0C\u7ACB\u5373\u505C\u6B62\uFF0C\u53EA\u8FD4\u56DE \`NEEDS_REALIGNMENT\` \u548C \`MANCODE_REFRAME_REQUIRED\`\u3002\u8FD9\u662F\u53EA\u8BFB\u8BCA\u65AD\uFF1A\u4E0D\u5F97\u8C03\u7528\u901A\u7528 workflow update \u5199 blocker\uFF0C\u4E0D\u6539 metadata/step/policy/requirements/plan/claims/handoff\uFF0C\u4E0D\u5F52\u6863\u6216\u91CA\u653E authority\u3002
15748
15793
 
15749
15794
  \u5982\u679C\u7528\u6237\u5728\u786E\u8BA4\u9636\u6BB5\u9009\u62E9"\u9000\u51FA"\u6216\u653E\u5F03\u56E2\u961F workflow\uFF1A\u7528 \`mancode workflow update <taskId> --status abandoned\` \u66F4\u65B0\u5E76\u6E05\u7406 Active Plans\uFF1B\u82E5\u6709\u6D3B\u8DC3 manba \u5B50\u4EFB\u52A1\uFF0C\u5148\u53D6\u5F97\u786E\u8BA4\u5E76\u9010\u4E2A abandoned\u3002\u6210\u529F\u540E\u518D\u7528 Edit \u66F4\u65B0 state \u56DE solo\u3002\u4E0D\u8981\u76F4\u63A5\u6539 metadata\uFF0C\u4E5F\u4E0D\u8981\u628A abandoned workflow \u7559\u5728 active state\u3002
@@ -16707,13 +16752,13 @@ var MODE_META = {
16707
16752
  "After each completed phase, advance through the CLI to the next numbered step;",
16708
16753
  "never advance state merely because a report was requested or an agent was called.",
16709
16754
  "",
16710
- "Step 1 \u2014 Scout: inspect the profile, existing implementation, dependencies, risks, and unknowns; write `scout-report.md`. When relevant and verifiable, include Current Behavior Evidence, Candidate Semantic Owner with confidence/conflict, Source of Truth split into authority/readers/writer/derived copies, and Historical / Compatibility Impact for existing workflows, legacy fixtures, transport, migration, and rollback. Never invent fields to fill the template.",
16711
- "Step 2 \u2014 Clarify by readiness, not a fixed round or question count. Ask every decision-changing question that cannot be resolved from project facts; use as many batches as needed without repeating confirmed answers. Classify unknowns as blocking, recommendable, or defaultable. When a good approach exists, present 2\u20133 options and make a clear recommendation. Create structured input with non-empty scope, exclusions, technical decisions, defaults, blocking unknowns, stable acceptance IDs, and explicit confirmed/defaulted/not-applicable coverage for platform, core scope, stack, data, performance, compatibility, and security. Run `mancode workflow requirements <taskId> finalize --file <input.json>`; only advance to Step 3 when the CLI returns ready.",
16712
- "Step 3 \u2014 Plan Coach first returns READY_FOR_PLAN or NEEDS_CLARIFICATION. Never hide blocking gaps inside assumptions. Every option must solve the same goal, acceptance boundary, and scope; name its complexity bearer and observable cost; return exactly one recommendation with rejection reasons and stop conditions. A simple task may have one real direction and must not manufacture alternatives. When ready, write `plan.md` with confirmed scope, technical choices and reasons, reuse, exclusions, behavior, risks/rollback, completion criteria, defaults, and real validation. For cross-platform entry differences, unclear owner/source of truth, contract/state changes, cross-workflow/team/transport work, or multi-version compatibility, add an optional Domain Matrix inside plan.md; it is not authority. First plan is v1; revisions use `--plan-version <current+1>`.",
16755
+ "Step 1 \u2014 Scout: run a bounded, read-only decision-impact discovery; test the user premise against repository evidence, inspect the end-to-end user goal and common domain failure/edge paths, and retain at most three material findings with stable IDs F-1 through F-3 and type premise, scope, technical, risk, or acceptance. Mark each repository_fact or domain_hypothesis; an unverified domain hypothesis becomes a focused question, never a fact. Discovery produces evidence and recommendations, never execution authority. Write `scout-report.md` with the profile, implementation, dependencies, risks, unknowns, and\u2014when verifiable\u2014Current Behavior Evidence, Candidate Semantic Owner with confidence/conflict, Source of Truth split into authority/readers/writer/derived copies, and Historical / Compatibility Impact for existing workflows, legacy fixtures, transport, migration, and rollback. Never invent fields to fill the template.",
16756
+ "Step 2 \u2014 Clarify by readiness, not a fixed round or question count. Ask every decision-changing question that cannot be resolved from project facts; use as many batches as needed without repeating confirmed answers. Classify unknowns as blocking, recommendable, or defaultable. When a good approach exists, present 2\u20133 options and make a clear recommendation. Give every F-ID one type-directed disposition: blocking findings stay in blockingUnknowns; accepted scope or behavior enters confirmedScope plus matching acceptanceCriteria; accepted technical choices enter technicalDecisions; only explicitly excluded behavior enters excludedScope; low-impact reversible details may enter defaults. An unaccepted proposal remains unauthorized and is not copied into every field. Create structured input with non-empty scope, exclusions, technical decisions, defaults, blocking unknowns, stable acceptance IDs, and explicit confirmed/defaulted/not-applicable coverage for platform, core scope, stack, data, performance, compatibility, and security. Run `mancode workflow requirements <taskId> finalize --file <input.json>`; only advance to Step 3 when the CLI returns ready.",
16757
+ "Step 3 \u2014 Plan Coach first returns READY_FOR_PLAN or NEEDS_CLARIFICATION. Never hide blocking gaps inside assumptions. Every option must solve the same goal, acceptance boundary, and scope; name its complexity bearer and observable cost; return exactly one recommendation with rejection reasons and stop conditions. A simple task may have one real direction and must not manufacture alternatives. When ready, write `plan.md` with confirmed scope, technical choices and reasons, reuse, exclusions, behavior, risks/rollback, completion criteria, defaults, and real validation. Add a user-visible implementation scope with non-empty repo-relative include, exclude, and module labels; include is the file-write upper bound, exclude wins, and modules do not authorize files. For cross-platform entry differences, unclear owner/source of truth, contract/state changes, cross-workflow/team/transport work, or multi-version compatibility, add an optional Domain Matrix inside plan.md; it is not authority. First plan is v1; revisions use `--plan-version <current+1>`.",
16713
16758
  "Step 4 \u2014 Plan gate: recommend based on risk and let the user choose (1) hand the confirmed plan to lightweight solo via `mancode workflow handoff <taskId> --to solo`, (2) continue full governed execution via `mancode workflow decide <taskId> --plan-decision governed_execution` before Step 5, (3) keep the plan only via `mancode workflow decide <taskId> --plan-decision plan_only`, or (4) revise. Do not implement before this choice. Before either execution path, echo the plan version, delivery, stack, inclusions, exclusions, validation, and residual assumptions.",
16714
- "Step 5 \u2014 Implement the confirmed minimum change.",
16759
+ "Step 5 \u2014 State material assumptions and verifiable success criteria, then implement the smallest direct change inside both the confirmed plan and implementation scope. Reuse existing code and dependencies; do not add speculative features, one-off abstractions, configurability, adjacent cleanup, or unrelated defenses. A newly discovered out-of-scope need authorizes only NEEDS_REALIGNMENT until the user approves reframe. If an upgraded already-running local man task has no executable scope, show the complete boundary and wait for explicit approval, then rerun plan revise with the exact unchanged current plan plus --scope-file; this compatibility bind stales old evidence and cannot change behavior or an already executable boundary.",
16715
16760
  "Step 6 \u2014 Run `workflow verify <taskId> init`, execute detected build/lint/typecheck/test and smoke checks, and record every required acceptance ID with reproducible evidence; automated passed/failed records include the command and exit code. Use require-manual when a foreground browser, device, or human judgment is necessary; stop for explicit user confirmation before confirm-manual. The CLI blocks Step 7 and review until all checks pass. Then write `review-scope.md` and initialize targeted or full review. An explicit user review skip uses `workflow review <taskId> skip --reason <reason>` at Step 6, never generic skipped metadata.",
16716
- "Step 7 \u2014 Run one quality review limited to the changed diff and direct impact. Findings require changed-line evidence and user impact, with at most three new findings. Record stable blocker IDs through `workflow review ... complete`; do not fix yet.",
16761
+ "Step 7 \u2014 Run one quality review limited to the changed diff and direct impact. Compare every changed path and behavior with confirmed requirements, acceptance IDs, and implementation scope; any unauthorized behavior, path outside include, or path matching exclude is a blocker. Findings require changed-line evidence and user impact, with at most three new findings. Record stable blocker IDs through `workflow review ... complete`; do not fix yet.",
16717
16762
  "Step 8 \u2014 Only full review runs the security/boundary reviewer. It must read Film #1, mark the same root cause duplicate, and stay within security, permissions, recovery, resources, and boundaries. A targeted review treats the second domain as not applicable; it is never recorded as a skipped step.",
16718
16763
  "Step 9 \u2014 If open blockers exist, fix them in one remediation round and record resolved IDs through `workflow review ... remediate`; remediation invalidates all earlier acceptance evidence, so re-run and re-record every required check at Step 9 without re-running completed reviewers. Write `summary.md` and set completed only when verification and required review domains are complete and blockers are zero.",
16719
16764
  "",
@@ -16733,6 +16778,10 @@ var MODE_META = {
16733
16778
  "and currentWorkflowMode to manteam. First collect branch, dirty-worktree, contributor,",
16734
16779
  "shared-module, and handoff risks in `team-context.md`.",
16735
16780
  "",
16781
+ "Run the same bounded Scout discovery as /man with stable F-IDs and typed findings. Discovery produces evidence and recommendations, never execution authority.",
16782
+ "Use the same type-directed disposition as /man, bind the confirmed plan to a user-visible implementation scope, and treat that scope as the file-write upper bound for claims, implementation, and review.",
16783
+ "After explicit user approval, a file-boundary-only adjustment may use `workflow scope change`; it versions plan authority, stales prior evidence, and reissues compatible claims. A behavior or acceptance change still requires reframe.",
16784
+ "",
16736
16785
  "Then execute every /man Step 1 through Step 9, including clarification,",
16737
16786
  "plan gate, validation, bounded risk-based review, conditional completion, planVersion,",
16738
16787
  "Active Plans, and linked manba child behavior. Add compatibility, rollback,",
@@ -41821,311 +41870,41 @@ function assertPositiveRevision6(value, label) {
41821
41870
  }
41822
41871
  }
41823
41872
 
41824
- // src/context/plan-revision.ts
41825
- async function reviseV3Plan(input) {
41873
+ // src/context/scope-change.ts
41874
+ import { createHash as createHash11 } from "crypto";
41875
+ async function changeV3WorkflowScope(input) {
41826
41876
  const taskRef = parseTaskRefValue(input.taskRef);
41827
- const plan = requirePlan(input.plan);
41828
- const planDecision = parsePlanDecision(input.planDecision);
41829
- if (taskRef.namespace === "shared") {
41830
- assertSharedTextSafe(plan, "plan");
41831
- }
41832
- const context = await openV3TaskOperation({
41833
- projectRoot: input.projectRoot,
41834
- taskRef,
41835
- sessionId: input.sessionId,
41836
- expectedTaskRevision: input.expectedTaskRevision,
41837
- operationId: input.operationId,
41838
- extraEntityLocks: taskRef.namespace === "shared" ? [taskHeadEntityKey(taskRef)] : [],
41839
- now: input.now
41840
- });
41841
- let journal = null;
41842
- try {
41843
- assertPlanRevisionEligible(
41844
- context.task.metadata,
41845
- context.task.requirements
41846
- );
41847
- if (context.task.metadata.workflowMode === "manteam" && planDecision === "governed_execution") {
41848
- assertManteamPlanContent(plan);
41849
- }
41850
- if (context.task.plan?.content === plan && planDecision === null) {
41851
- throw new Error("MANCODE_PLAN_CONTENT_UNCHANGED");
41852
- }
41853
- const planChanged = context.task.plan?.content !== plan;
41854
- const timestamp4 = context.now.toISOString();
41855
- const planDigest = planChanged ? digestCanonicalJson({
41856
- artifactRef: { taskRef, kind: "plan" },
41857
- content: plan
41858
- }) : context.task.plan?.digest;
41859
- if (planDigest === void 0) {
41860
- throw new Error("MANCODE_PLAN_FILE_REQUIRED");
41861
- }
41862
- const review = planChanged ? markTaskReviewStale(context.task.review, context.operationId, timestamp4) : context.task.review;
41863
- const verification = planChanged ? markTaskVerificationStale(
41864
- context.task.verification,
41865
- context.operationId,
41866
- timestamp4
41867
- ) : context.task.verification;
41868
- const metadata = updateMetadata(
41869
- context.task.metadata,
41870
- context.task.requirements,
41871
- review,
41872
- verification,
41873
- planChanged,
41874
- planDecision,
41875
- context.operationId,
41876
- timestamp4
41877
- );
41878
- const aggregate = buildTaskAggregateManifest({
41879
- metadata,
41880
- requirements: context.task.requirements,
41881
- review,
41882
- verification,
41883
- planDigest,
41884
- latestCheckpoint: context.task.latestCheckpoint
41885
- });
41886
- const taskHeadFence = nextTaskHeadFence(context, aggregate, timestamp4);
41887
- if (planDecision === "plan_only") {
41888
- await enqueueSessionPointerProjection(context.projectRoot, {
41889
- operationId: context.operationId,
41890
- action: "clear",
41891
- sessionId: context.session.sessionId,
41892
- expectedPreviousTaskRef: context.session.activeTaskRef,
41893
- taskRef,
41894
- workflowMode: metadata.workflowMode,
41895
- taskRevision: metadata.revision,
41896
- now: context.now
41897
- });
41898
- }
41899
- journal = await createTaskOperationJournal(context, {
41900
- type: "plan_revision",
41901
- action: taskRef.namespace === "shared" ? "shared_metadata_plan_mutation" : "local_workflow_mutation",
41902
- expectedRevisions: taskMutationExpectedRevisions(context, [
41903
- "plan",
41904
- "review",
41905
- "verification"
41906
- ]),
41907
- recovery: {
41908
- actions: [
41909
- ...planChanged ? [
41910
- createTaskAuthorityFileRecoveryAction({
41911
- stepId: "write-plan",
41912
- taskRef,
41913
- fileName: "plan.md",
41914
- beforeContent: context.task.plan?.content ?? null,
41915
- targetContent: plan
41916
- })
41917
- ] : [],
41918
- createTaskAuthorityFileRecoveryAction({
41919
- stepId: "update-metadata",
41920
- taskRef,
41921
- fileName: "metadata.json",
41922
- beforeContent: serializeTaskAuthority(context.task.metadata),
41923
- targetContent: serializeTaskAuthority(metadata)
41924
- }),
41925
- ...planChanged ? [
41926
- createTaskAuthorityFileRecoveryAction({
41927
- stepId: "mark-review-verification-stale",
41928
- taskRef,
41929
- fileName: "review-ledger.json",
41930
- beforeContent: serializeTaskAuthority(context.task.review),
41931
- targetContent: serializeTaskAuthority(review)
41932
- }),
41933
- createTaskAuthorityFileRecoveryAction({
41934
- stepId: "mark-review-verification-stale",
41935
- taskRef,
41936
- fileName: "verification-ledger.json",
41937
- beforeContent: serializeTaskAuthority(
41938
- context.task.verification
41939
- ),
41940
- targetContent: serializeTaskAuthority(verification)
41941
- })
41942
- ] : [],
41943
- ...taskHeadFence === null ? [] : [
41944
- createTaskHeadFenceRecoveryAction({
41945
- stepId: "update-task-head-fence",
41946
- before: context.coordination.taskHeadFence,
41947
- fence: taskHeadFence
41948
- })
41949
- ]
41950
- ],
41951
- noOpStepIds: [
41952
- ...planChanged ? [] : ["write-plan", "mark-review-verification-stale"],
41953
- ...taskHeadFence === null ? ["update-task-head-fence"] : []
41954
- ]
41955
- }
41956
- });
41957
- journal = await advanceTaskOperation(context, journal, "validate", true);
41958
- journal = await advanceTaskOperation(context, journal, "write-plan", false);
41959
- if (planChanged) {
41960
- await writeTaskAuthorityFile(context, "plan.md", plan);
41961
- }
41962
- journal = await advanceTaskOperation(
41963
- context,
41964
- journal,
41965
- "update-metadata",
41966
- false
41967
- );
41968
- await writeTaskAuthorityFile(
41969
- context,
41970
- "metadata.json",
41971
- `${JSON.stringify(metadata, null, 2)}
41972
- `
41973
- );
41974
- journal = await advanceTaskOperation(
41975
- context,
41976
- journal,
41977
- "mark-review-verification-stale",
41978
- false
41979
- );
41980
- if (planChanged) {
41981
- await writeTaskAuthorityFile(
41982
- context,
41983
- "review-ledger.json",
41984
- `${JSON.stringify(review, null, 2)}
41985
- `
41986
- );
41987
- await writeTaskAuthorityFile(
41988
- context,
41989
- "verification-ledger.json",
41990
- `${JSON.stringify(verification, null, 2)}
41991
- `
41992
- );
41993
- }
41994
- journal = await advanceTaskOperation(
41995
- context,
41996
- journal,
41997
- "update-task-head-fence",
41998
- false
41999
- );
42000
- if (taskHeadFence !== null) {
42001
- await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
42002
- await replaceTaskHeadFence(context.homeStore, taskHeadFence);
42003
- }
42004
- const operation = await commitTaskOperation(context, journal);
42005
- if (planDecision === "plan_only") {
42006
- try {
42007
- await reconcileProjectionIntents(
42008
- context.projectRoot,
42009
- context.operationId,
42010
- context.now
42011
- );
42012
- } catch {
42013
- }
42014
- }
42015
- return {
42016
- metadata,
42017
- review,
42018
- verification,
42019
- planDigest,
42020
- aggregate,
42021
- taskHeadFence,
42022
- operation
42023
- };
42024
- } catch (error) {
42025
- if (journal !== null) {
42026
- try {
42027
- await handleTaskOperationFailure(context, journal);
42028
- } catch {
42029
- }
42030
- }
42031
- throw error;
42032
- } finally {
42033
- await context.release();
42034
- }
42035
- }
42036
- function requirePlan(value) {
42037
- if (typeof value !== "string" || !value.trim() || value.includes("\0")) {
42038
- throw new Error("MANCODE_PLAN_CONTENT_REQUIRED");
42039
- }
42040
- return value;
42041
- }
42042
- function parsePlanDecision(value) {
42043
- if (value === void 0) return null;
42044
- if (value !== "plan_only" && value !== "governed_execution") {
42045
- throw new Error("MANCODE_PLAN_DECISION_INVALID");
42046
- }
42047
- return value;
42048
- }
42049
- function assertPlanRevisionEligible(metadata, requirements) {
42050
- if (metadata.workflowMode !== "man" && metadata.workflowMode !== "manteam") {
42051
- throw new Error("MANCODE_PLAN_WORKFLOW_MODE_INVALID");
42052
- }
42053
- if (metadata.status !== "in_progress") {
42054
- throw new Error("MANCODE_PLAN_WORKFLOW_NOT_ACTIVE");
42055
- }
42056
- if (metadata.currentStep < 2 || metadata.currentStep > 4) {
42057
- throw new Error("MANCODE_PLAN_STEP_INVALID");
42058
- }
42059
- if (metadata.governance.planDecision !== null || metadata.governance.requirementsStatus !== "ready" || metadata.governance.requirementsDigest !== requirements.contentDigest || requirements.status !== "confirmed" || !requirementsAreReady(requirements)) {
42060
- throw new Error("MANCODE_PLAN_REQUIREMENTS_OR_DECISION_INVALID");
41877
+ if (taskRef.namespace !== "shared") {
41878
+ throw new Error("MANCODE_SCOPE_CHANGE_REQUIRES_SHARED_TASK");
42061
41879
  }
42062
- }
42063
- function updateMetadata(previous, requirements, review, verification, planChanged, planDecision, operationId, updatedAt) {
42064
- const status2 = planDecision === "plan_only" ? "planned" : "in_progress";
42065
- const currentStep = planDecision === "governed_execution" ? 5 : 4;
42066
- const next = parseWorkflowMetadata({
42067
- ...previous,
42068
- status: status2,
42069
- currentStep,
42070
- revision: previous.revision + 1,
42071
- transitionState: "stable",
42072
- lastOperationId: operationId,
42073
- governance: {
42074
- ...previous.governance,
42075
- requirementsStatus: "ready",
42076
- requirementsDigest: requirements.contentDigest,
42077
- planVersion: previous.governance.planVersion + (planChanged ? 1 : 0),
42078
- planDecision,
42079
- reviewStatus: planChanged ? "stale" : previous.governance.reviewStatus,
42080
- reviewLedgerDigest: review.contentDigest,
42081
- verificationStatus: planChanged ? "stale" : previous.governance.verificationStatus,
42082
- verificationLedgerDigest: verification.contentDigest
42083
- },
42084
- updatedAt
42085
- });
42086
- assertWorkflowMetadataTransition(previous, next, "ordinary");
42087
- return next;
42088
- }
42089
-
42090
- // src/context/reframe.ts
42091
- async function reframeV3Workflow(input) {
42092
- const taskRef = parseTaskRefValue(input.taskRef);
42093
- assertUlid(input.checkpointId, "reframe checkpointId");
41880
+ const scope = normalizeImplementationScope(input.scope);
42094
41881
  const now = input.now ?? /* @__PURE__ */ new Date();
41882
+ const timestamp4 = now.toISOString();
41883
+ const checkpointId = input.checkpointId ?? createUlid(now.getTime());
42095
41884
  const operationId = input.operationId ?? createUlid(now.getTime());
42096
- assertUlid(operationId, "reframe operationId");
42097
- const opened = await openReframeContext({
41885
+ assertUlid(checkpointId, "scope change checkpointId");
41886
+ assertUlid(operationId, "scope change operationId");
41887
+ const opened = await openScopeChangeContext({
42098
41888
  projectRoot: input.projectRoot,
42099
41889
  taskRef,
42100
41890
  sessionId: input.sessionId,
42101
41891
  expectedTaskRevision: input.expectedTaskRevision,
42102
- checkpointId: input.checkpointId,
41892
+ scope,
41893
+ checkpointId,
41894
+ successorClaimIds: input.successorClaimIds,
42103
41895
  operationId,
42104
41896
  now
42105
41897
  });
42106
- const { context, activeClaims: activeClaims2, openHandoffs, activeChildren } = opened;
41898
+ const { context, activeClaims: activeClaims2, successorClaimIds, successorPredecessors } = opened;
42107
41899
  let journal = null;
42108
41900
  try {
42109
- assertReframeEligible(context, activeClaims2, openHandoffs, activeChildren);
42110
- assertReframeClaimsFresh(context, activeClaims2);
42111
- const timestamp4 = context.now.toISOString();
42112
- const archivedRequirementsContent = await readTaskAuthorityFileAtRoot(
42113
- context.task.location.taskRoot,
42114
- "requirements.json"
42115
- );
42116
- if (archivedRequirementsContent === null) {
42117
- throw new Error("MANCODE_REFRAME_REQUIREMENTS_MISSING");
42118
- }
42119
- const pendingMetadata = markReframeOperationPending(
41901
+ assertScopeChangeEligible(context, scope);
41902
+ assertClaimsFreshForScopeChange(context, activeClaims2);
41903
+ const pendingMetadata = markScopeChangeOperationPending(
42120
41904
  context.task.metadata,
42121
41905
  context.operationId,
42122
41906
  timestamp4
42123
41907
  );
42124
- const requirements = createReframedRequirements(
42125
- context.task.requirements,
42126
- context.operationId,
42127
- timestamp4
42128
- );
42129
41908
  const review = markTaskReviewStale(
42130
41909
  context.task.review,
42131
41910
  context.operationId,
@@ -42136,71 +41915,80 @@ async function reframeV3Workflow(input) {
42136
41915
  context.operationId,
42137
41916
  timestamp4
42138
41917
  );
42139
- const releasedClaims = activeClaims2.map(
42140
- (claim) => releaseClaimForReframe(claim, context.operationId, timestamp4)
42141
- );
42142
- const archiveAction = createTaskArchiveRecoveryAction({
42143
- stepId: "archive-requirements-plan",
42144
- taskRef,
42145
- archiveId: context.operationId,
42146
- sourceTaskRevision: context.task.metadata.revision,
42147
- sourcePlanVersion: context.task.metadata.governance.planVersion,
42148
- createdAt: timestamp4,
42149
- requirementsContent: archivedRequirementsContent,
42150
- planContent: context.task.plan?.content ?? null
42151
- });
42152
- const branch = await readCheckoutBranch(context.projectRoot);
42153
- const checkpoint = buildReframeCheckpoint({
41918
+ const branch = await readCheckoutBranch(context.projectRoot) ?? "HEAD";
41919
+ const checkpoint = buildScopeChangedCheckpoint(
42154
41920
  context,
42155
- checkpointId: input.checkpointId,
42156
- taskRevision: pendingMetadata.revision + 1,
42157
- requirements,
42158
- review,
42159
- verification,
42160
- summary: input.summary,
42161
- nextAction: input.nextAction,
41921
+ pendingMetadata,
41922
+ checkpointId,
41923
+ input.checkpointSummary,
41924
+ input.checkpointNextAction,
42162
41925
  branch,
42163
- timestamp: timestamp4
42164
- });
42165
- const metadata = completeReframeMetadata(
41926
+ pendingMetadata.governance.planVersion + 1,
41927
+ review.contentDigest,
41928
+ verification.contentDigest,
41929
+ timestamp4
41930
+ );
41931
+ const metadata = completeScopeChangeMetadata(
42166
41932
  pendingMetadata,
42167
- requirements,
42168
- review,
42169
- verification,
41933
+ scope,
42170
41934
  checkpoint,
41935
+ review.contentDigest,
41936
+ verification.contentDigest,
42171
41937
  context.operationId,
42172
41938
  timestamp4
42173
41939
  );
41940
+ const pendingSuccessorClaims = buildPendingSuccessorClaims2(
41941
+ successorPredecessors,
41942
+ successorClaimIds,
41943
+ metadata,
41944
+ branch,
41945
+ requireCodeHead3(context),
41946
+ context.operationId,
41947
+ timestamp4,
41948
+ capabilitiesFromProjectConfig(context.project.config)
41949
+ );
41950
+ const successorByPredecessor = new Map(
41951
+ successorPredecessors.map((claim, index) => {
41952
+ const successorClaimId = successorClaimIds[index];
41953
+ if (successorClaimId === void 0) {
41954
+ throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_COUNT_INVALID");
41955
+ }
41956
+ return [claim.claimId, successorClaimId];
41957
+ })
41958
+ );
41959
+ const terminatedClaims = activeClaims2.map(
41960
+ (claim) => terminateClaimForScopeChange(
41961
+ claim,
41962
+ successorByPredecessor.get(claim.claimId) ?? null,
41963
+ context.operationId,
41964
+ timestamp4
41965
+ )
41966
+ );
41967
+ const activeSuccessorClaims = pendingSuccessorClaims.map(
41968
+ (claim) => activateSuccessorClaim3(claim, context.operationId, timestamp4)
41969
+ );
42174
41970
  const aggregate = buildTaskAggregateManifest({
42175
41971
  metadata,
42176
- requirements,
41972
+ requirements: context.task.requirements,
42177
41973
  review,
42178
41974
  verification,
42179
41975
  planDigest: context.task.plan?.digest ?? null,
42180
41976
  latestCheckpoint: checkpoint
42181
41977
  });
42182
41978
  const taskHeadFence = nextTaskHeadFence(context, aggregate, timestamp4);
42183
- const refreshesSessionPointer = context.session.activeTaskRef !== null && sameTaskRef(context.session.activeTaskRef, taskRef);
42184
- if (refreshesSessionPointer) {
42185
- await enqueueSessionPointerProjection(context.projectRoot, {
42186
- operationId: context.operationId,
42187
- action: "resume",
42188
- sessionId: context.session.sessionId,
42189
- expectedPreviousTaskRef: context.session.activeTaskRef,
42190
- taskRef,
42191
- workflowMode: metadata.workflowMode,
42192
- taskRevision: metadata.revision,
42193
- now: context.now
42194
- });
41979
+ if (taskHeadFence === null) {
41980
+ throw new Error("MANCODE_TASK_HEAD_FENCE_MISSING");
42195
41981
  }
42196
41982
  journal = await createTaskOperationJournal(context, {
42197
- type: "reframe",
42198
- action: taskRef.namespace === "shared" ? "shared_metadata_plan_mutation" : "local_workflow_mutation",
42199
- expectedRevisions: reframeExpectedRevisions(
41983
+ type: "scope_change_reclaim",
41984
+ action: "task_complete_scope_change_child_merge",
41985
+ expectedRevisions: scopeChangeExpectedRevisions(
42200
41986
  context,
42201
- input.checkpointId,
42202
- activeClaims2
41987
+ checkpointId,
41988
+ activeClaims2,
41989
+ successorClaimIds
42203
41990
  ),
41991
+ conditions: { completionGateSatisfied: true },
42204
41992
  recovery: {
42205
41993
  actions: [
42206
41994
  createTaskAuthorityFileRecoveryAction({
@@ -42210,20 +41998,28 @@ async function reframeV3Workflow(input) {
42210
41998
  beforeContent: serializeTaskAuthority(context.task.metadata),
42211
41999
  targetContent: serializeTaskAuthority(pendingMetadata)
42212
42000
  }),
42213
- archiveAction,
42214
- ...releasedClaims.map(
42215
- (claim, index) => createClaimRecoveryAction({
42216
- stepId: "release-active-claims",
42217
- before: activeClaims2[index] ?? null,
42001
+ createCheckpointRecoveryAction({
42002
+ stepId: "write-scope-changed-checkpoint",
42003
+ before: null,
42004
+ checkpoint
42005
+ }),
42006
+ ...pendingSuccessorClaims.map(
42007
+ (claim) => createClaimRecoveryAction({
42008
+ stepId: "create-pending-successor-claims",
42009
+ before: null,
42218
42010
  claim
42219
42011
  })
42220
42012
  ),
42221
- createTaskAuthorityFileRecoveryAction({
42222
- stepId: "write-requirements-draft",
42223
- taskRef,
42224
- fileName: "requirements.json",
42225
- beforeContent: serializeTaskAuthority(context.task.requirements),
42226
- targetContent: serializeTaskAuthority(requirements)
42013
+ ...terminatedClaims.map((claim, index) => {
42014
+ const before = activeClaims2[index];
42015
+ if (before === void 0) {
42016
+ throw new Error("MANCODE_CLAIM_SET_CHANGED");
42017
+ }
42018
+ return createClaimRecoveryAction({
42019
+ stepId: "terminate-old-claims",
42020
+ before,
42021
+ claim
42022
+ });
42227
42023
  }),
42228
42024
  createTaskAuthorityFileRecoveryAction({
42229
42025
  stepId: "mark-review-verification-stale",
@@ -42239,29 +42035,34 @@ async function reframeV3Workflow(input) {
42239
42035
  beforeContent: serializeTaskAuthority(context.task.verification),
42240
42036
  targetContent: serializeTaskAuthority(verification)
42241
42037
  }),
42242
- createCheckpointRecoveryAction({
42243
- stepId: "write-reframe-checkpoint",
42244
- before: null,
42245
- checkpoint
42246
- }),
42247
42038
  createTaskAuthorityFileRecoveryAction({
42248
- stepId: "commit-reframed-metadata",
42039
+ stepId: "update-metadata-scope",
42249
42040
  taskRef,
42250
42041
  fileName: "metadata.json",
42251
42042
  beforeContent: serializeTaskAuthority(pendingMetadata),
42252
42043
  targetContent: serializeTaskAuthority(metadata)
42253
42044
  }),
42254
- ...taskHeadFence === null ? [] : [
42255
- createTaskHeadFenceRecoveryAction({
42256
- stepId: "update-task-head-fence",
42257
- before: context.coordination.taskHeadFence,
42258
- fence: taskHeadFence
42259
- })
42260
- ]
42045
+ ...activeSuccessorClaims.map((claim, index) => {
42046
+ const before = pendingSuccessorClaims[index];
42047
+ if (before === void 0) {
42048
+ throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_COUNT_INVALID");
42049
+ }
42050
+ return createClaimRecoveryAction({
42051
+ stepId: "activate-successor-claims",
42052
+ before,
42053
+ claim
42054
+ });
42055
+ }),
42056
+ createTaskHeadFenceRecoveryAction({
42057
+ stepId: "update-task-head-fence",
42058
+ before: context.coordination.taskHeadFence,
42059
+ fence: taskHeadFence
42060
+ })
42261
42061
  ],
42262
42062
  noOpStepIds: [
42263
- ...releasedClaims.length === 0 ? ["release-active-claims"] : [],
42264
- ...taskHeadFence === null ? ["update-task-head-fence"] : []
42063
+ ...pendingSuccessorClaims.length === 0 ? ["create-pending-successor-claims"] : [],
42064
+ ...terminatedClaims.length === 0 ? ["terminate-old-claims"] : [],
42065
+ ...activeSuccessorClaims.length === 0 ? ["activate-successor-claims"] : []
42265
42066
  ]
42266
42067
  }
42267
42068
  });
@@ -42272,65 +42073,1015 @@ async function reframeV3Workflow(input) {
42272
42073
  "mark-task-operation-pending",
42273
42074
  false
42274
42075
  );
42275
- await assertReframeCodeHeadUnchanged(context);
42076
+ await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
42276
42077
  await writeTaskAuthorityFile(
42277
42078
  context,
42278
42079
  "metadata.json",
42279
- serializeTaskAuthority(pendingMetadata)
42080
+ `${JSON.stringify(pendingMetadata, null, 2)}
42081
+ `
42280
42082
  );
42281
42083
  journal = await advanceTaskOperation(
42282
42084
  context,
42283
42085
  journal,
42284
- "archive-requirements-plan",
42086
+ "write-scope-changed-checkpoint",
42285
42087
  false
42286
42088
  );
42287
- await assertReframeCodeHeadUnchanged(context);
42288
- await writeTaskArchive(context, archiveAction);
42089
+ await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
42090
+ await writeTaskCheckpoint(context, checkpoint);
42289
42091
  journal = await advanceTaskOperation(
42290
42092
  context,
42291
42093
  journal,
42292
- "release-active-claims",
42094
+ "create-pending-successor-claims",
42293
42095
  false
42294
42096
  );
42295
- await assertReframeCodeHeadUnchanged(context);
42296
- for (const [index, claim] of releasedClaims.entries()) {
42297
- const previous = activeClaims2[index];
42298
- if (previous === void 0) throw new Error("MANCODE_CLAIM_SET_CHANGED");
42299
- await updateClaim(context.homeStore, claim, previous.revision);
42097
+ await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
42098
+ for (const claim of pendingSuccessorClaims) {
42099
+ await createClaim(context.homeStore, claim);
42300
42100
  }
42301
42101
  journal = await advanceTaskOperation(
42302
42102
  context,
42303
42103
  journal,
42304
- "write-requirements-draft",
42104
+ "terminate-old-claims",
42305
42105
  false
42306
42106
  );
42307
- await assertReframeCodeHeadUnchanged(context);
42308
- await writeTaskAuthorityFile(
42309
- context,
42310
- "requirements.json",
42311
- serializeTaskAuthority(requirements)
42312
- );
42107
+ await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
42108
+ for (const [index, claim] of terminatedClaims.entries()) {
42109
+ const previous = activeClaims2[index];
42110
+ if (previous === void 0) {
42111
+ throw new Error("MANCODE_CLAIM_SET_CHANGED");
42112
+ }
42113
+ await updateClaim(context.homeStore, claim, previous.revision);
42114
+ }
42313
42115
  journal = await advanceTaskOperation(
42314
42116
  context,
42315
42117
  journal,
42316
42118
  "mark-review-verification-stale",
42317
42119
  false
42318
42120
  );
42319
- await assertReframeCodeHeadUnchanged(context);
42121
+ await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
42320
42122
  await writeTaskAuthorityFile(
42321
42123
  context,
42322
42124
  "review-ledger.json",
42323
- serializeTaskAuthority(review)
42125
+ `${JSON.stringify(review, null, 2)}
42126
+ `
42324
42127
  );
42325
42128
  await writeTaskAuthorityFile(
42326
42129
  context,
42327
42130
  "verification-ledger.json",
42328
- serializeTaskAuthority(verification)
42131
+ `${JSON.stringify(verification, null, 2)}
42132
+ `
42329
42133
  );
42330
42134
  journal = await advanceTaskOperation(
42331
42135
  context,
42332
42136
  journal,
42333
- "write-reframe-checkpoint",
42137
+ "update-metadata-scope",
42138
+ false
42139
+ );
42140
+ await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
42141
+ await writeTaskAuthorityFile(
42142
+ context,
42143
+ "metadata.json",
42144
+ `${JSON.stringify(metadata, null, 2)}
42145
+ `
42146
+ );
42147
+ journal = await advanceTaskOperation(
42148
+ context,
42149
+ journal,
42150
+ "activate-successor-claims",
42151
+ false
42152
+ );
42153
+ await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
42154
+ for (const claim of activeSuccessorClaims) {
42155
+ await updateClaim(context.homeStore, claim, 1);
42156
+ }
42157
+ journal = await advanceTaskOperation(
42158
+ context,
42159
+ journal,
42160
+ "update-task-head-fence",
42161
+ false
42162
+ );
42163
+ await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
42164
+ await replaceTaskHeadFence(context.homeStore, taskHeadFence);
42165
+ const operation = await commitTaskOperation(context, journal);
42166
+ return {
42167
+ metadata,
42168
+ checkpoint,
42169
+ terminatedClaims,
42170
+ successorClaims: activeSuccessorClaims,
42171
+ aggregate,
42172
+ taskHeadFence,
42173
+ operation
42174
+ };
42175
+ } catch (error) {
42176
+ if (journal !== null) {
42177
+ try {
42178
+ await handleTaskOperationFailure(context, journal);
42179
+ } catch {
42180
+ }
42181
+ }
42182
+ throw error;
42183
+ } finally {
42184
+ await context.release();
42185
+ }
42186
+ }
42187
+ async function openScopeChangeContext(input) {
42188
+ for (let attempt = 0; attempt < 3; attempt += 1) {
42189
+ const runtime = await readProjectRuntimeContext(input.projectRoot);
42190
+ const store = new V3ContextStore(input.projectRoot);
42191
+ const homeStore = resolveTaskEntityHomeStore(
42192
+ runtime.entityHomeStoreContext,
42193
+ input.taskRef
42194
+ );
42195
+ const preflight = await store.readCoordinationSnapshot(
42196
+ input.taskRef,
42197
+ homeStore
42198
+ );
42199
+ const preflightClaims = activeClaims(preflight.claims);
42200
+ const preflightSuccessors = claimsWithinScope(preflightClaims, input.scope);
42201
+ const preflightSuccessorIds = resolveSuccessorClaimIds2(
42202
+ preflightSuccessors,
42203
+ input.successorClaimIds,
42204
+ input.operationId,
42205
+ input.now.toISOString()
42206
+ );
42207
+ const context = await openV3TaskOperation({
42208
+ projectRoot: input.projectRoot,
42209
+ taskRef: input.taskRef,
42210
+ sessionId: input.sessionId,
42211
+ expectedTaskRevision: input.expectedTaskRevision,
42212
+ operationId: input.operationId,
42213
+ extraEntityLocks: [
42214
+ `checkpoint:${input.checkpointId}`,
42215
+ taskHeadEntityKey(input.taskRef),
42216
+ ...preflightClaims.map((claim) => `claim:${claim.claimId}`),
42217
+ ...preflightSuccessorIds.map((claimId) => `claim:${claimId}`)
42218
+ ],
42219
+ now: input.now
42220
+ });
42221
+ const lockedClaims = activeClaims(context.coordination.claims);
42222
+ if (sameClaimIdSet(preflightClaims, lockedClaims)) {
42223
+ const successors = claimsWithinScope(lockedClaims, input.scope);
42224
+ const successorIds = resolveSuccessorClaimIds2(
42225
+ successors,
42226
+ input.successorClaimIds,
42227
+ input.operationId,
42228
+ input.now.toISOString()
42229
+ );
42230
+ return {
42231
+ context,
42232
+ activeClaims: lockedClaims,
42233
+ successorPredecessors: successors,
42234
+ successorClaimIds: successorIds
42235
+ };
42236
+ }
42237
+ await context.release();
42238
+ }
42239
+ throw new Error("MANCODE_CLAIM_SET_CHANGED");
42240
+ }
42241
+ function assertScopeChangeEligible(context, scope) {
42242
+ const metadata = context.task.metadata;
42243
+ if (context.project.config.transport.mode !== "local") {
42244
+ throw new Error("MANCODE_GIT_REF_TRANSPORT_NOT_IMPLEMENTED");
42245
+ }
42246
+ if (metadata.workflowMode !== "manteam") {
42247
+ throw new Error("MANCODE_SCOPE_CHANGE_WORKFLOW_MODE_INVALID");
42248
+ }
42249
+ if (metadata.status !== "in_progress") {
42250
+ throw new Error("MANCODE_SCOPE_CHANGE_WORKFLOW_NOT_ACTIVE");
42251
+ }
42252
+ if (metadata.ownerActorId !== context.session.actorId) {
42253
+ throw new Error("MANCODE_TASK_OWNER_REQUIRED");
42254
+ }
42255
+ if (metadata.parent !== null) {
42256
+ throw new Error("MANCODE_PARENT_SCOPE_INHERITANCE_REQUIRED");
42257
+ }
42258
+ if (metadata.implementationScope.digest === scope.digest) {
42259
+ throw new Error("MANCODE_SCOPE_CHANGE_NOOP");
42260
+ }
42261
+ }
42262
+ function assertClaimsFreshForScopeChange(context, claims) {
42263
+ const codeHead = requireCodeHead3(context);
42264
+ for (const claim of claims) {
42265
+ if (claim.authority.mode !== "local") {
42266
+ throw new Error("MANCODE_OPERATION_REPAIR_REQUIRED");
42267
+ }
42268
+ const validity = deriveClaimValidity(claim, {
42269
+ taskRef: context.taskRef,
42270
+ taskRevision: context.task.metadata.revision,
42271
+ implementationScopeDigest: context.task.metadata.implementationScope.digest,
42272
+ ownershipEpoch: context.task.metadata.ownershipEpoch,
42273
+ codeRefHead: codeHead,
42274
+ now: context.now,
42275
+ transportFreshness: "fresh"
42276
+ });
42277
+ if (validity !== "fresh") {
42278
+ throw new Error("MANCODE_CLAIM_REVALIDATION_REQUIRED");
42279
+ }
42280
+ }
42281
+ }
42282
+ function normalizeImplementationScope(value) {
42283
+ assertRecord(value, "workflow scope change");
42284
+ assertKnownKeys(
42285
+ value,
42286
+ ["include", "exclude", "modules"],
42287
+ "workflow scope change"
42288
+ );
42289
+ const scope = {
42290
+ source: "explicit",
42291
+ include: normalizeScopeValues(value.include, "include", true),
42292
+ exclude: normalizeScopeValues(value.exclude, "exclude", true),
42293
+ modules: normalizeScopeValues(value.modules, "modules", false)
42294
+ };
42295
+ const included = new Set(scope.include);
42296
+ if (scope.exclude.some((item) => included.has(item))) {
42297
+ throw new Error("MANCODE_SCOPE_INCLUDE_EXCLUDE_CONFLICT");
42298
+ }
42299
+ return { ...scope, digest: digestCanonicalJson(scope) };
42300
+ }
42301
+ function normalizeScopeValues(value, label, paths) {
42302
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !item.trim())) {
42303
+ throw new Error(`MANCODE_SCOPE_${label.toUpperCase()}_INVALID`);
42304
+ }
42305
+ const values = value.map((item) => item.trim());
42306
+ const normalized = sortUtf8StringSet(values);
42307
+ if (normalized.length !== values.length) {
42308
+ throw new Error(`MANCODE_SCOPE_${label.toUpperCase()}_DUPLICATE`);
42309
+ }
42310
+ for (const item of normalized) {
42311
+ assertSharedTextSafe(item, `workflow scope ${label}`);
42312
+ if (paths) assertScopePath(item);
42313
+ }
42314
+ return normalized;
42315
+ }
42316
+ function assertScopePath(value) {
42317
+ if (value.startsWith("/") || value.startsWith("~") || /^[A-Za-z]:/.test(value) || value.includes("\\") || value.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
42318
+ throw new Error("MANCODE_SCOPE_PATH_INVALID");
42319
+ }
42320
+ }
42321
+ function markScopeChangeOperationPending(previous, operationId, updatedAt) {
42322
+ const next = parseWorkflowMetadata({
42323
+ ...previous,
42324
+ revision: previous.revision + 1,
42325
+ transitionState: "operation_pending",
42326
+ lastOperationId: operationId,
42327
+ updatedAt
42328
+ });
42329
+ assertWorkflowMetadataTransition(previous, next, "ordinary");
42330
+ return next;
42331
+ }
42332
+ function completeScopeChangeMetadata(previous, scope, checkpoint, reviewLedgerDigest2, verificationLedgerDigest2, operationId, updatedAt) {
42333
+ const next = parseWorkflowMetadata({
42334
+ ...previous,
42335
+ revision: previous.revision + 1,
42336
+ transitionState: "stable",
42337
+ implementationScope: scope,
42338
+ governance: {
42339
+ ...previous.governance,
42340
+ planVersion: previous.governance.planVersion + 1,
42341
+ reviewStatus: "stale",
42342
+ reviewLedgerDigest: reviewLedgerDigest2,
42343
+ verificationStatus: "stale",
42344
+ verificationLedgerDigest: verificationLedgerDigest2
42345
+ },
42346
+ latestCheckpointRef: {
42347
+ taskRef: checkpoint.taskRef,
42348
+ kind: "checkpoint",
42349
+ artifactId: checkpoint.checkpointId
42350
+ },
42351
+ lastOperationId: operationId,
42352
+ updatedAt
42353
+ });
42354
+ assertWorkflowMetadataTransition(previous, next, "ordinary");
42355
+ return next;
42356
+ }
42357
+ function buildScopeChangedCheckpoint(context, pendingMetadata, checkpointId, summary, nextAction, branch, planVersion, reviewLedgerDigest2, verificationLedgerDigest2, timestamp4) {
42358
+ return parseCheckpoint({
42359
+ schemaVersion: 1,
42360
+ checkpointId,
42361
+ operationId: context.operationId,
42362
+ taskRef: context.taskRef,
42363
+ taskRevision: pendingMetadata.revision,
42364
+ ownershipEpochAtOffer: pendingMetadata.ownershipEpoch,
42365
+ kind: "scope_changed",
42366
+ git: {
42367
+ branch,
42368
+ head: requireCodeHead3(context),
42369
+ base: pendingMetadata.base?.head ?? null
42370
+ },
42371
+ summary: summary ?? "Changed the implementation scope and replaced affected coordination claims.",
42372
+ governance: {
42373
+ requirementsDigest: context.task.requirements.contentDigest,
42374
+ planVersion,
42375
+ reviewLedgerDigest: reviewLedgerDigest2,
42376
+ verificationLedgerDigest: verificationLedgerDigest2
42377
+ },
42378
+ nextAction: nextAction ?? "Re-read the updated scope and continue only with the successor claim.",
42379
+ createdBy: {
42380
+ actorId: context.session.actorId,
42381
+ client: context.session.client
42382
+ },
42383
+ createdAt: timestamp4
42384
+ });
42385
+ }
42386
+ function buildPendingSuccessorClaims2(predecessors, successorClaimIds, metadata, branch, codeHead, operationId, timestamp4, capabilities) {
42387
+ return predecessors.map((previous, index) => {
42388
+ const claimId = successorClaimIds[index];
42389
+ if (claimId === void 0) {
42390
+ throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_COUNT_INVALID");
42391
+ }
42392
+ return parseClaim({
42393
+ ...previous,
42394
+ claimId,
42395
+ authority: { mode: "local", remoteRevision: null },
42396
+ taskRevisionAtAcquire: metadata.revision,
42397
+ lastValidatedTaskRevision: metadata.revision,
42398
+ implementationScopeDigest: metadata.implementationScope.digest,
42399
+ ownershipEpochAtAcquire: metadata.ownershipEpoch,
42400
+ state: "pending",
42401
+ revision: 1,
42402
+ codeRefAtAcquire: { branch, head: codeHead },
42403
+ lastValidatedCodeRef: { branch, head: codeHead },
42404
+ acquisitionEnforcement: capabilities.claimAcquisition,
42405
+ writeGuard: capabilities.writeGuard,
42406
+ predecessorClaimId: previous.claimId,
42407
+ successorClaimId: null,
42408
+ lastOperationId: operationId,
42409
+ createdAt: timestamp4,
42410
+ updatedAt: timestamp4
42411
+ });
42412
+ });
42413
+ }
42414
+ function terminateClaimForScopeChange(previous, successorClaimId, operationId, timestamp4) {
42415
+ const next = parseClaim({
42416
+ ...previous,
42417
+ state: successorClaimId === null ? "released" : "transferred",
42418
+ revision: previous.revision + 1,
42419
+ successorClaimId,
42420
+ lastOperationId: operationId,
42421
+ updatedAt: timestamp4
42422
+ });
42423
+ assertClaimTransition(previous, next);
42424
+ return next;
42425
+ }
42426
+ function activateSuccessorClaim3(previous, operationId, timestamp4) {
42427
+ const next = parseClaim({
42428
+ ...previous,
42429
+ state: "active",
42430
+ revision: previous.revision + 1,
42431
+ lastOperationId: operationId,
42432
+ updatedAt: timestamp4
42433
+ });
42434
+ assertClaimTransition(previous, next);
42435
+ return next;
42436
+ }
42437
+ function scopeChangeExpectedRevisions(context, checkpointId, predecessors, successorClaimIds) {
42438
+ const expected = {
42439
+ [taskEntityKey(context.taskRef)]: context.task.metadata.revision,
42440
+ [`review:${context.taskRef.taskId}`]: context.task.review.revision,
42441
+ [`verification:${context.taskRef.taskId}`]: context.task.verification.revision,
42442
+ [`checkpoint:${checkpointId}`]: 0
42443
+ };
42444
+ for (const claim of predecessors) {
42445
+ expected[`claim:${claim.claimId}`] = claim.revision;
42446
+ }
42447
+ for (const claimId of successorClaimIds) {
42448
+ expected[`claim:${claimId}`] = 0;
42449
+ }
42450
+ const fence = context.coordination.taskHeadFence;
42451
+ if (fence === null) throw new Error("MANCODE_TASK_HEAD_FENCE_MISSING");
42452
+ expected[taskHeadEntityKey(context.taskRef)] = fence.fenceRevision;
42453
+ return expected;
42454
+ }
42455
+ function activeClaims(claims) {
42456
+ return claims.filter((claim) => claim.state === "active").sort((left, right) => compareUtf815(left.claimId, right.claimId));
42457
+ }
42458
+ function claimsWithinScope(claims, scope) {
42459
+ return claims.filter(
42460
+ (claim) => evaluateClaimScopeSubset(claim.scope, {
42461
+ source: scope.source,
42462
+ include: scope.include,
42463
+ exclude: scope.exclude,
42464
+ modules: scope.modules
42465
+ }).allowed
42466
+ );
42467
+ }
42468
+ function resolveSuccessorClaimIds2(predecessors, requested, operationId, timestamp4) {
42469
+ const ids = requested ?? predecessors.map(
42470
+ (claim) => scopeSuccessorClaimId(operationId, claim.claimId, timestamp4)
42471
+ );
42472
+ if (ids.length !== predecessors.length) {
42473
+ throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_COUNT_INVALID");
42474
+ }
42475
+ const predecessorIds = new Set(predecessors.map((claim) => claim.claimId));
42476
+ const seen = /* @__PURE__ */ new Set();
42477
+ for (const claimId of ids) {
42478
+ assertUlid(claimId, "scope successor claimId");
42479
+ if (predecessorIds.has(claimId) || seen.has(claimId)) {
42480
+ throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_INVALID");
42481
+ }
42482
+ seen.add(claimId);
42483
+ }
42484
+ return ids;
42485
+ }
42486
+ function scopeSuccessorClaimId(operationId, predecessorClaimId, timestamp4) {
42487
+ assertUlid(operationId, "scope change operationId");
42488
+ assertUlid(predecessorClaimId, "scope predecessor claimId");
42489
+ const milliseconds = Date.parse(timestamp4);
42490
+ if (Number.isNaN(milliseconds)) {
42491
+ throw new Error("MANCODE_SCOPE_TIMESTAMP_INVALID");
42492
+ }
42493
+ const entropy = createHash11("sha256").update(`scope-change:${operationId}:${predecessorClaimId}`, "utf8").digest().subarray(0, 10);
42494
+ return createUlid(milliseconds, entropy);
42495
+ }
42496
+ function requireCodeHead3(context) {
42497
+ if (context.codeHead === null) {
42498
+ throw new Error("MANCODE_TASK_HEAD_CODE_REF_UNAVAILABLE");
42499
+ }
42500
+ return context.codeHead;
42501
+ }
42502
+ function sameClaimIdSet(left, right) {
42503
+ return left.length === right.length && left.every((claim, index) => claim.claimId === right[index]?.claimId);
42504
+ }
42505
+ function compareUtf815(left, right) {
42506
+ return Buffer.from(left, "utf8").compare(Buffer.from(right, "utf8"));
42507
+ }
42508
+
42509
+ // src/context/plan-revision.ts
42510
+ async function reviseV3Plan(input) {
42511
+ const taskRef = parseTaskRefValue(input.taskRef);
42512
+ const plan = requirePlan(input.plan);
42513
+ const planDecision = parsePlanDecision(input.planDecision);
42514
+ const submittedScope = input.implementationScope === void 0 ? null : normalizeImplementationScope(input.implementationScope);
42515
+ if (taskRef.namespace === "shared") {
42516
+ assertSharedTextSafe(plan, "plan");
42517
+ }
42518
+ const context = await openV3TaskOperation({
42519
+ projectRoot: input.projectRoot,
42520
+ taskRef,
42521
+ sessionId: input.sessionId,
42522
+ expectedTaskRevision: input.expectedTaskRevision,
42523
+ operationId: input.operationId,
42524
+ extraEntityLocks: taskRef.namespace === "shared" ? [taskHeadEntityKey(taskRef)] : [],
42525
+ now: input.now
42526
+ });
42527
+ let journal = null;
42528
+ try {
42529
+ const planChanged = context.task.plan?.content !== plan;
42530
+ const executionScopeBinding = assertExecutionScopeBindingAttempt({
42531
+ metadata: context.task.metadata,
42532
+ currentPlan: context.task.plan?.content ?? null,
42533
+ submittedPlan: plan,
42534
+ submittedScope,
42535
+ planDecisionSupplied: input.planDecision !== void 0,
42536
+ sessionActorId: context.session.actorId
42537
+ });
42538
+ assertPlanRevisionEligible(
42539
+ context.task.metadata,
42540
+ context.task.requirements,
42541
+ executionScopeBinding
42542
+ );
42543
+ const implementationScope = submittedScope ?? context.task.metadata.implementationScope;
42544
+ const scopeChanged = submittedScope !== null && submittedScope.digest !== context.task.metadata.implementationScope.digest;
42545
+ if (planDecision === "governed_execution") {
42546
+ assertExecutableImplementationScope(implementationScope);
42547
+ }
42548
+ if (executionScopeBinding) {
42549
+ assertExecutableImplementationScope(implementationScope);
42550
+ }
42551
+ if (context.task.metadata.workflowMode === "manteam" && planDecision === "governed_execution") {
42552
+ assertManteamPlanContent(plan);
42553
+ }
42554
+ if (context.task.plan?.content === plan && planDecision === null && !scopeChanged) {
42555
+ throw new Error("MANCODE_PLAN_CONTENT_UNCHANGED");
42556
+ }
42557
+ const authorityChanged = planChanged || scopeChanged;
42558
+ const timestamp4 = context.now.toISOString();
42559
+ const planDigest = planChanged ? digestCanonicalJson({
42560
+ artifactRef: { taskRef, kind: "plan" },
42561
+ content: plan
42562
+ }) : context.task.plan?.digest;
42563
+ if (planDigest === void 0) {
42564
+ throw new Error("MANCODE_PLAN_FILE_REQUIRED");
42565
+ }
42566
+ const review = authorityChanged ? markTaskReviewStale(context.task.review, context.operationId, timestamp4) : context.task.review;
42567
+ const verification = authorityChanged ? markTaskVerificationStale(
42568
+ context.task.verification,
42569
+ context.operationId,
42570
+ timestamp4
42571
+ ) : context.task.verification;
42572
+ const metadata = updateMetadata(
42573
+ context.task.metadata,
42574
+ context.task.requirements,
42575
+ review,
42576
+ verification,
42577
+ implementationScope,
42578
+ authorityChanged,
42579
+ planDecision,
42580
+ executionScopeBinding,
42581
+ context.operationId,
42582
+ timestamp4
42583
+ );
42584
+ const aggregate = buildTaskAggregateManifest({
42585
+ metadata,
42586
+ requirements: context.task.requirements,
42587
+ review,
42588
+ verification,
42589
+ planDigest,
42590
+ latestCheckpoint: context.task.latestCheckpoint
42591
+ });
42592
+ const taskHeadFence = nextTaskHeadFence(context, aggregate, timestamp4);
42593
+ if (planDecision === "plan_only") {
42594
+ await enqueueSessionPointerProjection(context.projectRoot, {
42595
+ operationId: context.operationId,
42596
+ action: "clear",
42597
+ sessionId: context.session.sessionId,
42598
+ expectedPreviousTaskRef: context.session.activeTaskRef,
42599
+ taskRef,
42600
+ workflowMode: metadata.workflowMode,
42601
+ taskRevision: metadata.revision,
42602
+ now: context.now
42603
+ });
42604
+ }
42605
+ journal = await createTaskOperationJournal(context, {
42606
+ type: "plan_revision",
42607
+ action: taskRef.namespace === "shared" ? "shared_metadata_plan_mutation" : "local_workflow_mutation",
42608
+ expectedRevisions: taskMutationExpectedRevisions(context, [
42609
+ "plan",
42610
+ "review",
42611
+ "verification"
42612
+ ]),
42613
+ recovery: {
42614
+ actions: [
42615
+ ...planChanged ? [
42616
+ createTaskAuthorityFileRecoveryAction({
42617
+ stepId: "write-plan",
42618
+ taskRef,
42619
+ fileName: "plan.md",
42620
+ beforeContent: context.task.plan?.content ?? null,
42621
+ targetContent: plan
42622
+ })
42623
+ ] : [],
42624
+ createTaskAuthorityFileRecoveryAction({
42625
+ stepId: "update-metadata",
42626
+ taskRef,
42627
+ fileName: "metadata.json",
42628
+ beforeContent: serializeTaskAuthority(context.task.metadata),
42629
+ targetContent: serializeTaskAuthority(metadata)
42630
+ }),
42631
+ ...authorityChanged ? [
42632
+ createTaskAuthorityFileRecoveryAction({
42633
+ stepId: "mark-review-verification-stale",
42634
+ taskRef,
42635
+ fileName: "review-ledger.json",
42636
+ beforeContent: serializeTaskAuthority(context.task.review),
42637
+ targetContent: serializeTaskAuthority(review)
42638
+ }),
42639
+ createTaskAuthorityFileRecoveryAction({
42640
+ stepId: "mark-review-verification-stale",
42641
+ taskRef,
42642
+ fileName: "verification-ledger.json",
42643
+ beforeContent: serializeTaskAuthority(
42644
+ context.task.verification
42645
+ ),
42646
+ targetContent: serializeTaskAuthority(verification)
42647
+ })
42648
+ ] : [],
42649
+ ...taskHeadFence === null ? [] : [
42650
+ createTaskHeadFenceRecoveryAction({
42651
+ stepId: "update-task-head-fence",
42652
+ before: context.coordination.taskHeadFence,
42653
+ fence: taskHeadFence
42654
+ })
42655
+ ]
42656
+ ],
42657
+ noOpStepIds: [
42658
+ ...planChanged ? [] : ["write-plan"],
42659
+ ...authorityChanged ? [] : ["mark-review-verification-stale"],
42660
+ ...taskHeadFence === null ? ["update-task-head-fence"] : []
42661
+ ]
42662
+ }
42663
+ });
42664
+ journal = await advanceTaskOperation(context, journal, "validate", true);
42665
+ journal = await advanceTaskOperation(context, journal, "write-plan", false);
42666
+ if (planChanged) {
42667
+ await writeTaskAuthorityFile(context, "plan.md", plan);
42668
+ }
42669
+ journal = await advanceTaskOperation(
42670
+ context,
42671
+ journal,
42672
+ "update-metadata",
42673
+ false
42674
+ );
42675
+ await writeTaskAuthorityFile(
42676
+ context,
42677
+ "metadata.json",
42678
+ `${JSON.stringify(metadata, null, 2)}
42679
+ `
42680
+ );
42681
+ journal = await advanceTaskOperation(
42682
+ context,
42683
+ journal,
42684
+ "mark-review-verification-stale",
42685
+ false
42686
+ );
42687
+ if (authorityChanged) {
42688
+ await writeTaskAuthorityFile(
42689
+ context,
42690
+ "review-ledger.json",
42691
+ `${JSON.stringify(review, null, 2)}
42692
+ `
42693
+ );
42694
+ await writeTaskAuthorityFile(
42695
+ context,
42696
+ "verification-ledger.json",
42697
+ `${JSON.stringify(verification, null, 2)}
42698
+ `
42699
+ );
42700
+ }
42701
+ journal = await advanceTaskOperation(
42702
+ context,
42703
+ journal,
42704
+ "update-task-head-fence",
42705
+ false
42706
+ );
42707
+ if (taskHeadFence !== null) {
42708
+ await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
42709
+ await replaceTaskHeadFence(context.homeStore, taskHeadFence);
42710
+ }
42711
+ const operation = await commitTaskOperation(context, journal);
42712
+ if (planDecision === "plan_only") {
42713
+ try {
42714
+ await reconcileProjectionIntents(
42715
+ context.projectRoot,
42716
+ context.operationId,
42717
+ context.now
42718
+ );
42719
+ } catch {
42720
+ }
42721
+ }
42722
+ return {
42723
+ metadata,
42724
+ review,
42725
+ verification,
42726
+ planDigest,
42727
+ aggregate,
42728
+ taskHeadFence,
42729
+ operation
42730
+ };
42731
+ } catch (error) {
42732
+ if (journal !== null) {
42733
+ try {
42734
+ await handleTaskOperationFailure(context, journal);
42735
+ } catch {
42736
+ }
42737
+ }
42738
+ throw error;
42739
+ } finally {
42740
+ await context.release();
42741
+ }
42742
+ }
42743
+ function requirePlan(value) {
42744
+ if (typeof value !== "string" || !value.trim() || value.includes("\0")) {
42745
+ throw new Error("MANCODE_PLAN_CONTENT_REQUIRED");
42746
+ }
42747
+ return value;
42748
+ }
42749
+ function parsePlanDecision(value) {
42750
+ if (value === void 0) return null;
42751
+ if (value !== "plan_only" && value !== "governed_execution") {
42752
+ throw new Error("MANCODE_PLAN_DECISION_INVALID");
42753
+ }
42754
+ return value;
42755
+ }
42756
+ function assertPlanRevisionEligible(metadata, requirements, executionScopeBinding) {
42757
+ if (executionScopeBinding) {
42758
+ assertReadyPlanRequirements(metadata, requirements);
42759
+ return;
42760
+ }
42761
+ if (metadata.workflowMode !== "man" && metadata.workflowMode !== "manteam") {
42762
+ throw new Error("MANCODE_PLAN_WORKFLOW_MODE_INVALID");
42763
+ }
42764
+ if (metadata.status !== "in_progress") {
42765
+ throw new Error("MANCODE_PLAN_WORKFLOW_NOT_ACTIVE");
42766
+ }
42767
+ if (metadata.currentStep < 2 || metadata.currentStep > 4) {
42768
+ throw new Error("MANCODE_PLAN_STEP_INVALID");
42769
+ }
42770
+ if (metadata.governance.planDecision !== null) {
42771
+ throw new Error("MANCODE_PLAN_REQUIREMENTS_OR_DECISION_INVALID");
42772
+ }
42773
+ assertReadyPlanRequirements(metadata, requirements);
42774
+ }
42775
+ function assertReadyPlanRequirements(metadata, requirements) {
42776
+ if (metadata.governance.requirementsStatus !== "ready" || metadata.governance.requirementsDigest !== requirements.contentDigest || requirements.status !== "confirmed" || !requirementsAreReady(requirements)) {
42777
+ throw new Error("MANCODE_PLAN_REQUIREMENTS_OR_DECISION_INVALID");
42778
+ }
42779
+ assertRequirementsScopeConsistent(requirements);
42780
+ }
42781
+ function assertExecutionScopeBindingAttempt(input) {
42782
+ const decision = input.metadata.governance.planDecision;
42783
+ if (decision !== "governed_execution" && decision !== "solo_handoff") {
42784
+ return false;
42785
+ }
42786
+ if (input.metadata.workflowMode !== "man" || input.metadata.coordination !== "single" || input.metadata.taskRef.namespace !== "local") {
42787
+ throw new Error("MANCODE_EXECUTION_SCOPE_BINDING_LOCAL_MAN_ONLY");
42788
+ }
42789
+ const activeExecution = decision === "governed_execution" && input.metadata.status === "in_progress" && input.metadata.currentStep >= 5 || decision === "solo_handoff" && input.metadata.status === "planned" && input.metadata.currentStep === 4 && input.metadata.soloExecution?.state === "active";
42790
+ if (!activeExecution) {
42791
+ throw new Error("MANCODE_EXECUTION_SCOPE_BINDING_NOT_ACTIVE");
42792
+ }
42793
+ if (input.metadata.ownerActorId !== input.sessionActorId) {
42794
+ throw new Error("MANCODE_TASK_OWNER_REQUIRED");
42795
+ }
42796
+ if (implementationScopeIsExecutable(input.metadata.implementationScope)) {
42797
+ throw new Error("MANCODE_EXECUTION_SCOPE_ALREADY_BOUND");
42798
+ }
42799
+ if (input.submittedScope === null) {
42800
+ throw new Error("MANCODE_IMPLEMENTATION_SCOPE_REQUIRED");
42801
+ }
42802
+ if (input.currentPlan === null || input.currentPlan !== input.submittedPlan) {
42803
+ throw new Error("MANCODE_EXECUTION_SCOPE_BINDING_PLAN_CHANGED");
42804
+ }
42805
+ if (input.planDecisionSupplied) {
42806
+ throw new Error("MANCODE_EXECUTION_SCOPE_BINDING_DECISION_INVALID");
42807
+ }
42808
+ assertExecutableImplementationScope(input.submittedScope);
42809
+ return true;
42810
+ }
42811
+ function updateMetadata(previous, requirements, review, verification, implementationScope, authorityChanged, planDecision, executionScopeBinding, operationId, updatedAt) {
42812
+ const status2 = executionScopeBinding ? previous.status : planDecision === "plan_only" ? "planned" : "in_progress";
42813
+ const currentStep = executionScopeBinding ? previous.currentStep : planDecision === "governed_execution" ? 5 : 4;
42814
+ const nextPlanVersion = previous.governance.planVersion + (authorityChanged ? 1 : 0);
42815
+ const next = parseWorkflowMetadata({
42816
+ ...previous,
42817
+ status: status2,
42818
+ currentStep,
42819
+ revision: previous.revision + 1,
42820
+ transitionState: "stable",
42821
+ lastOperationId: operationId,
42822
+ implementationScope,
42823
+ governance: {
42824
+ ...previous.governance,
42825
+ requirementsStatus: "ready",
42826
+ requirementsDigest: requirements.contentDigest,
42827
+ planVersion: nextPlanVersion,
42828
+ planDecision: executionScopeBinding ? previous.governance.planDecision : planDecision,
42829
+ reviewStatus: authorityChanged ? "stale" : previous.governance.reviewStatus,
42830
+ reviewLedgerDigest: review.contentDigest,
42831
+ verificationStatus: authorityChanged ? "stale" : previous.governance.verificationStatus,
42832
+ verificationLedgerDigest: verification.contentDigest
42833
+ },
42834
+ soloExecution: executionScopeBinding && previous.soloExecution !== null ? { ...previous.soloExecution, planVersion: nextPlanVersion } : previous.soloExecution,
42835
+ updatedAt
42836
+ });
42837
+ assertWorkflowMetadataTransition(previous, next, "ordinary");
42838
+ return next;
42839
+ }
42840
+
42841
+ // src/context/reframe.ts
42842
+ async function reframeV3Workflow(input) {
42843
+ const taskRef = parseTaskRefValue(input.taskRef);
42844
+ assertUlid(input.checkpointId, "reframe checkpointId");
42845
+ const now = input.now ?? /* @__PURE__ */ new Date();
42846
+ const operationId = input.operationId ?? createUlid(now.getTime());
42847
+ assertUlid(operationId, "reframe operationId");
42848
+ const opened = await openReframeContext({
42849
+ projectRoot: input.projectRoot,
42850
+ taskRef,
42851
+ sessionId: input.sessionId,
42852
+ expectedTaskRevision: input.expectedTaskRevision,
42853
+ checkpointId: input.checkpointId,
42854
+ operationId,
42855
+ now
42856
+ });
42857
+ const { context, activeClaims: activeClaims2, openHandoffs, activeChildren } = opened;
42858
+ let journal = null;
42859
+ try {
42860
+ assertReframeEligible(context, activeClaims2, openHandoffs, activeChildren);
42861
+ assertReframeClaimsFresh(context, activeClaims2);
42862
+ const timestamp4 = context.now.toISOString();
42863
+ const archivedRequirementsContent = await readTaskAuthorityFileAtRoot(
42864
+ context.task.location.taskRoot,
42865
+ "requirements.json"
42866
+ );
42867
+ if (archivedRequirementsContent === null) {
42868
+ throw new Error("MANCODE_REFRAME_REQUIREMENTS_MISSING");
42869
+ }
42870
+ const pendingMetadata = markReframeOperationPending(
42871
+ context.task.metadata,
42872
+ context.operationId,
42873
+ timestamp4
42874
+ );
42875
+ const requirements = createReframedRequirements(
42876
+ context.task.requirements,
42877
+ context.operationId,
42878
+ timestamp4
42879
+ );
42880
+ const review = markTaskReviewStale(
42881
+ context.task.review,
42882
+ context.operationId,
42883
+ timestamp4
42884
+ );
42885
+ const verification = markTaskVerificationStale(
42886
+ context.task.verification,
42887
+ context.operationId,
42888
+ timestamp4
42889
+ );
42890
+ const releasedClaims = activeClaims2.map(
42891
+ (claim) => releaseClaimForReframe(claim, context.operationId, timestamp4)
42892
+ );
42893
+ const archiveAction = createTaskArchiveRecoveryAction({
42894
+ stepId: "archive-requirements-plan",
42895
+ taskRef,
42896
+ archiveId: context.operationId,
42897
+ sourceTaskRevision: context.task.metadata.revision,
42898
+ sourcePlanVersion: context.task.metadata.governance.planVersion,
42899
+ createdAt: timestamp4,
42900
+ requirementsContent: archivedRequirementsContent,
42901
+ planContent: context.task.plan?.content ?? null
42902
+ });
42903
+ const branch = await readCheckoutBranch(context.projectRoot);
42904
+ const checkpoint = buildReframeCheckpoint({
42905
+ context,
42906
+ checkpointId: input.checkpointId,
42907
+ taskRevision: pendingMetadata.revision + 1,
42908
+ requirements,
42909
+ review,
42910
+ verification,
42911
+ summary: input.summary,
42912
+ nextAction: input.nextAction,
42913
+ branch,
42914
+ timestamp: timestamp4
42915
+ });
42916
+ const metadata = completeReframeMetadata(
42917
+ pendingMetadata,
42918
+ requirements,
42919
+ review,
42920
+ verification,
42921
+ checkpoint,
42922
+ context.operationId,
42923
+ timestamp4
42924
+ );
42925
+ const aggregate = buildTaskAggregateManifest({
42926
+ metadata,
42927
+ requirements,
42928
+ review,
42929
+ verification,
42930
+ planDigest: context.task.plan?.digest ?? null,
42931
+ latestCheckpoint: checkpoint
42932
+ });
42933
+ const taskHeadFence = nextTaskHeadFence(context, aggregate, timestamp4);
42934
+ const refreshesSessionPointer = context.session.activeTaskRef !== null && sameTaskRef(context.session.activeTaskRef, taskRef);
42935
+ if (refreshesSessionPointer) {
42936
+ await enqueueSessionPointerProjection(context.projectRoot, {
42937
+ operationId: context.operationId,
42938
+ action: "resume",
42939
+ sessionId: context.session.sessionId,
42940
+ expectedPreviousTaskRef: context.session.activeTaskRef,
42941
+ taskRef,
42942
+ workflowMode: metadata.workflowMode,
42943
+ taskRevision: metadata.revision,
42944
+ now: context.now
42945
+ });
42946
+ }
42947
+ journal = await createTaskOperationJournal(context, {
42948
+ type: "reframe",
42949
+ action: taskRef.namespace === "shared" ? "shared_metadata_plan_mutation" : "local_workflow_mutation",
42950
+ expectedRevisions: reframeExpectedRevisions(
42951
+ context,
42952
+ input.checkpointId,
42953
+ activeClaims2
42954
+ ),
42955
+ recovery: {
42956
+ actions: [
42957
+ createTaskAuthorityFileRecoveryAction({
42958
+ stepId: "mark-task-operation-pending",
42959
+ taskRef,
42960
+ fileName: "metadata.json",
42961
+ beforeContent: serializeTaskAuthority(context.task.metadata),
42962
+ targetContent: serializeTaskAuthority(pendingMetadata)
42963
+ }),
42964
+ archiveAction,
42965
+ ...releasedClaims.map(
42966
+ (claim, index) => createClaimRecoveryAction({
42967
+ stepId: "release-active-claims",
42968
+ before: activeClaims2[index] ?? null,
42969
+ claim
42970
+ })
42971
+ ),
42972
+ createTaskAuthorityFileRecoveryAction({
42973
+ stepId: "write-requirements-draft",
42974
+ taskRef,
42975
+ fileName: "requirements.json",
42976
+ beforeContent: serializeTaskAuthority(context.task.requirements),
42977
+ targetContent: serializeTaskAuthority(requirements)
42978
+ }),
42979
+ createTaskAuthorityFileRecoveryAction({
42980
+ stepId: "mark-review-verification-stale",
42981
+ taskRef,
42982
+ fileName: "review-ledger.json",
42983
+ beforeContent: serializeTaskAuthority(context.task.review),
42984
+ targetContent: serializeTaskAuthority(review)
42985
+ }),
42986
+ createTaskAuthorityFileRecoveryAction({
42987
+ stepId: "mark-review-verification-stale",
42988
+ taskRef,
42989
+ fileName: "verification-ledger.json",
42990
+ beforeContent: serializeTaskAuthority(context.task.verification),
42991
+ targetContent: serializeTaskAuthority(verification)
42992
+ }),
42993
+ createCheckpointRecoveryAction({
42994
+ stepId: "write-reframe-checkpoint",
42995
+ before: null,
42996
+ checkpoint
42997
+ }),
42998
+ createTaskAuthorityFileRecoveryAction({
42999
+ stepId: "commit-reframed-metadata",
43000
+ taskRef,
43001
+ fileName: "metadata.json",
43002
+ beforeContent: serializeTaskAuthority(pendingMetadata),
43003
+ targetContent: serializeTaskAuthority(metadata)
43004
+ }),
43005
+ ...taskHeadFence === null ? [] : [
43006
+ createTaskHeadFenceRecoveryAction({
43007
+ stepId: "update-task-head-fence",
43008
+ before: context.coordination.taskHeadFence,
43009
+ fence: taskHeadFence
43010
+ })
43011
+ ]
43012
+ ],
43013
+ noOpStepIds: [
43014
+ ...releasedClaims.length === 0 ? ["release-active-claims"] : [],
43015
+ ...taskHeadFence === null ? ["update-task-head-fence"] : []
43016
+ ]
43017
+ }
43018
+ });
43019
+ journal = await advanceTaskOperation(context, journal, "validate", true);
43020
+ journal = await advanceTaskOperation(
43021
+ context,
43022
+ journal,
43023
+ "mark-task-operation-pending",
43024
+ false
43025
+ );
43026
+ await assertReframeCodeHeadUnchanged(context);
43027
+ await writeTaskAuthorityFile(
43028
+ context,
43029
+ "metadata.json",
43030
+ serializeTaskAuthority(pendingMetadata)
43031
+ );
43032
+ journal = await advanceTaskOperation(
43033
+ context,
43034
+ journal,
43035
+ "archive-requirements-plan",
43036
+ false
43037
+ );
43038
+ await assertReframeCodeHeadUnchanged(context);
43039
+ await writeTaskArchive(context, archiveAction);
43040
+ journal = await advanceTaskOperation(
43041
+ context,
43042
+ journal,
43043
+ "release-active-claims",
43044
+ false
43045
+ );
43046
+ await assertReframeCodeHeadUnchanged(context);
43047
+ for (const [index, claim] of releasedClaims.entries()) {
43048
+ const previous = activeClaims2[index];
43049
+ if (previous === void 0) throw new Error("MANCODE_CLAIM_SET_CHANGED");
43050
+ await updateClaim(context.homeStore, claim, previous.revision);
43051
+ }
43052
+ journal = await advanceTaskOperation(
43053
+ context,
43054
+ journal,
43055
+ "write-requirements-draft",
43056
+ false
43057
+ );
43058
+ await assertReframeCodeHeadUnchanged(context);
43059
+ await writeTaskAuthorityFile(
43060
+ context,
43061
+ "requirements.json",
43062
+ serializeTaskAuthority(requirements)
43063
+ );
43064
+ journal = await advanceTaskOperation(
43065
+ context,
43066
+ journal,
43067
+ "mark-review-verification-stale",
43068
+ false
43069
+ );
43070
+ await assertReframeCodeHeadUnchanged(context);
43071
+ await writeTaskAuthorityFile(
43072
+ context,
43073
+ "review-ledger.json",
43074
+ serializeTaskAuthority(review)
43075
+ );
43076
+ await writeTaskAuthorityFile(
43077
+ context,
43078
+ "verification-ledger.json",
43079
+ serializeTaskAuthority(verification)
43080
+ );
43081
+ journal = await advanceTaskOperation(
43082
+ context,
43083
+ journal,
43084
+ "write-reframe-checkpoint",
42334
43085
  false
42335
43086
  );
42336
43087
  await assertReframeCodeHeadUnchanged(context);
@@ -42658,6 +43409,9 @@ async function writeV3Requirements(input, action) {
42658
43409
  if (action === "finalize" && submitted.status !== "confirmed") {
42659
43410
  throw new Error("MANCODE_REQUIREMENTS_CONFIRMATION_REQUIRED");
42660
43411
  }
43412
+ if (action === "finalize") {
43413
+ assertRequirementsScopeConsistent(submitted);
43414
+ }
42661
43415
  if (action === "draft" && submitted.status !== "draft") {
42662
43416
  throw new Error("MANCODE_REQUIREMENTS_DRAFT_REQUIRED");
42663
43417
  }
@@ -42930,454 +43684,95 @@ async function applyV3ReviewLedger(input) {
42930
43684
  journal = await createTaskOperationJournal(context, {
42931
43685
  type: "review_remediation",
42932
43686
  action: authorization.action,
42933
- evidence: authorization.evidence,
42934
- conditions: authorization.conditions,
42935
- expectedRevisions: taskMutationExpectedRevisions(context, [
42936
- "review",
42937
- "verification"
42938
- ]),
42939
- recovery: {
42940
- actions: [
42941
- createTaskAuthorityFileRecoveryAction({
42942
- stepId: "write-review-ledger",
42943
- taskRef,
42944
- fileName: "review-ledger.json",
42945
- beforeContent: serializeTaskAuthority(context.task.review),
42946
- targetContent: serializeTaskAuthority(review)
42947
- }),
42948
- createTaskAuthorityFileRecoveryAction({
42949
- stepId: "mark-verification-stale",
42950
- taskRef,
42951
- fileName: "verification-ledger.json",
42952
- beforeContent: serializeTaskAuthority(context.task.verification),
42953
- targetContent: serializeTaskAuthority(verification)
42954
- }),
42955
- createTaskAuthorityFileRecoveryAction({
42956
- stepId: "update-metadata",
42957
- taskRef,
42958
- fileName: "metadata.json",
42959
- beforeContent: serializeTaskAuthority(context.task.metadata),
42960
- targetContent: serializeTaskAuthority(metadata)
42961
- }),
42962
- ...taskHeadFence === null ? [] : [
42963
- createTaskHeadFenceRecoveryAction({
42964
- stepId: "update-task-head-fence",
42965
- before: context.coordination.taskHeadFence,
42966
- fence: taskHeadFence
42967
- })
42968
- ]
42969
- ],
42970
- noOpStepIds: taskHeadFence === null ? ["update-task-head-fence"] : []
42971
- }
42972
- });
42973
- journal = await advanceTaskOperation(context, journal, "validate", true);
42974
- journal = await advanceTaskOperation(
42975
- context,
42976
- journal,
42977
- "write-review-ledger",
42978
- false
42979
- );
42980
- await writeTaskAuthorityFile(
42981
- context,
42982
- "review-ledger.json",
42983
- serializeTaskAuthority(review)
42984
- );
42985
- journal = await advanceTaskOperation(
42986
- context,
42987
- journal,
42988
- "mark-verification-stale",
42989
- false
42990
- );
42991
- await writeTaskAuthorityFile(
42992
- context,
42993
- "verification-ledger.json",
42994
- serializeTaskAuthority(verification)
42995
- );
42996
- journal = await advanceTaskOperation(
42997
- context,
42998
- journal,
42999
- "update-metadata",
43000
- false
43001
- );
43002
- await writeTaskAuthorityFile(
43003
- context,
43004
- "metadata.json",
43005
- serializeTaskAuthority(metadata)
43006
- );
43007
- journal = await advanceTaskOperation(
43008
- context,
43009
- journal,
43010
- "update-task-head-fence",
43011
- false
43012
- );
43013
- if (taskHeadFence !== null) {
43014
- await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
43015
- await replaceTaskHeadFence(context.homeStore, taskHeadFence);
43016
- }
43017
- const operation = await commitTaskOperation(context, journal);
43018
- return {
43019
- metadata,
43020
- review,
43021
- verification,
43022
- aggregate,
43023
- taskHeadFence,
43024
- operation
43025
- };
43026
- } catch (error) {
43027
- if (journal !== null) {
43028
- try {
43029
- await handleTaskOperationFailure(context, journal);
43030
- } catch {
43031
- }
43032
- }
43033
- throw error;
43034
- } finally {
43035
- await context.release();
43036
- }
43037
- }
43038
- function assertReviewEligible(metadata, hasPlan) {
43039
- if (metadata.workflowMode !== "man" && metadata.workflowMode !== "manteam") {
43040
- throw new Error("MANCODE_REVIEW_WORKFLOW_MODE_INVALID");
43041
- }
43042
- if (metadata.status !== "in_progress" && metadata.status !== "blocked") {
43043
- throw new Error("MANCODE_REVIEW_WORKFLOW_NOT_ACTIVE");
43044
- }
43045
- if (metadata.currentStep < 5 || metadata.governance.planDecision !== "governed_execution" || !hasPlan) {
43046
- throw new Error("MANCODE_REVIEW_PLAN_GATE_REQUIRED");
43047
- }
43048
- }
43049
- function createCurrentReview(previous, submitted, metadata, operationId, updatedAt) {
43050
- if (submitted.requirementsDigest !== metadata.governance.requirementsDigest || submitted.planVersion !== metadata.governance.planVersion) {
43051
- throw new Error("MANCODE_REVIEW_CONTEXT_STALE");
43052
- }
43053
- const draft = {
43054
- ...submitted,
43055
- taskRef: previous.taskRef,
43056
- revision: previous.revision + 1,
43057
- contentDigest: "",
43058
- lastOperationId: operationId,
43059
- updatedAt
43060
- };
43061
- const next = parseReviewLedger({
43062
- ...draft,
43063
- contentDigest: reviewLedgerDigest(draft)
43064
- });
43065
- assertReviewLedgerTransition(previous, next);
43066
- assertReviewLedgerAgainstContext(next, {
43067
- requirementsDigest: metadata.governance.requirementsDigest,
43068
- planVersion: metadata.governance.planVersion
43069
- });
43070
- return next;
43071
- }
43072
- function updateMetadata3(previous, review, verification, operationId, updatedAt) {
43073
- const next = parseWorkflowMetadata({
43074
- ...previous,
43075
- revision: previous.revision + 1,
43076
- transitionState: "stable",
43077
- lastOperationId: operationId,
43078
- governance: {
43079
- ...previous.governance,
43080
- reviewStatus: review.status,
43081
- reviewLedgerDigest: review.contentDigest,
43082
- verificationStatus: verification.status,
43083
- verificationLedgerDigest: verification.contentDigest
43084
- },
43085
- updatedAt
43086
- });
43087
- assertWorkflowMetadataTransition(previous, next, "ordinary");
43088
- return next;
43089
- }
43090
- function reviewAuthorization(context, next) {
43091
- if (context.taskRef.namespace === "local") {
43092
- return { action: "local_workflow_mutation" };
43093
- }
43094
- if (next.skip !== null) {
43095
- return {
43096
- action: "review_skip_or_waiver",
43097
- conditions: { reviewAction: "skip", reason: next.skip.reason }
43098
- };
43099
- }
43100
- const waivers = next.blockers.filter(
43101
- (blocker) => blocker.status === "waived"
43102
- );
43103
- if (waivers.length > 0) {
43104
- for (const blocker of waivers) {
43105
- if (blocker.severity === "p0" || blocker.severity === "legacy_unknown" || blocker.waiver === null) {
43106
- throw new Error("MANCODE_WAIVER_FORBIDDEN");
43107
- }
43108
- }
43109
- const first = waivers[0];
43110
- if (first?.waiver === null || first === void 0) {
43111
- throw new Error("MANCODE_WAIVER_FORBIDDEN");
43112
- }
43113
- return {
43114
- action: "review_skip_or_waiver",
43115
- conditions: {
43116
- reviewAction: "waiver",
43117
- reviewSeverity: first.severity,
43118
- reason: first.waiver.reason
43119
- }
43120
- };
43121
- }
43122
- return {
43123
- action: "shared_ledger_evidence",
43124
- evidence: {
43125
- assignedToActor: context.task.metadata.ownerActorId === context.session.actorId,
43126
- restrictsWriteToAssignedItem: true
43127
- }
43128
- };
43129
- }
43130
-
43131
- // src/context/scope-change.ts
43132
- import { createHash as createHash11 } from "crypto";
43133
- async function changeV3WorkflowScope(input) {
43134
- const taskRef = parseTaskRefValue(input.taskRef);
43135
- if (taskRef.namespace !== "shared") {
43136
- throw new Error("MANCODE_SCOPE_CHANGE_REQUIRES_SHARED_TASK");
43137
- }
43138
- const scope = normalizeImplementationScope(input.scope);
43139
- const now = input.now ?? /* @__PURE__ */ new Date();
43140
- const timestamp4 = now.toISOString();
43141
- const checkpointId = input.checkpointId ?? createUlid(now.getTime());
43142
- const operationId = input.operationId ?? createUlid(now.getTime());
43143
- assertUlid(checkpointId, "scope change checkpointId");
43144
- assertUlid(operationId, "scope change operationId");
43145
- const opened = await openScopeChangeContext({
43146
- projectRoot: input.projectRoot,
43147
- taskRef,
43148
- sessionId: input.sessionId,
43149
- expectedTaskRevision: input.expectedTaskRevision,
43150
- scope,
43151
- checkpointId,
43152
- successorClaimIds: input.successorClaimIds,
43153
- operationId,
43154
- now
43155
- });
43156
- const { context, activeClaims: activeClaims2, successorClaimIds, successorPredecessors } = opened;
43157
- let journal = null;
43158
- try {
43159
- assertScopeChangeEligible(context, scope);
43160
- assertClaimsFreshForScopeChange(context, activeClaims2);
43161
- const pendingMetadata = markScopeChangeOperationPending(
43162
- context.task.metadata,
43163
- context.operationId,
43164
- timestamp4
43165
- );
43166
- const branch = await readCheckoutBranch(context.projectRoot) ?? "HEAD";
43167
- const checkpoint = buildScopeChangedCheckpoint(
43168
- context,
43169
- pendingMetadata,
43170
- checkpointId,
43171
- input.checkpointSummary,
43172
- input.checkpointNextAction,
43173
- branch,
43174
- timestamp4
43175
- );
43176
- const metadata = completeScopeChangeMetadata(
43177
- pendingMetadata,
43178
- scope,
43179
- checkpoint,
43180
- context.operationId,
43181
- timestamp4
43182
- );
43183
- const pendingSuccessorClaims = buildPendingSuccessorClaims2(
43184
- successorPredecessors,
43185
- successorClaimIds,
43186
- metadata,
43187
- branch,
43188
- requireCodeHead3(context),
43189
- context.operationId,
43190
- timestamp4,
43191
- capabilitiesFromProjectConfig(context.project.config)
43192
- );
43193
- const successorByPredecessor = new Map(
43194
- successorPredecessors.map((claim, index) => {
43195
- const successorClaimId = successorClaimIds[index];
43196
- if (successorClaimId === void 0) {
43197
- throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_COUNT_INVALID");
43198
- }
43199
- return [claim.claimId, successorClaimId];
43200
- })
43201
- );
43202
- const terminatedClaims = activeClaims2.map(
43203
- (claim) => terminateClaimForScopeChange(
43204
- claim,
43205
- successorByPredecessor.get(claim.claimId) ?? null,
43206
- context.operationId,
43207
- timestamp4
43208
- )
43209
- );
43210
- const activeSuccessorClaims = pendingSuccessorClaims.map(
43211
- (claim) => activateSuccessorClaim3(claim, context.operationId, timestamp4)
43212
- );
43213
- const aggregate = buildTaskAggregateManifest({
43214
- metadata,
43215
- requirements: context.task.requirements,
43216
- review: context.task.review,
43217
- verification: context.task.verification,
43218
- planDigest: context.task.plan?.digest ?? null,
43219
- latestCheckpoint: checkpoint
43220
- });
43221
- const taskHeadFence = nextTaskHeadFence(context, aggregate, timestamp4);
43222
- if (taskHeadFence === null) {
43223
- throw new Error("MANCODE_TASK_HEAD_FENCE_MISSING");
43224
- }
43225
- journal = await createTaskOperationJournal(context, {
43226
- type: "scope_change_reclaim",
43227
- action: "task_complete_scope_change_child_merge",
43228
- expectedRevisions: scopeChangeExpectedRevisions(
43229
- context,
43230
- checkpointId,
43231
- activeClaims2,
43232
- successorClaimIds
43233
- ),
43234
- conditions: { completionGateSatisfied: true },
43687
+ evidence: authorization.evidence,
43688
+ conditions: authorization.conditions,
43689
+ expectedRevisions: taskMutationExpectedRevisions(context, [
43690
+ "review",
43691
+ "verification"
43692
+ ]),
43235
43693
  recovery: {
43236
43694
  actions: [
43237
43695
  createTaskAuthorityFileRecoveryAction({
43238
- stepId: "mark-task-operation-pending",
43696
+ stepId: "write-review-ledger",
43239
43697
  taskRef,
43240
- fileName: "metadata.json",
43241
- beforeContent: serializeTaskAuthority(context.task.metadata),
43242
- targetContent: serializeTaskAuthority(pendingMetadata)
43243
- }),
43244
- createCheckpointRecoveryAction({
43245
- stepId: "write-scope-changed-checkpoint",
43246
- before: null,
43247
- checkpoint
43698
+ fileName: "review-ledger.json",
43699
+ beforeContent: serializeTaskAuthority(context.task.review),
43700
+ targetContent: serializeTaskAuthority(review)
43248
43701
  }),
43249
- ...pendingSuccessorClaims.map(
43250
- (claim) => createClaimRecoveryAction({
43251
- stepId: "create-pending-successor-claims",
43252
- before: null,
43253
- claim
43254
- })
43255
- ),
43256
- ...terminatedClaims.map((claim, index) => {
43257
- const before = activeClaims2[index];
43258
- if (before === void 0) {
43259
- throw new Error("MANCODE_CLAIM_SET_CHANGED");
43260
- }
43261
- return createClaimRecoveryAction({
43262
- stepId: "terminate-old-claims",
43263
- before,
43264
- claim
43265
- });
43702
+ createTaskAuthorityFileRecoveryAction({
43703
+ stepId: "mark-verification-stale",
43704
+ taskRef,
43705
+ fileName: "verification-ledger.json",
43706
+ beforeContent: serializeTaskAuthority(context.task.verification),
43707
+ targetContent: serializeTaskAuthority(verification)
43266
43708
  }),
43267
43709
  createTaskAuthorityFileRecoveryAction({
43268
- stepId: "update-metadata-scope",
43710
+ stepId: "update-metadata",
43269
43711
  taskRef,
43270
43712
  fileName: "metadata.json",
43271
- beforeContent: serializeTaskAuthority(pendingMetadata),
43713
+ beforeContent: serializeTaskAuthority(context.task.metadata),
43272
43714
  targetContent: serializeTaskAuthority(metadata)
43273
43715
  }),
43274
- ...activeSuccessorClaims.map((claim, index) => {
43275
- const before = pendingSuccessorClaims[index];
43276
- if (before === void 0) {
43277
- throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_COUNT_INVALID");
43278
- }
43279
- return createClaimRecoveryAction({
43280
- stepId: "activate-successor-claims",
43281
- before,
43282
- claim
43283
- });
43284
- }),
43285
- createTaskHeadFenceRecoveryAction({
43286
- stepId: "update-task-head-fence",
43287
- before: context.coordination.taskHeadFence,
43288
- fence: taskHeadFence
43289
- })
43716
+ ...taskHeadFence === null ? [] : [
43717
+ createTaskHeadFenceRecoveryAction({
43718
+ stepId: "update-task-head-fence",
43719
+ before: context.coordination.taskHeadFence,
43720
+ fence: taskHeadFence
43721
+ })
43722
+ ]
43290
43723
  ],
43291
- noOpStepIds: [
43292
- ...pendingSuccessorClaims.length === 0 ? ["create-pending-successor-claims"] : [],
43293
- ...terminatedClaims.length === 0 ? ["terminate-old-claims"] : [],
43294
- ...activeSuccessorClaims.length === 0 ? ["activate-successor-claims"] : []
43295
- ]
43724
+ noOpStepIds: taskHeadFence === null ? ["update-task-head-fence"] : []
43296
43725
  }
43297
43726
  });
43298
43727
  journal = await advanceTaskOperation(context, journal, "validate", true);
43299
43728
  journal = await advanceTaskOperation(
43300
43729
  context,
43301
43730
  journal,
43302
- "mark-task-operation-pending",
43731
+ "write-review-ledger",
43303
43732
  false
43304
43733
  );
43305
- await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
43306
43734
  await writeTaskAuthorityFile(
43307
43735
  context,
43308
- "metadata.json",
43309
- `${JSON.stringify(pendingMetadata, null, 2)}
43310
- `
43311
- );
43312
- journal = await advanceTaskOperation(
43313
- context,
43314
- journal,
43315
- "write-scope-changed-checkpoint",
43316
- false
43736
+ "review-ledger.json",
43737
+ serializeTaskAuthority(review)
43317
43738
  );
43318
- await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
43319
- await writeTaskCheckpoint(context, checkpoint);
43320
43739
  journal = await advanceTaskOperation(
43321
43740
  context,
43322
43741
  journal,
43323
- "create-pending-successor-claims",
43742
+ "mark-verification-stale",
43324
43743
  false
43325
43744
  );
43326
- await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
43327
- for (const claim of pendingSuccessorClaims) {
43328
- await createClaim(context.homeStore, claim);
43329
- }
43330
- journal = await advanceTaskOperation(
43745
+ await writeTaskAuthorityFile(
43331
43746
  context,
43332
- journal,
43333
- "terminate-old-claims",
43334
- false
43747
+ "verification-ledger.json",
43748
+ serializeTaskAuthority(verification)
43335
43749
  );
43336
- await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
43337
- for (const [index, claim] of terminatedClaims.entries()) {
43338
- const previous = activeClaims2[index];
43339
- if (previous === void 0) {
43340
- throw new Error("MANCODE_CLAIM_SET_CHANGED");
43341
- }
43342
- await updateClaim(context.homeStore, claim, previous.revision);
43343
- }
43344
43750
  journal = await advanceTaskOperation(
43345
43751
  context,
43346
43752
  journal,
43347
- "update-metadata-scope",
43753
+ "update-metadata",
43348
43754
  false
43349
43755
  );
43350
- await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
43351
43756
  await writeTaskAuthorityFile(
43352
43757
  context,
43353
43758
  "metadata.json",
43354
- `${JSON.stringify(metadata, null, 2)}
43355
- `
43356
- );
43357
- journal = await advanceTaskOperation(
43358
- context,
43359
- journal,
43360
- "activate-successor-claims",
43361
- false
43759
+ serializeTaskAuthority(metadata)
43362
43760
  );
43363
- await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
43364
- for (const claim of activeSuccessorClaims) {
43365
- await updateClaim(context.homeStore, claim, 1);
43366
- }
43367
43761
  journal = await advanceTaskOperation(
43368
43762
  context,
43369
43763
  journal,
43370
43764
  "update-task-head-fence",
43371
43765
  false
43372
43766
  );
43373
- await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
43374
- await replaceTaskHeadFence(context.homeStore, taskHeadFence);
43767
+ if (taskHeadFence !== null) {
43768
+ await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
43769
+ await replaceTaskHeadFence(context.homeStore, taskHeadFence);
43770
+ }
43375
43771
  const operation = await commitTaskOperation(context, journal);
43376
43772
  return {
43377
43773
  metadata,
43378
- checkpoint,
43379
- terminatedClaims,
43380
- successorClaims: activeSuccessorClaims,
43774
+ review,
43775
+ verification,
43381
43776
  aggregate,
43382
43777
  taskHeadFence,
43383
43778
  operation
@@ -43394,312 +43789,97 @@ async function changeV3WorkflowScope(input) {
43394
43789
  await context.release();
43395
43790
  }
43396
43791
  }
43397
- async function openScopeChangeContext(input) {
43398
- for (let attempt = 0; attempt < 3; attempt += 1) {
43399
- const runtime = await readProjectRuntimeContext(input.projectRoot);
43400
- const store = new V3ContextStore(input.projectRoot);
43401
- const homeStore = resolveTaskEntityHomeStore(
43402
- runtime.entityHomeStoreContext,
43403
- input.taskRef
43404
- );
43405
- const preflight = await store.readCoordinationSnapshot(
43406
- input.taskRef,
43407
- homeStore
43408
- );
43409
- const preflightClaims = activeClaims(preflight.claims);
43410
- const preflightSuccessors = claimsWithinScope(preflightClaims, input.scope);
43411
- const preflightSuccessorIds = resolveSuccessorClaimIds2(
43412
- preflightSuccessors,
43413
- input.successorClaimIds,
43414
- input.operationId,
43415
- input.now.toISOString()
43416
- );
43417
- const context = await openV3TaskOperation({
43418
- projectRoot: input.projectRoot,
43419
- taskRef: input.taskRef,
43420
- sessionId: input.sessionId,
43421
- expectedTaskRevision: input.expectedTaskRevision,
43422
- operationId: input.operationId,
43423
- extraEntityLocks: [
43424
- `checkpoint:${input.checkpointId}`,
43425
- taskHeadEntityKey(input.taskRef),
43426
- ...preflightClaims.map((claim) => `claim:${claim.claimId}`),
43427
- ...preflightSuccessorIds.map((claimId) => `claim:${claimId}`)
43428
- ],
43429
- now: input.now
43430
- });
43431
- const lockedClaims = activeClaims(context.coordination.claims);
43432
- if (sameClaimIdSet(preflightClaims, lockedClaims)) {
43433
- const successors = claimsWithinScope(lockedClaims, input.scope);
43434
- const successorIds = resolveSuccessorClaimIds2(
43435
- successors,
43436
- input.successorClaimIds,
43437
- input.operationId,
43438
- input.now.toISOString()
43439
- );
43440
- return {
43441
- context,
43442
- activeClaims: lockedClaims,
43443
- successorPredecessors: successors,
43444
- successorClaimIds: successorIds
43445
- };
43446
- }
43447
- await context.release();
43448
- }
43449
- throw new Error("MANCODE_CLAIM_SET_CHANGED");
43450
- }
43451
- function assertScopeChangeEligible(context, scope) {
43452
- const metadata = context.task.metadata;
43453
- if (context.project.config.transport.mode !== "local") {
43454
- throw new Error("MANCODE_GIT_REF_TRANSPORT_NOT_IMPLEMENTED");
43455
- }
43456
- if (metadata.workflowMode !== "manteam") {
43457
- throw new Error("MANCODE_SCOPE_CHANGE_WORKFLOW_MODE_INVALID");
43458
- }
43459
- if (metadata.status !== "in_progress") {
43460
- throw new Error("MANCODE_SCOPE_CHANGE_WORKFLOW_NOT_ACTIVE");
43461
- }
43462
- if (metadata.ownerActorId !== context.session.actorId) {
43463
- throw new Error("MANCODE_TASK_OWNER_REQUIRED");
43464
- }
43465
- if (metadata.parent !== null) {
43466
- throw new Error("MANCODE_PARENT_SCOPE_INHERITANCE_REQUIRED");
43467
- }
43468
- if (metadata.implementationScope.digest === scope.digest) {
43469
- throw new Error("MANCODE_SCOPE_CHANGE_NOOP");
43470
- }
43471
- }
43472
- function assertClaimsFreshForScopeChange(context, claims) {
43473
- const codeHead = requireCodeHead3(context);
43474
- for (const claim of claims) {
43475
- if (claim.authority.mode !== "local") {
43476
- throw new Error("MANCODE_OPERATION_REPAIR_REQUIRED");
43477
- }
43478
- const validity = deriveClaimValidity(claim, {
43479
- taskRef: context.taskRef,
43480
- taskRevision: context.task.metadata.revision,
43481
- implementationScopeDigest: context.task.metadata.implementationScope.digest,
43482
- ownershipEpoch: context.task.metadata.ownershipEpoch,
43483
- codeRefHead: codeHead,
43484
- now: context.now,
43485
- transportFreshness: "fresh"
43486
- });
43487
- if (validity !== "fresh") {
43488
- throw new Error("MANCODE_CLAIM_REVALIDATION_REQUIRED");
43489
- }
43490
- }
43491
- }
43492
- function normalizeImplementationScope(value) {
43493
- assertRecord(value, "workflow scope change");
43494
- assertKnownKeys(
43495
- value,
43496
- ["include", "exclude", "modules"],
43497
- "workflow scope change"
43498
- );
43499
- const scope = {
43500
- source: "explicit",
43501
- include: normalizeScopeValues(value.include, "include", true),
43502
- exclude: normalizeScopeValues(value.exclude, "exclude", true),
43503
- modules: normalizeScopeValues(value.modules, "modules", false)
43504
- };
43505
- return { ...scope, digest: digestCanonicalJson(scope) };
43506
- }
43507
- function normalizeScopeValues(value, label, paths) {
43508
- if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !item.trim())) {
43509
- throw new Error(`MANCODE_SCOPE_${label.toUpperCase()}_INVALID`);
43792
+ function assertReviewEligible(metadata, hasPlan) {
43793
+ if (metadata.workflowMode !== "man" && metadata.workflowMode !== "manteam") {
43794
+ throw new Error("MANCODE_REVIEW_WORKFLOW_MODE_INVALID");
43510
43795
  }
43511
- const values = value.map((item) => item.trim());
43512
- const normalized = sortUtf8StringSet(values);
43513
- if (normalized.length !== values.length) {
43514
- throw new Error(`MANCODE_SCOPE_${label.toUpperCase()}_DUPLICATE`);
43796
+ if (metadata.status !== "in_progress" && metadata.status !== "blocked") {
43797
+ throw new Error("MANCODE_REVIEW_WORKFLOW_NOT_ACTIVE");
43515
43798
  }
43516
- for (const item of normalized) {
43517
- assertSharedTextSafe(item, `workflow scope ${label}`);
43518
- if (paths) assertScopePath(item);
43799
+ if (metadata.currentStep < 5 || metadata.governance.planDecision !== "governed_execution" || !hasPlan) {
43800
+ throw new Error("MANCODE_REVIEW_PLAN_GATE_REQUIRED");
43519
43801
  }
43520
- return normalized;
43521
43802
  }
43522
- function assertScopePath(value) {
43523
- if (value.startsWith("/") || value.startsWith("~") || /^[A-Za-z]:/.test(value) || value.includes("\\") || value.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
43524
- throw new Error("MANCODE_SCOPE_PATH_INVALID");
43803
+ function createCurrentReview(previous, submitted, metadata, operationId, updatedAt) {
43804
+ if (submitted.requirementsDigest !== metadata.governance.requirementsDigest || submitted.planVersion !== metadata.governance.planVersion) {
43805
+ throw new Error("MANCODE_REVIEW_CONTEXT_STALE");
43525
43806
  }
43526
- }
43527
- function markScopeChangeOperationPending(previous, operationId, updatedAt) {
43528
- const next = parseWorkflowMetadata({
43529
- ...previous,
43807
+ const draft = {
43808
+ ...submitted,
43809
+ taskRef: previous.taskRef,
43530
43810
  revision: previous.revision + 1,
43531
- transitionState: "operation_pending",
43811
+ contentDigest: "",
43532
43812
  lastOperationId: operationId,
43533
43813
  updatedAt
43814
+ };
43815
+ const next = parseReviewLedger({
43816
+ ...draft,
43817
+ contentDigest: reviewLedgerDigest(draft)
43818
+ });
43819
+ assertReviewLedgerTransition(previous, next);
43820
+ assertReviewLedgerAgainstContext(next, {
43821
+ requirementsDigest: metadata.governance.requirementsDigest,
43822
+ planVersion: metadata.governance.planVersion
43534
43823
  });
43535
- assertWorkflowMetadataTransition(previous, next, "ordinary");
43536
43824
  return next;
43537
43825
  }
43538
- function completeScopeChangeMetadata(previous, scope, checkpoint, operationId, updatedAt) {
43826
+ function updateMetadata3(previous, review, verification, operationId, updatedAt) {
43539
43827
  const next = parseWorkflowMetadata({
43540
43828
  ...previous,
43541
43829
  revision: previous.revision + 1,
43542
43830
  transitionState: "stable",
43543
- implementationScope: scope,
43544
- latestCheckpointRef: {
43545
- taskRef: checkpoint.taskRef,
43546
- kind: "checkpoint",
43547
- artifactId: checkpoint.checkpointId
43548
- },
43549
43831
  lastOperationId: operationId,
43550
- updatedAt
43551
- });
43552
- assertWorkflowMetadataTransition(previous, next, "ordinary");
43553
- return next;
43554
- }
43555
- function buildScopeChangedCheckpoint(context, pendingMetadata, checkpointId, summary, nextAction, branch, timestamp4) {
43556
- return parseCheckpoint({
43557
- schemaVersion: 1,
43558
- checkpointId,
43559
- operationId: context.operationId,
43560
- taskRef: context.taskRef,
43561
- taskRevision: pendingMetadata.revision,
43562
- ownershipEpochAtOffer: pendingMetadata.ownershipEpoch,
43563
- kind: "scope_changed",
43564
- git: {
43565
- branch,
43566
- head: requireCodeHead3(context),
43567
- base: pendingMetadata.base?.head ?? null
43568
- },
43569
- summary: summary ?? "Changed the implementation scope and replaced affected coordination claims.",
43570
43832
  governance: {
43571
- requirementsDigest: context.task.requirements.contentDigest,
43572
- planVersion: pendingMetadata.governance.planVersion,
43573
- reviewLedgerDigest: context.task.review.contentDigest,
43574
- verificationLedgerDigest: context.task.verification.contentDigest
43575
- },
43576
- nextAction: nextAction ?? "Re-read the updated scope and continue only with the successor claim.",
43577
- createdBy: {
43578
- actorId: context.session.actorId,
43579
- client: context.session.client
43833
+ ...previous.governance,
43834
+ reviewStatus: review.status,
43835
+ reviewLedgerDigest: review.contentDigest,
43836
+ verificationStatus: verification.status,
43837
+ verificationLedgerDigest: verification.contentDigest
43580
43838
  },
43581
- createdAt: timestamp4
43582
- });
43583
- }
43584
- function buildPendingSuccessorClaims2(predecessors, successorClaimIds, metadata, branch, codeHead, operationId, timestamp4, capabilities) {
43585
- return predecessors.map((previous, index) => {
43586
- const claimId = successorClaimIds[index];
43587
- if (claimId === void 0) {
43588
- throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_COUNT_INVALID");
43589
- }
43590
- return parseClaim({
43591
- ...previous,
43592
- claimId,
43593
- authority: { mode: "local", remoteRevision: null },
43594
- taskRevisionAtAcquire: metadata.revision,
43595
- lastValidatedTaskRevision: metadata.revision,
43596
- implementationScopeDigest: metadata.implementationScope.digest,
43597
- ownershipEpochAtAcquire: metadata.ownershipEpoch,
43598
- state: "pending",
43599
- revision: 1,
43600
- codeRefAtAcquire: { branch, head: codeHead },
43601
- lastValidatedCodeRef: { branch, head: codeHead },
43602
- acquisitionEnforcement: capabilities.claimAcquisition,
43603
- writeGuard: capabilities.writeGuard,
43604
- predecessorClaimId: previous.claimId,
43605
- successorClaimId: null,
43606
- lastOperationId: operationId,
43607
- createdAt: timestamp4,
43608
- updatedAt: timestamp4
43609
- });
43610
- });
43611
- }
43612
- function terminateClaimForScopeChange(previous, successorClaimId, operationId, timestamp4) {
43613
- const next = parseClaim({
43614
- ...previous,
43615
- state: successorClaimId === null ? "released" : "transferred",
43616
- revision: previous.revision + 1,
43617
- successorClaimId,
43618
- lastOperationId: operationId,
43619
- updatedAt: timestamp4
43620
- });
43621
- assertClaimTransition(previous, next);
43622
- return next;
43623
- }
43624
- function activateSuccessorClaim3(previous, operationId, timestamp4) {
43625
- const next = parseClaim({
43626
- ...previous,
43627
- state: "active",
43628
- revision: previous.revision + 1,
43629
- lastOperationId: operationId,
43630
- updatedAt: timestamp4
43839
+ updatedAt
43631
43840
  });
43632
- assertClaimTransition(previous, next);
43841
+ assertWorkflowMetadataTransition(previous, next, "ordinary");
43633
43842
  return next;
43634
43843
  }
43635
- function scopeChangeExpectedRevisions(context, checkpointId, predecessors, successorClaimIds) {
43636
- const expected = {
43637
- [taskEntityKey(context.taskRef)]: context.task.metadata.revision,
43638
- [`checkpoint:${checkpointId}`]: 0
43639
- };
43640
- for (const claim of predecessors) {
43641
- expected[`claim:${claim.claimId}`] = claim.revision;
43844
+ function reviewAuthorization(context, next) {
43845
+ if (context.taskRef.namespace === "local") {
43846
+ return { action: "local_workflow_mutation" };
43642
43847
  }
43643
- for (const claimId of successorClaimIds) {
43644
- expected[`claim:${claimId}`] = 0;
43848
+ if (next.skip !== null) {
43849
+ return {
43850
+ action: "review_skip_or_waiver",
43851
+ conditions: { reviewAction: "skip", reason: next.skip.reason }
43852
+ };
43645
43853
  }
43646
- const fence = context.coordination.taskHeadFence;
43647
- if (fence === null) throw new Error("MANCODE_TASK_HEAD_FENCE_MISSING");
43648
- expected[taskHeadEntityKey(context.taskRef)] = fence.fenceRevision;
43649
- return expected;
43650
- }
43651
- function activeClaims(claims) {
43652
- return claims.filter((claim) => claim.state === "active").sort((left, right) => compareUtf815(left.claimId, right.claimId));
43653
- }
43654
- function claimsWithinScope(claims, scope) {
43655
- return claims.filter(
43656
- (claim) => evaluateClaimScopeSubset(claim.scope, {
43657
- source: scope.source,
43658
- include: scope.include,
43659
- exclude: scope.exclude,
43660
- modules: scope.modules
43661
- }).allowed
43662
- );
43663
- }
43664
- function resolveSuccessorClaimIds2(predecessors, requested, operationId, timestamp4) {
43665
- const ids = requested ?? predecessors.map(
43666
- (claim) => scopeSuccessorClaimId(operationId, claim.claimId, timestamp4)
43854
+ const waivers = next.blockers.filter(
43855
+ (blocker) => blocker.status === "waived"
43667
43856
  );
43668
- if (ids.length !== predecessors.length) {
43669
- throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_COUNT_INVALID");
43670
- }
43671
- const predecessorIds = new Set(predecessors.map((claim) => claim.claimId));
43672
- const seen = /* @__PURE__ */ new Set();
43673
- for (const claimId of ids) {
43674
- assertUlid(claimId, "scope successor claimId");
43675
- if (predecessorIds.has(claimId) || seen.has(claimId)) {
43676
- throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_INVALID");
43857
+ if (waivers.length > 0) {
43858
+ for (const blocker of waivers) {
43859
+ if (blocker.severity === "p0" || blocker.severity === "legacy_unknown" || blocker.waiver === null) {
43860
+ throw new Error("MANCODE_WAIVER_FORBIDDEN");
43861
+ }
43677
43862
  }
43678
- seen.add(claimId);
43679
- }
43680
- return ids;
43681
- }
43682
- function scopeSuccessorClaimId(operationId, predecessorClaimId, timestamp4) {
43683
- assertUlid(operationId, "scope change operationId");
43684
- assertUlid(predecessorClaimId, "scope predecessor claimId");
43685
- const milliseconds = Date.parse(timestamp4);
43686
- if (Number.isNaN(milliseconds)) {
43687
- throw new Error("MANCODE_SCOPE_TIMESTAMP_INVALID");
43688
- }
43689
- const entropy = createHash11("sha256").update(`scope-change:${operationId}:${predecessorClaimId}`, "utf8").digest().subarray(0, 10);
43690
- return createUlid(milliseconds, entropy);
43691
- }
43692
- function requireCodeHead3(context) {
43693
- if (context.codeHead === null) {
43694
- throw new Error("MANCODE_TASK_HEAD_CODE_REF_UNAVAILABLE");
43863
+ const first = waivers[0];
43864
+ if (first?.waiver === null || first === void 0) {
43865
+ throw new Error("MANCODE_WAIVER_FORBIDDEN");
43866
+ }
43867
+ return {
43868
+ action: "review_skip_or_waiver",
43869
+ conditions: {
43870
+ reviewAction: "waiver",
43871
+ reviewSeverity: first.severity,
43872
+ reason: first.waiver.reason
43873
+ }
43874
+ };
43695
43875
  }
43696
- return context.codeHead;
43697
- }
43698
- function sameClaimIdSet(left, right) {
43699
- return left.length === right.length && left.every((claim, index) => claim.claimId === right[index]?.claimId);
43700
- }
43701
- function compareUtf815(left, right) {
43702
- return Buffer.from(left, "utf8").compare(Buffer.from(right, "utf8"));
43876
+ return {
43877
+ action: "shared_ledger_evidence",
43878
+ evidence: {
43879
+ assignedToActor: context.task.metadata.ownerActorId === context.session.actorId,
43880
+ restrictsWriteToAssignedItem: true
43881
+ }
43882
+ };
43703
43883
  }
43704
43884
 
43705
43885
  // src/context/solo-handoff.ts
@@ -43949,6 +44129,8 @@ function assertSoloStartEligible(context) {
43949
44129
  if (metadata.workflowMode !== "man" || metadata.coordination !== "single" || metadata.status !== "in_progress" || metadata.currentStep !== 4 || metadata.governance.planDecision !== null || metadata.soloExecution !== null || metadata.ownerActorId !== context.session.actorId || plan === null || requirements.status !== "confirmed" || !requirementsAreReady(requirements) || metadata.governance.requirementsStatus !== "ready" || metadata.governance.requirementsDigest !== requirements.contentDigest) {
43950
44130
  throw new Error("MANCODE_SOLO_HANDOFF_NOT_ELIGIBLE");
43951
44131
  }
44132
+ assertRequirementsScopeConsistent(requirements);
44133
+ assertExecutableImplementationScope(metadata.implementationScope);
43952
44134
  }
43953
44135
  function assertSoloCompletionEligible(context) {
43954
44136
  const { metadata } = context.task;
@@ -45237,11 +45419,20 @@ function initialScope(parent, explicitScope) {
45237
45419
  };
45238
45420
  return { ...inherited, digest: digestCanonicalJson(inherited) };
45239
45421
  }
45422
+ if (explicitScope === void 0) {
45423
+ const unspecified = {
45424
+ source: "legacy_unspecified",
45425
+ include: [],
45426
+ exclude: [],
45427
+ modules: []
45428
+ };
45429
+ return { ...unspecified, digest: digestCanonicalJson(unspecified) };
45430
+ }
45240
45431
  const explicit = {
45241
45432
  source: "explicit",
45242
- include: [...explicitScope?.include ?? []],
45243
- exclude: [...explicitScope?.exclude ?? []],
45244
- modules: [...explicitScope?.modules ?? []]
45433
+ include: [...explicitScope.include ?? []],
45434
+ exclude: [...explicitScope.exclude ?? []],
45435
+ modules: [...explicitScope.modules ?? []]
45245
45436
  };
45246
45437
  return { ...explicit, digest: digestCanonicalJson(explicit) };
45247
45438
  }
@@ -45703,10 +45894,22 @@ async function changeGitRefWorkflowScope(input) {
45703
45894
  operationId,
45704
45895
  timestamp4
45705
45896
  );
45897
+ const review = markTaskReviewStale(
45898
+ opened.context.task.review,
45899
+ operationId,
45900
+ timestamp4
45901
+ );
45902
+ const verification = markTaskVerificationStale(
45903
+ opened.context.task.verification,
45904
+ operationId,
45905
+ timestamp4
45906
+ );
45706
45907
  const metadata = scopeChangedMetadata(
45707
45908
  pendingMetadata,
45708
45909
  scope,
45709
45910
  checkpointId,
45911
+ review.contentDigest,
45912
+ verification.contentDigest,
45710
45913
  operationId,
45711
45914
  timestamp4
45712
45915
  );
@@ -45717,6 +45920,9 @@ async function changeGitRefWorkflowScope(input) {
45717
45920
  summary: input.checkpointSummary,
45718
45921
  nextAction: input.checkpointNextAction,
45719
45922
  codeRef: opened.bundle.codeRef,
45923
+ planVersion: pendingMetadata.governance.planVersion + 1,
45924
+ reviewLedgerDigest: review.contentDigest,
45925
+ verificationLedgerDigest: verification.contentDigest,
45720
45926
  timestamp: timestamp4
45721
45927
  });
45722
45928
  const finalMetadata = parseWorkflowMetadata({
@@ -45730,8 +45936,8 @@ async function changeGitRefWorkflowScope(input) {
45730
45936
  const aggregate = buildTaskAggregateManifest({
45731
45937
  metadata: finalMetadata,
45732
45938
  requirements: opened.context.task.requirements,
45733
- review: opened.context.task.review,
45734
- verification: opened.context.task.verification,
45939
+ review,
45940
+ verification,
45735
45941
  planDigest: opened.context.task.plan?.digest ?? null,
45736
45942
  latestCheckpoint: checkpoint
45737
45943
  });
@@ -45754,6 +45960,8 @@ async function changeGitRefWorkflowScope(input) {
45754
45960
  task: {
45755
45961
  ...opened.context.task,
45756
45962
  metadata: finalMetadata,
45963
+ review,
45964
+ verification,
45757
45965
  latestCheckpoint: checkpoint,
45758
45966
  aggregate
45759
45967
  },
@@ -46173,12 +46381,20 @@ function assertClaimsFresh(context, bundle, claims) {
46173
46381
  }
46174
46382
  }
46175
46383
  }
46176
- function scopeChangedMetadata(previous, scope, checkpointId, operationId, updatedAt) {
46384
+ function scopeChangedMetadata(previous, scope, checkpointId, reviewLedgerDigest2, verificationLedgerDigest2, operationId, updatedAt) {
46177
46385
  const next = parseWorkflowMetadata({
46178
46386
  ...previous,
46179
46387
  revision: previous.revision + 1,
46180
46388
  transitionState: "stable",
46181
46389
  implementationScope: scope,
46390
+ governance: {
46391
+ ...previous.governance,
46392
+ planVersion: previous.governance.planVersion + 1,
46393
+ reviewStatus: "stale",
46394
+ reviewLedgerDigest: reviewLedgerDigest2,
46395
+ verificationStatus: "stale",
46396
+ verificationLedgerDigest: verificationLedgerDigest2
46397
+ },
46182
46398
  latestCheckpointRef: {
46183
46399
  taskRef: previous.taskRef,
46184
46400
  kind: "checkpoint",
@@ -46207,9 +46423,9 @@ function scopeChangedCheckpoint(input) {
46207
46423
  summary: input.summary ?? "Changed the implementation scope and replaced affected coordination claims.",
46208
46424
  governance: {
46209
46425
  requirementsDigest: input.context.task.requirements.contentDigest,
46210
- planVersion: input.metadata.governance.planVersion,
46211
- reviewLedgerDigest: input.context.task.review.contentDigest,
46212
- verificationLedgerDigest: input.context.task.verification.contentDigest
46426
+ planVersion: input.planVersion,
46427
+ reviewLedgerDigest: input.reviewLedgerDigest,
46428
+ verificationLedgerDigest: input.verificationLedgerDigest
46213
46429
  },
46214
46430
  nextAction: input.nextAction ?? "Re-read the updated scope and continue only with the successor claim.",
46215
46431
  createdBy: {
@@ -47400,7 +47616,7 @@ async function workflowPlanV3(rootDir, args, options) {
47400
47616
  return printV3Error(
47401
47617
  options.json,
47402
47618
  "MANCODE_PLAN_ARGUMENT_INVALID",
47403
- "Use: workflow plan <namespace:ULID> revise --expected-revision <n> --file <path>, or confirm --expected-revision <n> --plan-decision <plan_only|governed_execution>.",
47619
+ "Use: workflow plan <namespace:ULID> revise --expected-revision <n> --file <path> [--scope-file <path>], or confirm --expected-revision <n> --plan-decision <plan_only|governed_execution>.",
47404
47620
  EXIT_INVALID_ARG3
47405
47621
  );
47406
47622
  }
@@ -47429,6 +47645,14 @@ async function workflowPlanV3(rootDir, args, options) {
47429
47645
  EXIT_INVALID_ARG3
47430
47646
  );
47431
47647
  }
47648
+ if (action === "confirm" && options.scopeFile !== void 0) {
47649
+ return printV3Error(
47650
+ options.json,
47651
+ "MANCODE_PLAN_SCOPE_REVISE_REQUIRED",
47652
+ "Bind implementation scope with workflow plan revise before confirmation.",
47653
+ EXIT_INVALID_ARG3
47654
+ );
47655
+ }
47432
47656
  try {
47433
47657
  const project = await readV3CommandProject(rootDir);
47434
47658
  const taskRef = parseTaskRef(task);
@@ -47445,12 +47669,17 @@ async function workflowPlanV3(rootDir, args, options) {
47445
47669
  if (plan === void 0 || plan === null) {
47446
47670
  throw new Error("MANCODE_PLAN_FILE_REQUIRED");
47447
47671
  }
47672
+ const implementationScope = action === "revise" && options.scopeFile !== void 0 ? await readWorkflowJsonInputFile(
47673
+ project.projectRoot,
47674
+ options.scopeFile
47675
+ ) : void 0;
47448
47676
  const result2 = await reviseV3Plan({
47449
47677
  projectRoot: project.projectRoot,
47450
47678
  taskRef,
47451
47679
  sessionId: session.sessionId,
47452
47680
  expectedTaskRevision,
47453
47681
  plan,
47682
+ implementationScope,
47454
47683
  planDecision: parseV3PlanDecision(options.planDecision)
47455
47684
  });
47456
47685
  return printV3Result(options.json, {
@@ -47703,6 +47932,7 @@ async function workflowRequirements(rootDir, args, options) {
47703
47932
  const inputPath = path69.isAbsolute(options.file) ? options.file : path69.resolve(rootDir, options.file);
47704
47933
  const input = await readFile48(inputPath, "utf-8");
47705
47934
  const requirements = parseRequirementsLedger2(input);
47935
+ assertRequirementsScopeConsistent2(requirements);
47706
47936
  [originalJson, originalMarkdown, originalMetadata] = await Promise.all([
47707
47937
  readOptionalText2(jsonPath),
47708
47938
  readOptionalText2(markdownPath),
@@ -48887,6 +49117,9 @@ program.command("workflow <subcommand> [args...]").description("Manage mancode w
48887
49117
  ).option(
48888
49118
  "--file <path>",
48889
49119
  "Semantic requirements JSON, plan Markdown, or ledger input file"
49120
+ ).option(
49121
+ "--scope-file <path>",
49122
+ "Plan implementation scope JSON {include,exclude,modules}"
48890
49123
  ).option("--acceptance <id>", "Acceptance criterion id (for example AC-1)").option("--method <method>", "Verification method: automated or manual").option("--result <result>", "Verification result").option("--evidence <text>", "Verification evidence or user confirmation").option("--command <command>", "Command used for automated verification").option("--exit-code <code>", "Exit code from automated verification").option("--evidence-file <path>", "Existing verification report or artifact").option("--reason <reason>", "Reason for an explicit review skip").option("--json", "Output as JSON (for scripts)").action(async (subcommand, args, options) => {
48891
49124
  const code = await workflow(process.cwd(), subcommand, args ?? [], {
48892
49125
  ...options,