mancode 0.3.4 → 0.3.6
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.md +20 -19
- package/README.zh-CN.md +19 -18
- package/dist/cli.js +236 -102
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -308,8 +308,8 @@ var HEAD_COACH_AGENT = {
|
|
|
308
308
|
- \u5C06\u5173\u952E\u51B3\u7B56\u4EA4\u7ED9\u8C03\u7528\u65B9 appendTeamDecision\uFF0C\u5E76\u66F4\u65B0 Active Plans\u3002
|
|
309
309
|
- \u5408\u5E76 worktree \u524D\u53D6\u5F97\u7528\u6237\u786E\u8BA4\uFF1B\u6E05\u7406\u4E34\u65F6\u6587\u4EF6\u3002
|
|
310
310
|
|
|
311
|
-
**/
|
|
312
|
-
- \u5F53\u771F\u5B9E\u6D4F\u89C8\u5668\u9A8C\u8BC1\u3001\u590D\u6742\u590D\u73B0\u6216\u56DE\u5F52\u9700\u8981\u4E13\u95E8\u8BCA\u65AD\u65F6\uFF0C\u901A\u8FC7 \`mancode workflow create
|
|
311
|
+
**/manba \u4EA4\u63A5\u9636\u6BB5**\uFF1A
|
|
312
|
+
- \u5F53\u771F\u5B9E\u6D4F\u89C8\u5668\u9A8C\u8BC1\u3001\u590D\u6742\u590D\u73B0\u6216\u56DE\u5F52\u9700\u8981\u4E13\u95E8\u8BCA\u65AD\u65F6\uFF0C\u901A\u8FC7 \`mancode workflow create manba ... --parent-task <taskId>\` \u521B\u5EFA\u5B50 workflow\uFF1B\u6240\u6709 metadata \u53D8\u5316\u90FD\u8D70 workflow CLI\u3002
|
|
313
313
|
- \u5B50\u4EFB\u52A1 fixed/verified/no_repro \u540E\u56DE\u5230\u7236 /man Step 6\uFF1B\u82E5\u7236\u66FE\u56E0\u8BE5\u5B50\u4EFB\u52A1 blocked\uFF0C\u5148\u7528 workflow CLI \u6062\u590D\u4E3A in_progress\u3002blocked \u6216 manual_test_required \u65F6\u8BA9\u7236 workflow \u540C\u6B65 blocked\uFF0C\u540E\u8005\u4E0D\u5F97\u81EA\u52A8\u6062\u590D\u3002
|
|
314
314
|
|
|
315
315
|
\u4E3B\u89C1\u5F3A\uFF0C\u5FC5\u8981\u65F6\u624D\u95EE\u7528\u6237\u3002\u5F00\u5E72\u3002`
|
|
@@ -531,7 +531,8 @@ if (!state) {
|
|
|
531
531
|
process.exit(0);
|
|
532
532
|
}
|
|
533
533
|
|
|
534
|
-
const
|
|
534
|
+
const storedMode = text(state.currentMode) || 'solo';
|
|
535
|
+
const mode = storedMode === 'mamba' ? 'manba' : storedMode;
|
|
535
536
|
const techStack = sanitize(state.techStack);
|
|
536
537
|
const uiLibrary = sanitize(state.uiLibrary);
|
|
537
538
|
const output = [
|
|
@@ -848,7 +849,7 @@ var MAN_SKILL = {
|
|
|
848
849
|
|
|
849
850
|
### Step 6: \u81EA\u6D4B\u3001\u8BCA\u65AD\u4E0E\u56DE\u5F52
|
|
850
851
|
|
|
851
|
-
\u8FD0\u884C\u5B9E\u9645 build/lint/typecheck/test \u548C smoke test\u3002\u76F8\u540C\u4EE3\u7801\u3001\u73AF\u5883\u3001\u547D\u4EE4\u4E0B\u76F8\u540C\u9519\u8BEF\u7B7E\u540D\u5931\u8D25\u4E24\u6B21\uFF0C\u505C\u6B62\u76F2\u8BD5\u5E76\u8BCA\u65AD\u6839\u56E0\u3002\u9700\u8981\u771F\u5B9E\u6D4F\u89C8\u5668\u3001\u590D\u6742\u590D\u73B0\u6216\u56DE\u5F52\u65F6\uFF0C\u7528 \`mancode workflow create
|
|
852
|
+
\u8FD0\u884C\u5B9E\u9645 build/lint/typecheck/test \u548C smoke test\u3002\u76F8\u540C\u4EE3\u7801\u3001\u73AF\u5883\u3001\u547D\u4EE4\u4E0B\u76F8\u540C\u9519\u8BEF\u7B7E\u540D\u5931\u8D25\u4E24\u6B21\uFF0C\u505C\u6B62\u76F2\u8BD5\u5E76\u8BCA\u65AD\u6839\u56E0\u3002\u9700\u8981\u771F\u5B9E\u6D4F\u89C8\u5668\u3001\u590D\u6742\u590D\u73B0\u6216\u56DE\u5F52\u65F6\uFF0C\u7528 \`mancode workflow create manba "<\u95EE\u9898>" --parent-task <taskId> --json\` \u521B\u5EFA\u5B50 workflow\uFF1B\u7236\u4EFB\u52A1\u4FDD\u6301 Step 6\u3002\u5B50\u4EFB\u52A1 fixed/verified/no_repro \u540E\u6062\u590D\u672C\u4EFB\u52A1\uFF1B\u82E5\u7236\u66FE\u56E0\u8BE5\u5B50\u4EFB\u52A1 blocked\uFF0C\u5148\u901A\u8FC7 \`workflow update --status in_progress\` \u6062\u590D\uFF0C\u518D\u66F4\u65B0\u81F3 Step 7\u3002blocked \u6216 manual_test_required \u4F1A\u7531 CLI \u81EA\u52A8\u963B\u585E\u7236\u4EFB\u52A1\uFF0C\u4E0D\u5F97\u624B\u6539\u7236 metadata\uFF0C\u4E5F\u4E0D\u5F97\u81EA\u52A8\u8D8A\u8FC7\u4EBA\u5DE5\u9A8C\u8BC1\u8981\u6C42\u3002
|
|
852
853
|
|
|
853
854
|
\u9A8C\u8BC1\u540E\u57FA\u4E8E**\u5B9E\u9645 diff**\u5199 \`review-scope.md\`\uFF1Abase\u3001\u6539\u52A8\u6587\u4EF6\u3001\u9700\u6C42\u3001\u5DF2\u8DD1\u9A8C\u8BC1\u3001\u786C\u98CE\u9669\u548C\u5BA1\u67E5\u6DF1\u5EA6\u3002\u9274\u6743\u3001\u652F\u4ED8\u3001\u654F\u611F\u6570\u636E\u3001\u8FC1\u79FB/\u5220\u9664\u3001\u516C\u5F00 API\u3001\u672A\u53EF\u4FE1\u8F93\u5165\u3001\u5E76\u53D1\u3001\u8DE8\u670D\u52A1\u6216\u57FA\u7840\u8BBE\u65BD\u547D\u4E2D\u4EFB\u4E00\u9879\u65F6\u7528\u5B8C\u6574\u5BA1\u67E5 \`full\`\uFF1B\u5426\u5219\u7528\u5B9A\u5411\u5BA1\u67E5 \`targeted\`\u3002\u8FD0\u884C \`mancode workflow review <taskId> init --review-depth targeted --review-domain quality\` \u6216 \`--review-depth full\`\u3002\u7528\u6237\u660E\u786E\u8DF3\u8FC7\u5BA1\u67E5\u65F6\u624D\u628A \`review\` \u5199\u5165\u7D2F\u8BA1 skippedSteps\uFF0C\u5E76\u8BB0\u5F55\u6B8B\u4F59\u98CE\u9669\u3002
|
|
854
855
|
|
|
@@ -877,15 +878,15 @@ ${CORE_CODING_PRINCIPLES}
|
|
|
877
878
|
|
|
878
879
|
// src/templates/skills/mamba.ts
|
|
879
880
|
var MAMBA_SKILL = {
|
|
880
|
-
name: "
|
|
881
|
+
name: "manba",
|
|
881
882
|
description: "Diagnose bugs and validate real user flows. Reproduce, find the root cause, run targeted regression checks, and use browser automation when the platform supports it.",
|
|
882
|
-
body: `# mancode \xB7 /
|
|
883
|
+
body: `# mancode \xB7 /manba (Diagnosis & Real Validation)
|
|
883
884
|
|
|
884
|
-
\u7528\u6237\u7528 \`/
|
|
885
|
+
\u7528\u6237\u7528 \`/manba <\u95EE\u9898\u6216\u6A21\u5757>\` \u89E6\u53D1\u4F60\u3002\u76EE\u6807\u662F\u7528\u8BC1\u636E\u56DE\u7B54\uFF1A\u80FD\u5426\u590D\u73B0\u3001\u6839\u56E0\u5728\u54EA\u91CC\u3001\u4FEE\u590D\u662F\u5426\u6709\u6548\u3001\u5173\u952E\u8DEF\u5F84\u662F\u5426\u56DE\u5F52\u3002\u5BF9\u5916\u6A21\u5F0F\u540D\u662F manba\uFF1B\u6301\u4E45\u5316 workflow/state \u4E3A\u517C\u5BB9\u5386\u53F2\u6570\u636E\u7EE7\u7EED\u4F7F\u7528\u5185\u90E8\u503C mamba\u3002
|
|
885
886
|
|
|
886
887
|
## 1. \u5EFA\u7ACB\u4EFB\u52A1
|
|
887
888
|
|
|
888
|
-
\u5148\u8BFB state\u3002\u82E5 \`currentTask\` \u6307\u5411 unrelated active workflow\uFF0C\u505C\u6B62\u5E76\u8BA9\u7528\u6237\u9009\u62E9\u6062\u590D\u8BE5\u6D41\u7A0B\u6216\u5148\u7528 /mansolo \u653E\u5F03\uFF1B\u4E0D\u5F97\u8986\u76D6\u65E7\u6307\u9488\u3002\u72EC\u7ACB\u4EFB\u52A1\u8FD0\u884C \`mancode workflow create
|
|
889
|
+
\u5148\u8BFB state\u3002\u82E5 \`currentTask\` \u6307\u5411 unrelated active workflow\uFF0C\u505C\u6B62\u5E76\u8BA9\u7528\u6237\u9009\u62E9\u6062\u590D\u8BE5\u6D41\u7A0B\u6216\u5148\u7528 /mansolo \u653E\u5F03\uFF1B\u4E0D\u5F97\u8986\u76D6\u65E7\u6307\u9488\u3002\u72EC\u7ACB\u4EFB\u52A1\u8FD0\u884C \`mancode workflow create manba "<\u95EE\u9898\u6216\u6A21\u5757>" --json\`\uFF1B\u7531 /man \u6216 /manteam Step 6 \u8F6C\u5165\u65F6\u8FD0\u884C \`mancode workflow create manba "<\u95EE\u9898\u6216\u6A21\u5757>" --parent-task <\u7236taskId> --json\`\u3002\u8BFB\u53D6\u8FD4\u56DE taskId \u540E\uFF0C\u5C06 state \u7684 currentMode/currentTask/currentWorkflowMode \u6307\u5411\u5185\u90E8\u517C\u5BB9\u503C mamba\u3002\u4E0D\u5F97\u76F4\u63A5\u521B\u5EFA\u6216\u6539\u5199 metadata.json\u3002
|
|
889
890
|
|
|
890
891
|
\u8BB0\u5F55\u73B0\u8C61\u3001\u73AF\u5883\u3001\u590D\u73B0\u6761\u4EF6\u3001\u9884\u671F\u4E0E\u5B9E\u9645\u7ED3\u679C\u3001\u4E0D\u53EF\u89E6\u78B0\u7684\u6570\u636E\u3002\u5148\u68C0\u67E5\u5DF2\u6709\u6D4B\u8BD5\u3001\u8DEF\u7531\u3001\u6A21\u5757\u5165\u53E3\u548C README\uFF1B\u4ECD\u65E0\u6CD5\u786E\u5B9A\u6700\u5C0F\u8DEF\u5F84\u65F6\u53EA\u95EE\u5173\u952E\u8DEF\u5F84\u95EE\u9898\u3002\u5B8C\u6210\u540E\u7528 CLI \u66F4\u65B0\u81F3 Step 2\u3002
|
|
891
892
|
|
|
@@ -900,7 +901,7 @@ var MAMBA_SKILL = {
|
|
|
900
901
|
|
|
901
902
|
\u4EC5\u5F53 profile \u786E\u8BA4 Web UI \u4E14\u6D4F\u89C8\u5668\u80FD\u529B\u53EF\u7528\u65F6\uFF0C\u68C0\u67E5 \`npx\` \u5E76\u4F7F\u7528\u9879\u76EE\u7684 Playwright CLI wrapper\u3002\u5176\u4ED6\u9879\u76EE\u7C7B\u578B\u4F7F\u7528\u5DF2\u68C0\u6D4B\u5230\u7684 API\u3001\u6A21\u62DF\u5668\u3001\u8BBE\u5907\u3001\u547D\u4EE4\u6216\u5951\u7EA6\u9A8C\u8BC1\u65B9\u5F0F\u3002\u6D4F\u89C8\u5668\u9A8C\u8BC1\u65F6\u5148 snapshot \u518D\u4F7F\u7528\u5143\u7D20\u5F15\u7528\uFF1B\u5BFC\u822A\u3001\u5F39\u7A97\u6216 UI \u5927\u53D8\u5316\u540E\u91CD\u65B0 snapshot\u3002\u622A\u56FE\u3001trace \u548C\u6D4F\u89C8\u5668\u65E5\u5FD7\u5199\u5165 \`.mancode/workflows/<taskId>/artifacts/playwright/\`\uFF0C\u62A5\u544A\u53EA\u5199\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u5E76\u8131\u654F Token\u3001Cookie\u3001\u4E2A\u4EBA\u6216\u4E1A\u52A1\u654F\u611F\u6570\u636E\u3002
|
|
902
903
|
|
|
903
|
-
\u73AF\u5883\u5C31\u7EEA\u540E\u7528 CLI \u66F4\u65B0\u81F3 Step 3\uFF1B\u7F3A\u5C11\u73AF\u5883\u3001\u6743\u9650\u6216\u6570\u636E\u5219\u76F4\u63A5\u5199 blocked + blockingReason\uFF0C\u5E76\u4FDD\u7559 state \u6307\u5411\u5F53\u524D
|
|
904
|
+
\u73AF\u5883\u5C31\u7EEA\u540E\u7528 CLI \u66F4\u65B0\u81F3 Step 3\uFF1B\u7F3A\u5C11\u73AF\u5883\u3001\u6743\u9650\u6216\u6570\u636E\u5219\u76F4\u63A5\u5199 blocked + blockingReason\uFF0C\u5E76\u4FDD\u7559 state \u6307\u5411\u5F53\u524D manba \u4EE5\u4FBF\u6062\u590D\u3002
|
|
904
905
|
|
|
905
906
|
## 3. \u590D\u73B0\u4E0E\u8BCA\u65AD
|
|
906
907
|
|
|
@@ -920,7 +921,7 @@ var MAMBA_SKILL = {
|
|
|
920
921
|
- \u7F3A\u5C11\u73AF\u5883\u3001\u6743\u9650\u6216\u6570\u636E\uFF0C\u6216\u4FEE\u590D\u4ECD\u5931\u8D25\uFF1A\`status: "blocked"\` + \`blockingReason\`
|
|
921
922
|
- \u53D7\u9650\u5E73\u53F0\u53EA\u80FD\u751F\u6210\u624B\u6D4B\u65B9\u6848\uFF1A\`status: "completed", outcome: "manual_test_required"\`\uFF1B\u5FC5\u987B\u660E\u786E\u6CA1\u6709\u6267\u884C\u771F\u5B9E\u6D4B\u8BD5
|
|
922
923
|
|
|
923
|
-
\u7528 \`mancode workflow update <taskId> --status <status> [--outcome <outcome>] [--blocking-reason <\u539F\u56E0>]\` \u5199\u7ED3\u8BBA\u3002\u7236\u5B50\u4EFB\u52A1\u7684 blocked/manual_test_required \u4F20\u64AD\u7531 CLI \u8D1F\u8D23\u3002\u5173\u8054\u5B50\u4EFB\u52A1\u4EE5 fixed/verified/no_repro \u5B8C\u6210\u540E\uFF0C\u5148\u8BFB\u53D6\u7236 workflow\uFF1B\u82E5\u7236\u4ECD\u56E0\u672C\u5B50\u4EFB\u52A1 blocked\uFF0C\u8FD0\u884C \`mancode workflow update <parentTaskId> --status in_progress\` \u6E05\u9664\u963B\u585E\uFF0C\u518D\u628A state \u6062\u590D\u5230\u7236 workflow \u7684 Step 6\u3002manual_test_required \u4E0D\u5F97\u81EA\u52A8\u6062\u590D\u7236\u4EFB\u52A1\u3002\u72EC\u7ACB\u4EFB\u52A1\u5B8C\u6210\u540E\u56DE solo\uFF1Bblocked \u7684\u72EC\u7ACB\u4EFB\u52A1\u7EE7\u7EED\u4FDD\u6301
|
|
924
|
+
\u7528 \`mancode workflow update <taskId> --status <status> [--outcome <outcome>] [--blocking-reason <\u539F\u56E0>]\` \u5199\u7ED3\u8BBA\u3002\u7236\u5B50\u4EFB\u52A1\u7684 blocked/manual_test_required \u4F20\u64AD\u7531 CLI \u8D1F\u8D23\u3002\u5173\u8054\u5B50\u4EFB\u52A1\u4EE5 fixed/verified/no_repro \u5B8C\u6210\u540E\uFF0C\u5148\u8BFB\u53D6\u7236 workflow\uFF1B\u82E5\u7236\u4ECD\u56E0\u672C\u5B50\u4EFB\u52A1 blocked\uFF0C\u8FD0\u884C \`mancode workflow update <parentTaskId> --status in_progress\` \u6E05\u9664\u963B\u585E\uFF0C\u518D\u628A state \u6062\u590D\u5230\u7236 workflow \u7684 Step 6\u3002manual_test_required \u4E0D\u5F97\u81EA\u52A8\u6062\u590D\u7236\u4EFB\u52A1\u3002\u72EC\u7ACB\u4EFB\u52A1\u5B8C\u6210\u540E\u56DE solo\uFF1Bblocked \u7684\u72EC\u7ACB\u4EFB\u52A1\u7EE7\u7EED\u4FDD\u6301 manba \u6A21\u5F0F\uFF08state \u5185\u90E8\u503C\u4E3A mamba\uFF09\u3002\u4EFB\u4F55\u60C5\u51B5\u4E0B\u90FD\u4E0D\u5F97\u76F4\u63A5\u7F16\u8F91 metadata \u7ED5\u8FC7 CLI\u3002
|
|
924
925
|
|
|
925
926
|
${CORE_CODING_PRINCIPLES}
|
|
926
927
|
`
|
|
@@ -1121,8 +1122,8 @@ var MANSOLO_SKILL = {
|
|
|
1121
1122
|
|
|
1122
1123
|
- **\u6CA1\u6709 .mancode/state.json**\uFF1A\u544A\u8BC9\u7528\u6237\uFF1A"\u9879\u76EE\u672A\u521D\u59CB\u5316\uFF0C\u8FD0\u884C \`mancode init\`\u3002"
|
|
1123
1124
|
- **state.json \u5DF2\u662F solo**\uFF1A\u4ECD\u6B63\u5E38\u6267\u884C\uFF0C\u544A\u77E5\u7528\u6237\u5F53\u524D\u5DF2\u662F solo\u3002
|
|
1124
|
-
- **\u5F53\u524D task \u5DF2\u662F completed/abandoned**\uFF1A\u4E0D\u8981\u5C1D\u8BD5\u628A\u7EC8\u6001\u6539\u6210 abandoned\uFF1B\u76F4\u63A5\u6E05\u7406 state\u3002\u82E5\u5B83\u662F\u5173\u8054
|
|
1125
|
-
- **\u5F53\u524D\u5728 active /man /
|
|
1125
|
+
- **\u5F53\u524D task \u5DF2\u662F completed/abandoned**\uFF1A\u4E0D\u8981\u5C1D\u8BD5\u628A\u7EC8\u6001\u6539\u6210 abandoned\uFF1B\u76F4\u63A5\u6E05\u7406 state\u3002\u82E5\u5B83\u662F\u5173\u8054 manba \u4E14\u7236\u4EFB\u52A1\u4ECD active\uFF0C\u5148\u5C55\u793A\u7236\u4EFB\u52A1\u5E76\u6309\u4E0B\u4E00\u6761\u786E\u8BA4\u662F\u5426\u4E00\u5E76\u653E\u5F03\u3002
|
|
1126
|
+
- **\u5F53\u524D\u5728 active /man /manba /manteam \u6D41\u7A0B\u4E2D**\uFF1A\u7528 AskUserQuestion \u95EE\u7528\u6237\uFF1A
|
|
1126
1127
|
\`\`\`
|
|
1127
1128
|
AskUserQuestion({
|
|
1128
1129
|
questions: [{
|
|
@@ -1138,7 +1139,7 @@ var MANSOLO_SKILL = {
|
|
|
1138
1139
|
\`\`\`
|
|
1139
1140
|
\u7528\u6237\u786E\u8BA4\u540E\uFF1A
|
|
1140
1141
|
- \u5148\u7528 \`mancode workflow show <taskId> --json\` \u68C0\u67E5\u7236\u5B50\u5173\u7CFB\u548C activeChildren\u3002
|
|
1141
|
-
- \u82E5\u5B58\u5728\u6D3B\u8DC3\u5B50\u4EFB\u52A1\u6216\u5F53\u524D\u662F\u5E26 parentTaskId \u7684
|
|
1142
|
+
- \u82E5\u5B58\u5728\u6D3B\u8DC3\u5B50\u4EFB\u52A1\u6216\u5F53\u524D\u662F\u5E26 parentTaskId \u7684 manba\uFF0C\u660E\u786E\u8BF4\u660E\u5C06\u653E\u5F03\u7684 workflow \u94FE\uFF1B\u5148\u9010\u4E2A\u7528 CLI \u6807\u8BB0\u5B50\u4EFB\u52A1 abandoned\uFF0C\u518D\u6807\u8BB0\u7236/\u5F53\u524D\u4EFB\u52A1 abandoned\u3002
|
|
1142
1143
|
- \u6240\u6709 metadata \u72B6\u6001\u90FD\u5FC5\u987B\u901A\u8FC7 \`mancode workflow update <taskId> --status abandoned\` \u66F4\u65B0\uFF1BCLI \u62D2\u7EDD\u65F6\u505C\u6B62\uFF0C\u4E0D\u5F97\u76F4\u63A5 Edit \u7ED5\u8FC7\u3002
|
|
1143
1144
|
- \u6210\u529F\u540E\u518D\u66F4\u65B0 state.json \u5207\u56DE solo\uFF1BCLI \u4F1A\u540C\u6B65\u6E05\u7406 Active Plans\u3002
|
|
1144
1145
|
|
|
@@ -1193,12 +1194,12 @@ var MANTEAM_SKILL = {
|
|
|
1193
1194
|
3. Game Plan\uFF1A\u8BA1\u5212\u91CC\u5FC5\u987B\u5305\u542B\u53D8\u66F4\u8FB9\u754C\u3001\u517C\u5BB9\u6027\u98CE\u9669\u3001\u56DE\u6EDA\u65B9\u5F0F\uFF1BPlan Coach \u53EA\u8FD4\u56DE\u8BA1\u5212\u6587\u672C\uFF0C\u7981\u6B62\u63D0\u524D\u4FEE\u6539\u4E1A\u52A1\u6587\u4EF6\u6216\u56E2\u961F memory\u3002
|
|
1194
1195
|
4. \u8BA1\u5212\u5173\u5361\uFF1A\u7528\u6237\u53EF\u53EA\u4FDD\u7559\u8BA1\u5212\u3001\u7EE7\u7EED\u6267\u884C\u6216\u91CD\u5199\u8BA1\u5212\uFF1BActive Plans \u6309 taskId \u66F4\u65B0\u3002
|
|
1195
1196
|
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
|
|
1196
|
-
6. Self-test\uFF1A\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\u771F\u5B9E\u9A8C\u8BC1\u65F6\u521B\u5EFA\u5E26 parentTaskId \u7684 /
|
|
1197
|
+
6. Self-test\uFF1A\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\u771F\u5B9E\u9A8C\u8BC1\u65F6\u521B\u5EFA\u5E26 parentTaskId \u7684 /manba \u5B50\u4EFB\u52A1\u3002\u5B50\u4EFB\u52A1\u4FEE\u590D\u540E\u82E5\u7236\u4EFB\u52A1\u66FE\u56E0\u6B64 blocked\uFF0C\u5148\u7528 workflow CLI \u6062\u590D\u7236\u4EFB\u52A1\u4E3A in_progress\uFF1Bmanual_test_required \u4E0D\u5F97\u81EA\u52A8\u6062\u590D\u3002
|
|
1197
1198
|
7. Review scope + Film #1\uFF1A\u57FA\u4E8E\u5B9E\u9645 diff \u5199 \`review-scope.md\`\uFF0C\u7528 \`workflow review ... init\` \u9009\u62E9 targeted \u6216 full\uFF1B\u91CD\u70B9\u5BA1\u67E5\u884C\u4E3A\u3001\u53EF\u7EF4\u62A4\u6027\u3001\u56E2\u961F\u98CE\u683C\u4E0E\u6D4B\u8BD5\uFF0Cfinding \u5FC5\u987B\u6709\u8BC1\u636E\u548C\u7A33\u5B9A ID\u3002
|
|
1198
1199
|
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\u3002\u7528\u6237\u660E\u786E\u8981\u6C42\u624D\u53EF\u8DF3\u8FC7\u5168\u90E8 review\uFF0C\u5E76\u5199\u5165 \`skippedSteps\` \u548C\u6B8B\u4F59\u98CE\u9669\u3002
|
|
1199
1200
|
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
|
|
1200
1201
|
|
|
1201
|
-
\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
|
|
1202
|
+
\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
|
|
1202
1203
|
|
|
1203
1204
|
## Team Hand-off Summary
|
|
1204
1205
|
|
|
@@ -1493,6 +1494,7 @@ var LEGACY_CLAUDE_SKILL_SETTINGS = {
|
|
|
1493
1494
|
man: ".claude/skills/mancode-man.md",
|
|
1494
1495
|
mansolo: ".claude/skills/mancode-mansolo.md"
|
|
1495
1496
|
};
|
|
1497
|
+
var LEGACY_MVP2_SKILL_NAMES = ["mamba", "man8"];
|
|
1496
1498
|
async function validateClaudeCodeSettings(projectRoot) {
|
|
1497
1499
|
await readClaudeSettings(path3.join(projectRoot, ".claude"));
|
|
1498
1500
|
}
|
|
@@ -1500,6 +1502,7 @@ async function installClaudeCode(projectRoot, options) {
|
|
|
1500
1502
|
const claudeDir = path3.join(projectRoot, ".claude");
|
|
1501
1503
|
const settings = await readClaudeSettings(claudeDir);
|
|
1502
1504
|
const force = options.force ?? false;
|
|
1505
|
+
await validateClaudeWriteTargets(claudeDir, options.minimal ?? false, force);
|
|
1503
1506
|
await installMancodeCore(projectRoot);
|
|
1504
1507
|
await mkdir3(path3.join(claudeDir, "skills"), { recursive: true });
|
|
1505
1508
|
await installSoloSkill(path3.join(claudeDir, "skills"), force);
|
|
@@ -1516,6 +1519,33 @@ async function installClaudeCode(projectRoot, options) {
|
|
|
1516
1519
|
await updateClaudeSettings(claudeDir, settings);
|
|
1517
1520
|
await removeLegacyHookFiles(projectRoot);
|
|
1518
1521
|
}
|
|
1522
|
+
async function validateClaudeWriteTargets(claudeDir, minimal, force) {
|
|
1523
|
+
if (!force) return;
|
|
1524
|
+
const skillsDir = path3.join(claudeDir, "skills");
|
|
1525
|
+
await assertWritableClaudeSkill(skillsDir, "solo");
|
|
1526
|
+
if (minimal) return;
|
|
1527
|
+
for (const skill of MVP2_SKILLS) {
|
|
1528
|
+
await assertWritableClaudeSkill(skillsDir, skill.name);
|
|
1529
|
+
}
|
|
1530
|
+
for (const agent of ALL_AGENTS) {
|
|
1531
|
+
const agentPath = path3.join(claudeDir, "agents", `${agent.name}.md`);
|
|
1532
|
+
const existing = await readTextIfExists2(agentPath);
|
|
1533
|
+
if (existing !== null && !isGeneratedClaudeAgent(existing, agent.name)) {
|
|
1534
|
+
throw new Error(
|
|
1535
|
+
`refusing to overwrite user-authored Claude Code agent: ${agentPath}`
|
|
1536
|
+
);
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
async function assertWritableClaudeSkill(skillsDir, modeName) {
|
|
1541
|
+
const skillPath = path3.join(skillsDir, modeName, "SKILL.md");
|
|
1542
|
+
const existing = await readTextIfExists2(skillPath);
|
|
1543
|
+
if (existing !== null && !isGeneratedClaudeSkill(existing, modeName)) {
|
|
1544
|
+
throw new Error(
|
|
1545
|
+
`refusing to overwrite user-authored Claude Code skill: ${skillPath}`
|
|
1546
|
+
);
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1519
1549
|
async function removeLegacyHookFiles(projectRoot) {
|
|
1520
1550
|
const hooksDir = path3.join(projectRoot, ".mancode", "hooks");
|
|
1521
1551
|
await Promise.all([
|
|
@@ -1536,20 +1566,24 @@ async function installSoloSkill(skillsDir, force) {
|
|
|
1536
1566
|
await removeLegacyFlatSkill(skillsDir, "mancode-solo", "solo");
|
|
1537
1567
|
}
|
|
1538
1568
|
async function installMvp2Skills(skillsDir, force) {
|
|
1539
|
-
await removeManagedLegacyMan8Skill(skillsDir);
|
|
1540
1569
|
for (const skill of MVP2_SKILLS) {
|
|
1541
1570
|
await installProjectSkill(skillsDir, skill, force);
|
|
1542
1571
|
await removeLegacyFlatSkill(skillsDir, `mancode-${skill.name}`, skill.name);
|
|
1543
1572
|
}
|
|
1573
|
+
await removeManagedLegacyMvp2Skills(skillsDir);
|
|
1544
1574
|
}
|
|
1545
|
-
async function
|
|
1546
|
-
|
|
1575
|
+
async function removeManagedLegacyMvp2Skills(skillsDir) {
|
|
1576
|
+
for (const modeName of LEGACY_MVP2_SKILL_NAMES) {
|
|
1577
|
+
await removeGeneratedSkillDir(skillsDir, modeName);
|
|
1578
|
+
await removeLegacyFlatSkill(skillsDir, `mancode-${modeName}`, modeName);
|
|
1579
|
+
}
|
|
1547
1580
|
}
|
|
1548
1581
|
async function uninstallMvp2Skills(skillsDir) {
|
|
1549
1582
|
for (const skill of MVP2_SKILLS) {
|
|
1550
1583
|
await removeGeneratedSkillDir(skillsDir, skill.name);
|
|
1551
1584
|
await removeLegacyFlatSkill(skillsDir, `mancode-${skill.name}`, skill.name);
|
|
1552
1585
|
}
|
|
1586
|
+
await removeManagedLegacyMvp2Skills(skillsDir);
|
|
1553
1587
|
}
|
|
1554
1588
|
async function installProjectSkill(skillsDir, skill, force = true) {
|
|
1555
1589
|
const skillDir = path3.join(skillsDir, skill.name);
|
|
@@ -1615,7 +1649,7 @@ async function removeClaudeGeneratedContent(projectRoot) {
|
|
|
1615
1649
|
const skillsDir = path3.join(claudeDir, "skills");
|
|
1616
1650
|
for (const modeName of [
|
|
1617
1651
|
"solo",
|
|
1618
|
-
|
|
1652
|
+
...LEGACY_MVP2_SKILL_NAMES,
|
|
1619
1653
|
...MVP2_SKILLS.map((skill) => skill.name)
|
|
1620
1654
|
]) {
|
|
1621
1655
|
await removeGeneratedSkillDir(skillsDir, modeName);
|
|
@@ -1650,8 +1684,9 @@ ${marker}
|
|
|
1650
1684
|
async function readTextIfExists2(filePath) {
|
|
1651
1685
|
try {
|
|
1652
1686
|
return await readFile3(filePath, "utf-8");
|
|
1653
|
-
} catch {
|
|
1654
|
-
return null;
|
|
1687
|
+
} catch (error) {
|
|
1688
|
+
if (isNodeError2(error) && error.code === "ENOENT") return null;
|
|
1689
|
+
throw error;
|
|
1655
1690
|
}
|
|
1656
1691
|
}
|
|
1657
1692
|
async function removeIfEmpty(dir) {
|
|
@@ -1783,13 +1818,13 @@ import path6 from "path";
|
|
|
1783
1818
|
import { mkdir as mkdir4, readFile as readFile4, readdir as readdir2, rm as rm2, writeFile as writeFile4 } from "fs/promises";
|
|
1784
1819
|
import path4 from "path";
|
|
1785
1820
|
var MODE_NAMES = [
|
|
1786
|
-
"
|
|
1821
|
+
"manba",
|
|
1787
1822
|
"man",
|
|
1788
1823
|
"manteam",
|
|
1789
1824
|
"manps",
|
|
1790
1825
|
"mansolo"
|
|
1791
1826
|
];
|
|
1792
|
-
var LEGACY_MODE_NAMES = ["man8"];
|
|
1827
|
+
var LEGACY_MODE_NAMES = ["mamba", "man8"];
|
|
1793
1828
|
var CODEX_SKILL_MANAGED_MARKER = "<!-- Managed by mancode:codex-skill. Do not edit this file manually. -->";
|
|
1794
1829
|
var ZCODE_SKILL_MANAGED_MARKER = "<!-- Managed by mancode:zcode-skill. Do not edit this file manually. -->";
|
|
1795
1830
|
var MODE_FILE_MANAGED_MARKER = "<!-- Managed by mancode:mode-file. Do not edit this file manually. -->";
|
|
@@ -1799,7 +1834,7 @@ var MANCODE_AGENT_SKILL_MARKERS = [
|
|
|
1799
1834
|
];
|
|
1800
1835
|
function renderModeSkill(mode, commandPrefix = "$") {
|
|
1801
1836
|
const meta = MODE_META[mode];
|
|
1802
|
-
const stateMode = mode === "mansolo" ? "solo" : mode;
|
|
1837
|
+
const stateMode = mode === "mansolo" ? "solo" : mode === "manba" ? "mamba" : mode;
|
|
1803
1838
|
const modesList = MODE_NAMES.map((m) => `${commandPrefix}${m}`).join(", ");
|
|
1804
1839
|
return [
|
|
1805
1840
|
meta.intro,
|
|
@@ -1840,7 +1875,6 @@ async function installCodexSkills(projectRoot, minimal) {
|
|
|
1840
1875
|
return;
|
|
1841
1876
|
}
|
|
1842
1877
|
const skillsDir = path4.join(projectRoot, ".agents", "skills");
|
|
1843
|
-
await removeLegacyManagedSkills(skillsDir, MANCODE_AGENT_SKILL_MARKERS);
|
|
1844
1878
|
for (const mode of MODE_NAMES) {
|
|
1845
1879
|
const modeDir = path4.join(skillsDir, mode);
|
|
1846
1880
|
await mkdir4(modeDir, { recursive: true });
|
|
@@ -1864,6 +1898,7 @@ async function installCodexSkills(projectRoot, minimal) {
|
|
|
1864
1898
|
MANCODE_AGENT_SKILL_MARKERS
|
|
1865
1899
|
);
|
|
1866
1900
|
}
|
|
1901
|
+
await removeLegacyManagedSkills(skillsDir, MANCODE_AGENT_SKILL_MARKERS);
|
|
1867
1902
|
}
|
|
1868
1903
|
async function installZcodeSkills(projectRoot, minimal) {
|
|
1869
1904
|
if (minimal) {
|
|
@@ -1871,7 +1906,6 @@ async function installZcodeSkills(projectRoot, minimal) {
|
|
|
1871
1906
|
return;
|
|
1872
1907
|
}
|
|
1873
1908
|
const skillsDir = path4.join(projectRoot, ".agents", "skills");
|
|
1874
|
-
await removeLegacyManagedSkills(skillsDir, MANCODE_AGENT_SKILL_MARKERS);
|
|
1875
1909
|
for (const mode of MODE_NAMES) {
|
|
1876
1910
|
const modeDir = path4.join(skillsDir, mode);
|
|
1877
1911
|
await mkdir4(modeDir, { recursive: true });
|
|
@@ -1895,6 +1929,7 @@ async function installZcodeSkills(projectRoot, minimal) {
|
|
|
1895
1929
|
MANCODE_AGENT_SKILL_MARKERS
|
|
1896
1930
|
);
|
|
1897
1931
|
}
|
|
1932
|
+
await removeLegacyManagedSkills(skillsDir, MANCODE_AGENT_SKILL_MARKERS);
|
|
1898
1933
|
}
|
|
1899
1934
|
async function installCursorCommands(projectRoot, minimal) {
|
|
1900
1935
|
if (minimal) {
|
|
@@ -1903,7 +1938,6 @@ async function installCursorCommands(projectRoot, minimal) {
|
|
|
1903
1938
|
}
|
|
1904
1939
|
const commandsDir = path4.join(projectRoot, ".cursor", "commands");
|
|
1905
1940
|
await mkdir4(commandsDir, { recursive: true });
|
|
1906
|
-
await removeLegacyGeneratedModeFile(path4.join(commandsDir, "man8.md"));
|
|
1907
1941
|
for (const mode of MODE_NAMES) {
|
|
1908
1942
|
const meta = MODE_META[mode];
|
|
1909
1943
|
const content = [
|
|
@@ -1923,6 +1957,8 @@ async function installCursorCommands(projectRoot, minimal) {
|
|
|
1923
1957
|
"Cursor"
|
|
1924
1958
|
);
|
|
1925
1959
|
}
|
|
1960
|
+
await removeManagedModeFile(path4.join(commandsDir, "mamba.md"), "mamba");
|
|
1961
|
+
await removeLegacyGeneratedModeFile(path4.join(commandsDir, "man8.md"));
|
|
1926
1962
|
}
|
|
1927
1963
|
async function installCopilotPrompts(projectRoot, minimal) {
|
|
1928
1964
|
if (minimal) {
|
|
@@ -1931,7 +1967,6 @@ async function installCopilotPrompts(projectRoot, minimal) {
|
|
|
1931
1967
|
}
|
|
1932
1968
|
const promptsDir = path4.join(projectRoot, ".github", "prompts");
|
|
1933
1969
|
await mkdir4(promptsDir, { recursive: true });
|
|
1934
|
-
await removeLegacyGeneratedModeFile(path4.join(promptsDir, "man8.prompt.md"));
|
|
1935
1970
|
for (const mode of MODE_NAMES) {
|
|
1936
1971
|
const meta = MODE_META[mode];
|
|
1937
1972
|
const content = [
|
|
@@ -1952,6 +1987,11 @@ async function installCopilotPrompts(projectRoot, minimal) {
|
|
|
1952
1987
|
"GitHub Copilot"
|
|
1953
1988
|
);
|
|
1954
1989
|
}
|
|
1990
|
+
await removeManagedModeFile(
|
|
1991
|
+
path4.join(promptsDir, "mamba.prompt.md"),
|
|
1992
|
+
"mamba"
|
|
1993
|
+
);
|
|
1994
|
+
await removeLegacyGeneratedModeFile(path4.join(promptsDir, "man8.prompt.md"));
|
|
1955
1995
|
}
|
|
1956
1996
|
async function removeCodexSkills(projectRoot) {
|
|
1957
1997
|
if (!await platformNeedsSharedSkills(projectRoot, "zcode")) {
|
|
@@ -2090,18 +2130,22 @@ function isRecord2(value) {
|
|
|
2090
2130
|
async function readTextIfExists3(filePath) {
|
|
2091
2131
|
try {
|
|
2092
2132
|
return await readFile4(filePath, "utf-8");
|
|
2093
|
-
} catch {
|
|
2094
|
-
return null;
|
|
2133
|
+
} catch (error) {
|
|
2134
|
+
if (isNodeError3(error) && error.code === "ENOENT") return null;
|
|
2135
|
+
throw error;
|
|
2095
2136
|
}
|
|
2096
2137
|
}
|
|
2138
|
+
function isNodeError3(error) {
|
|
2139
|
+
return error instanceof Error && "code" in error;
|
|
2140
|
+
}
|
|
2097
2141
|
var MODE_META = {
|
|
2098
|
-
|
|
2142
|
+
manba: {
|
|
2099
2143
|
description: "Diagnose bugs and validate real user flows with targeted regression checks.",
|
|
2100
|
-
intro: "# mancode
|
|
2144
|
+
intro: "# mancode manba \u2014 Diagnosis and Real Validation",
|
|
2101
2145
|
workflow: [
|
|
2102
2146
|
"## Five-step workflow (simulate roles in one conversation)",
|
|
2103
2147
|
"",
|
|
2104
|
-
'Use `mancode workflow create
|
|
2148
|
+
'Use `mancode workflow create manba "<task>" --json`; when called from',
|
|
2105
2149
|
"a /man or /manteam Step 6 workflow, add `--parent-task <taskId>`. Persist the returned",
|
|
2106
2150
|
"taskId in `.mancode/state.json` as currentTask; set currentMode and",
|
|
2107
2151
|
"currentWorkflowMode to mamba. Never edit metadata.json directly; use",
|
|
@@ -2137,7 +2181,7 @@ var MODE_META = {
|
|
|
2137
2181
|
"Step 3 \u2014 Plan: write `plan.md` with scope, reuse, exclusions, risks, completion criteria, and real validation. First plan is v1; revisions use `--plan-version <current+1>` and Active Plans is updated by the CLI.",
|
|
2138
2182
|
"Step 4 \u2014 Plan gate: the user chooses plan-only (`status planned`), continue to execution, or revise the plan. Do not implement before this choice.",
|
|
2139
2183
|
"Step 5 \u2014 Implement the confirmed minimum change.",
|
|
2140
|
-
"Step 6 \u2014 Run detected build/lint/typecheck/test and smoke checks. A real or complex diagnosis creates a linked
|
|
2184
|
+
"Step 6 \u2014 Run detected build/lint/typecheck/test and smoke checks. A real or complex diagnosis creates a linked manba child while the parent remains at Step 6. After a resolved child, restore a parent blocked by that child with `workflow update --status in_progress` before Step 7; never auto-resume manual_test_required. Then write `review-scope.md` from the actual diff, verification evidence, and hard-risk triggers. Initialize a targeted review for routine governed changes or a full review for auth, payment, sensitive data, migrations/deletion, public APIs, untrusted input, concurrency, cross-service, or infrastructure changes using `mancode workflow review <taskId> init ...`.",
|
|
2141
2185
|
"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.",
|
|
2142
2186
|
"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 ends after Film #1.",
|
|
2143
2187
|
"Step 9 \u2014 If open blockers exist, fix them in one remediation round and record resolved IDs through `workflow review ... remediate`; with no blockers, do not create a remediation round. Re-run affected verification without re-running completed reviewers. Write `summary.md` and set completed only when required domains are complete and blockers are zero; otherwise set blocked+blockingReason.",
|
|
@@ -2158,9 +2202,9 @@ var MODE_META = {
|
|
|
2158
2202
|
"",
|
|
2159
2203
|
"Then execute every /man Step 1 through Step 9, including clarification,",
|
|
2160
2204
|
"plan gate, validation, bounded risk-based review, conditional completion, planVersion,",
|
|
2161
|
-
"Active Plans, and linked
|
|
2205
|
+
"Active Plans, and linked manba child behavior. Add compatibility, rollback,",
|
|
2162
2206
|
"ownership, conflict, and handoff notes at each relevant step.",
|
|
2163
|
-
"When a resolved
|
|
2207
|
+
"When a resolved manba child had blocked the parent, restore the parent through",
|
|
2164
2208
|
"`workflow update --status in_progress`; never auto-resume manual_test_required.",
|
|
2165
2209
|
"",
|
|
2166
2210
|
"Read `.mancode/memory/prd.md`, `spec.md`, and `decisions.md`; append durable",
|
|
@@ -2234,7 +2278,7 @@ function renderProjectContext(state, tokens, profile, options) {
|
|
|
2234
2278
|
const currentProfile = options.projectProfile ?? profile;
|
|
2235
2279
|
const techStack = options.projectProfile ? options.techStack.join(" + ") || "Unknown" : state?.techStack || options.techStack.join(" + ") || "Unknown";
|
|
2236
2280
|
const uiLibrary = options.projectProfile ? options.uiLibrary || "None" : state?.uiLibrary || tokens?.uiLibrary || options.uiLibrary || "None";
|
|
2237
|
-
const mode = state?.currentMode || "solo";
|
|
2281
|
+
const mode = state?.currentMode === "mamba" ? "manba" : state?.currentMode || "solo";
|
|
2238
2282
|
return [
|
|
2239
2283
|
"## mancode Project Context",
|
|
2240
2284
|
"",
|
|
@@ -2298,7 +2342,7 @@ function renderAesthetics(tokens) {
|
|
|
2298
2342
|
function renderModes(options) {
|
|
2299
2343
|
let commandLabel;
|
|
2300
2344
|
if (options.capabilities.skills === "agents-skills") {
|
|
2301
|
-
commandLabel = "Invoke mode skills with `$man`, `$
|
|
2345
|
+
commandLabel = "Invoke mode skills with `$man`, `$manba`, `$manteam`, `$manps`, `$mansolo`.";
|
|
2302
2346
|
} else if (options.capabilities.slashCommands === "native") {
|
|
2303
2347
|
commandLabel = "Use the named commands directly when available.";
|
|
2304
2348
|
} else {
|
|
@@ -2309,7 +2353,7 @@ function renderModes(options) {
|
|
|
2309
2353
|
"",
|
|
2310
2354
|
`- solo: default lightweight mode. ${commandLabel}`,
|
|
2311
2355
|
"- man: progressive governance workflow with planning and optional full execution.",
|
|
2312
|
-
"-
|
|
2356
|
+
"- manba: diagnose bugs and validate real user flows or regressions.",
|
|
2313
2357
|
"- manteam: use team memory and leave handoff-friendly summaries.",
|
|
2314
2358
|
"- manps: run project health and cleanup scans before remediation.",
|
|
2315
2359
|
"- mansolo: return to solo mode."
|
|
@@ -2371,11 +2415,15 @@ var MANCODE_CURSOR_CORE_RULE_FILES = [
|
|
|
2371
2415
|
"mancode-solo.mdc"
|
|
2372
2416
|
];
|
|
2373
2417
|
var MANCODE_CURSOR_ADVANCED_RULE_FILES = [
|
|
2374
|
-
"mancode-
|
|
2418
|
+
"mancode-manba.mdc",
|
|
2375
2419
|
"mancode-man.mdc",
|
|
2376
2420
|
"mancode-manteam.mdc",
|
|
2377
2421
|
"mancode-manps.mdc"
|
|
2378
2422
|
];
|
|
2423
|
+
var MANCODE_CURSOR_LEGACY_RULE_FILES = [
|
|
2424
|
+
"mancode-mamba.mdc",
|
|
2425
|
+
"mancode-man8.mdc"
|
|
2426
|
+
];
|
|
2379
2427
|
var CURSOR_RULE_MANAGED_MARKER = "<!-- Managed by mancode:cursor-rule. Do not edit this marker. -->";
|
|
2380
2428
|
var MANCODE_CURSOR_RULE_FILES = [
|
|
2381
2429
|
...MANCODE_CURSOR_CORE_RULE_FILES,
|
|
@@ -2427,13 +2475,12 @@ async function installCursor(projectRoot, options) {
|
|
|
2427
2475
|
await installCursorCommands(projectRoot, true);
|
|
2428
2476
|
return;
|
|
2429
2477
|
}
|
|
2430
|
-
await removeLegacyCursorRules(projectRoot);
|
|
2431
2478
|
await writeRule(
|
|
2432
2479
|
rulesDir,
|
|
2433
|
-
"mancode-
|
|
2480
|
+
"mancode-manba.mdc",
|
|
2434
2481
|
"Use for bug diagnosis and real regression testing",
|
|
2435
2482
|
false,
|
|
2436
|
-
|
|
2483
|
+
renderManbaRule()
|
|
2437
2484
|
);
|
|
2438
2485
|
await writeRule(
|
|
2439
2486
|
rulesDir,
|
|
@@ -2456,6 +2503,7 @@ async function installCursor(projectRoot, options) {
|
|
|
2456
2503
|
false,
|
|
2457
2504
|
renderManpsRule()
|
|
2458
2505
|
);
|
|
2506
|
+
await removeLegacyCursorRules(projectRoot);
|
|
2459
2507
|
await installCursorCommands(projectRoot, options.minimal ?? false);
|
|
2460
2508
|
}
|
|
2461
2509
|
async function writeRule(rulesDir, fileName, description, alwaysApply, body) {
|
|
@@ -2503,18 +2551,9 @@ async function removeCursorGeneratedRules(projectRoot) {
|
|
|
2503
2551
|
await removeLegacyCursorRules(projectRoot);
|
|
2504
2552
|
}
|
|
2505
2553
|
async function removeLegacyCursorRules(projectRoot) {
|
|
2506
|
-
const
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
"rules",
|
|
2510
|
-
"mancode-man8.mdc"
|
|
2511
|
-
);
|
|
2512
|
-
try {
|
|
2513
|
-
const content = await readFile6(legacyPath, "utf-8");
|
|
2514
|
-
if (content.includes("# mancode man8 \u2014 Investigate and Plan") && content.includes("## Mode Persistence")) {
|
|
2515
|
-
await rm3(legacyPath, { force: true });
|
|
2516
|
-
}
|
|
2517
|
-
} catch {
|
|
2554
|
+
const rulesDir = path6.join(projectRoot, ".cursor", "rules");
|
|
2555
|
+
for (const fileName of MANCODE_CURSOR_LEGACY_RULE_FILES) {
|
|
2556
|
+
await removeGeneratedCursorRule(rulesDir, fileName);
|
|
2518
2557
|
}
|
|
2519
2558
|
}
|
|
2520
2559
|
async function removeGeneratedCursorRule(rulesDir, fileName) {
|
|
@@ -2541,10 +2580,14 @@ function isGeneratedCursorRule(content, fileName) {
|
|
|
2541
2580
|
async function readTextIfExists4(filePath) {
|
|
2542
2581
|
try {
|
|
2543
2582
|
return await readFile6(filePath, "utf-8");
|
|
2544
|
-
} catch {
|
|
2545
|
-
return null;
|
|
2583
|
+
} catch (error) {
|
|
2584
|
+
if (isNodeError4(error) && error.code === "ENOENT") return null;
|
|
2585
|
+
throw error;
|
|
2546
2586
|
}
|
|
2547
2587
|
}
|
|
2588
|
+
function isNodeError4(error) {
|
|
2589
|
+
return error instanceof Error && "code" in error;
|
|
2590
|
+
}
|
|
2548
2591
|
function renderPracticeRule() {
|
|
2549
2592
|
return [
|
|
2550
2593
|
"# mancode Practice",
|
|
@@ -2575,8 +2618,8 @@ function renderSoloRule() {
|
|
|
2575
2618
|
"- Recommend /man only for auth, payment, sensitive data, migrations/deletion, public APIs, untrusted input, concurrency, or infrastructure risk."
|
|
2576
2619
|
].join("\n");
|
|
2577
2620
|
}
|
|
2578
|
-
function
|
|
2579
|
-
return renderModeSkill("
|
|
2621
|
+
function renderManbaRule() {
|
|
2622
|
+
return renderModeSkill("manba", "/");
|
|
2580
2623
|
}
|
|
2581
2624
|
function renderManRule() {
|
|
2582
2625
|
return renderModeSkill("man", "/");
|
|
@@ -2763,7 +2806,7 @@ function renderCopilotPromptConventions() {
|
|
|
2763
2806
|
"GitHub Copilot does not provide native mancode slash commands, hooks, or isolated subagents. Treat these names as user prompt conventions:",
|
|
2764
2807
|
"",
|
|
2765
2808
|
"- man: use progressive research, planning, implementation, verification, and bounded risk-based review.",
|
|
2766
|
-
"-
|
|
2809
|
+
"- manba: diagnose bugs and validate real user flows or regressions.",
|
|
2767
2810
|
"- manteam: read team memory and write handoff-friendly summaries.",
|
|
2768
2811
|
"- manps: prefer `mancode manps [area]` before cleanup.",
|
|
2769
2812
|
"- mansolo: exit any active mode and return to default solo behavior.",
|
|
@@ -2968,16 +3011,85 @@ async function detectSystemDeps(env = process3.env) {
|
|
|
2968
3011
|
}
|
|
2969
3012
|
|
|
2970
3013
|
// src/system/init-onboarding.ts
|
|
3014
|
+
import { execFileSync } from "child_process";
|
|
2971
3015
|
import { promises as fs } from "fs";
|
|
2972
3016
|
import path11 from "path";
|
|
2973
3017
|
import process4 from "process";
|
|
2974
3018
|
import { stdin, stdout } from "process";
|
|
2975
3019
|
import { createInterface } from "readline/promises";
|
|
2976
3020
|
var ALL_PLATFORMS = Object.keys(PLATFORM_INSTALLERS);
|
|
2977
|
-
|
|
3021
|
+
var cachedNativeSystemLocale;
|
|
3022
|
+
function detectInitLocale(override, environment = process4.env, systemLocale = Intl.DateTimeFormat().resolvedOptions().locale, nativeLocale) {
|
|
2978
3023
|
if (override) return parseLocale(override);
|
|
2979
|
-
const
|
|
2980
|
-
return parseLocale(
|
|
3024
|
+
const resolvedNativeLocale = nativeLocale === void 0 ? getNativeSystemLocale() : nativeLocale;
|
|
3025
|
+
return parseLocale(resolvedNativeLocale) ?? detectEnvironmentLocale(environment) ?? parseLocale(systemLocale) ?? "en";
|
|
3026
|
+
}
|
|
3027
|
+
function detectNativeSystemLocale(platform = process4.platform, runCommand = runLocaleCommand) {
|
|
3028
|
+
if (platform === "darwin") {
|
|
3029
|
+
const languages = runCommand("defaults", ["read", "-g", "AppleLanguages"]);
|
|
3030
|
+
const primaryLanguage = parsePrimaryAppleLanguage(languages);
|
|
3031
|
+
if (primaryLanguage) return primaryLanguage;
|
|
3032
|
+
return cleanLocaleOutput(
|
|
3033
|
+
runCommand("defaults", ["read", "-g", "AppleLocale"])
|
|
3034
|
+
);
|
|
3035
|
+
}
|
|
3036
|
+
if (platform === "win32") {
|
|
3037
|
+
return cleanLocaleOutput(
|
|
3038
|
+
runCommand("powershell.exe", [
|
|
3039
|
+
"-NoLogo",
|
|
3040
|
+
"-NoProfile",
|
|
3041
|
+
"-NonInteractive",
|
|
3042
|
+
"-Command",
|
|
3043
|
+
"[System.Globalization.CultureInfo]::CurrentUICulture.Name"
|
|
3044
|
+
])
|
|
3045
|
+
);
|
|
3046
|
+
}
|
|
3047
|
+
return null;
|
|
3048
|
+
}
|
|
3049
|
+
function getNativeSystemLocale() {
|
|
3050
|
+
if (cachedNativeSystemLocale === void 0) {
|
|
3051
|
+
cachedNativeSystemLocale = detectNativeSystemLocale();
|
|
3052
|
+
}
|
|
3053
|
+
return cachedNativeSystemLocale;
|
|
3054
|
+
}
|
|
3055
|
+
function detectEnvironmentLocale(environment) {
|
|
3056
|
+
const candidates = [
|
|
3057
|
+
environment.LANGUAGE,
|
|
3058
|
+
environment.LC_ALL,
|
|
3059
|
+
environment.LC_MESSAGES,
|
|
3060
|
+
environment.LANG
|
|
3061
|
+
];
|
|
3062
|
+
for (const candidate of candidates) {
|
|
3063
|
+
for (const locale of candidate?.split(":") ?? []) {
|
|
3064
|
+
const parsed = parseLocale(locale);
|
|
3065
|
+
if (parsed) return parsed;
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
3068
|
+
return null;
|
|
3069
|
+
}
|
|
3070
|
+
function runLocaleCommand(command, args) {
|
|
3071
|
+
try {
|
|
3072
|
+
const output = execFileSync(command, [...args], {
|
|
3073
|
+
encoding: "utf8",
|
|
3074
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
3075
|
+
timeout: 2e3,
|
|
3076
|
+
windowsHide: true
|
|
3077
|
+
});
|
|
3078
|
+
return cleanLocaleOutput(output);
|
|
3079
|
+
} catch {
|
|
3080
|
+
return null;
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
function parsePrimaryAppleLanguage(output) {
|
|
3084
|
+
const cleaned = cleanLocaleOutput(output);
|
|
3085
|
+
if (!cleaned) return null;
|
|
3086
|
+
const quoted = cleaned.match(/"([^"]+)"/)?.[1];
|
|
3087
|
+
if (quoted) return quoted;
|
|
3088
|
+
return cleaned.split(/[\s(),]+/).find((value) => /^[a-z]{2,3}(?:[-_][a-z0-9]+)*$/i.test(value)) ?? null;
|
|
3089
|
+
}
|
|
3090
|
+
function cleanLocaleOutput(output) {
|
|
3091
|
+
const cleaned = output?.replace(/^\uFEFF/, "").trim();
|
|
3092
|
+
return cleaned || null;
|
|
2981
3093
|
}
|
|
2982
3094
|
function parseLocale(value) {
|
|
2983
3095
|
if (!value) return null;
|
|
@@ -4333,7 +4445,9 @@ function getInitManagedFilePaths(rootDir, platforms) {
|
|
|
4333
4445
|
".mancode/hooks/user-prompt-submit.sh",
|
|
4334
4446
|
".claude/settings.json",
|
|
4335
4447
|
".claude/skills/man8/SKILL.md",
|
|
4448
|
+
".claude/skills/mamba/SKILL.md",
|
|
4336
4449
|
".claude/skills/solo/SKILL.md",
|
|
4450
|
+
".claude/skills/mancode-mamba.md",
|
|
4337
4451
|
".claude/skills/mancode-solo.md",
|
|
4338
4452
|
".claude/skills/mancode-man8.md"
|
|
4339
4453
|
);
|
|
@@ -4348,7 +4462,12 @@ function getInitManagedFilePaths(rootDir, platforms) {
|
|
|
4348
4462
|
}
|
|
4349
4463
|
}
|
|
4350
4464
|
if (platforms.includes("cursor")) {
|
|
4351
|
-
files.push(
|
|
4465
|
+
files.push(
|
|
4466
|
+
".cursor/rules/mancode-mamba.mdc",
|
|
4467
|
+
".cursor/rules/mancode-man8.mdc",
|
|
4468
|
+
".cursor/commands/mamba.md",
|
|
4469
|
+
".cursor/commands/man8.md"
|
|
4470
|
+
);
|
|
4352
4471
|
for (const fileName of MANCODE_CURSOR_RULE_FILES) {
|
|
4353
4472
|
files.push(`.cursor/rules/${fileName}`);
|
|
4354
4473
|
}
|
|
@@ -4357,19 +4476,23 @@ function getInitManagedFilePaths(rootDir, platforms) {
|
|
|
4357
4476
|
}
|
|
4358
4477
|
}
|
|
4359
4478
|
if (platforms.includes("codex") || platforms.includes("zcode")) {
|
|
4360
|
-
files.push(
|
|
4479
|
+
files.push(
|
|
4480
|
+
"AGENTS.md",
|
|
4481
|
+
".agents/skills/mamba/SKILL.md",
|
|
4482
|
+
".agents/skills/man8/SKILL.md"
|
|
4483
|
+
);
|
|
4361
4484
|
for (const mode of MODE_NAMES) {
|
|
4362
4485
|
files.push(`.agents/skills/${mode}/SKILL.md`);
|
|
4363
4486
|
}
|
|
4364
4487
|
}
|
|
4365
4488
|
if (platforms.includes("codex")) {
|
|
4366
|
-
files.push(".codex/skills/man8/SKILL.md");
|
|
4489
|
+
files.push(".codex/skills/mamba/SKILL.md", ".codex/skills/man8/SKILL.md");
|
|
4367
4490
|
for (const mode of MODE_NAMES) {
|
|
4368
4491
|
files.push(`.codex/skills/${mode}/SKILL.md`);
|
|
4369
4492
|
}
|
|
4370
4493
|
}
|
|
4371
4494
|
if (platforms.includes("zcode")) {
|
|
4372
|
-
files.push(".zcode/skills/man8/SKILL.md");
|
|
4495
|
+
files.push(".zcode/skills/mamba/SKILL.md", ".zcode/skills/man8/SKILL.md");
|
|
4373
4496
|
for (const mode of MODE_NAMES) {
|
|
4374
4497
|
files.push(`.zcode/skills/${mode}/SKILL.md`);
|
|
4375
4498
|
}
|
|
@@ -4377,6 +4500,7 @@ function getInitManagedFilePaths(rootDir, platforms) {
|
|
|
4377
4500
|
if (platforms.includes("copilot")) {
|
|
4378
4501
|
files.push(
|
|
4379
4502
|
".github/copilot-instructions.md",
|
|
4503
|
+
".github/prompts/mamba.prompt.md",
|
|
4380
4504
|
".github/prompts/man8.prompt.md"
|
|
4381
4505
|
);
|
|
4382
4506
|
for (const mode of MODE_NAMES) {
|
|
@@ -4391,7 +4515,7 @@ async function snapshotFiles(filePaths) {
|
|
|
4391
4515
|
try {
|
|
4392
4516
|
return { filePath, content: await fs3.readFile(filePath, "utf-8") };
|
|
4393
4517
|
} catch (error) {
|
|
4394
|
-
if (
|
|
4518
|
+
if (isNodeError5(error) && error.code === "ENOENT") {
|
|
4395
4519
|
return { filePath, content: null };
|
|
4396
4520
|
}
|
|
4397
4521
|
throw error;
|
|
@@ -4437,7 +4561,7 @@ async function removeNewEmptyDirectories(snapshots) {
|
|
|
4437
4561
|
function isRecord3(value) {
|
|
4438
4562
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4439
4563
|
}
|
|
4440
|
-
function
|
|
4564
|
+
function isNodeError5(error) {
|
|
4441
4565
|
return error instanceof Error && "code" in error;
|
|
4442
4566
|
}
|
|
4443
4567
|
function printPlatformCreatedFiles(platform, locale) {
|
|
@@ -4866,13 +4990,13 @@ async function readConfig(rootDir) {
|
|
|
4866
4990
|
const raw = await fs5.readFile(configPath, "utf-8");
|
|
4867
4991
|
return { config: JSON.parse(raw), valid: true };
|
|
4868
4992
|
} catch (err) {
|
|
4869
|
-
if (
|
|
4993
|
+
if (isNodeError6(err) && err.code === "ENOENT") {
|
|
4870
4994
|
return { config: {}, valid: false };
|
|
4871
4995
|
}
|
|
4872
4996
|
throw err;
|
|
4873
4997
|
}
|
|
4874
4998
|
}
|
|
4875
|
-
function
|
|
4999
|
+
function isNodeError6(err) {
|
|
4876
5000
|
return err instanceof Error && "code" in err;
|
|
4877
5001
|
}
|
|
4878
5002
|
async function updateConfig(rootDir, config) {
|
|
@@ -5680,7 +5804,7 @@ async function readIssueDatabase(issueDbPath) {
|
|
|
5680
5804
|
try {
|
|
5681
5805
|
raw = await readFile8(issueDbPath, "utf-8");
|
|
5682
5806
|
} catch (err) {
|
|
5683
|
-
if (
|
|
5807
|
+
if (isNodeError7(err) && err.code === "ENOENT") {
|
|
5684
5808
|
return emptyIssueDatabase();
|
|
5685
5809
|
}
|
|
5686
5810
|
throw err;
|
|
@@ -5891,7 +6015,7 @@ async function pathExists6(file) {
|
|
|
5891
6015
|
return false;
|
|
5892
6016
|
}
|
|
5893
6017
|
}
|
|
5894
|
-
function
|
|
6018
|
+
function isNodeError7(err) {
|
|
5895
6019
|
return err instanceof Error && "code" in err;
|
|
5896
6020
|
}
|
|
5897
6021
|
function isRecord6(value) {
|
|
@@ -6186,7 +6310,7 @@ async function ensureReplaceableFile(filePath) {
|
|
|
6186
6310
|
throw new Error(`cannot replace non-file path: ${filePath}`);
|
|
6187
6311
|
}
|
|
6188
6312
|
} catch (error) {
|
|
6189
|
-
if (
|
|
6313
|
+
if (isNodeError8(error) && error.code === "ENOENT") return;
|
|
6190
6314
|
throw error;
|
|
6191
6315
|
}
|
|
6192
6316
|
}
|
|
@@ -6203,7 +6327,7 @@ async function readOptionalText(filePath) {
|
|
|
6203
6327
|
try {
|
|
6204
6328
|
return await fs7.readFile(filePath, "utf-8");
|
|
6205
6329
|
} catch (error) {
|
|
6206
|
-
if (
|
|
6330
|
+
if (isNodeError8(error) && error.code === "ENOENT") return null;
|
|
6207
6331
|
throw error;
|
|
6208
6332
|
}
|
|
6209
6333
|
}
|
|
@@ -6266,7 +6390,7 @@ async function readRequiredState(filePath) {
|
|
|
6266
6390
|
function isRecord7(value) {
|
|
6267
6391
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6268
6392
|
}
|
|
6269
|
-
function
|
|
6393
|
+
function isNodeError8(error) {
|
|
6270
6394
|
return error instanceof Error && "code" in error;
|
|
6271
6395
|
}
|
|
6272
6396
|
async function pathExists8(filePath) {
|
|
@@ -6686,7 +6810,7 @@ async function allocateTaskId(projectRoot, baseTaskId) {
|
|
|
6686
6810
|
await mkdir9(workflowDir(projectRoot, taskId));
|
|
6687
6811
|
return taskId;
|
|
6688
6812
|
} catch (err) {
|
|
6689
|
-
if (
|
|
6813
|
+
if (isNodeError9(err) && err.code === "EEXIST") {
|
|
6690
6814
|
continue;
|
|
6691
6815
|
}
|
|
6692
6816
|
throw err;
|
|
@@ -6802,7 +6926,7 @@ function isWorkflowOutcome(value) {
|
|
|
6802
6926
|
async function validateParentTask(projectRoot, mode, parentTaskId, requireStepSix = false) {
|
|
6803
6927
|
if (!parentTaskId) return;
|
|
6804
6928
|
if (mode !== "mamba") {
|
|
6805
|
-
throw new Error("only
|
|
6929
|
+
throw new Error("only manba workflows can have a parent task");
|
|
6806
6930
|
}
|
|
6807
6931
|
const parent = await readWorkflow(projectRoot, parentTaskId);
|
|
6808
6932
|
if (!parent || parent.mode !== "man" && parent.mode !== "manteam") {
|
|
@@ -6842,14 +6966,14 @@ async function validateWorkflowMeta(projectRoot, updated, existing) {
|
|
|
6842
6966
|
);
|
|
6843
6967
|
}
|
|
6844
6968
|
if (updated.status === "planned" && updated.mode === "mamba") {
|
|
6845
|
-
throw new Error("
|
|
6969
|
+
throw new Error("manba workflows cannot be planned");
|
|
6846
6970
|
}
|
|
6847
6971
|
if (updated.status === "planned" && updated.currentStep !== 4) {
|
|
6848
6972
|
throw new Error("planned workflows must be at step 4");
|
|
6849
6973
|
}
|
|
6850
6974
|
if (updated.status === "completed" && updated.currentStep !== maxWorkflowStep(updated.mode)) {
|
|
6851
6975
|
throw new Error(
|
|
6852
|
-
`completed ${updated.mode} workflows must be at step ${maxWorkflowStep(updated.mode)}`
|
|
6976
|
+
`completed ${updated.mode === "mamba" ? "manba" : updated.mode} workflows must be at step ${maxWorkflowStep(updated.mode)}`
|
|
6853
6977
|
);
|
|
6854
6978
|
}
|
|
6855
6979
|
if (updated.blockingReason !== void 0 && typeof updated.blockingReason !== "string") {
|
|
@@ -6863,25 +6987,25 @@ async function validateWorkflowMeta(projectRoot, updated, existing) {
|
|
|
6863
6987
|
throw new Error("only blocked workflows can have a blocking reason");
|
|
6864
6988
|
}
|
|
6865
6989
|
if (updated.mode !== "mamba" && updated.outcome !== void 0) {
|
|
6866
|
-
throw new Error("only
|
|
6990
|
+
throw new Error("only manba workflows can have an outcome");
|
|
6867
6991
|
}
|
|
6868
6992
|
if (updated.outcome !== void 0 && !isWorkflowOutcome(updated.outcome)) {
|
|
6869
6993
|
throw new Error(`invalid workflow outcome: ${updated.outcome}`);
|
|
6870
6994
|
}
|
|
6871
6995
|
if (updated.outcome !== void 0 && updated.status !== "completed") {
|
|
6872
|
-
throw new Error("
|
|
6996
|
+
throw new Error("manba outcomes can only be set on completed workflows");
|
|
6873
6997
|
}
|
|
6874
6998
|
if (updated.mode === "mamba" && updated.status === "completed" && !updated.outcome) {
|
|
6875
|
-
throw new Error("completed
|
|
6999
|
+
throw new Error("completed manba workflows require an outcome");
|
|
6876
7000
|
}
|
|
6877
7001
|
if (updated.mode === "mamba" && updated.planVersion !== void 0) {
|
|
6878
|
-
throw new Error("
|
|
7002
|
+
throw new Error("manba workflows cannot have a plan version");
|
|
6879
7003
|
}
|
|
6880
7004
|
if (updated.reviewPolicyVersion !== void 0 && updated.reviewPolicyVersion !== 1) {
|
|
6881
7005
|
throw new Error("invalid workflow review policy version");
|
|
6882
7006
|
}
|
|
6883
7007
|
if (updated.mode === "mamba" && updated.reviewPolicyVersion !== void 0) {
|
|
6884
|
-
throw new Error("
|
|
7008
|
+
throw new Error("manba workflows cannot have a review policy version");
|
|
6885
7009
|
}
|
|
6886
7010
|
if (updated.planVersion !== void 0 && (!Number.isInteger(updated.planVersion) || updated.planVersion < 1)) {
|
|
6887
7011
|
throw new Error("workflow plan version must be a positive integer");
|
|
@@ -6894,7 +7018,7 @@ async function validateWorkflowMeta(projectRoot, updated, existing) {
|
|
|
6894
7018
|
}
|
|
6895
7019
|
await validateParentTask(projectRoot, updated.mode, updated.parentTaskId);
|
|
6896
7020
|
if ((isTerminalWorkflowStatus(updated.status) || updated.status === "planned") && (await listActiveMambaChildren(projectRoot, updated.taskId)).length > 0) {
|
|
6897
|
-
throw new Error("cannot finish workflow with an active
|
|
7021
|
+
throw new Error("cannot finish workflow with an active manba child");
|
|
6898
7022
|
}
|
|
6899
7023
|
if (updated.status === "completed" && updated.reviewPolicyVersion === 1 && !reviewWasExplicitlySkipped(updated) && !await reviewCanComplete(projectRoot, updated.taskId)) {
|
|
6900
7024
|
throw new Error("workflow review is incomplete or still has open blockers");
|
|
@@ -6965,7 +7089,7 @@ async function propagateChildStatus(projectRoot, child) {
|
|
|
6965
7089
|
if (!parentTaskId) return;
|
|
6966
7090
|
const parent = await readWorkflow(projectRoot, parentTaskId);
|
|
6967
7091
|
if (!parent || parent.status !== "in_progress") return;
|
|
6968
|
-
const reason = child.status === "blocked" ? `
|
|
7092
|
+
const reason = child.status === "blocked" ? `manba child ${child.taskId} is blocked: ${child.blockingReason ?? "unknown reason"}` : `manba child ${child.taskId} requires manual testing`;
|
|
6969
7093
|
await writeMetadata(workflowDir(projectRoot, parent.taskId), {
|
|
6970
7094
|
...parent,
|
|
6971
7095
|
status: "blocked",
|
|
@@ -6980,7 +7104,7 @@ async function propagateChildStatus(projectRoot, child) {
|
|
|
6980
7104
|
});
|
|
6981
7105
|
}
|
|
6982
7106
|
}
|
|
6983
|
-
function
|
|
7107
|
+
function isNodeError9(err) {
|
|
6984
7108
|
return err instanceof Error && "code" in err;
|
|
6985
7109
|
}
|
|
6986
7110
|
function assertValidTaskId2(taskId) {
|
|
@@ -7240,7 +7364,8 @@ function runHookEstimate(rootDir, hookPath) {
|
|
|
7240
7364
|
});
|
|
7241
7365
|
}
|
|
7242
7366
|
function printText(r) {
|
|
7243
|
-
const
|
|
7367
|
+
const publicMode = r.mode === "mamba" ? "manba" : r.mode;
|
|
7368
|
+
const modeLabel = publicMode === "solo" ? `${publicMode} (default)` : publicMode;
|
|
7244
7369
|
console.log("");
|
|
7245
7370
|
console.log(`mancode v${r.version}`);
|
|
7246
7371
|
console.log("");
|
|
@@ -7617,7 +7742,7 @@ async function workflow(rootDir, subcommand, args = [], options = {}) {
|
|
|
7617
7742
|
} else {
|
|
7618
7743
|
console.error(`\u2717 Invalid workflow subcommand: ${subcommand}`);
|
|
7619
7744
|
console.error(
|
|
7620
|
-
" Use: create <man|
|
|
7745
|
+
" Use: create <man|manba|manteam> <task> | update <taskId> | review <taskId> <init|complete|remediate|show> | list | show <taskId> | clean"
|
|
7621
7746
|
);
|
|
7622
7747
|
}
|
|
7623
7748
|
return EXIT_INVALID_ARG2;
|
|
@@ -7721,20 +7846,21 @@ function parseCsv(value) {
|
|
|
7721
7846
|
return (value ?? "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
7722
7847
|
}
|
|
7723
7848
|
async function workflowCreate(rootDir, args, options) {
|
|
7724
|
-
const
|
|
7849
|
+
const requestedMode = args[0];
|
|
7850
|
+
const mode = parsePublicWorkflowMode(requestedMode);
|
|
7725
7851
|
const task = args.slice(1).join(" ").trim();
|
|
7726
|
-
if (mode
|
|
7852
|
+
if (!mode) {
|
|
7727
7853
|
return invalidArg(
|
|
7728
7854
|
options,
|
|
7729
|
-
`invalid workflow mode: ${
|
|
7730
|
-
"Use: mancode workflow create <man|
|
|
7855
|
+
`invalid workflow mode: ${requestedMode ?? ""}`,
|
|
7856
|
+
"Use: mancode workflow create <man|manba|manteam> <task> [--parent-task <taskId>]"
|
|
7731
7857
|
);
|
|
7732
7858
|
}
|
|
7733
7859
|
if (!task) {
|
|
7734
7860
|
return invalidArg(
|
|
7735
7861
|
options,
|
|
7736
7862
|
"missing workflow task",
|
|
7737
|
-
"Use: mancode workflow create <man|
|
|
7863
|
+
"Use: mancode workflow create <man|manba|manteam> <task> [--parent-task <taskId>]"
|
|
7738
7864
|
);
|
|
7739
7865
|
}
|
|
7740
7866
|
try {
|
|
@@ -7804,7 +7930,7 @@ async function workflowUpdate(rootDir, taskId, options) {
|
|
|
7804
7930
|
if (existing.mode !== "mamba" || nextStatus !== "completed") {
|
|
7805
7931
|
return invalidArg(
|
|
7806
7932
|
options,
|
|
7807
|
-
"--outcome is only valid when completing a
|
|
7933
|
+
"--outcome is only valid when completing a manba workflow"
|
|
7808
7934
|
);
|
|
7809
7935
|
}
|
|
7810
7936
|
patch.outcome = options.outcome;
|
|
@@ -7912,7 +8038,7 @@ async function workflowShow(rootDir, taskId, options) {
|
|
|
7912
8038
|
}
|
|
7913
8039
|
console.log(`Workflow: ${meta.taskId}`);
|
|
7914
8040
|
console.log(`Task: ${meta.task}`);
|
|
7915
|
-
console.log(`Mode: ${meta.mode}`);
|
|
8041
|
+
console.log(`Mode: ${formatPublicWorkflowMode(meta.mode)}`);
|
|
7916
8042
|
console.log(`Status: ${meta.status}`);
|
|
7917
8043
|
console.log(`Current step:${meta.currentStep}/${maxWorkflowStep(meta.mode)}`);
|
|
7918
8044
|
console.log(
|
|
@@ -7927,7 +8053,7 @@ async function workflowShow(rootDir, taskId, options) {
|
|
|
7927
8053
|
if (meta.blockingReason) console.log(`Blocked: ${meta.blockingReason}`);
|
|
7928
8054
|
if (children !== void 0) {
|
|
7929
8055
|
if (children.length > 0) {
|
|
7930
|
-
console.log(`Children: ${children.length} active
|
|
8056
|
+
console.log(`Children: ${children.length} active manba workflow(s)`);
|
|
7931
8057
|
for (const child of children) {
|
|
7932
8058
|
console.log(
|
|
7933
8059
|
` - ${child.taskId} (Step ${child.currentStep}/5, ${child.status})`
|
|
@@ -8015,7 +8141,15 @@ function formatWorkflowRow(meta) {
|
|
|
8015
8141
|
meta.blockingReason ? `blocked=${meta.blockingReason}` : "",
|
|
8016
8142
|
meta.activeChildren && meta.activeChildren.length > 0 ? `children=${meta.activeChildren.map((child) => child.taskId).join(",")}` : ""
|
|
8017
8143
|
].filter(Boolean);
|
|
8018
|
-
return `${meta.taskId.padEnd(42)} ${meta.mode.padEnd(7)} ${meta.status.padEnd(11)} ${step}${details.length > 0 ? ` | ${details.join(" | ")}` : ""}`;
|
|
8144
|
+
return `${meta.taskId.padEnd(42)} ${formatPublicWorkflowMode(meta.mode).padEnd(7)} ${meta.status.padEnd(11)} ${step}${details.length > 0 ? ` | ${details.join(" | ")}` : ""}`;
|
|
8145
|
+
}
|
|
8146
|
+
function parsePublicWorkflowMode(value) {
|
|
8147
|
+
if (value === "manba" || value === "mamba") return "mamba";
|
|
8148
|
+
if (value === "man" || value === "manteam") return value;
|
|
8149
|
+
return null;
|
|
8150
|
+
}
|
|
8151
|
+
function formatPublicWorkflowMode(mode) {
|
|
8152
|
+
return mode === "mamba" ? "manba" : mode;
|
|
8019
8153
|
}
|
|
8020
8154
|
function attachActiveChildren(workflows) {
|
|
8021
8155
|
return workflows.map((meta) => {
|
|
@@ -8073,7 +8207,7 @@ async function pathExists12(p) {
|
|
|
8073
8207
|
|
|
8074
8208
|
// src/cli.ts
|
|
8075
8209
|
program.name("mancode").description(
|
|
8076
|
-
"AI coding agent harness. Modes: solo, man,
|
|
8210
|
+
"AI coding agent harness. Modes: solo, man, manba, manteam, manps."
|
|
8077
8211
|
).version(VERSION);
|
|
8078
8212
|
program.command("init").description("Initialize mancode in the current project").option("--force", "Reinstall even if already initialized").option("--yes", "Skip all confirmations (CI mode)").option("--team", "Force enable team mode (MVP-2)").option("--no-team", "Force disable team mode (MVP-2)").option("--style <name>", "Specify aesthetic style (MVP-2)").option("--platform <platforms>", "Adapters: comma-separated names or all").option("--empty", "Initialize a safe empty directory as a generic project").option("--lang <locale>", "Initialization language: zh-CN or en").action(async (options) => {
|
|
8079
8213
|
const code = await init(process.cwd(), {
|
|
@@ -8106,8 +8240,8 @@ program.command("uninstall [platform]").description("Remove platform adapter or
|
|
|
8106
8240
|
});
|
|
8107
8241
|
program.command("workflow <subcommand> [args...]").description("Manage mancode workflows").option("--dry-run", "Preview clean without deleting").option("--older-than <duration>", "Clean workflows older than (e.g. 30d)").option("--step <n>", "Update workflow current step").option("--status <status>", "Update workflow status").option(
|
|
8108
8242
|
"--parent-task <taskId>",
|
|
8109
|
-
"Parent /man or /manteam workflow for
|
|
8110
|
-
).option("--blocking-reason <reason>", "Explain why a workflow is blocked").option("--outcome <outcome>", "Set
|
|
8243
|
+
"Parent /man or /manteam workflow for manba"
|
|
8244
|
+
).option("--blocking-reason <reason>", "Explain why a workflow is blocked").option("--outcome <outcome>", "Set manba outcome").option("--plan-version <n>", "Set the next man/manteam plan revision").option("--skipped <steps>", "Update skipped steps as comma-separated values").option("--review-depth <depth>", "Review depth: targeted or full").option("--review-domain <domain>", "Review domain: quality or security").option(
|
|
8111
8245
|
"--report <path>",
|
|
8112
8246
|
"Relative Markdown report path for a review domain"
|
|
8113
8247
|
).option("--blockers <ids>", "Comma-separated blocker ids found by a review").option(
|