mancode 0.5.3 → 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/README.en.md +26 -5
- package/README.md +19 -6
- package/dist/{chunk-2JOKDC3X.js → chunk-AWOIP2LC.js} +19 -4
- package/dist/chunk-AWOIP2LC.js.map +1 -0
- package/dist/{chunk-VHZI2WKD.js → chunk-YWHFHZ4A.js} +24 -1
- package/dist/chunk-YWHFHZ4A.js.map +1 -0
- package/dist/cli.js +1399 -1117
- package/dist/cli.js.map +1 -1
- package/dist/{store-EEWJJANB.js → store-DREAZNIX.js} +2 -2
- package/dist/{v3-adapter-DBVEX5H5.js → v3-adapter-TCEFETAG.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-2JOKDC3X.js.map +0 -1
- package/dist/chunk-VHZI2WKD.js.map +0 -1
- /package/dist/{store-EEWJJANB.js.map → store-DREAZNIX.js.map} +0 -0
- /package/dist/{v3-adapter-DBVEX5H5.js.map → v3-adapter-TCEFETAG.js.map} +0 -0
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,13 +114,15 @@ import {
|
|
|
111
114
|
workflowMetadataDigest,
|
|
112
115
|
writeOperationReservation,
|
|
113
116
|
writeProjectFacts
|
|
114
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-YWHFHZ4A.js";
|
|
115
118
|
import {
|
|
116
119
|
DEFAULT_MANCODE_END_MARKER,
|
|
117
120
|
DEFAULT_MANCODE_START_MARKER,
|
|
121
|
+
INTERFACE_EMOJI_ICON_GUIDANCE,
|
|
118
122
|
V3_ADAPTER_FILE_TARGETS,
|
|
119
123
|
V3_ADAPTER_PLATFORMS,
|
|
120
124
|
V3_ADAPTER_VERSION,
|
|
125
|
+
VISUAL_DIRECTION_SELECTION_GUIDANCE,
|
|
121
126
|
adapterManagedContentDigest,
|
|
122
127
|
applyV3AdapterFilePlan,
|
|
123
128
|
assertV3AdapterInstallable,
|
|
@@ -134,7 +139,7 @@ import {
|
|
|
134
139
|
stageV3AdapterUpgradeFiles,
|
|
135
140
|
v3AdapterTargetPath,
|
|
136
141
|
v3AdapterVersionsFromStatuses
|
|
137
|
-
} from "./chunk-
|
|
142
|
+
} from "./chunk-AWOIP2LC.js";
|
|
138
143
|
|
|
139
144
|
// src/cli.ts
|
|
140
145
|
import { Option, program } from "commander";
|
|
@@ -1152,6 +1157,11 @@ var OPERATION_DEFINITIONS = {
|
|
|
1152
1157
|
expectedRevisionPrefixes: ["claim:"],
|
|
1153
1158
|
requiredLockPrefixes: ["claim:"]
|
|
1154
1159
|
}),
|
|
1160
|
+
write(
|
|
1161
|
+
"mark-review-verification-stale",
|
|
1162
|
+
["review:", "verification:", "task:"],
|
|
1163
|
+
["task:"]
|
|
1164
|
+
),
|
|
1155
1165
|
write("update-metadata-scope", ["task:"], ["task:"]),
|
|
1156
1166
|
write("activate-successor-claims", ["task:"], ["task:"], {
|
|
1157
1167
|
expectedRevisionPrefixes: ["claim:"],
|
|
@@ -5692,11 +5702,13 @@ function parseRequirementsLedger2(raw, options = {}) {
|
|
|
5692
5702
|
"requirements need at least one required acceptance criterion"
|
|
5693
5703
|
);
|
|
5694
5704
|
}
|
|
5705
|
+
const confirmedScope = normalizeStrings(value.confirmedScope);
|
|
5706
|
+
const excludedScope = normalizeStrings(value.excludedScope);
|
|
5695
5707
|
return {
|
|
5696
5708
|
version: 1,
|
|
5697
5709
|
goal: value.goal.trim(),
|
|
5698
|
-
confirmedScope
|
|
5699
|
-
excludedScope
|
|
5710
|
+
confirmedScope,
|
|
5711
|
+
excludedScope,
|
|
5700
5712
|
technicalDecisions: normalizeStrings(value.technicalDecisions),
|
|
5701
5713
|
defaults: normalizeStrings(value.defaults),
|
|
5702
5714
|
blockingUnknowns: normalizeStrings(value.blockingUnknowns),
|
|
@@ -5704,6 +5716,12 @@ function parseRequirementsLedger2(raw, options = {}) {
|
|
|
5704
5716
|
acceptanceCriteria
|
|
5705
5717
|
};
|
|
5706
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
|
+
}
|
|
5707
5725
|
function requirementsAreReady2(ledger) {
|
|
5708
5726
|
return ledger.blockingUnknowns.length === 0;
|
|
5709
5727
|
}
|
|
@@ -9620,7 +9638,7 @@ async function activateLegacyMigration(input) {
|
|
|
9620
9638
|
if (session === null || session.status !== "active") {
|
|
9621
9639
|
throw new Error("MANCODE_SESSION_NOT_FOUND");
|
|
9622
9640
|
}
|
|
9623
|
-
const store = new (await import("./store-
|
|
9641
|
+
const store = new (await import("./store-DREAZNIX.js")).V3ContextStore(root);
|
|
9624
9642
|
const project = await store.readProjectSnapshot();
|
|
9625
9643
|
const stage = await readMigrationStage(root, input.stageId);
|
|
9626
9644
|
if (stage.state !== "staged" || stage.revision !== input.expectedStageRevision) {
|
|
@@ -9883,7 +9901,7 @@ async function activateLegacyMigration(input) {
|
|
|
9883
9901
|
for (const action of payload.actions.filter(
|
|
9884
9902
|
(action2) => action2.kind === "v3_adapter_file"
|
|
9885
9903
|
)) {
|
|
9886
|
-
const { applyV3AdapterFilePlan: applyV3AdapterFilePlan2 } = await import("./v3-adapter-
|
|
9904
|
+
const { applyV3AdapterFilePlan: applyV3AdapterFilePlan2 } = await import("./v3-adapter-TCEFETAG.js");
|
|
9887
9905
|
await applyV3AdapterFilePlan2(root, action);
|
|
9888
9906
|
}
|
|
9889
9907
|
journal = await completeActivationStep(
|
|
@@ -13739,7 +13757,7 @@ async function upgradeV3Adapters(input) {
|
|
|
13739
13757
|
if (unfinished.length > 0) {
|
|
13740
13758
|
throw new Error("MANCODE_ADAPTER_UPGRADE_OPERATION_PENDING");
|
|
13741
13759
|
}
|
|
13742
|
-
const actualVersions = await import("./v3-adapter-
|
|
13760
|
+
const actualVersions = await import("./v3-adapter-TCEFETAG.js").then(
|
|
13743
13761
|
({ inspectV3AdapterVersions: inspectV3AdapterVersions2 }) => inspectV3AdapterVersions2(
|
|
13744
13762
|
root,
|
|
13745
13763
|
managedAdapterNames(project.manifest.managedAdapters)
|
|
@@ -14330,7 +14348,7 @@ import path26 from "path";
|
|
|
14330
14348
|
var SCOUT_AGENT = {
|
|
14331
14349
|
name: "scout",
|
|
14332
14350
|
description: "Investigates the codebase for mancode /man workflows. Finds similar implementations, reusable modules, files to change, and risks. Does not write code.",
|
|
14333
|
-
tools: ["Read", "Grep", "Glob"
|
|
14351
|
+
tools: ["Read", "Grep", "Glob"],
|
|
14334
14352
|
body: `\u4F60\u662F mancode \u6559\u7EC3\u7EC4\u7684 Scout\uFF08\u7403\u63A2\uFF09\u3002
|
|
14335
14353
|
|
|
14336
14354
|
\u4F60\u7684\u804C\u8D23\uFF1A\u8C03\u7814\u4EE3\u7801\u5E93\uFF0C\u4E3A Head Coach \u51C6\u5907\u6218\u672F\u4FE1\u606F\u3002
|
|
@@ -14341,6 +14359,8 @@ var SCOUT_AGENT = {
|
|
|
14341
14359
|
- \u53EA\u5217\u5BF9\u5B9E\u65BD\u6709\u7528\u7684\u4FE1\u606F
|
|
14342
14360
|
- \u627E\u5230\u98CE\u9669\u70B9\u8981\u6807\u6CE8\uFF08\u26A0\uFE0F\uFF09
|
|
14343
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
|
|
14344
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
|
|
14345
14365
|
- \u5F15\u7528\u6587\u4EF6\u7528 \`path:line\` \u683C\u5F0F\uFF0C\u8BA9 Head Coach \u4E00\u79D2\u8DF3\u8FC7\u53BB
|
|
14346
14366
|
|
|
@@ -14406,6 +14426,16 @@ var SCOUT_AGENT = {
|
|
|
14406
14426
|
- Transport/platform: <\u5F71\u54CD\u6216 no change>
|
|
14407
14427
|
- Migration/rollback: <\u9700\u8981\u7684\u8BC1\u636E\u6216 no change>
|
|
14408
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
|
+
|
|
14409
14439
|
## \u76F8\u4F3C\u5B9E\u73B0
|
|
14410
14440
|
- \`<detected-source-root>/<relevant-file>:<line>\` \u2014 \u7B80\u8FF0\u53EF\u590D\u7528\u7684\u903B\u8F91
|
|
14411
14441
|
|
|
@@ -14441,8 +14471,8 @@ trigger: <\u88AB\u65B0\u8BC1\u636E\u63A8\u7FFB\u6216\u8D85\u51FA\u5F53\u524D req
|
|
|
14441
14471
|
|
|
14442
14472
|
- \u7528 Grep / Glob \u627E\u4EE3\u7801\uFF0C\u4E0D\u8981 cat \u6574\u4E2A\u6587\u4EF6
|
|
14443
14473
|
- \u7528 Read \u770B file:line \u9644\u8FD1\u7684\u4E0A\u4E0B\u6587
|
|
14444
|
-
- \u7528
|
|
14445
|
-
- **\u4E0D\u8981** Edit / Write \u2014 \u90A3\u662F
|
|
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
|
|
14446
14476
|
|
|
14447
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`
|
|
14448
14478
|
};
|
|
@@ -14466,7 +14496,11 @@ var PLAN_COACH_AGENT = {
|
|
|
14466
14496
|
|
|
14467
14497
|
## \u8F93\u5165\u5C31\u7EEA\u68C0\u67E5
|
|
14468
14498
|
|
|
14469
|
-
\u5148\u8BFB\u53D6 \`requirements.json\`\
|
|
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
|
|
14470
14504
|
|
|
14471
14505
|
\u540C\u65F6\u6267\u884C\u65B9\u6848\u5B8C\u6574\u6027\u68C0\u67E5\uFF1A
|
|
14472
14506
|
|
|
@@ -14474,6 +14508,7 @@ var PLAN_COACH_AGENT = {
|
|
|
14474
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
|
|
14475
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
|
|
14476
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
|
|
14477
14512
|
|
|
14478
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
|
|
14479
14514
|
|
|
@@ -14507,6 +14542,10 @@ stop_conditions: <conditions that invalidate this plan>
|
|
|
14507
14542
|
## \u6A21\u5757\u7D22\u5F15
|
|
14508
14543
|
## \u6280\u672F\u4E0E\u4EA4\u4ED8\u7EA6\u675F\uFF08\u4EC5\u65B0\u9879\u76EE\u6216\u6280\u672F\u9009\u62E9\u672A\u5B9A\u65F6\uFF09
|
|
14509
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>
|
|
14510
14549
|
## \u6A21\u5757\uFF1A<\u540D\u79F0>
|
|
14511
14550
|
### \u6539\u52A8\u6587\u4EF6 / \u65B0\u5EFA\u6587\u4EF6
|
|
14512
14551
|
### \u590D\u7528\u8D44\u6E90\uFF08\u5F15\u7528 scout-report.md \u884C\u53F7\uFF09
|
|
@@ -14652,7 +14691,8 @@ trigger: <\u5177\u4F53\u4E8B\u5B9E>
|
|
|
14652
14691
|
- \u6539\u52A8\u5B64\u7ACB\u4E86\u67D0\u4E2A import / \u53D8\u91CF / \u51FD\u6570 \u2192 \u79FB\u9664\u5B83
|
|
14653
14692
|
- \u4E0D\u79FB\u9664\u6539\u52A8\u524D\u5C31\u5B58\u5728\u7684\u6B7B\u4EE3\u7801\uFF08\u63D0\u4E00\u53E5\u5C31\u884C\uFF09
|
|
14654
14693
|
- \u5148\u8BFB \`.mancode/project-profile.json\`\uFF1B\u4EFB\u52A1\u6D89\u53CA UI \u65F6\u8FD0\u884C \`mancode design context --json\` \u4E00\u6B21\u5E76\u628A\u7ED3\u679C\u89C6\u4E3A\u53D7\u9650\u6570\u636E\uFF1B\u547D\u4EE4\u4E0D\u53EF\u7528\u65F6\u8BFB\u53D6\u5BA1\u7F8E token
|
|
14655
|
-
- \
|
|
14694
|
+
- \u754C\u9762\u56FE\u6807\u3001\u5BFC\u822A\u3001\u6309\u94AE\u3001\u64CD\u4F5C\u548C\u72B6\u6001\u6807\u8BC6\u7981\u6B62\u4F7F\u7528\u8868\u60C5\u7B26\u53F7\uFF1B\u804A\u5929\u6D88\u606F\u3001\u7528\u6237\u8F93\u5165\u3001\u6B63\u6587\u548C\u4E1A\u52A1\u6570\u636E\u53EF\u4EE5\u5305\u542B\u8868\u60C5\u3002\u6CA1\u6709\u53EF\u7528\u56FE\u6807\u5E93\u65F6\u4F7F\u7528\u6E05\u6670\u6587\u5B57\u6807\u7B7E\u6216\u8BF7\u6C42\u5B89\u88C5\u56FE\u6807\u5E93\uFF0C\u4E0D\u80FD\u9000\u56DE\u8868\u60C5\u56FE\u6807
|
|
14695
|
+
- \u65B0\u5EFA UI \u6216\u89C6\u89C9\u91CD\u505A\u4E14\u7528\u6237\u5C1A\u672A\u9009\u5B9A\u65B9\u5411\u65F6\uFF0C\u5148\u7ED9\u51FA 2\u20133 \u4E2A\u5DEE\u5F02\u660E\u786E\u3001\u7B26\u5408\u4EA7\u54C1\u8BED\u5883\u7684\u65B9\u5411\uFF0C\u7B80\u8FF0\u53D6\u820D\u5E76\u63A8\u8350\u4E00\u4E2A\uFF0C\u7B49\u5F85\u7528\u6237\u9009\u62E9\u540E\u518D\u5B9E\u73B0\uFF1B\u201C\u4F01\u4E1A\u7EA7\u201D\u201C\u7B80\u6D01\u201D\u201C\u73B0\u4EE3\u201D\u201C\u9AD8\u7EA7\u201D\u201C\u4E0D\u82B1\u54E8\u201D\u7B49\u5BBD\u6CDB\u5F62\u5BB9\u8BCD\u53EA\u662F\u7EA6\u675F\uFF0C\u4E0D\u7B97\u5DF2\u7ECF\u9009\u5B9A\u89C6\u89C9\u65B9\u5411\uFF1B\u5C40\u90E8 UI \u4FEE\u590D\u6216\u5DF2\u6709\u65B9\u5411\u5185\u7684\u5DE5\u4F5C\u76F4\u63A5\u6267\u884C
|
|
14656
14696
|
|
|
14657
14697
|
---
|
|
14658
14698
|
|
|
@@ -14761,6 +14801,7 @@ var FILM_ANALYST_OFFENSE_AGENT = {
|
|
|
14761
14801
|
- \u6700\u540E\u7ED9\u8BC4\u5206\uFF081-10\uFF09+ \u901A\u8FC7 / \u4E0D\u901A\u8FC7
|
|
14762
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
|
|
14763
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
|
|
14764
14805
|
|
|
14765
14806
|
## \u4F60\u4E0D\u5199\u4EE3\u7801
|
|
14766
14807
|
|
|
@@ -14770,6 +14811,7 @@ var FILM_ANALYST_OFFENSE_AGENT = {
|
|
|
14770
14811
|
|
|
14771
14812
|
| \u7EF4\u5EA6 | \u68C0\u67E5\u4EC0\u4E48 |
|
|
14772
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 |
|
|
14773
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 |
|
|
14774
14816
|
| **\u53EF\u7EF4\u62A4\u6027** | \u6A21\u5757\u8FB9\u754C\u3001\u8026\u5408\u5EA6\u3001\u6269\u5C55\u6027 |
|
|
14775
14817
|
| **\u98CE\u683C\u4E00\u81F4\u6027** | \u662F\u5426\u5339\u914D\u9879\u76EE\u5DF2\u6709\u98CE\u683C\uFF08\u5373\u4F7F\u4F60\u4E0D\u8BA4\u540C\uFF09 |
|
|
@@ -15059,6 +15101,8 @@ const state = readJson(path.join(mancodeDir, 'state.json')) || {};
|
|
|
15059
15101
|
const profile = readJson(path.join(mancodeDir, 'project-profile.json')) || {};
|
|
15060
15102
|
const mode = typeof state.currentMode === 'string' ? state.currentMode : '';
|
|
15061
15103
|
const output = [];
|
|
15104
|
+
const interfaceEmojiIconGuidance = ${JSON.stringify(INTERFACE_EMOJI_ICON_GUIDANCE)};
|
|
15105
|
+
const visualDirectionSelectionGuidance = ${JSON.stringify(VISUAL_DIRECTION_SELECTION_GUIDANCE)};
|
|
15062
15106
|
|
|
15063
15107
|
if (mode === 'solo') {
|
|
15064
15108
|
output.push(
|
|
@@ -15122,9 +15166,25 @@ if (
|
|
|
15122
15166
|
);
|
|
15123
15167
|
}
|
|
15124
15168
|
|
|
15125
|
-
const
|
|
15169
|
+
const strongUiPattern = /\b(?:ui|ux|front-?end|html|web ?page|page|button|icon|lucide|layout|css|card|modal|dialog|header|footer|sidebar|navigation|navbar|menu|dropdown|tooltip|toast|avatar|badge|dashboard|status indicator)s?\b|界面|页面|网页|前端|按钮|图标|布局|弹窗|导航|菜单|卡片|状态标识|状态图标|美化|优化.*界面|调整.*样式/iu;
|
|
15170
|
+
const weakVisualPattern = /\b(?:component|style|design|color|font|theme|input|visual|aesthetic)s?\b|样式|颜色|字体|主题|组件|输入框|审美|视觉|美观|好看/iu;
|
|
15171
|
+
const hasStrongUiSignal = strongUiPattern.test(userPrompt);
|
|
15172
|
+
const hasWeakVisualSignal = weakVisualPattern.test(userPrompt);
|
|
15173
|
+
const isUiPrompt =
|
|
15174
|
+
hasStrongUiSignal ||
|
|
15175
|
+
(profile.uiAssets === 'detected' && hasWeakVisualSignal);
|
|
15176
|
+
|
|
15177
|
+
if (isUiPrompt) {
|
|
15178
|
+
output.push(
|
|
15179
|
+
'## mancode UI design baseline',
|
|
15180
|
+
'',
|
|
15181
|
+
interfaceEmojiIconGuidance,
|
|
15182
|
+
visualDirectionSelectionGuidance,
|
|
15183
|
+
'',
|
|
15184
|
+
);
|
|
15185
|
+
}
|
|
15126
15186
|
|
|
15127
|
-
if (profile.uiAssets === 'detected' &&
|
|
15187
|
+
if (profile.uiAssets === 'detected' && isUiPrompt) {
|
|
15128
15188
|
appendAestheticSummary(
|
|
15129
15189
|
output,
|
|
15130
15190
|
readJson(path.join(mancodeDir, 'aesthetics', 'style-tokens.json')),
|
|
@@ -15266,11 +15326,13 @@ trigger: <\u5177\u4F53\u4E8B\u5B9E>
|
|
|
15266
15326
|
\u8FD9\u662F\u53EA\u8BFB\u8BCA\u65AD\u3002\u4FDD\u7559 requirements\u3001plan\u3001review/verification ledger\u3001claims\u3001handoff \u548C metadata\uFF1B\u4E0D\u8C03\u7528\u901A\u7528 \`workflow update\`\uFF0C\u4E0D\u5199 blocked/currentStep/planning\uFF0C\u4E0D\u5F52\u6863\u65E7\u6587\u4EF6\uFF0C\u4E0D\u91CA\u653E claim\uFF0C\u4E0D\u53D6\u6D88 handoff\uFF0C\u4E5F\u4E0D\u5BA3\u79F0\u5DF2\u56DE\u5230 Step 2\u3002
|
|
15267
15327
|
|
|
15268
15328
|
### UI \u4EFB\u52A1\uFF08\u6761\u4EF6\u6267\u884C\uFF09
|
|
15269
|
-
\
|
|
15270
|
-
|
|
15271
|
-
|
|
15272
|
-
|
|
15273
|
-
|
|
15329
|
+
\u4EFB\u52A1\u6D89\u53CA\u754C\u9762\u65F6\uFF1A
|
|
15330
|
+
- ${INTERFACE_EMOJI_ICON_GUIDANCE}
|
|
15331
|
+
- ${VISUAL_DIRECTION_SELECTION_GUIDANCE}
|
|
15332
|
+
- project-profile \u786E\u8BA4\u6709 UI \u8D44\u4EA7\u65F6\uFF0CUserPromptSubmit hook \u4F1A\u6CE8\u5165\u9879\u76EE\u5BA1\u7F8E token\uFF08\u5982\u6709\uFF09
|
|
15333
|
+
- \u4E25\u683C\u4F7F\u7528\u5DF2\u6709 token \u548C\u7EC4\u4EF6\uFF1B\u6CA1\u6709\u53EF\u9760 token \u65F6\u5148\u68C0\u67E5\u73B0\u6709\u754C\u9762\uFF0C\u518D\u63D0\u51FA\u6700\u5C0F\u4E00\u81F4\u65B9\u6848
|
|
15334
|
+
- \u4E0D\u628A\u7279\u5B9A\u6846\u67B6\u3001\u7EC4\u4EF6\u540D\u3001\u8272\u677F\u6216\u4EA4\u4E92\u8303\u5F0F\u5F53\u4F5C\u9ED8\u8BA4
|
|
15335
|
+
- \u4EE5\u9879\u76EE\u65E2\u6709\u7684\u65E0\u969C\u788D\u3001\u54CD\u5E94\u5F0F\u4E0E\u53CD\u9988\u65B9\u5F0F\u4E3A\u51C6
|
|
15274
15336
|
|
|
15275
15337
|
### \u754C\u9762\u8D28\u91CF\u68C0\u67E5\uFF08\u6761\u4EF6\u6267\u884C\uFF09
|
|
15276
15338
|
\u53EA\u68C0\u67E5\u672C\u6B21 diff \u65B0\u589E\u6216\u6539\u53D8\u7684\u754C\u9762\u884C\u4E3A\uFF1A\u590D\u7528\u5DF2\u6709\u5C42\u7EA7\u3001token \u548C\u7EC4\u4EF6\uFF1B\u65B0\u589E\u5F02\u6B65\u6216\u4EA4\u4E92\u8DEF\u5F84\u65F6\u624D\u68C0\u67E5\u5BF9\u5E94\u7684\u52A0\u8F7D\u3001\u5931\u8D25\u548C\u53EF\u8FBE\u6027\u72B6\u6001\u3002\u4E0D\u8981\u501F UI \u81EA\u68C0\u5DE1\u67E5\u672A\u6539\u52A8\u9875\u9762\u6216\u8865\u9F50\u63A8\u6D4B\u6027\u72B6\u6001\u3002
|
|
@@ -15298,11 +15360,11 @@ trigger: <\u5177\u4F53\u4E8B\u5B9E>
|
|
|
15298
15360
|
// src/templates/skills/principles.ts
|
|
15299
15361
|
var CORE_CODING_PRINCIPLES = `## \u94C1\u5F8B\uFF08\u6C38\u4E0D\u8FDD\u53CD\uFF09
|
|
15300
15362
|
|
|
15301
|
-
1. **\u4E0D\u505A\u65E0\u5173\u4FEE\u6539** \u2014 \u53EA\u6539 plan \u8303\u56F4\
|
|
15302
|
-
2. **\u5148\u9A8C\u8BC1\u518D\u58F0\u79F0\u5B8C\u6210** \u2014
|
|
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
|
|
15303
15365
|
3. **\u5931\u8D25\u4E24\u6B21\u5FC5\u987B\u505C\u4E0B** \u2014 \u4E0D\u76F2\u8BD5
|
|
15304
15366
|
4. **\u4E0D\u53EF\u9006\u64CD\u4F5C\u5148\u95EE** \u2014 \u5220\u9664\u3001force push\u3001worktree \u5408\u5E76
|
|
15305
|
-
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`;
|
|
15306
15368
|
|
|
15307
15369
|
// src/templates/skills/man.ts
|
|
15308
15370
|
var MAN_SKILL = {
|
|
@@ -15322,7 +15384,7 @@ var MAN_SKILL = {
|
|
|
15322
15384
|
|
|
15323
15385
|
### Step 1: Scout \u8C03\u7814
|
|
15324
15386
|
|
|
15325
|
-
\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
|
|
15326
15388
|
|
|
15327
15389
|
### Step 2: \u9700\u6C42\u6F84\u6E05
|
|
15328
15390
|
|
|
@@ -15333,6 +15395,8 @@ var MAN_SKILL = {
|
|
|
15333
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
|
|
15334
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
|
|
15335
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
|
+
|
|
15336
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
|
|
15337
15401
|
|
|
15338
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
|
|
@@ -15343,7 +15407,7 @@ var MAN_SKILL = {
|
|
|
15343
15407
|
|
|
15344
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
|
|
15345
15409
|
|
|
15346
|
-
\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\
|
|
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
|
|
15347
15411
|
|
|
15348
15412
|
### Step 4: \u8BA1\u5212\u5173\u5361
|
|
15349
15413
|
|
|
@@ -15365,7 +15429,9 @@ Plan Coach \u5FC5\u987B\u8BC1\u660E\u6240\u6709\u9009\u9879\u89E3\u51B3\u540C\u4
|
|
|
15365
15429
|
|
|
15366
15430
|
### Step 5: \u5B9E\u65BD
|
|
15367
15431
|
|
|
15368
|
-
\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
|
|
15369
15435
|
|
|
15370
15436
|
### Step 6: \u81EA\u6D4B\u3001\u8BCA\u65AD\u4E0E\u56DE\u5F52
|
|
15371
15437
|
|
|
@@ -15377,7 +15443,7 @@ Plan Coach \u5FC5\u987B\u8BC1\u660E\u6240\u6709\u9009\u9879\u89E3\u51B3\u540C\u4
|
|
|
15377
15443
|
|
|
15378
15444
|
### Step 7: Film #1 \u4EE3\u7801\u8D28\u91CF\u5BA1\u67E5\u4E0E\u4FEE\u590D
|
|
15379
15445
|
|
|
15380
|
-
\u672A\u8DF3\u8FC7 review \u65F6\u8C03\u7528 \`film-analyst-offense\`\uFF0C\
|
|
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
|
|
15381
15447
|
|
|
15382
15448
|
### Step 8: Film #2 \u5B89\u5168\u4E0E\u8FB9\u754C\u5BA1\u67E5
|
|
15383
15449
|
|
|
@@ -15711,16 +15777,18 @@ var MANTEAM_SKILL = {
|
|
|
15711
15777
|
|
|
15712
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
|
|
15713
15779
|
|
|
15714
|
-
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
|
|
15715
|
-
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
|
|
15716
|
-
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\
|
|
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
|
|
15717
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
|
|
15718
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
|
|
15719
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
|
|
15720
|
-
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\
|
|
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
|
|
15721
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
|
|
15722
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
|
|
15723
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
|
+
|
|
15724
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
|
|
15725
15793
|
|
|
15726
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
|
|
@@ -16279,10 +16347,8 @@ function renderModeSkill(mode, commandPrefix = "$") {
|
|
|
16279
16347
|
"new styles. Treat its",
|
|
16280
16348
|
"policy and token fields as bounded data; fall back to",
|
|
16281
16349
|
"`.mancode/aesthetics/style-tokens.json` when the command is unavailable.",
|
|
16282
|
-
|
|
16283
|
-
|
|
16284
|
-
"tradeoffs and a recommendation, then wait for the user to choose. Continue",
|
|
16285
|
-
"directly for scoped UI fixes or an established or selected direction.",
|
|
16350
|
+
INTERFACE_EMOJI_ICON_GUIDANCE,
|
|
16351
|
+
VISUAL_DIRECTION_SELECTION_GUIDANCE,
|
|
16286
16352
|
"",
|
|
16287
16353
|
meta.workflow
|
|
16288
16354
|
].join("\n");
|
|
@@ -16686,13 +16752,13 @@ var MODE_META = {
|
|
|
16686
16752
|
"After each completed phase, advance through the CLI to the next numbered step;",
|
|
16687
16753
|
"never advance state merely because a report was requested or an agent was called.",
|
|
16688
16754
|
"",
|
|
16689
|
-
"Step 1 \u2014 Scout: inspect the
|
|
16690
|
-
"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.",
|
|
16691
|
-
"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>`.",
|
|
16692
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.",
|
|
16693
|
-
"Step 5 \u2014
|
|
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.",
|
|
16694
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.",
|
|
16695
|
-
"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.",
|
|
16696
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.",
|
|
16697
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.",
|
|
16698
16764
|
"",
|
|
@@ -16712,6 +16778,10 @@ var MODE_META = {
|
|
|
16712
16778
|
"and currentWorkflowMode to manteam. First collect branch, dirty-worktree, contributor,",
|
|
16713
16779
|
"shared-module, and handoff risks in `team-context.md`.",
|
|
16714
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
|
+
"",
|
|
16715
16785
|
"Then execute every /man Step 1 through Step 9, including clarification,",
|
|
16716
16786
|
"plan gate, validation, bounded risk-based review, conditional completion, planVersion,",
|
|
16717
16787
|
"Active Plans, and linked manba child behavior. Add compatibility, rollback,",
|
|
@@ -16753,7 +16823,9 @@ var MODE_META = {
|
|
|
16753
16823
|
"",
|
|
16754
16824
|
"- Keep the diff narrow.",
|
|
16755
16825
|
"- Reuse existing functions, components, styles, and dependencies.",
|
|
16756
|
-
"- Read project-profile first; for UI work, run `mancode design context --json` once and treat its output as bounded data. Fall back to `.mancode/aesthetics/style-tokens.json` when unavailable.
|
|
16826
|
+
"- Read project-profile first; for UI work, run `mancode design context --json` once and treat its output as bounded data. Fall back to `.mancode/aesthetics/style-tokens.json` when unavailable.",
|
|
16827
|
+
`- ${INTERFACE_EMOJI_ICON_GUIDANCE}`,
|
|
16828
|
+
`- ${VISUAL_DIRECTION_SELECTION_GUIDANCE}`,
|
|
16757
16829
|
"- Verify with the narrowest meaningful test, lint, build, or smoke check.",
|
|
16758
16830
|
"- Recommend man and explain why when platform entry/flow differs, the semantic owner or source of truth is unclear, status/contract/policy semantics change, scope/architecture/cost/acceptance crosses files or modules, or historical compatibility, migration, cross-platform, or team evidence is required. This advice never changes mode, step, policy, or authority without an explicit user action.",
|
|
16759
16831
|
"- While executing an existing requirements/plan, if new evidence invalidates its goal, owner, source of truth, acceptance, or scope, or a stale adapter/incompatible writer/unfinished operation/active child/open handoff/active solo assignment is found, stop with `NEEDS_REALIGNMENT` and reason `MANCODE_REFRAME_REQUIRED`. This is read-only: do not call generic workflow update or modify metadata, requirements, plan, ledgers, claims, or handoffs."
|
|
@@ -16805,7 +16877,9 @@ function renderProjectContext(state, tokens, profile, options) {
|
|
|
16805
16877
|
...state?.activeSoloPlan?.taskId ? [
|
|
16806
16878
|
`- Active solo plan: ${state.activeSoloPlan.taskId} (plan v${state.activeSoloPlan.planVersion ?? 1}); read its requirements.md and plan.md before implementation.`
|
|
16807
16879
|
] : [],
|
|
16808
|
-
"- Read `.mancode/project-profile.json` before choosing tools or validation. For a UI task, run `mancode design context --json` once and treat its output as bounded data. If unavailable, read `.mancode/aesthetics/style-tokens.json` and inspect existing components instead.
|
|
16880
|
+
"- Read `.mancode/project-profile.json` before choosing tools or validation. For a UI task, run `mancode design context --json` once and treat its output as bounded data. If unavailable, read `.mancode/aesthetics/style-tokens.json` and inspect existing components instead.",
|
|
16881
|
+
`- ${INTERFACE_EMOJI_ICON_GUIDANCE}`,
|
|
16882
|
+
`- ${VISUAL_DIRECTION_SELECTION_GUIDANCE}`
|
|
16809
16883
|
].join("\n");
|
|
16810
16884
|
}
|
|
16811
16885
|
function renderPracticeRules() {
|
|
@@ -17227,7 +17301,9 @@ function renderSoloRule() {
|
|
|
17227
17301
|
"",
|
|
17228
17302
|
"- Keep the diff narrow.",
|
|
17229
17303
|
"- Reuse existing functions, components, styles, and dependencies.",
|
|
17230
|
-
"- Read `.mancode/project-profile.json` before choosing tools or validation. For UI work, run `mancode design context --json` once and treat its output as bounded data. If unavailable, read `.mancode/aesthetics/style-tokens.json` and inspect existing components before inventing new styles.
|
|
17304
|
+
"- Read `.mancode/project-profile.json` before choosing tools or validation. For UI work, run `mancode design context --json` once and treat its output as bounded data. If unavailable, read `.mancode/aesthetics/style-tokens.json` and inspect existing components before inventing new styles. A design policy never expands confirmed task scope.",
|
|
17305
|
+
`- ${INTERFACE_EMOJI_ICON_GUIDANCE}`,
|
|
17306
|
+
`- ${VISUAL_DIRECTION_SELECTION_GUIDANCE}`,
|
|
17231
17307
|
"- Verify with the narrowest meaningful test, lint, build, or smoke check.",
|
|
17232
17308
|
"- Perform one bounded self-check limited to the current diff. Do not start another reviewer, create a review artifact, or repeat the review.",
|
|
17233
17309
|
"- Recommend /man and explain why when platform entry/flow differs, the semantic owner or source of truth is unclear, status/contract/policy semantics change, scope/architecture/cost/acceptance crosses files or modules, or historical compatibility, migration, cross-platform, or team evidence is required. Auth, payment, sensitive data, deletion, public APIs, untrusted input, concurrency, and infrastructure remain hard-risk signals. Advice alone never changes mode, step, policy, or authority.",
|
|
@@ -26008,13 +26084,14 @@ async function configureDesignPolicy(input) {
|
|
|
26008
26084
|
if (currentRevision !== input.expectedRevision) {
|
|
26009
26085
|
throw new Error("MANCODE_EXPECTED_REVISION_CONFLICT");
|
|
26010
26086
|
}
|
|
26087
|
+
const emojiPolicy = input.emojiPolicy ?? current?.emojiPolicy ?? DEFAULT_DESIGN_POLICY.emojiPolicy;
|
|
26011
26088
|
const next = parseDesignPolicy({
|
|
26012
26089
|
...current ?? DEFAULT_DESIGN_POLICY,
|
|
26013
26090
|
revision: currentRevision + 1,
|
|
26014
26091
|
enabled: input.enabled ?? current?.enabled ?? true,
|
|
26015
26092
|
preset: input.preset ?? current?.preset ?? DEFAULT_DESIGN_POLICY.preset,
|
|
26016
26093
|
iconPolicy: input.iconPolicy ?? current?.iconPolicy ?? DEFAULT_DESIGN_POLICY.iconPolicy,
|
|
26017
|
-
emojiPolicy:
|
|
26094
|
+
emojiPolicy: emojiPolicy === "allow" ? "forbid-as-interface-icon" : emojiPolicy,
|
|
26018
26095
|
motionPolicy: input.motionPolicy ?? current?.motionPolicy ?? DEFAULT_DESIGN_POLICY.motionPolicy,
|
|
26019
26096
|
browserValidation: input.browserValidation ?? current?.browserValidation ?? DEFAULT_DESIGN_POLICY.browserValidation,
|
|
26020
26097
|
lastOperationId: operationId,
|
|
@@ -26134,12 +26211,14 @@ async function designStatus(rootDir = process2.cwd(), options = {}) {
|
|
|
26134
26211
|
policyStatus: policyResult.status,
|
|
26135
26212
|
policy: policyResult.policy,
|
|
26136
26213
|
effectivePreset: policyResult.policy?.enabled === true ? policyResult.policy.preset : "preserve",
|
|
26214
|
+
effectiveEmojiPolicy: "forbid-as-interface-icon",
|
|
26137
26215
|
policyPath: relativePath(rootDir, designPolicyPath(rootDir)),
|
|
26138
|
-
warning: policyResult.warning
|
|
26216
|
+
warning: effectivePolicyWarning(policyResult.policy, policyResult.warning)
|
|
26139
26217
|
};
|
|
26140
26218
|
return printResult(options.json, payload, [
|
|
26141
26219
|
`Design policy: ${payload.policyStatus}`,
|
|
26142
26220
|
`Effective preset: ${payload.effectivePreset}`,
|
|
26221
|
+
`Effective emoji policy: ${payload.effectiveEmojiPolicy}`,
|
|
26143
26222
|
`Revision: ${payload.policy?.revision ?? 0}`,
|
|
26144
26223
|
...payload.warning === null ? [] : [`Warning: ${payload.warning}`]
|
|
26145
26224
|
]);
|
|
@@ -26162,7 +26241,7 @@ async function designContext(rootDir = process2.cwd(), options = {}) {
|
|
|
26162
26241
|
]);
|
|
26163
26242
|
const configured = policyResult.policy;
|
|
26164
26243
|
const active = configured?.enabled === true;
|
|
26165
|
-
const policy = active ? configured : disabledPolicy();
|
|
26244
|
+
const policy = effectivePolicy(active ? configured : disabledPolicy());
|
|
26166
26245
|
const rootUiDetected = profile?.uiAssets === "detected";
|
|
26167
26246
|
const scopedUiDetected = style.scopeRoot !== "." && style.lastScanned !== null;
|
|
26168
26247
|
const applicable = rootUiDetected || scopedUiDetected;
|
|
@@ -26185,10 +26264,16 @@ async function designContext(rootDir = process2.cwd(), options = {}) {
|
|
|
26185
26264
|
doNotExpandTaskScope: true,
|
|
26186
26265
|
reuseExistingDesignSystem: true,
|
|
26187
26266
|
dependencyChangesRequireTaskApproval: true,
|
|
26188
|
-
experimentalDoesNotAuthorizeProductChanges: true
|
|
26267
|
+
experimentalDoesNotAuthorizeProductChanges: true,
|
|
26268
|
+
interfaceEmojiIconsForbidden: true,
|
|
26269
|
+
contentEmojiAllowed: true,
|
|
26270
|
+
iconFallbackMustNotBeEmoji: true
|
|
26189
26271
|
} : {
|
|
26190
26272
|
doNotExpandTaskScope: true,
|
|
26191
|
-
reuseExistingDesignSystem: true
|
|
26273
|
+
reuseExistingDesignSystem: true,
|
|
26274
|
+
interfaceEmojiIconsForbidden: true,
|
|
26275
|
+
contentEmojiAllowed: true,
|
|
26276
|
+
iconFallbackMustNotBeEmoji: true
|
|
26192
26277
|
},
|
|
26193
26278
|
project: {
|
|
26194
26279
|
kind: profile?.projectKind ?? "unknown",
|
|
@@ -26198,7 +26283,7 @@ async function designContext(rootDir = process2.cwd(), options = {}) {
|
|
|
26198
26283
|
guidance: designGuidance(policy),
|
|
26199
26284
|
qualityGates: designQualityGates(policy),
|
|
26200
26285
|
style,
|
|
26201
|
-
warning: policyResult.warning
|
|
26286
|
+
warning: effectivePolicyWarning(configured, policyResult.warning)
|
|
26202
26287
|
};
|
|
26203
26288
|
return printResult(options.json, payload, [
|
|
26204
26289
|
`Applicable: ${payload.applicable ? "yes" : "no"}`,
|
|
@@ -26237,6 +26322,7 @@ async function designConfigure(rootDir, options) {
|
|
|
26237
26322
|
);
|
|
26238
26323
|
}
|
|
26239
26324
|
try {
|
|
26325
|
+
const legacyEmojiAllow = options.emoji === "allow";
|
|
26240
26326
|
const result2 = await configureDesignPolicy({
|
|
26241
26327
|
projectRoot: rootDir,
|
|
26242
26328
|
expectedRevision,
|
|
@@ -26244,9 +26330,11 @@ async function designConfigure(rootDir, options) {
|
|
|
26244
26330
|
confirmExperimental: options.confirmExperimental,
|
|
26245
26331
|
...values
|
|
26246
26332
|
});
|
|
26247
|
-
|
|
26333
|
+
const warning = legacyEmojiAllow ? "--emoji allow is deprecated and was normalized to forbid-as-interface-icon; emoji remains allowed in user-authored content, chat messages, editorial copy, and domain data." : null;
|
|
26334
|
+
return printResult(options.json, { schemaVersion: 1, ...result2, warning }, [
|
|
26248
26335
|
`Design policy configured: ${result2.policy.preset}`,
|
|
26249
|
-
`Revision: ${result2.policy.revision}
|
|
26336
|
+
`Revision: ${result2.policy.revision}`,
|
|
26337
|
+
...warning === null ? [] : [`Warning: ${warning}`]
|
|
26250
26338
|
]);
|
|
26251
26339
|
} catch (error) {
|
|
26252
26340
|
const code = errorCode3(error, "MANCODE_DESIGN_CONFIGURE_FAILED");
|
|
@@ -26304,7 +26392,7 @@ function parseConfigureValues(options) {
|
|
|
26304
26392
|
return {
|
|
26305
26393
|
preset: options.preset,
|
|
26306
26394
|
iconPolicy: options.icons,
|
|
26307
|
-
emojiPolicy: options.emoji,
|
|
26395
|
+
emojiPolicy: options.emoji === "allow" ? "forbid-as-interface-icon" : options.emoji,
|
|
26308
26396
|
motionPolicy: options.motion,
|
|
26309
26397
|
browserValidation: options.browserValidation
|
|
26310
26398
|
};
|
|
@@ -26389,22 +26477,28 @@ async function styleFreshness(rootDir, scopeRoot, lastScanned, sourceFiles) {
|
|
|
26389
26477
|
function disabledPolicy() {
|
|
26390
26478
|
return {
|
|
26391
26479
|
...DEFAULT_DESIGN_POLICY,
|
|
26392
|
-
emojiPolicy: "allow",
|
|
26393
26480
|
motionPolicy: "minimal",
|
|
26394
26481
|
browserValidation: "off"
|
|
26395
26482
|
};
|
|
26396
26483
|
}
|
|
26484
|
+
function effectivePolicy(policy) {
|
|
26485
|
+
return policy.emojiPolicy === "forbid-as-interface-icon" ? policy : { ...policy, emojiPolicy: "forbid-as-interface-icon" };
|
|
26486
|
+
}
|
|
26487
|
+
function effectivePolicyWarning(policy, warning) {
|
|
26488
|
+
const legacyWarning = policy?.emojiPolicy === "allow" ? 'The legacy emoji policy "allow" is constrained to forbid-as-interface-icon; emoji remains allowed in user-authored content, chat messages, editorial copy, and domain data.' : null;
|
|
26489
|
+
return [warning, legacyWarning].filter(Boolean).join(" ") || null;
|
|
26490
|
+
}
|
|
26397
26491
|
function designGuidance(policy) {
|
|
26398
26492
|
return [
|
|
26399
26493
|
directionSelectionGuidance(),
|
|
26400
26494
|
presetGuidance(policy.preset),
|
|
26401
26495
|
iconGuidance(policy.iconPolicy),
|
|
26402
|
-
emojiGuidance(
|
|
26496
|
+
emojiGuidance(),
|
|
26403
26497
|
motionGuidance(policy.motionPolicy)
|
|
26404
26498
|
];
|
|
26405
26499
|
}
|
|
26406
26500
|
function directionSelectionGuidance() {
|
|
26407
|
-
return
|
|
26501
|
+
return VISUAL_DIRECTION_SELECTION_GUIDANCE;
|
|
26408
26502
|
}
|
|
26409
26503
|
function presetGuidance(preset) {
|
|
26410
26504
|
if (preset === "refine") {
|
|
@@ -26418,8 +26512,8 @@ function presetGuidance(preset) {
|
|
|
26418
26512
|
function iconGuidance(policy) {
|
|
26419
26513
|
return policy === "lucide" ? "Use Lucide for interface icons when it is already available; adding or replacing a dependency requires explicit task approval." : "Reuse the project's existing icon system; do not introduce another icon library without explicit task approval.";
|
|
26420
26514
|
}
|
|
26421
|
-
function emojiGuidance(
|
|
26422
|
-
return
|
|
26515
|
+
function emojiGuidance() {
|
|
26516
|
+
return INTERFACE_EMOJI_ICON_GUIDANCE.replace("Never use", "Do not use");
|
|
26423
26517
|
}
|
|
26424
26518
|
function motionGuidance(policy) {
|
|
26425
26519
|
return policy === "purposeful" ? "Use motion only to clarify hierarchy, state changes, or spatial relationships, and preserve reduced-motion accessibility." : "Keep motion minimal and preserve reduced-motion accessibility.";
|
|
@@ -26429,6 +26523,7 @@ function designQualityGates(policy) {
|
|
|
26429
26523
|
return [
|
|
26430
26524
|
"Preserve task-critical workflows, keyboard access, visible focus, readable contrast, and responsive behavior on changed surfaces.",
|
|
26431
26525
|
"Check changed surfaces for clipping, unintended overlap, horizontal overflow, and unstable layout.",
|
|
26526
|
+
"Inspect changed navigation, buttons, controls, actions, and status indicators to confirm that no emoji is used as an interface icon; do not flag emoji in user-authored content, chat messages, editorial copy, or domain data.",
|
|
26432
26527
|
browserGate
|
|
26433
26528
|
];
|
|
26434
26529
|
}
|
|
@@ -41775,311 +41870,41 @@ function assertPositiveRevision6(value, label) {
|
|
|
41775
41870
|
}
|
|
41776
41871
|
}
|
|
41777
41872
|
|
|
41778
|
-
// src/context/
|
|
41779
|
-
|
|
41873
|
+
// src/context/scope-change.ts
|
|
41874
|
+
import { createHash as createHash11 } from "crypto";
|
|
41875
|
+
async function changeV3WorkflowScope(input) {
|
|
41780
41876
|
const taskRef = parseTaskRefValue(input.taskRef);
|
|
41781
|
-
|
|
41782
|
-
|
|
41783
|
-
if (taskRef.namespace === "shared") {
|
|
41784
|
-
assertSharedTextSafe(plan, "plan");
|
|
41785
|
-
}
|
|
41786
|
-
const context = await openV3TaskOperation({
|
|
41787
|
-
projectRoot: input.projectRoot,
|
|
41788
|
-
taskRef,
|
|
41789
|
-
sessionId: input.sessionId,
|
|
41790
|
-
expectedTaskRevision: input.expectedTaskRevision,
|
|
41791
|
-
operationId: input.operationId,
|
|
41792
|
-
extraEntityLocks: taskRef.namespace === "shared" ? [taskHeadEntityKey(taskRef)] : [],
|
|
41793
|
-
now: input.now
|
|
41794
|
-
});
|
|
41795
|
-
let journal = null;
|
|
41796
|
-
try {
|
|
41797
|
-
assertPlanRevisionEligible(
|
|
41798
|
-
context.task.metadata,
|
|
41799
|
-
context.task.requirements
|
|
41800
|
-
);
|
|
41801
|
-
if (context.task.metadata.workflowMode === "manteam" && planDecision === "governed_execution") {
|
|
41802
|
-
assertManteamPlanContent(plan);
|
|
41803
|
-
}
|
|
41804
|
-
if (context.task.plan?.content === plan && planDecision === null) {
|
|
41805
|
-
throw new Error("MANCODE_PLAN_CONTENT_UNCHANGED");
|
|
41806
|
-
}
|
|
41807
|
-
const planChanged = context.task.plan?.content !== plan;
|
|
41808
|
-
const timestamp4 = context.now.toISOString();
|
|
41809
|
-
const planDigest = planChanged ? digestCanonicalJson({
|
|
41810
|
-
artifactRef: { taskRef, kind: "plan" },
|
|
41811
|
-
content: plan
|
|
41812
|
-
}) : context.task.plan?.digest;
|
|
41813
|
-
if (planDigest === void 0) {
|
|
41814
|
-
throw new Error("MANCODE_PLAN_FILE_REQUIRED");
|
|
41815
|
-
}
|
|
41816
|
-
const review = planChanged ? markTaskReviewStale(context.task.review, context.operationId, timestamp4) : context.task.review;
|
|
41817
|
-
const verification = planChanged ? markTaskVerificationStale(
|
|
41818
|
-
context.task.verification,
|
|
41819
|
-
context.operationId,
|
|
41820
|
-
timestamp4
|
|
41821
|
-
) : context.task.verification;
|
|
41822
|
-
const metadata = updateMetadata(
|
|
41823
|
-
context.task.metadata,
|
|
41824
|
-
context.task.requirements,
|
|
41825
|
-
review,
|
|
41826
|
-
verification,
|
|
41827
|
-
planChanged,
|
|
41828
|
-
planDecision,
|
|
41829
|
-
context.operationId,
|
|
41830
|
-
timestamp4
|
|
41831
|
-
);
|
|
41832
|
-
const aggregate = buildTaskAggregateManifest({
|
|
41833
|
-
metadata,
|
|
41834
|
-
requirements: context.task.requirements,
|
|
41835
|
-
review,
|
|
41836
|
-
verification,
|
|
41837
|
-
planDigest,
|
|
41838
|
-
latestCheckpoint: context.task.latestCheckpoint
|
|
41839
|
-
});
|
|
41840
|
-
const taskHeadFence = nextTaskHeadFence(context, aggregate, timestamp4);
|
|
41841
|
-
if (planDecision === "plan_only") {
|
|
41842
|
-
await enqueueSessionPointerProjection(context.projectRoot, {
|
|
41843
|
-
operationId: context.operationId,
|
|
41844
|
-
action: "clear",
|
|
41845
|
-
sessionId: context.session.sessionId,
|
|
41846
|
-
expectedPreviousTaskRef: context.session.activeTaskRef,
|
|
41847
|
-
taskRef,
|
|
41848
|
-
workflowMode: metadata.workflowMode,
|
|
41849
|
-
taskRevision: metadata.revision,
|
|
41850
|
-
now: context.now
|
|
41851
|
-
});
|
|
41852
|
-
}
|
|
41853
|
-
journal = await createTaskOperationJournal(context, {
|
|
41854
|
-
type: "plan_revision",
|
|
41855
|
-
action: taskRef.namespace === "shared" ? "shared_metadata_plan_mutation" : "local_workflow_mutation",
|
|
41856
|
-
expectedRevisions: taskMutationExpectedRevisions(context, [
|
|
41857
|
-
"plan",
|
|
41858
|
-
"review",
|
|
41859
|
-
"verification"
|
|
41860
|
-
]),
|
|
41861
|
-
recovery: {
|
|
41862
|
-
actions: [
|
|
41863
|
-
...planChanged ? [
|
|
41864
|
-
createTaskAuthorityFileRecoveryAction({
|
|
41865
|
-
stepId: "write-plan",
|
|
41866
|
-
taskRef,
|
|
41867
|
-
fileName: "plan.md",
|
|
41868
|
-
beforeContent: context.task.plan?.content ?? null,
|
|
41869
|
-
targetContent: plan
|
|
41870
|
-
})
|
|
41871
|
-
] : [],
|
|
41872
|
-
createTaskAuthorityFileRecoveryAction({
|
|
41873
|
-
stepId: "update-metadata",
|
|
41874
|
-
taskRef,
|
|
41875
|
-
fileName: "metadata.json",
|
|
41876
|
-
beforeContent: serializeTaskAuthority(context.task.metadata),
|
|
41877
|
-
targetContent: serializeTaskAuthority(metadata)
|
|
41878
|
-
}),
|
|
41879
|
-
...planChanged ? [
|
|
41880
|
-
createTaskAuthorityFileRecoveryAction({
|
|
41881
|
-
stepId: "mark-review-verification-stale",
|
|
41882
|
-
taskRef,
|
|
41883
|
-
fileName: "review-ledger.json",
|
|
41884
|
-
beforeContent: serializeTaskAuthority(context.task.review),
|
|
41885
|
-
targetContent: serializeTaskAuthority(review)
|
|
41886
|
-
}),
|
|
41887
|
-
createTaskAuthorityFileRecoveryAction({
|
|
41888
|
-
stepId: "mark-review-verification-stale",
|
|
41889
|
-
taskRef,
|
|
41890
|
-
fileName: "verification-ledger.json",
|
|
41891
|
-
beforeContent: serializeTaskAuthority(
|
|
41892
|
-
context.task.verification
|
|
41893
|
-
),
|
|
41894
|
-
targetContent: serializeTaskAuthority(verification)
|
|
41895
|
-
})
|
|
41896
|
-
] : [],
|
|
41897
|
-
...taskHeadFence === null ? [] : [
|
|
41898
|
-
createTaskHeadFenceRecoveryAction({
|
|
41899
|
-
stepId: "update-task-head-fence",
|
|
41900
|
-
before: context.coordination.taskHeadFence,
|
|
41901
|
-
fence: taskHeadFence
|
|
41902
|
-
})
|
|
41903
|
-
]
|
|
41904
|
-
],
|
|
41905
|
-
noOpStepIds: [
|
|
41906
|
-
...planChanged ? [] : ["write-plan", "mark-review-verification-stale"],
|
|
41907
|
-
...taskHeadFence === null ? ["update-task-head-fence"] : []
|
|
41908
|
-
]
|
|
41909
|
-
}
|
|
41910
|
-
});
|
|
41911
|
-
journal = await advanceTaskOperation(context, journal, "validate", true);
|
|
41912
|
-
journal = await advanceTaskOperation(context, journal, "write-plan", false);
|
|
41913
|
-
if (planChanged) {
|
|
41914
|
-
await writeTaskAuthorityFile(context, "plan.md", plan);
|
|
41915
|
-
}
|
|
41916
|
-
journal = await advanceTaskOperation(
|
|
41917
|
-
context,
|
|
41918
|
-
journal,
|
|
41919
|
-
"update-metadata",
|
|
41920
|
-
false
|
|
41921
|
-
);
|
|
41922
|
-
await writeTaskAuthorityFile(
|
|
41923
|
-
context,
|
|
41924
|
-
"metadata.json",
|
|
41925
|
-
`${JSON.stringify(metadata, null, 2)}
|
|
41926
|
-
`
|
|
41927
|
-
);
|
|
41928
|
-
journal = await advanceTaskOperation(
|
|
41929
|
-
context,
|
|
41930
|
-
journal,
|
|
41931
|
-
"mark-review-verification-stale",
|
|
41932
|
-
false
|
|
41933
|
-
);
|
|
41934
|
-
if (planChanged) {
|
|
41935
|
-
await writeTaskAuthorityFile(
|
|
41936
|
-
context,
|
|
41937
|
-
"review-ledger.json",
|
|
41938
|
-
`${JSON.stringify(review, null, 2)}
|
|
41939
|
-
`
|
|
41940
|
-
);
|
|
41941
|
-
await writeTaskAuthorityFile(
|
|
41942
|
-
context,
|
|
41943
|
-
"verification-ledger.json",
|
|
41944
|
-
`${JSON.stringify(verification, null, 2)}
|
|
41945
|
-
`
|
|
41946
|
-
);
|
|
41947
|
-
}
|
|
41948
|
-
journal = await advanceTaskOperation(
|
|
41949
|
-
context,
|
|
41950
|
-
journal,
|
|
41951
|
-
"update-task-head-fence",
|
|
41952
|
-
false
|
|
41953
|
-
);
|
|
41954
|
-
if (taskHeadFence !== null) {
|
|
41955
|
-
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
41956
|
-
await replaceTaskHeadFence(context.homeStore, taskHeadFence);
|
|
41957
|
-
}
|
|
41958
|
-
const operation = await commitTaskOperation(context, journal);
|
|
41959
|
-
if (planDecision === "plan_only") {
|
|
41960
|
-
try {
|
|
41961
|
-
await reconcileProjectionIntents(
|
|
41962
|
-
context.projectRoot,
|
|
41963
|
-
context.operationId,
|
|
41964
|
-
context.now
|
|
41965
|
-
);
|
|
41966
|
-
} catch {
|
|
41967
|
-
}
|
|
41968
|
-
}
|
|
41969
|
-
return {
|
|
41970
|
-
metadata,
|
|
41971
|
-
review,
|
|
41972
|
-
verification,
|
|
41973
|
-
planDigest,
|
|
41974
|
-
aggregate,
|
|
41975
|
-
taskHeadFence,
|
|
41976
|
-
operation
|
|
41977
|
-
};
|
|
41978
|
-
} catch (error) {
|
|
41979
|
-
if (journal !== null) {
|
|
41980
|
-
try {
|
|
41981
|
-
await handleTaskOperationFailure(context, journal);
|
|
41982
|
-
} catch {
|
|
41983
|
-
}
|
|
41984
|
-
}
|
|
41985
|
-
throw error;
|
|
41986
|
-
} finally {
|
|
41987
|
-
await context.release();
|
|
41988
|
-
}
|
|
41989
|
-
}
|
|
41990
|
-
function requirePlan(value) {
|
|
41991
|
-
if (typeof value !== "string" || !value.trim() || value.includes("\0")) {
|
|
41992
|
-
throw new Error("MANCODE_PLAN_CONTENT_REQUIRED");
|
|
41993
|
-
}
|
|
41994
|
-
return value;
|
|
41995
|
-
}
|
|
41996
|
-
function parsePlanDecision(value) {
|
|
41997
|
-
if (value === void 0) return null;
|
|
41998
|
-
if (value !== "plan_only" && value !== "governed_execution") {
|
|
41999
|
-
throw new Error("MANCODE_PLAN_DECISION_INVALID");
|
|
42000
|
-
}
|
|
42001
|
-
return value;
|
|
42002
|
-
}
|
|
42003
|
-
function assertPlanRevisionEligible(metadata, requirements) {
|
|
42004
|
-
if (metadata.workflowMode !== "man" && metadata.workflowMode !== "manteam") {
|
|
42005
|
-
throw new Error("MANCODE_PLAN_WORKFLOW_MODE_INVALID");
|
|
42006
|
-
}
|
|
42007
|
-
if (metadata.status !== "in_progress") {
|
|
42008
|
-
throw new Error("MANCODE_PLAN_WORKFLOW_NOT_ACTIVE");
|
|
42009
|
-
}
|
|
42010
|
-
if (metadata.currentStep < 2 || metadata.currentStep > 4) {
|
|
42011
|
-
throw new Error("MANCODE_PLAN_STEP_INVALID");
|
|
42012
|
-
}
|
|
42013
|
-
if (metadata.governance.planDecision !== null || metadata.governance.requirementsStatus !== "ready" || metadata.governance.requirementsDigest !== requirements.contentDigest || requirements.status !== "confirmed" || !requirementsAreReady(requirements)) {
|
|
42014
|
-
throw new Error("MANCODE_PLAN_REQUIREMENTS_OR_DECISION_INVALID");
|
|
41877
|
+
if (taskRef.namespace !== "shared") {
|
|
41878
|
+
throw new Error("MANCODE_SCOPE_CHANGE_REQUIRES_SHARED_TASK");
|
|
42015
41879
|
}
|
|
42016
|
-
|
|
42017
|
-
function updateMetadata(previous, requirements, review, verification, planChanged, planDecision, operationId, updatedAt) {
|
|
42018
|
-
const status2 = planDecision === "plan_only" ? "planned" : "in_progress";
|
|
42019
|
-
const currentStep = planDecision === "governed_execution" ? 5 : 4;
|
|
42020
|
-
const next = parseWorkflowMetadata({
|
|
42021
|
-
...previous,
|
|
42022
|
-
status: status2,
|
|
42023
|
-
currentStep,
|
|
42024
|
-
revision: previous.revision + 1,
|
|
42025
|
-
transitionState: "stable",
|
|
42026
|
-
lastOperationId: operationId,
|
|
42027
|
-
governance: {
|
|
42028
|
-
...previous.governance,
|
|
42029
|
-
requirementsStatus: "ready",
|
|
42030
|
-
requirementsDigest: requirements.contentDigest,
|
|
42031
|
-
planVersion: previous.governance.planVersion + (planChanged ? 1 : 0),
|
|
42032
|
-
planDecision,
|
|
42033
|
-
reviewStatus: planChanged ? "stale" : previous.governance.reviewStatus,
|
|
42034
|
-
reviewLedgerDigest: review.contentDigest,
|
|
42035
|
-
verificationStatus: planChanged ? "stale" : previous.governance.verificationStatus,
|
|
42036
|
-
verificationLedgerDigest: verification.contentDigest
|
|
42037
|
-
},
|
|
42038
|
-
updatedAt
|
|
42039
|
-
});
|
|
42040
|
-
assertWorkflowMetadataTransition(previous, next, "ordinary");
|
|
42041
|
-
return next;
|
|
42042
|
-
}
|
|
42043
|
-
|
|
42044
|
-
// src/context/reframe.ts
|
|
42045
|
-
async function reframeV3Workflow(input) {
|
|
42046
|
-
const taskRef = parseTaskRefValue(input.taskRef);
|
|
42047
|
-
assertUlid(input.checkpointId, "reframe checkpointId");
|
|
41880
|
+
const scope = normalizeImplementationScope(input.scope);
|
|
42048
41881
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
41882
|
+
const timestamp4 = now.toISOString();
|
|
41883
|
+
const checkpointId = input.checkpointId ?? createUlid(now.getTime());
|
|
42049
41884
|
const operationId = input.operationId ?? createUlid(now.getTime());
|
|
42050
|
-
assertUlid(
|
|
42051
|
-
|
|
41885
|
+
assertUlid(checkpointId, "scope change checkpointId");
|
|
41886
|
+
assertUlid(operationId, "scope change operationId");
|
|
41887
|
+
const opened = await openScopeChangeContext({
|
|
42052
41888
|
projectRoot: input.projectRoot,
|
|
42053
41889
|
taskRef,
|
|
42054
41890
|
sessionId: input.sessionId,
|
|
42055
41891
|
expectedTaskRevision: input.expectedTaskRevision,
|
|
42056
|
-
|
|
41892
|
+
scope,
|
|
41893
|
+
checkpointId,
|
|
41894
|
+
successorClaimIds: input.successorClaimIds,
|
|
42057
41895
|
operationId,
|
|
42058
41896
|
now
|
|
42059
41897
|
});
|
|
42060
|
-
const { context, activeClaims: activeClaims2,
|
|
41898
|
+
const { context, activeClaims: activeClaims2, successorClaimIds, successorPredecessors } = opened;
|
|
42061
41899
|
let journal = null;
|
|
42062
41900
|
try {
|
|
42063
|
-
|
|
42064
|
-
|
|
42065
|
-
const
|
|
42066
|
-
const archivedRequirementsContent = await readTaskAuthorityFileAtRoot(
|
|
42067
|
-
context.task.location.taskRoot,
|
|
42068
|
-
"requirements.json"
|
|
42069
|
-
);
|
|
42070
|
-
if (archivedRequirementsContent === null) {
|
|
42071
|
-
throw new Error("MANCODE_REFRAME_REQUIREMENTS_MISSING");
|
|
42072
|
-
}
|
|
42073
|
-
const pendingMetadata = markReframeOperationPending(
|
|
41901
|
+
assertScopeChangeEligible(context, scope);
|
|
41902
|
+
assertClaimsFreshForScopeChange(context, activeClaims2);
|
|
41903
|
+
const pendingMetadata = markScopeChangeOperationPending(
|
|
42074
41904
|
context.task.metadata,
|
|
42075
41905
|
context.operationId,
|
|
42076
41906
|
timestamp4
|
|
42077
41907
|
);
|
|
42078
|
-
const requirements = createReframedRequirements(
|
|
42079
|
-
context.task.requirements,
|
|
42080
|
-
context.operationId,
|
|
42081
|
-
timestamp4
|
|
42082
|
-
);
|
|
42083
41908
|
const review = markTaskReviewStale(
|
|
42084
41909
|
context.task.review,
|
|
42085
41910
|
context.operationId,
|
|
@@ -42090,71 +41915,80 @@ async function reframeV3Workflow(input) {
|
|
|
42090
41915
|
context.operationId,
|
|
42091
41916
|
timestamp4
|
|
42092
41917
|
);
|
|
42093
|
-
const
|
|
42094
|
-
|
|
42095
|
-
);
|
|
42096
|
-
const archiveAction = createTaskArchiveRecoveryAction({
|
|
42097
|
-
stepId: "archive-requirements-plan",
|
|
42098
|
-
taskRef,
|
|
42099
|
-
archiveId: context.operationId,
|
|
42100
|
-
sourceTaskRevision: context.task.metadata.revision,
|
|
42101
|
-
sourcePlanVersion: context.task.metadata.governance.planVersion,
|
|
42102
|
-
createdAt: timestamp4,
|
|
42103
|
-
requirementsContent: archivedRequirementsContent,
|
|
42104
|
-
planContent: context.task.plan?.content ?? null
|
|
42105
|
-
});
|
|
42106
|
-
const branch = await readCheckoutBranch(context.projectRoot);
|
|
42107
|
-
const checkpoint = buildReframeCheckpoint({
|
|
41918
|
+
const branch = await readCheckoutBranch(context.projectRoot) ?? "HEAD";
|
|
41919
|
+
const checkpoint = buildScopeChangedCheckpoint(
|
|
42108
41920
|
context,
|
|
42109
|
-
|
|
42110
|
-
|
|
42111
|
-
|
|
42112
|
-
|
|
42113
|
-
verification,
|
|
42114
|
-
summary: input.summary,
|
|
42115
|
-
nextAction: input.nextAction,
|
|
41921
|
+
pendingMetadata,
|
|
41922
|
+
checkpointId,
|
|
41923
|
+
input.checkpointSummary,
|
|
41924
|
+
input.checkpointNextAction,
|
|
42116
41925
|
branch,
|
|
42117
|
-
|
|
42118
|
-
|
|
42119
|
-
|
|
41926
|
+
pendingMetadata.governance.planVersion + 1,
|
|
41927
|
+
review.contentDigest,
|
|
41928
|
+
verification.contentDigest,
|
|
41929
|
+
timestamp4
|
|
41930
|
+
);
|
|
41931
|
+
const metadata = completeScopeChangeMetadata(
|
|
42120
41932
|
pendingMetadata,
|
|
42121
|
-
|
|
42122
|
-
review,
|
|
42123
|
-
verification,
|
|
41933
|
+
scope,
|
|
42124
41934
|
checkpoint,
|
|
41935
|
+
review.contentDigest,
|
|
41936
|
+
verification.contentDigest,
|
|
42125
41937
|
context.operationId,
|
|
42126
41938
|
timestamp4
|
|
42127
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
|
+
);
|
|
42128
41970
|
const aggregate = buildTaskAggregateManifest({
|
|
42129
41971
|
metadata,
|
|
42130
|
-
requirements,
|
|
41972
|
+
requirements: context.task.requirements,
|
|
42131
41973
|
review,
|
|
42132
41974
|
verification,
|
|
42133
41975
|
planDigest: context.task.plan?.digest ?? null,
|
|
42134
41976
|
latestCheckpoint: checkpoint
|
|
42135
41977
|
});
|
|
42136
41978
|
const taskHeadFence = nextTaskHeadFence(context, aggregate, timestamp4);
|
|
42137
|
-
|
|
42138
|
-
|
|
42139
|
-
await enqueueSessionPointerProjection(context.projectRoot, {
|
|
42140
|
-
operationId: context.operationId,
|
|
42141
|
-
action: "resume",
|
|
42142
|
-
sessionId: context.session.sessionId,
|
|
42143
|
-
expectedPreviousTaskRef: context.session.activeTaskRef,
|
|
42144
|
-
taskRef,
|
|
42145
|
-
workflowMode: metadata.workflowMode,
|
|
42146
|
-
taskRevision: metadata.revision,
|
|
42147
|
-
now: context.now
|
|
42148
|
-
});
|
|
41979
|
+
if (taskHeadFence === null) {
|
|
41980
|
+
throw new Error("MANCODE_TASK_HEAD_FENCE_MISSING");
|
|
42149
41981
|
}
|
|
42150
41982
|
journal = await createTaskOperationJournal(context, {
|
|
42151
|
-
type: "
|
|
42152
|
-
action:
|
|
42153
|
-
expectedRevisions:
|
|
41983
|
+
type: "scope_change_reclaim",
|
|
41984
|
+
action: "task_complete_scope_change_child_merge",
|
|
41985
|
+
expectedRevisions: scopeChangeExpectedRevisions(
|
|
42154
41986
|
context,
|
|
42155
|
-
|
|
42156
|
-
activeClaims2
|
|
41987
|
+
checkpointId,
|
|
41988
|
+
activeClaims2,
|
|
41989
|
+
successorClaimIds
|
|
42157
41990
|
),
|
|
41991
|
+
conditions: { completionGateSatisfied: true },
|
|
42158
41992
|
recovery: {
|
|
42159
41993
|
actions: [
|
|
42160
41994
|
createTaskAuthorityFileRecoveryAction({
|
|
@@ -42164,20 +41998,28 @@ async function reframeV3Workflow(input) {
|
|
|
42164
41998
|
beforeContent: serializeTaskAuthority(context.task.metadata),
|
|
42165
41999
|
targetContent: serializeTaskAuthority(pendingMetadata)
|
|
42166
42000
|
}),
|
|
42167
|
-
|
|
42168
|
-
|
|
42169
|
-
|
|
42170
|
-
|
|
42171
|
-
|
|
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,
|
|
42172
42010
|
claim
|
|
42173
42011
|
})
|
|
42174
42012
|
),
|
|
42175
|
-
|
|
42176
|
-
|
|
42177
|
-
|
|
42178
|
-
|
|
42179
|
-
|
|
42180
|
-
|
|
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
|
+
});
|
|
42181
42023
|
}),
|
|
42182
42024
|
createTaskAuthorityFileRecoveryAction({
|
|
42183
42025
|
stepId: "mark-review-verification-stale",
|
|
@@ -42193,29 +42035,34 @@ async function reframeV3Workflow(input) {
|
|
|
42193
42035
|
beforeContent: serializeTaskAuthority(context.task.verification),
|
|
42194
42036
|
targetContent: serializeTaskAuthority(verification)
|
|
42195
42037
|
}),
|
|
42196
|
-
createCheckpointRecoveryAction({
|
|
42197
|
-
stepId: "write-reframe-checkpoint",
|
|
42198
|
-
before: null,
|
|
42199
|
-
checkpoint
|
|
42200
|
-
}),
|
|
42201
42038
|
createTaskAuthorityFileRecoveryAction({
|
|
42202
|
-
stepId: "
|
|
42039
|
+
stepId: "update-metadata-scope",
|
|
42203
42040
|
taskRef,
|
|
42204
42041
|
fileName: "metadata.json",
|
|
42205
42042
|
beforeContent: serializeTaskAuthority(pendingMetadata),
|
|
42206
42043
|
targetContent: serializeTaskAuthority(metadata)
|
|
42207
42044
|
}),
|
|
42208
|
-
...
|
|
42209
|
-
|
|
42210
|
-
|
|
42211
|
-
|
|
42212
|
-
|
|
42213
|
-
|
|
42214
|
-
|
|
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
|
+
})
|
|
42215
42061
|
],
|
|
42216
42062
|
noOpStepIds: [
|
|
42217
|
-
...
|
|
42218
|
-
...
|
|
42063
|
+
...pendingSuccessorClaims.length === 0 ? ["create-pending-successor-claims"] : [],
|
|
42064
|
+
...terminatedClaims.length === 0 ? ["terminate-old-claims"] : [],
|
|
42065
|
+
...activeSuccessorClaims.length === 0 ? ["activate-successor-claims"] : []
|
|
42219
42066
|
]
|
|
42220
42067
|
}
|
|
42221
42068
|
});
|
|
@@ -42226,36 +42073,986 @@ async function reframeV3Workflow(input) {
|
|
|
42226
42073
|
"mark-task-operation-pending",
|
|
42227
42074
|
false
|
|
42228
42075
|
);
|
|
42229
|
-
await
|
|
42076
|
+
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
42230
42077
|
await writeTaskAuthorityFile(
|
|
42231
42078
|
context,
|
|
42232
42079
|
"metadata.json",
|
|
42233
|
-
|
|
42080
|
+
`${JSON.stringify(pendingMetadata, null, 2)}
|
|
42081
|
+
`
|
|
42234
42082
|
);
|
|
42235
42083
|
journal = await advanceTaskOperation(
|
|
42236
42084
|
context,
|
|
42237
42085
|
journal,
|
|
42238
|
-
"
|
|
42086
|
+
"write-scope-changed-checkpoint",
|
|
42239
42087
|
false
|
|
42240
42088
|
);
|
|
42241
|
-
await
|
|
42242
|
-
await
|
|
42089
|
+
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
42090
|
+
await writeTaskCheckpoint(context, checkpoint);
|
|
42243
42091
|
journal = await advanceTaskOperation(
|
|
42244
42092
|
context,
|
|
42245
42093
|
journal,
|
|
42246
|
-
"
|
|
42094
|
+
"create-pending-successor-claims",
|
|
42247
42095
|
false
|
|
42248
42096
|
);
|
|
42249
|
-
await
|
|
42250
|
-
for (const
|
|
42097
|
+
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
42098
|
+
for (const claim of pendingSuccessorClaims) {
|
|
42099
|
+
await createClaim(context.homeStore, claim);
|
|
42100
|
+
}
|
|
42101
|
+
journal = await advanceTaskOperation(
|
|
42102
|
+
context,
|
|
42103
|
+
journal,
|
|
42104
|
+
"terminate-old-claims",
|
|
42105
|
+
false
|
|
42106
|
+
);
|
|
42107
|
+
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
42108
|
+
for (const [index, claim] of terminatedClaims.entries()) {
|
|
42251
42109
|
const previous = activeClaims2[index];
|
|
42252
|
-
if (previous === void 0)
|
|
42110
|
+
if (previous === void 0) {
|
|
42111
|
+
throw new Error("MANCODE_CLAIM_SET_CHANGED");
|
|
42112
|
+
}
|
|
42253
42113
|
await updateClaim(context.homeStore, claim, previous.revision);
|
|
42254
42114
|
}
|
|
42255
42115
|
journal = await advanceTaskOperation(
|
|
42256
42116
|
context,
|
|
42257
42117
|
journal,
|
|
42258
|
-
"
|
|
42118
|
+
"mark-review-verification-stale",
|
|
42119
|
+
false
|
|
42120
|
+
);
|
|
42121
|
+
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
42122
|
+
await writeTaskAuthorityFile(
|
|
42123
|
+
context,
|
|
42124
|
+
"review-ledger.json",
|
|
42125
|
+
`${JSON.stringify(review, null, 2)}
|
|
42126
|
+
`
|
|
42127
|
+
);
|
|
42128
|
+
await writeTaskAuthorityFile(
|
|
42129
|
+
context,
|
|
42130
|
+
"verification-ledger.json",
|
|
42131
|
+
`${JSON.stringify(verification, null, 2)}
|
|
42132
|
+
`
|
|
42133
|
+
);
|
|
42134
|
+
journal = await advanceTaskOperation(
|
|
42135
|
+
context,
|
|
42136
|
+
journal,
|
|
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",
|
|
42259
43056
|
false
|
|
42260
43057
|
);
|
|
42261
43058
|
await assertReframeCodeHeadUnchanged(context);
|
|
@@ -42612,6 +43409,9 @@ async function writeV3Requirements(input, action) {
|
|
|
42612
43409
|
if (action === "finalize" && submitted.status !== "confirmed") {
|
|
42613
43410
|
throw new Error("MANCODE_REQUIREMENTS_CONFIRMATION_REQUIRED");
|
|
42614
43411
|
}
|
|
43412
|
+
if (action === "finalize") {
|
|
43413
|
+
assertRequirementsScopeConsistent(submitted);
|
|
43414
|
+
}
|
|
42615
43415
|
if (action === "draft" && submitted.status !== "draft") {
|
|
42616
43416
|
throw new Error("MANCODE_REQUIREMENTS_DRAFT_REQUIRED");
|
|
42617
43417
|
}
|
|
@@ -42884,454 +43684,95 @@ async function applyV3ReviewLedger(input) {
|
|
|
42884
43684
|
journal = await createTaskOperationJournal(context, {
|
|
42885
43685
|
type: "review_remediation",
|
|
42886
43686
|
action: authorization.action,
|
|
42887
|
-
evidence: authorization.evidence,
|
|
42888
|
-
conditions: authorization.conditions,
|
|
42889
|
-
expectedRevisions: taskMutationExpectedRevisions(context, [
|
|
42890
|
-
"review",
|
|
42891
|
-
"verification"
|
|
42892
|
-
]),
|
|
42893
|
-
recovery: {
|
|
42894
|
-
actions: [
|
|
42895
|
-
createTaskAuthorityFileRecoveryAction({
|
|
42896
|
-
stepId: "write-review-ledger",
|
|
42897
|
-
taskRef,
|
|
42898
|
-
fileName: "review-ledger.json",
|
|
42899
|
-
beforeContent: serializeTaskAuthority(context.task.review),
|
|
42900
|
-
targetContent: serializeTaskAuthority(review)
|
|
42901
|
-
}),
|
|
42902
|
-
createTaskAuthorityFileRecoveryAction({
|
|
42903
|
-
stepId: "mark-verification-stale",
|
|
42904
|
-
taskRef,
|
|
42905
|
-
fileName: "verification-ledger.json",
|
|
42906
|
-
beforeContent: serializeTaskAuthority(context.task.verification),
|
|
42907
|
-
targetContent: serializeTaskAuthority(verification)
|
|
42908
|
-
}),
|
|
42909
|
-
createTaskAuthorityFileRecoveryAction({
|
|
42910
|
-
stepId: "update-metadata",
|
|
42911
|
-
taskRef,
|
|
42912
|
-
fileName: "metadata.json",
|
|
42913
|
-
beforeContent: serializeTaskAuthority(context.task.metadata),
|
|
42914
|
-
targetContent: serializeTaskAuthority(metadata)
|
|
42915
|
-
}),
|
|
42916
|
-
...taskHeadFence === null ? [] : [
|
|
42917
|
-
createTaskHeadFenceRecoveryAction({
|
|
42918
|
-
stepId: "update-task-head-fence",
|
|
42919
|
-
before: context.coordination.taskHeadFence,
|
|
42920
|
-
fence: taskHeadFence
|
|
42921
|
-
})
|
|
42922
|
-
]
|
|
42923
|
-
],
|
|
42924
|
-
noOpStepIds: taskHeadFence === null ? ["update-task-head-fence"] : []
|
|
42925
|
-
}
|
|
42926
|
-
});
|
|
42927
|
-
journal = await advanceTaskOperation(context, journal, "validate", true);
|
|
42928
|
-
journal = await advanceTaskOperation(
|
|
42929
|
-
context,
|
|
42930
|
-
journal,
|
|
42931
|
-
"write-review-ledger",
|
|
42932
|
-
false
|
|
42933
|
-
);
|
|
42934
|
-
await writeTaskAuthorityFile(
|
|
42935
|
-
context,
|
|
42936
|
-
"review-ledger.json",
|
|
42937
|
-
serializeTaskAuthority(review)
|
|
42938
|
-
);
|
|
42939
|
-
journal = await advanceTaskOperation(
|
|
42940
|
-
context,
|
|
42941
|
-
journal,
|
|
42942
|
-
"mark-verification-stale",
|
|
42943
|
-
false
|
|
42944
|
-
);
|
|
42945
|
-
await writeTaskAuthorityFile(
|
|
42946
|
-
context,
|
|
42947
|
-
"verification-ledger.json",
|
|
42948
|
-
serializeTaskAuthority(verification)
|
|
42949
|
-
);
|
|
42950
|
-
journal = await advanceTaskOperation(
|
|
42951
|
-
context,
|
|
42952
|
-
journal,
|
|
42953
|
-
"update-metadata",
|
|
42954
|
-
false
|
|
42955
|
-
);
|
|
42956
|
-
await writeTaskAuthorityFile(
|
|
42957
|
-
context,
|
|
42958
|
-
"metadata.json",
|
|
42959
|
-
serializeTaskAuthority(metadata)
|
|
42960
|
-
);
|
|
42961
|
-
journal = await advanceTaskOperation(
|
|
42962
|
-
context,
|
|
42963
|
-
journal,
|
|
42964
|
-
"update-task-head-fence",
|
|
42965
|
-
false
|
|
42966
|
-
);
|
|
42967
|
-
if (taskHeadFence !== null) {
|
|
42968
|
-
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
42969
|
-
await replaceTaskHeadFence(context.homeStore, taskHeadFence);
|
|
42970
|
-
}
|
|
42971
|
-
const operation = await commitTaskOperation(context, journal);
|
|
42972
|
-
return {
|
|
42973
|
-
metadata,
|
|
42974
|
-
review,
|
|
42975
|
-
verification,
|
|
42976
|
-
aggregate,
|
|
42977
|
-
taskHeadFence,
|
|
42978
|
-
operation
|
|
42979
|
-
};
|
|
42980
|
-
} catch (error) {
|
|
42981
|
-
if (journal !== null) {
|
|
42982
|
-
try {
|
|
42983
|
-
await handleTaskOperationFailure(context, journal);
|
|
42984
|
-
} catch {
|
|
42985
|
-
}
|
|
42986
|
-
}
|
|
42987
|
-
throw error;
|
|
42988
|
-
} finally {
|
|
42989
|
-
await context.release();
|
|
42990
|
-
}
|
|
42991
|
-
}
|
|
42992
|
-
function assertReviewEligible(metadata, hasPlan) {
|
|
42993
|
-
if (metadata.workflowMode !== "man" && metadata.workflowMode !== "manteam") {
|
|
42994
|
-
throw new Error("MANCODE_REVIEW_WORKFLOW_MODE_INVALID");
|
|
42995
|
-
}
|
|
42996
|
-
if (metadata.status !== "in_progress" && metadata.status !== "blocked") {
|
|
42997
|
-
throw new Error("MANCODE_REVIEW_WORKFLOW_NOT_ACTIVE");
|
|
42998
|
-
}
|
|
42999
|
-
if (metadata.currentStep < 5 || metadata.governance.planDecision !== "governed_execution" || !hasPlan) {
|
|
43000
|
-
throw new Error("MANCODE_REVIEW_PLAN_GATE_REQUIRED");
|
|
43001
|
-
}
|
|
43002
|
-
}
|
|
43003
|
-
function createCurrentReview(previous, submitted, metadata, operationId, updatedAt) {
|
|
43004
|
-
if (submitted.requirementsDigest !== metadata.governance.requirementsDigest || submitted.planVersion !== metadata.governance.planVersion) {
|
|
43005
|
-
throw new Error("MANCODE_REVIEW_CONTEXT_STALE");
|
|
43006
|
-
}
|
|
43007
|
-
const draft = {
|
|
43008
|
-
...submitted,
|
|
43009
|
-
taskRef: previous.taskRef,
|
|
43010
|
-
revision: previous.revision + 1,
|
|
43011
|
-
contentDigest: "",
|
|
43012
|
-
lastOperationId: operationId,
|
|
43013
|
-
updatedAt
|
|
43014
|
-
};
|
|
43015
|
-
const next = parseReviewLedger({
|
|
43016
|
-
...draft,
|
|
43017
|
-
contentDigest: reviewLedgerDigest(draft)
|
|
43018
|
-
});
|
|
43019
|
-
assertReviewLedgerTransition(previous, next);
|
|
43020
|
-
assertReviewLedgerAgainstContext(next, {
|
|
43021
|
-
requirementsDigest: metadata.governance.requirementsDigest,
|
|
43022
|
-
planVersion: metadata.governance.planVersion
|
|
43023
|
-
});
|
|
43024
|
-
return next;
|
|
43025
|
-
}
|
|
43026
|
-
function updateMetadata3(previous, review, verification, operationId, updatedAt) {
|
|
43027
|
-
const next = parseWorkflowMetadata({
|
|
43028
|
-
...previous,
|
|
43029
|
-
revision: previous.revision + 1,
|
|
43030
|
-
transitionState: "stable",
|
|
43031
|
-
lastOperationId: operationId,
|
|
43032
|
-
governance: {
|
|
43033
|
-
...previous.governance,
|
|
43034
|
-
reviewStatus: review.status,
|
|
43035
|
-
reviewLedgerDigest: review.contentDigest,
|
|
43036
|
-
verificationStatus: verification.status,
|
|
43037
|
-
verificationLedgerDigest: verification.contentDigest
|
|
43038
|
-
},
|
|
43039
|
-
updatedAt
|
|
43040
|
-
});
|
|
43041
|
-
assertWorkflowMetadataTransition(previous, next, "ordinary");
|
|
43042
|
-
return next;
|
|
43043
|
-
}
|
|
43044
|
-
function reviewAuthorization(context, next) {
|
|
43045
|
-
if (context.taskRef.namespace === "local") {
|
|
43046
|
-
return { action: "local_workflow_mutation" };
|
|
43047
|
-
}
|
|
43048
|
-
if (next.skip !== null) {
|
|
43049
|
-
return {
|
|
43050
|
-
action: "review_skip_or_waiver",
|
|
43051
|
-
conditions: { reviewAction: "skip", reason: next.skip.reason }
|
|
43052
|
-
};
|
|
43053
|
-
}
|
|
43054
|
-
const waivers = next.blockers.filter(
|
|
43055
|
-
(blocker) => blocker.status === "waived"
|
|
43056
|
-
);
|
|
43057
|
-
if (waivers.length > 0) {
|
|
43058
|
-
for (const blocker of waivers) {
|
|
43059
|
-
if (blocker.severity === "p0" || blocker.severity === "legacy_unknown" || blocker.waiver === null) {
|
|
43060
|
-
throw new Error("MANCODE_WAIVER_FORBIDDEN");
|
|
43061
|
-
}
|
|
43062
|
-
}
|
|
43063
|
-
const first = waivers[0];
|
|
43064
|
-
if (first?.waiver === null || first === void 0) {
|
|
43065
|
-
throw new Error("MANCODE_WAIVER_FORBIDDEN");
|
|
43066
|
-
}
|
|
43067
|
-
return {
|
|
43068
|
-
action: "review_skip_or_waiver",
|
|
43069
|
-
conditions: {
|
|
43070
|
-
reviewAction: "waiver",
|
|
43071
|
-
reviewSeverity: first.severity,
|
|
43072
|
-
reason: first.waiver.reason
|
|
43073
|
-
}
|
|
43074
|
-
};
|
|
43075
|
-
}
|
|
43076
|
-
return {
|
|
43077
|
-
action: "shared_ledger_evidence",
|
|
43078
|
-
evidence: {
|
|
43079
|
-
assignedToActor: context.task.metadata.ownerActorId === context.session.actorId,
|
|
43080
|
-
restrictsWriteToAssignedItem: true
|
|
43081
|
-
}
|
|
43082
|
-
};
|
|
43083
|
-
}
|
|
43084
|
-
|
|
43085
|
-
// src/context/scope-change.ts
|
|
43086
|
-
import { createHash as createHash11 } from "crypto";
|
|
43087
|
-
async function changeV3WorkflowScope(input) {
|
|
43088
|
-
const taskRef = parseTaskRefValue(input.taskRef);
|
|
43089
|
-
if (taskRef.namespace !== "shared") {
|
|
43090
|
-
throw new Error("MANCODE_SCOPE_CHANGE_REQUIRES_SHARED_TASK");
|
|
43091
|
-
}
|
|
43092
|
-
const scope = normalizeImplementationScope(input.scope);
|
|
43093
|
-
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
43094
|
-
const timestamp4 = now.toISOString();
|
|
43095
|
-
const checkpointId = input.checkpointId ?? createUlid(now.getTime());
|
|
43096
|
-
const operationId = input.operationId ?? createUlid(now.getTime());
|
|
43097
|
-
assertUlid(checkpointId, "scope change checkpointId");
|
|
43098
|
-
assertUlid(operationId, "scope change operationId");
|
|
43099
|
-
const opened = await openScopeChangeContext({
|
|
43100
|
-
projectRoot: input.projectRoot,
|
|
43101
|
-
taskRef,
|
|
43102
|
-
sessionId: input.sessionId,
|
|
43103
|
-
expectedTaskRevision: input.expectedTaskRevision,
|
|
43104
|
-
scope,
|
|
43105
|
-
checkpointId,
|
|
43106
|
-
successorClaimIds: input.successorClaimIds,
|
|
43107
|
-
operationId,
|
|
43108
|
-
now
|
|
43109
|
-
});
|
|
43110
|
-
const { context, activeClaims: activeClaims2, successorClaimIds, successorPredecessors } = opened;
|
|
43111
|
-
let journal = null;
|
|
43112
|
-
try {
|
|
43113
|
-
assertScopeChangeEligible(context, scope);
|
|
43114
|
-
assertClaimsFreshForScopeChange(context, activeClaims2);
|
|
43115
|
-
const pendingMetadata = markScopeChangeOperationPending(
|
|
43116
|
-
context.task.metadata,
|
|
43117
|
-
context.operationId,
|
|
43118
|
-
timestamp4
|
|
43119
|
-
);
|
|
43120
|
-
const branch = await readCheckoutBranch(context.projectRoot) ?? "HEAD";
|
|
43121
|
-
const checkpoint = buildScopeChangedCheckpoint(
|
|
43122
|
-
context,
|
|
43123
|
-
pendingMetadata,
|
|
43124
|
-
checkpointId,
|
|
43125
|
-
input.checkpointSummary,
|
|
43126
|
-
input.checkpointNextAction,
|
|
43127
|
-
branch,
|
|
43128
|
-
timestamp4
|
|
43129
|
-
);
|
|
43130
|
-
const metadata = completeScopeChangeMetadata(
|
|
43131
|
-
pendingMetadata,
|
|
43132
|
-
scope,
|
|
43133
|
-
checkpoint,
|
|
43134
|
-
context.operationId,
|
|
43135
|
-
timestamp4
|
|
43136
|
-
);
|
|
43137
|
-
const pendingSuccessorClaims = buildPendingSuccessorClaims2(
|
|
43138
|
-
successorPredecessors,
|
|
43139
|
-
successorClaimIds,
|
|
43140
|
-
metadata,
|
|
43141
|
-
branch,
|
|
43142
|
-
requireCodeHead3(context),
|
|
43143
|
-
context.operationId,
|
|
43144
|
-
timestamp4,
|
|
43145
|
-
capabilitiesFromProjectConfig(context.project.config)
|
|
43146
|
-
);
|
|
43147
|
-
const successorByPredecessor = new Map(
|
|
43148
|
-
successorPredecessors.map((claim, index) => {
|
|
43149
|
-
const successorClaimId = successorClaimIds[index];
|
|
43150
|
-
if (successorClaimId === void 0) {
|
|
43151
|
-
throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_COUNT_INVALID");
|
|
43152
|
-
}
|
|
43153
|
-
return [claim.claimId, successorClaimId];
|
|
43154
|
-
})
|
|
43155
|
-
);
|
|
43156
|
-
const terminatedClaims = activeClaims2.map(
|
|
43157
|
-
(claim) => terminateClaimForScopeChange(
|
|
43158
|
-
claim,
|
|
43159
|
-
successorByPredecessor.get(claim.claimId) ?? null,
|
|
43160
|
-
context.operationId,
|
|
43161
|
-
timestamp4
|
|
43162
|
-
)
|
|
43163
|
-
);
|
|
43164
|
-
const activeSuccessorClaims = pendingSuccessorClaims.map(
|
|
43165
|
-
(claim) => activateSuccessorClaim3(claim, context.operationId, timestamp4)
|
|
43166
|
-
);
|
|
43167
|
-
const aggregate = buildTaskAggregateManifest({
|
|
43168
|
-
metadata,
|
|
43169
|
-
requirements: context.task.requirements,
|
|
43170
|
-
review: context.task.review,
|
|
43171
|
-
verification: context.task.verification,
|
|
43172
|
-
planDigest: context.task.plan?.digest ?? null,
|
|
43173
|
-
latestCheckpoint: checkpoint
|
|
43174
|
-
});
|
|
43175
|
-
const taskHeadFence = nextTaskHeadFence(context, aggregate, timestamp4);
|
|
43176
|
-
if (taskHeadFence === null) {
|
|
43177
|
-
throw new Error("MANCODE_TASK_HEAD_FENCE_MISSING");
|
|
43178
|
-
}
|
|
43179
|
-
journal = await createTaskOperationJournal(context, {
|
|
43180
|
-
type: "scope_change_reclaim",
|
|
43181
|
-
action: "task_complete_scope_change_child_merge",
|
|
43182
|
-
expectedRevisions: scopeChangeExpectedRevisions(
|
|
43183
|
-
context,
|
|
43184
|
-
checkpointId,
|
|
43185
|
-
activeClaims2,
|
|
43186
|
-
successorClaimIds
|
|
43187
|
-
),
|
|
43188
|
-
conditions: { completionGateSatisfied: true },
|
|
43687
|
+
evidence: authorization.evidence,
|
|
43688
|
+
conditions: authorization.conditions,
|
|
43689
|
+
expectedRevisions: taskMutationExpectedRevisions(context, [
|
|
43690
|
+
"review",
|
|
43691
|
+
"verification"
|
|
43692
|
+
]),
|
|
43189
43693
|
recovery: {
|
|
43190
43694
|
actions: [
|
|
43191
43695
|
createTaskAuthorityFileRecoveryAction({
|
|
43192
|
-
stepId: "
|
|
43696
|
+
stepId: "write-review-ledger",
|
|
43193
43697
|
taskRef,
|
|
43194
|
-
fileName: "
|
|
43195
|
-
beforeContent: serializeTaskAuthority(context.task.
|
|
43196
|
-
targetContent: serializeTaskAuthority(
|
|
43197
|
-
}),
|
|
43198
|
-
createCheckpointRecoveryAction({
|
|
43199
|
-
stepId: "write-scope-changed-checkpoint",
|
|
43200
|
-
before: null,
|
|
43201
|
-
checkpoint
|
|
43698
|
+
fileName: "review-ledger.json",
|
|
43699
|
+
beforeContent: serializeTaskAuthority(context.task.review),
|
|
43700
|
+
targetContent: serializeTaskAuthority(review)
|
|
43202
43701
|
}),
|
|
43203
|
-
|
|
43204
|
-
|
|
43205
|
-
|
|
43206
|
-
|
|
43207
|
-
|
|
43208
|
-
|
|
43209
|
-
),
|
|
43210
|
-
...terminatedClaims.map((claim, index) => {
|
|
43211
|
-
const before = activeClaims2[index];
|
|
43212
|
-
if (before === void 0) {
|
|
43213
|
-
throw new Error("MANCODE_CLAIM_SET_CHANGED");
|
|
43214
|
-
}
|
|
43215
|
-
return createClaimRecoveryAction({
|
|
43216
|
-
stepId: "terminate-old-claims",
|
|
43217
|
-
before,
|
|
43218
|
-
claim
|
|
43219
|
-
});
|
|
43702
|
+
createTaskAuthorityFileRecoveryAction({
|
|
43703
|
+
stepId: "mark-verification-stale",
|
|
43704
|
+
taskRef,
|
|
43705
|
+
fileName: "verification-ledger.json",
|
|
43706
|
+
beforeContent: serializeTaskAuthority(context.task.verification),
|
|
43707
|
+
targetContent: serializeTaskAuthority(verification)
|
|
43220
43708
|
}),
|
|
43221
43709
|
createTaskAuthorityFileRecoveryAction({
|
|
43222
|
-
stepId: "update-metadata
|
|
43710
|
+
stepId: "update-metadata",
|
|
43223
43711
|
taskRef,
|
|
43224
43712
|
fileName: "metadata.json",
|
|
43225
|
-
beforeContent: serializeTaskAuthority(
|
|
43713
|
+
beforeContent: serializeTaskAuthority(context.task.metadata),
|
|
43226
43714
|
targetContent: serializeTaskAuthority(metadata)
|
|
43227
43715
|
}),
|
|
43228
|
-
...
|
|
43229
|
-
|
|
43230
|
-
|
|
43231
|
-
|
|
43232
|
-
|
|
43233
|
-
|
|
43234
|
-
|
|
43235
|
-
before,
|
|
43236
|
-
claim
|
|
43237
|
-
});
|
|
43238
|
-
}),
|
|
43239
|
-
createTaskHeadFenceRecoveryAction({
|
|
43240
|
-
stepId: "update-task-head-fence",
|
|
43241
|
-
before: context.coordination.taskHeadFence,
|
|
43242
|
-
fence: taskHeadFence
|
|
43243
|
-
})
|
|
43716
|
+
...taskHeadFence === null ? [] : [
|
|
43717
|
+
createTaskHeadFenceRecoveryAction({
|
|
43718
|
+
stepId: "update-task-head-fence",
|
|
43719
|
+
before: context.coordination.taskHeadFence,
|
|
43720
|
+
fence: taskHeadFence
|
|
43721
|
+
})
|
|
43722
|
+
]
|
|
43244
43723
|
],
|
|
43245
|
-
noOpStepIds: [
|
|
43246
|
-
...pendingSuccessorClaims.length === 0 ? ["create-pending-successor-claims"] : [],
|
|
43247
|
-
...terminatedClaims.length === 0 ? ["terminate-old-claims"] : [],
|
|
43248
|
-
...activeSuccessorClaims.length === 0 ? ["activate-successor-claims"] : []
|
|
43249
|
-
]
|
|
43724
|
+
noOpStepIds: taskHeadFence === null ? ["update-task-head-fence"] : []
|
|
43250
43725
|
}
|
|
43251
43726
|
});
|
|
43252
43727
|
journal = await advanceTaskOperation(context, journal, "validate", true);
|
|
43253
43728
|
journal = await advanceTaskOperation(
|
|
43254
43729
|
context,
|
|
43255
43730
|
journal,
|
|
43256
|
-
"
|
|
43731
|
+
"write-review-ledger",
|
|
43257
43732
|
false
|
|
43258
43733
|
);
|
|
43259
|
-
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
43260
43734
|
await writeTaskAuthorityFile(
|
|
43261
43735
|
context,
|
|
43262
|
-
"
|
|
43263
|
-
|
|
43264
|
-
`
|
|
43265
|
-
);
|
|
43266
|
-
journal = await advanceTaskOperation(
|
|
43267
|
-
context,
|
|
43268
|
-
journal,
|
|
43269
|
-
"write-scope-changed-checkpoint",
|
|
43270
|
-
false
|
|
43736
|
+
"review-ledger.json",
|
|
43737
|
+
serializeTaskAuthority(review)
|
|
43271
43738
|
);
|
|
43272
|
-
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
43273
|
-
await writeTaskCheckpoint(context, checkpoint);
|
|
43274
43739
|
journal = await advanceTaskOperation(
|
|
43275
43740
|
context,
|
|
43276
43741
|
journal,
|
|
43277
|
-
"
|
|
43742
|
+
"mark-verification-stale",
|
|
43278
43743
|
false
|
|
43279
43744
|
);
|
|
43280
|
-
await
|
|
43281
|
-
for (const claim of pendingSuccessorClaims) {
|
|
43282
|
-
await createClaim(context.homeStore, claim);
|
|
43283
|
-
}
|
|
43284
|
-
journal = await advanceTaskOperation(
|
|
43745
|
+
await writeTaskAuthorityFile(
|
|
43285
43746
|
context,
|
|
43286
|
-
|
|
43287
|
-
|
|
43288
|
-
false
|
|
43747
|
+
"verification-ledger.json",
|
|
43748
|
+
serializeTaskAuthority(verification)
|
|
43289
43749
|
);
|
|
43290
|
-
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
43291
|
-
for (const [index, claim] of terminatedClaims.entries()) {
|
|
43292
|
-
const previous = activeClaims2[index];
|
|
43293
|
-
if (previous === void 0) {
|
|
43294
|
-
throw new Error("MANCODE_CLAIM_SET_CHANGED");
|
|
43295
|
-
}
|
|
43296
|
-
await updateClaim(context.homeStore, claim, previous.revision);
|
|
43297
|
-
}
|
|
43298
43750
|
journal = await advanceTaskOperation(
|
|
43299
43751
|
context,
|
|
43300
43752
|
journal,
|
|
43301
|
-
"update-metadata
|
|
43753
|
+
"update-metadata",
|
|
43302
43754
|
false
|
|
43303
43755
|
);
|
|
43304
|
-
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
43305
43756
|
await writeTaskAuthorityFile(
|
|
43306
43757
|
context,
|
|
43307
43758
|
"metadata.json",
|
|
43308
|
-
|
|
43309
|
-
`
|
|
43310
|
-
);
|
|
43311
|
-
journal = await advanceTaskOperation(
|
|
43312
|
-
context,
|
|
43313
|
-
journal,
|
|
43314
|
-
"activate-successor-claims",
|
|
43315
|
-
false
|
|
43759
|
+
serializeTaskAuthority(metadata)
|
|
43316
43760
|
);
|
|
43317
|
-
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
43318
|
-
for (const claim of activeSuccessorClaims) {
|
|
43319
|
-
await updateClaim(context.homeStore, claim, 1);
|
|
43320
|
-
}
|
|
43321
43761
|
journal = await advanceTaskOperation(
|
|
43322
43762
|
context,
|
|
43323
43763
|
journal,
|
|
43324
43764
|
"update-task-head-fence",
|
|
43325
43765
|
false
|
|
43326
43766
|
);
|
|
43327
|
-
|
|
43328
|
-
|
|
43767
|
+
if (taskHeadFence !== null) {
|
|
43768
|
+
await assertTaskCodeHeadUnchanged(context.projectRoot, context.codeHead);
|
|
43769
|
+
await replaceTaskHeadFence(context.homeStore, taskHeadFence);
|
|
43770
|
+
}
|
|
43329
43771
|
const operation = await commitTaskOperation(context, journal);
|
|
43330
43772
|
return {
|
|
43331
43773
|
metadata,
|
|
43332
|
-
|
|
43333
|
-
|
|
43334
|
-
successorClaims: activeSuccessorClaims,
|
|
43774
|
+
review,
|
|
43775
|
+
verification,
|
|
43335
43776
|
aggregate,
|
|
43336
43777
|
taskHeadFence,
|
|
43337
43778
|
operation
|
|
@@ -43348,312 +43789,97 @@ async function changeV3WorkflowScope(input) {
|
|
|
43348
43789
|
await context.release();
|
|
43349
43790
|
}
|
|
43350
43791
|
}
|
|
43351
|
-
|
|
43352
|
-
|
|
43353
|
-
|
|
43354
|
-
const store = new V3ContextStore(input.projectRoot);
|
|
43355
|
-
const homeStore = resolveTaskEntityHomeStore(
|
|
43356
|
-
runtime.entityHomeStoreContext,
|
|
43357
|
-
input.taskRef
|
|
43358
|
-
);
|
|
43359
|
-
const preflight = await store.readCoordinationSnapshot(
|
|
43360
|
-
input.taskRef,
|
|
43361
|
-
homeStore
|
|
43362
|
-
);
|
|
43363
|
-
const preflightClaims = activeClaims(preflight.claims);
|
|
43364
|
-
const preflightSuccessors = claimsWithinScope(preflightClaims, input.scope);
|
|
43365
|
-
const preflightSuccessorIds = resolveSuccessorClaimIds2(
|
|
43366
|
-
preflightSuccessors,
|
|
43367
|
-
input.successorClaimIds,
|
|
43368
|
-
input.operationId,
|
|
43369
|
-
input.now.toISOString()
|
|
43370
|
-
);
|
|
43371
|
-
const context = await openV3TaskOperation({
|
|
43372
|
-
projectRoot: input.projectRoot,
|
|
43373
|
-
taskRef: input.taskRef,
|
|
43374
|
-
sessionId: input.sessionId,
|
|
43375
|
-
expectedTaskRevision: input.expectedTaskRevision,
|
|
43376
|
-
operationId: input.operationId,
|
|
43377
|
-
extraEntityLocks: [
|
|
43378
|
-
`checkpoint:${input.checkpointId}`,
|
|
43379
|
-
taskHeadEntityKey(input.taskRef),
|
|
43380
|
-
...preflightClaims.map((claim) => `claim:${claim.claimId}`),
|
|
43381
|
-
...preflightSuccessorIds.map((claimId) => `claim:${claimId}`)
|
|
43382
|
-
],
|
|
43383
|
-
now: input.now
|
|
43384
|
-
});
|
|
43385
|
-
const lockedClaims = activeClaims(context.coordination.claims);
|
|
43386
|
-
if (sameClaimIdSet(preflightClaims, lockedClaims)) {
|
|
43387
|
-
const successors = claimsWithinScope(lockedClaims, input.scope);
|
|
43388
|
-
const successorIds = resolveSuccessorClaimIds2(
|
|
43389
|
-
successors,
|
|
43390
|
-
input.successorClaimIds,
|
|
43391
|
-
input.operationId,
|
|
43392
|
-
input.now.toISOString()
|
|
43393
|
-
);
|
|
43394
|
-
return {
|
|
43395
|
-
context,
|
|
43396
|
-
activeClaims: lockedClaims,
|
|
43397
|
-
successorPredecessors: successors,
|
|
43398
|
-
successorClaimIds: successorIds
|
|
43399
|
-
};
|
|
43400
|
-
}
|
|
43401
|
-
await context.release();
|
|
43402
|
-
}
|
|
43403
|
-
throw new Error("MANCODE_CLAIM_SET_CHANGED");
|
|
43404
|
-
}
|
|
43405
|
-
function assertScopeChangeEligible(context, scope) {
|
|
43406
|
-
const metadata = context.task.metadata;
|
|
43407
|
-
if (context.project.config.transport.mode !== "local") {
|
|
43408
|
-
throw new Error("MANCODE_GIT_REF_TRANSPORT_NOT_IMPLEMENTED");
|
|
43409
|
-
}
|
|
43410
|
-
if (metadata.workflowMode !== "manteam") {
|
|
43411
|
-
throw new Error("MANCODE_SCOPE_CHANGE_WORKFLOW_MODE_INVALID");
|
|
43412
|
-
}
|
|
43413
|
-
if (metadata.status !== "in_progress") {
|
|
43414
|
-
throw new Error("MANCODE_SCOPE_CHANGE_WORKFLOW_NOT_ACTIVE");
|
|
43415
|
-
}
|
|
43416
|
-
if (metadata.ownerActorId !== context.session.actorId) {
|
|
43417
|
-
throw new Error("MANCODE_TASK_OWNER_REQUIRED");
|
|
43418
|
-
}
|
|
43419
|
-
if (metadata.parent !== null) {
|
|
43420
|
-
throw new Error("MANCODE_PARENT_SCOPE_INHERITANCE_REQUIRED");
|
|
43421
|
-
}
|
|
43422
|
-
if (metadata.implementationScope.digest === scope.digest) {
|
|
43423
|
-
throw new Error("MANCODE_SCOPE_CHANGE_NOOP");
|
|
43424
|
-
}
|
|
43425
|
-
}
|
|
43426
|
-
function assertClaimsFreshForScopeChange(context, claims) {
|
|
43427
|
-
const codeHead = requireCodeHead3(context);
|
|
43428
|
-
for (const claim of claims) {
|
|
43429
|
-
if (claim.authority.mode !== "local") {
|
|
43430
|
-
throw new Error("MANCODE_OPERATION_REPAIR_REQUIRED");
|
|
43431
|
-
}
|
|
43432
|
-
const validity = deriveClaimValidity(claim, {
|
|
43433
|
-
taskRef: context.taskRef,
|
|
43434
|
-
taskRevision: context.task.metadata.revision,
|
|
43435
|
-
implementationScopeDigest: context.task.metadata.implementationScope.digest,
|
|
43436
|
-
ownershipEpoch: context.task.metadata.ownershipEpoch,
|
|
43437
|
-
codeRefHead: codeHead,
|
|
43438
|
-
now: context.now,
|
|
43439
|
-
transportFreshness: "fresh"
|
|
43440
|
-
});
|
|
43441
|
-
if (validity !== "fresh") {
|
|
43442
|
-
throw new Error("MANCODE_CLAIM_REVALIDATION_REQUIRED");
|
|
43443
|
-
}
|
|
43444
|
-
}
|
|
43445
|
-
}
|
|
43446
|
-
function normalizeImplementationScope(value) {
|
|
43447
|
-
assertRecord(value, "workflow scope change");
|
|
43448
|
-
assertKnownKeys(
|
|
43449
|
-
value,
|
|
43450
|
-
["include", "exclude", "modules"],
|
|
43451
|
-
"workflow scope change"
|
|
43452
|
-
);
|
|
43453
|
-
const scope = {
|
|
43454
|
-
source: "explicit",
|
|
43455
|
-
include: normalizeScopeValues(value.include, "include", true),
|
|
43456
|
-
exclude: normalizeScopeValues(value.exclude, "exclude", true),
|
|
43457
|
-
modules: normalizeScopeValues(value.modules, "modules", false)
|
|
43458
|
-
};
|
|
43459
|
-
return { ...scope, digest: digestCanonicalJson(scope) };
|
|
43460
|
-
}
|
|
43461
|
-
function normalizeScopeValues(value, label, paths) {
|
|
43462
|
-
if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !item.trim())) {
|
|
43463
|
-
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");
|
|
43464
43795
|
}
|
|
43465
|
-
|
|
43466
|
-
|
|
43467
|
-
if (normalized.length !== values.length) {
|
|
43468
|
-
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");
|
|
43469
43798
|
}
|
|
43470
|
-
|
|
43471
|
-
|
|
43472
|
-
if (paths) assertScopePath(item);
|
|
43799
|
+
if (metadata.currentStep < 5 || metadata.governance.planDecision !== "governed_execution" || !hasPlan) {
|
|
43800
|
+
throw new Error("MANCODE_REVIEW_PLAN_GATE_REQUIRED");
|
|
43473
43801
|
}
|
|
43474
|
-
return normalized;
|
|
43475
43802
|
}
|
|
43476
|
-
function
|
|
43477
|
-
if (
|
|
43478
|
-
throw new Error("
|
|
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");
|
|
43479
43806
|
}
|
|
43480
|
-
|
|
43481
|
-
|
|
43482
|
-
|
|
43483
|
-
...previous,
|
|
43807
|
+
const draft = {
|
|
43808
|
+
...submitted,
|
|
43809
|
+
taskRef: previous.taskRef,
|
|
43484
43810
|
revision: previous.revision + 1,
|
|
43485
|
-
|
|
43811
|
+
contentDigest: "",
|
|
43486
43812
|
lastOperationId: operationId,
|
|
43487
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
|
|
43488
43823
|
});
|
|
43489
|
-
assertWorkflowMetadataTransition(previous, next, "ordinary");
|
|
43490
43824
|
return next;
|
|
43491
43825
|
}
|
|
43492
|
-
function
|
|
43826
|
+
function updateMetadata3(previous, review, verification, operationId, updatedAt) {
|
|
43493
43827
|
const next = parseWorkflowMetadata({
|
|
43494
43828
|
...previous,
|
|
43495
43829
|
revision: previous.revision + 1,
|
|
43496
43830
|
transitionState: "stable",
|
|
43497
|
-
implementationScope: scope,
|
|
43498
|
-
latestCheckpointRef: {
|
|
43499
|
-
taskRef: checkpoint.taskRef,
|
|
43500
|
-
kind: "checkpoint",
|
|
43501
|
-
artifactId: checkpoint.checkpointId
|
|
43502
|
-
},
|
|
43503
43831
|
lastOperationId: operationId,
|
|
43504
|
-
updatedAt
|
|
43505
|
-
});
|
|
43506
|
-
assertWorkflowMetadataTransition(previous, next, "ordinary");
|
|
43507
|
-
return next;
|
|
43508
|
-
}
|
|
43509
|
-
function buildScopeChangedCheckpoint(context, pendingMetadata, checkpointId, summary, nextAction, branch, timestamp4) {
|
|
43510
|
-
return parseCheckpoint({
|
|
43511
|
-
schemaVersion: 1,
|
|
43512
|
-
checkpointId,
|
|
43513
|
-
operationId: context.operationId,
|
|
43514
|
-
taskRef: context.taskRef,
|
|
43515
|
-
taskRevision: pendingMetadata.revision,
|
|
43516
|
-
ownershipEpochAtOffer: pendingMetadata.ownershipEpoch,
|
|
43517
|
-
kind: "scope_changed",
|
|
43518
|
-
git: {
|
|
43519
|
-
branch,
|
|
43520
|
-
head: requireCodeHead3(context),
|
|
43521
|
-
base: pendingMetadata.base?.head ?? null
|
|
43522
|
-
},
|
|
43523
|
-
summary: summary ?? "Changed the implementation scope and replaced affected coordination claims.",
|
|
43524
43832
|
governance: {
|
|
43525
|
-
|
|
43526
|
-
|
|
43527
|
-
reviewLedgerDigest:
|
|
43528
|
-
|
|
43529
|
-
|
|
43530
|
-
nextAction: nextAction ?? "Re-read the updated scope and continue only with the successor claim.",
|
|
43531
|
-
createdBy: {
|
|
43532
|
-
actorId: context.session.actorId,
|
|
43533
|
-
client: context.session.client
|
|
43833
|
+
...previous.governance,
|
|
43834
|
+
reviewStatus: review.status,
|
|
43835
|
+
reviewLedgerDigest: review.contentDigest,
|
|
43836
|
+
verificationStatus: verification.status,
|
|
43837
|
+
verificationLedgerDigest: verification.contentDigest
|
|
43534
43838
|
},
|
|
43535
|
-
|
|
43536
|
-
});
|
|
43537
|
-
}
|
|
43538
|
-
function buildPendingSuccessorClaims2(predecessors, successorClaimIds, metadata, branch, codeHead, operationId, timestamp4, capabilities) {
|
|
43539
|
-
return predecessors.map((previous, index) => {
|
|
43540
|
-
const claimId = successorClaimIds[index];
|
|
43541
|
-
if (claimId === void 0) {
|
|
43542
|
-
throw new Error("MANCODE_SCOPE_SUCCESSOR_CLAIM_COUNT_INVALID");
|
|
43543
|
-
}
|
|
43544
|
-
return parseClaim({
|
|
43545
|
-
...previous,
|
|
43546
|
-
claimId,
|
|
43547
|
-
authority: { mode: "local", remoteRevision: null },
|
|
43548
|
-
taskRevisionAtAcquire: metadata.revision,
|
|
43549
|
-
lastValidatedTaskRevision: metadata.revision,
|
|
43550
|
-
implementationScopeDigest: metadata.implementationScope.digest,
|
|
43551
|
-
ownershipEpochAtAcquire: metadata.ownershipEpoch,
|
|
43552
|
-
state: "pending",
|
|
43553
|
-
revision: 1,
|
|
43554
|
-
codeRefAtAcquire: { branch, head: codeHead },
|
|
43555
|
-
lastValidatedCodeRef: { branch, head: codeHead },
|
|
43556
|
-
acquisitionEnforcement: capabilities.claimAcquisition,
|
|
43557
|
-
writeGuard: capabilities.writeGuard,
|
|
43558
|
-
predecessorClaimId: previous.claimId,
|
|
43559
|
-
successorClaimId: null,
|
|
43560
|
-
lastOperationId: operationId,
|
|
43561
|
-
createdAt: timestamp4,
|
|
43562
|
-
updatedAt: timestamp4
|
|
43563
|
-
});
|
|
43564
|
-
});
|
|
43565
|
-
}
|
|
43566
|
-
function terminateClaimForScopeChange(previous, successorClaimId, operationId, timestamp4) {
|
|
43567
|
-
const next = parseClaim({
|
|
43568
|
-
...previous,
|
|
43569
|
-
state: successorClaimId === null ? "released" : "transferred",
|
|
43570
|
-
revision: previous.revision + 1,
|
|
43571
|
-
successorClaimId,
|
|
43572
|
-
lastOperationId: operationId,
|
|
43573
|
-
updatedAt: timestamp4
|
|
43574
|
-
});
|
|
43575
|
-
assertClaimTransition(previous, next);
|
|
43576
|
-
return next;
|
|
43577
|
-
}
|
|
43578
|
-
function activateSuccessorClaim3(previous, operationId, timestamp4) {
|
|
43579
|
-
const next = parseClaim({
|
|
43580
|
-
...previous,
|
|
43581
|
-
state: "active",
|
|
43582
|
-
revision: previous.revision + 1,
|
|
43583
|
-
lastOperationId: operationId,
|
|
43584
|
-
updatedAt: timestamp4
|
|
43839
|
+
updatedAt
|
|
43585
43840
|
});
|
|
43586
|
-
|
|
43841
|
+
assertWorkflowMetadataTransition(previous, next, "ordinary");
|
|
43587
43842
|
return next;
|
|
43588
43843
|
}
|
|
43589
|
-
function
|
|
43590
|
-
|
|
43591
|
-
|
|
43592
|
-
[`checkpoint:${checkpointId}`]: 0
|
|
43593
|
-
};
|
|
43594
|
-
for (const claim of predecessors) {
|
|
43595
|
-
expected[`claim:${claim.claimId}`] = claim.revision;
|
|
43844
|
+
function reviewAuthorization(context, next) {
|
|
43845
|
+
if (context.taskRef.namespace === "local") {
|
|
43846
|
+
return { action: "local_workflow_mutation" };
|
|
43596
43847
|
}
|
|
43597
|
-
|
|
43598
|
-
|
|
43848
|
+
if (next.skip !== null) {
|
|
43849
|
+
return {
|
|
43850
|
+
action: "review_skip_or_waiver",
|
|
43851
|
+
conditions: { reviewAction: "skip", reason: next.skip.reason }
|
|
43852
|
+
};
|
|
43599
43853
|
}
|
|
43600
|
-
const
|
|
43601
|
-
|
|
43602
|
-
expected[taskHeadEntityKey(context.taskRef)] = fence.fenceRevision;
|
|
43603
|
-
return expected;
|
|
43604
|
-
}
|
|
43605
|
-
function activeClaims(claims) {
|
|
43606
|
-
return claims.filter((claim) => claim.state === "active").sort((left, right) => compareUtf815(left.claimId, right.claimId));
|
|
43607
|
-
}
|
|
43608
|
-
function claimsWithinScope(claims, scope) {
|
|
43609
|
-
return claims.filter(
|
|
43610
|
-
(claim) => evaluateClaimScopeSubset(claim.scope, {
|
|
43611
|
-
source: scope.source,
|
|
43612
|
-
include: scope.include,
|
|
43613
|
-
exclude: scope.exclude,
|
|
43614
|
-
modules: scope.modules
|
|
43615
|
-
}).allowed
|
|
43616
|
-
);
|
|
43617
|
-
}
|
|
43618
|
-
function resolveSuccessorClaimIds2(predecessors, requested, operationId, timestamp4) {
|
|
43619
|
-
const ids = requested ?? predecessors.map(
|
|
43620
|
-
(claim) => scopeSuccessorClaimId(operationId, claim.claimId, timestamp4)
|
|
43854
|
+
const waivers = next.blockers.filter(
|
|
43855
|
+
(blocker) => blocker.status === "waived"
|
|
43621
43856
|
);
|
|
43622
|
-
if (
|
|
43623
|
-
|
|
43624
|
-
|
|
43625
|
-
|
|
43626
|
-
|
|
43627
|
-
for (const claimId of ids) {
|
|
43628
|
-
assertUlid(claimId, "scope successor claimId");
|
|
43629
|
-
if (predecessorIds.has(claimId) || seen.has(claimId)) {
|
|
43630
|
-
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
|
+
}
|
|
43631
43862
|
}
|
|
43632
|
-
|
|
43633
|
-
|
|
43634
|
-
|
|
43635
|
-
}
|
|
43636
|
-
|
|
43637
|
-
|
|
43638
|
-
|
|
43639
|
-
|
|
43640
|
-
|
|
43641
|
-
|
|
43642
|
-
|
|
43643
|
-
|
|
43644
|
-
return createUlid(milliseconds, entropy);
|
|
43645
|
-
}
|
|
43646
|
-
function requireCodeHead3(context) {
|
|
43647
|
-
if (context.codeHead === null) {
|
|
43648
|
-
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
|
+
};
|
|
43649
43875
|
}
|
|
43650
|
-
return
|
|
43651
|
-
|
|
43652
|
-
|
|
43653
|
-
|
|
43654
|
-
|
|
43655
|
-
|
|
43656
|
-
|
|
43876
|
+
return {
|
|
43877
|
+
action: "shared_ledger_evidence",
|
|
43878
|
+
evidence: {
|
|
43879
|
+
assignedToActor: context.task.metadata.ownerActorId === context.session.actorId,
|
|
43880
|
+
restrictsWriteToAssignedItem: true
|
|
43881
|
+
}
|
|
43882
|
+
};
|
|
43657
43883
|
}
|
|
43658
43884
|
|
|
43659
43885
|
// src/context/solo-handoff.ts
|
|
@@ -43903,6 +44129,8 @@ function assertSoloStartEligible(context) {
|
|
|
43903
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) {
|
|
43904
44130
|
throw new Error("MANCODE_SOLO_HANDOFF_NOT_ELIGIBLE");
|
|
43905
44131
|
}
|
|
44132
|
+
assertRequirementsScopeConsistent(requirements);
|
|
44133
|
+
assertExecutableImplementationScope(metadata.implementationScope);
|
|
43906
44134
|
}
|
|
43907
44135
|
function assertSoloCompletionEligible(context) {
|
|
43908
44136
|
const { metadata } = context.task;
|
|
@@ -45191,11 +45419,20 @@ function initialScope(parent, explicitScope) {
|
|
|
45191
45419
|
};
|
|
45192
45420
|
return { ...inherited, digest: digestCanonicalJson(inherited) };
|
|
45193
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
|
+
}
|
|
45194
45431
|
const explicit = {
|
|
45195
45432
|
source: "explicit",
|
|
45196
|
-
include: [...explicitScope
|
|
45197
|
-
exclude: [...explicitScope
|
|
45198
|
-
modules: [...explicitScope
|
|
45433
|
+
include: [...explicitScope.include ?? []],
|
|
45434
|
+
exclude: [...explicitScope.exclude ?? []],
|
|
45435
|
+
modules: [...explicitScope.modules ?? []]
|
|
45199
45436
|
};
|
|
45200
45437
|
return { ...explicit, digest: digestCanonicalJson(explicit) };
|
|
45201
45438
|
}
|
|
@@ -45657,10 +45894,22 @@ async function changeGitRefWorkflowScope(input) {
|
|
|
45657
45894
|
operationId,
|
|
45658
45895
|
timestamp4
|
|
45659
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
|
+
);
|
|
45660
45907
|
const metadata = scopeChangedMetadata(
|
|
45661
45908
|
pendingMetadata,
|
|
45662
45909
|
scope,
|
|
45663
45910
|
checkpointId,
|
|
45911
|
+
review.contentDigest,
|
|
45912
|
+
verification.contentDigest,
|
|
45664
45913
|
operationId,
|
|
45665
45914
|
timestamp4
|
|
45666
45915
|
);
|
|
@@ -45671,6 +45920,9 @@ async function changeGitRefWorkflowScope(input) {
|
|
|
45671
45920
|
summary: input.checkpointSummary,
|
|
45672
45921
|
nextAction: input.checkpointNextAction,
|
|
45673
45922
|
codeRef: opened.bundle.codeRef,
|
|
45923
|
+
planVersion: pendingMetadata.governance.planVersion + 1,
|
|
45924
|
+
reviewLedgerDigest: review.contentDigest,
|
|
45925
|
+
verificationLedgerDigest: verification.contentDigest,
|
|
45674
45926
|
timestamp: timestamp4
|
|
45675
45927
|
});
|
|
45676
45928
|
const finalMetadata = parseWorkflowMetadata({
|
|
@@ -45684,8 +45936,8 @@ async function changeGitRefWorkflowScope(input) {
|
|
|
45684
45936
|
const aggregate = buildTaskAggregateManifest({
|
|
45685
45937
|
metadata: finalMetadata,
|
|
45686
45938
|
requirements: opened.context.task.requirements,
|
|
45687
|
-
review
|
|
45688
|
-
verification
|
|
45939
|
+
review,
|
|
45940
|
+
verification,
|
|
45689
45941
|
planDigest: opened.context.task.plan?.digest ?? null,
|
|
45690
45942
|
latestCheckpoint: checkpoint
|
|
45691
45943
|
});
|
|
@@ -45708,6 +45960,8 @@ async function changeGitRefWorkflowScope(input) {
|
|
|
45708
45960
|
task: {
|
|
45709
45961
|
...opened.context.task,
|
|
45710
45962
|
metadata: finalMetadata,
|
|
45963
|
+
review,
|
|
45964
|
+
verification,
|
|
45711
45965
|
latestCheckpoint: checkpoint,
|
|
45712
45966
|
aggregate
|
|
45713
45967
|
},
|
|
@@ -46127,12 +46381,20 @@ function assertClaimsFresh(context, bundle, claims) {
|
|
|
46127
46381
|
}
|
|
46128
46382
|
}
|
|
46129
46383
|
}
|
|
46130
|
-
function scopeChangedMetadata(previous, scope, checkpointId, operationId, updatedAt) {
|
|
46384
|
+
function scopeChangedMetadata(previous, scope, checkpointId, reviewLedgerDigest2, verificationLedgerDigest2, operationId, updatedAt) {
|
|
46131
46385
|
const next = parseWorkflowMetadata({
|
|
46132
46386
|
...previous,
|
|
46133
46387
|
revision: previous.revision + 1,
|
|
46134
46388
|
transitionState: "stable",
|
|
46135
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
|
+
},
|
|
46136
46398
|
latestCheckpointRef: {
|
|
46137
46399
|
taskRef: previous.taskRef,
|
|
46138
46400
|
kind: "checkpoint",
|
|
@@ -46161,9 +46423,9 @@ function scopeChangedCheckpoint(input) {
|
|
|
46161
46423
|
summary: input.summary ?? "Changed the implementation scope and replaced affected coordination claims.",
|
|
46162
46424
|
governance: {
|
|
46163
46425
|
requirementsDigest: input.context.task.requirements.contentDigest,
|
|
46164
|
-
planVersion: input.
|
|
46165
|
-
reviewLedgerDigest: input.
|
|
46166
|
-
verificationLedgerDigest: input.
|
|
46426
|
+
planVersion: input.planVersion,
|
|
46427
|
+
reviewLedgerDigest: input.reviewLedgerDigest,
|
|
46428
|
+
verificationLedgerDigest: input.verificationLedgerDigest
|
|
46167
46429
|
},
|
|
46168
46430
|
nextAction: input.nextAction ?? "Re-read the updated scope and continue only with the successor claim.",
|
|
46169
46431
|
createdBy: {
|
|
@@ -47354,7 +47616,7 @@ async function workflowPlanV3(rootDir, args, options) {
|
|
|
47354
47616
|
return printV3Error(
|
|
47355
47617
|
options.json,
|
|
47356
47618
|
"MANCODE_PLAN_ARGUMENT_INVALID",
|
|
47357
|
-
"Use: workflow plan <namespace:ULID> revise --expected-revision <n> --file <path
|
|
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>.",
|
|
47358
47620
|
EXIT_INVALID_ARG3
|
|
47359
47621
|
);
|
|
47360
47622
|
}
|
|
@@ -47383,6 +47645,14 @@ async function workflowPlanV3(rootDir, args, options) {
|
|
|
47383
47645
|
EXIT_INVALID_ARG3
|
|
47384
47646
|
);
|
|
47385
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
|
+
}
|
|
47386
47656
|
try {
|
|
47387
47657
|
const project = await readV3CommandProject(rootDir);
|
|
47388
47658
|
const taskRef = parseTaskRef(task);
|
|
@@ -47399,12 +47669,17 @@ async function workflowPlanV3(rootDir, args, options) {
|
|
|
47399
47669
|
if (plan === void 0 || plan === null) {
|
|
47400
47670
|
throw new Error("MANCODE_PLAN_FILE_REQUIRED");
|
|
47401
47671
|
}
|
|
47672
|
+
const implementationScope = action === "revise" && options.scopeFile !== void 0 ? await readWorkflowJsonInputFile(
|
|
47673
|
+
project.projectRoot,
|
|
47674
|
+
options.scopeFile
|
|
47675
|
+
) : void 0;
|
|
47402
47676
|
const result2 = await reviseV3Plan({
|
|
47403
47677
|
projectRoot: project.projectRoot,
|
|
47404
47678
|
taskRef,
|
|
47405
47679
|
sessionId: session.sessionId,
|
|
47406
47680
|
expectedTaskRevision,
|
|
47407
47681
|
plan,
|
|
47682
|
+
implementationScope,
|
|
47408
47683
|
planDecision: parseV3PlanDecision(options.planDecision)
|
|
47409
47684
|
});
|
|
47410
47685
|
return printV3Result(options.json, {
|
|
@@ -47657,6 +47932,7 @@ async function workflowRequirements(rootDir, args, options) {
|
|
|
47657
47932
|
const inputPath = path69.isAbsolute(options.file) ? options.file : path69.resolve(rootDir, options.file);
|
|
47658
47933
|
const input = await readFile48(inputPath, "utf-8");
|
|
47659
47934
|
const requirements = parseRequirementsLedger2(input);
|
|
47935
|
+
assertRequirementsScopeConsistent2(requirements);
|
|
47660
47936
|
[originalJson, originalMarkdown, originalMetadata] = await Promise.all([
|
|
47661
47937
|
readOptionalText2(jsonPath),
|
|
47662
47938
|
readOptionalText2(markdownPath),
|
|
@@ -48841,6 +49117,9 @@ program.command("workflow <subcommand> [args...]").description("Manage mancode w
|
|
|
48841
49117
|
).option(
|
|
48842
49118
|
"--file <path>",
|
|
48843
49119
|
"Semantic requirements JSON, plan Markdown, or ledger input file"
|
|
49120
|
+
).option(
|
|
49121
|
+
"--scope-file <path>",
|
|
49122
|
+
"Plan implementation scope JSON {include,exclude,modules}"
|
|
48844
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) => {
|
|
48845
49124
|
const code = await workflow(process.cwd(), subcommand, args ?? [], {
|
|
48846
49125
|
...options,
|
|
@@ -49174,7 +49453,10 @@ designProgram.command("context").description("Emit bounded UI design context for
|
|
|
49174
49453
|
designProgram.command("configure").description("CAS-update the optional project design policy").requiredOption(
|
|
49175
49454
|
"--expected-revision <n>",
|
|
49176
49455
|
"Current policy revision; use 0 when absent"
|
|
49177
|
-
).option("--preset <preset>", "preserve, refine, or experimental").option("--icons <policy>", "existing-first or lucide").option(
|
|
49456
|
+
).option("--preset <preset>", "preserve, refine, or experimental").option("--icons <policy>", "existing-first or lucide").option(
|
|
49457
|
+
"--emoji <policy>",
|
|
49458
|
+
"forbid-as-interface-icon; legacy allow is normalized"
|
|
49459
|
+
).option("--motion <policy>", "minimal or purposeful").option("--browser-validation <mode>", "off, when-available, or required").option("--confirm-experimental", "Explicitly allow the experimental preset").option("--json", "Output as JSON (for scripts)").action(async (options) => {
|
|
49178
49460
|
process.exitCode = await designConfigure(process.cwd(), options);
|
|
49179
49461
|
});
|
|
49180
49462
|
designProgram.command("disable").description("Disable the project design policy without deleting it").requiredOption("--expected-revision <n>", "Current policy revision").option("--json", "Output as JSON (for scripts)").action(async (options) => {
|