lee-spec-kit 0.6.41 → 0.6.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +270 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -478,7 +478,7 @@ var koContext = {
|
|
|
478
478
|
"context.commandDetail.codeReviewPushFix": "({scope}) \uB9AC\uBDF0 \uC218\uC815 \uCEE4\uBC0B\uC744 push\uD558\uC138\uC694",
|
|
479
479
|
"context.commandDetail.prePrReviewRun": "({scope}) \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent)\uB85C PR \uC804 \uB9AC\uBDF0\uB97C \uC2E4\uD589\uD574 `review-trace.json`\uC744 \uC900\uBE44\uD558\uC138\uC694",
|
|
480
480
|
"context.commandDetail.prePrReviewRecord": "({scope}) Pre-PR \uB9AC\uBDF0 evidence\uB97C decisions.md\uC640 tasks.md\uC5D0 \uAE30\uB85D\uD558\uC138\uC694",
|
|
481
|
-
"context.commandDetail.codeReviewRun": "({scope}) \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent)\uB85C
|
|
481
|
+
"context.commandDetail.codeReviewRun": "({scope}) \uB9AC\uBDF0 \uCF54\uBA58\uD2B8\uB97C \uD655\uC778\uD558\uACE0, \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent)\uB85C \uC218\uC815 \uC791\uC5C5/evidence \uC815\uB9AC\uB97C \uC9C4\uD589\uD558\uC138\uC694",
|
|
482
482
|
"context.actionSummary.runDocsCommand": "\uBB38\uC11C \uC791\uC5C5 \uBA85\uB839\uC744 \uC2E4\uD589\uD558\uC138\uC694",
|
|
483
483
|
"context.actionSummary.runProjectCommand": "\uD504\uB85C\uC81D\uD2B8 \uC791\uC5C5 \uBA85\uB839\uC744 \uC2E4\uD589\uD558\uC138\uC694",
|
|
484
484
|
"context.actionDetail.featureFolder": "Feature \uD3F4\uB354\uC640 \uAE30\uBCF8 \uBB38\uC11C \uACE8\uACA9\uC744 \uC900\uBE44\uD558\uC138\uC694",
|
|
@@ -496,12 +496,13 @@ var koContext = {
|
|
|
496
496
|
"context.actionDetail.issueCreatePrepareFromDoc": "issue.md \uCD08\uC548\uC744 \uBCF4\uC644\uD558\uACE0 \uC0C1\uD0DC\uB97C Ready\uB85C \uC124\uC815\uD558\uC138\uC694",
|
|
497
497
|
"context.actionDetail.issueCreateFromDoc": "Ready \uC0C1\uD0DC issue.md\uB85C \uC774\uC288\uB97C \uC0DD\uC131\uD558\uACE0 \uBC88\uD638\uB97C \uB3D9\uAE30\uD654\uD558\uC138\uC694",
|
|
498
498
|
"context.actionDetail.taskExecute": "\uD604\uC7AC \uD0DC\uC2A4\uD06C\uB97C \uC9C4\uD589\uD558\uC138\uC694",
|
|
499
|
-
"context.actionDetail.taskExecuteRun": "\uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent) \uC791\uC5C5 handoff\uB97C \uC900\uBE44\uD558\uACE0 \uD0DC\uC2A4\uD06C\uB97C \uC2DC\uC791\uD558\uC138\uC694. (TODO\uBA74 DOING\uC73C\uB85C \uBCC0\uACBD)",
|
|
500
|
-
"context.actionDetail.taskExecuteContinue": "\uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent) \uC791\uC5C5 handoff\uB97C \uC900\uBE44\uD574 \uC9C4\uD589 \uC911\uC778 \uD0DC\uC2A4\uD06C\uB97C \
|
|
499
|
+
"context.actionDetail.taskExecuteRun": "\uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent) \uC791\uC5C5 handoff\uB97C \uC900\uBE44\uD558\uACE0 \uD0DC\uC2A4\uD06C\uB97C \uC2DC\uC791\uD558\uC138\uC694: {task}. (TODO\uBA74 DOING\uC73C\uB85C \uBCC0\uACBD)",
|
|
500
|
+
"context.actionDetail.taskExecuteContinue": "\uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent) \uC791\uC5C5 handoff\uB97C \uC900\uBE44\uD574 \uC9C4\uD589 \uC911\uC778 \uD0DC\uC2A4\uD06C\uB97C \uB9C8\uBB34\uB9AC\uD558\uC138\uC694: {task}. (\uC644\uB8CC \uD6C4 \uACB0\uACFC/\uAC80\uC99D\uC744 \uACF5\uC720\uD558\uACE0 DONE\uC73C\uB85C \uBCC0\uACBD)",
|
|
501
|
+
"context.actionDetail.taskExecuteComplete": "\uD604\uC7AC \uD0DC\uC2A4\uD06C\uB97C \uC644\uB8CC \uCC98\uB9AC\uD558\uC138\uC694: {task}. (DOING\uC744 DONE\uC73C\uB85C \uBCC0\uACBD)",
|
|
501
502
|
"context.actionDetail.reviewFixCommit": "\uD574\uACB0\uD55C \uB9AC\uBDF0 \uD56D\uBAA9 \uC694\uC57D\uC73C\uB85C \uB9AC\uBDF0 \uC218\uC815 \uCEE4\uBC0B\uC744 \uB9CC\uB4DC\uC138\uC694",
|
|
502
503
|
"context.actionDetail.prePrReviewRun": "\uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent)\uB85C PR \uC804 \uB9AC\uBDF0\uB97C \uC2E4\uD589\uD574 `review-trace.json`\uC744 \uC900\uBE44\uD558\uC138\uC694",
|
|
503
504
|
"context.actionDetail.prePrReviewRecord": "PR \uC804 \uB9AC\uBDF0 evidence\uB97C decisions.md\uC640 tasks.md\uC5D0 \uAE30\uB85D\uD558\uC138\uC694",
|
|
504
|
-
"context.actionDetail.codeReviewRun": "\uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent)\uB85C
|
|
505
|
+
"context.actionDetail.codeReviewRun": "\uB9AC\uBDF0 \uCF54\uBA58\uD2B8\uB97C \uD655\uC778\uD558\uACE0, \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent)\uB85C \uC218\uC815 \uC791\uC5C5/evidence \uC815\uB9AC\uB97C \uC9C4\uD589\uD558\uC138\uC694",
|
|
505
506
|
"context.actionDetail.prCreate": "PR\uC744 \uC0DD\uC131\uD558\uACE0 tasks \uAE30.md\uC758 PR \uC815\uBCF4\uB97C \uB9DE\uCD94\uC138\uC694",
|
|
506
507
|
"context.actionDetail.prCreateRequiredSequence": "PR 2\uB2E8\uACC4(\uCD08\uC548/\uC2B9\uC778 \uD6C4 \uC0DD\uC131/\uB3D9\uAE30\uD654)\uB97C \uC21C\uC11C\uB300\uB85C \uC644\uB8CC\uD558\uC138\uC694",
|
|
507
508
|
"context.actionDetail.prCreatePrepareFromDoc": "pr.md \uCD08\uC548\uC744 \uBCF4\uC644\uD558\uACE0 \uC0C1\uD0DC\uB97C Ready\uB85C \uC124\uC815\uD558\uC138\uC694",
|
|
@@ -1030,7 +1031,7 @@ var enContext = {
|
|
|
1030
1031
|
"context.commandDetail.codeReviewPushFix": "({scope}) push review-fix commits",
|
|
1031
1032
|
"context.commandDetail.prePrReviewRun": "({scope}) run the pre-PR review via a helper agent/sub-agent and prepare `review-trace.json`",
|
|
1032
1033
|
"context.commandDetail.prePrReviewRecord": "({scope}) record pre-PR review evidence into decisions.md + tasks.md",
|
|
1033
|
-
"context.commandDetail.codeReviewRun": "({scope})
|
|
1034
|
+
"context.commandDetail.codeReviewRun": "({scope}) check PR review comments, then use a helper agent/sub-agent for the follow-up fixes and evidence summary",
|
|
1034
1035
|
"context.actionSummary.runDocsCommand": "Run docs command",
|
|
1035
1036
|
"context.actionSummary.runProjectCommand": "Run project command",
|
|
1036
1037
|
"context.actionDetail.featureFolder": "Prepare feature folder and baseline docs",
|
|
@@ -1048,12 +1049,13 @@ var enContext = {
|
|
|
1048
1049
|
"context.actionDetail.issueCreatePrepareFromDoc": "Refine issue.md draft and set Status to Ready",
|
|
1049
1050
|
"context.actionDetail.issueCreateFromDoc": "Create GitHub Issue from ready issue.md and sync Issue",
|
|
1050
1051
|
"context.actionDetail.taskExecute": "Proceed with the current task",
|
|
1051
|
-
"context.actionDetail.taskExecuteRun": "Prepare helper agent/sub-agent task handoff and start the task. (TODO becomes DOING)",
|
|
1052
|
-
"context.actionDetail.taskExecuteContinue": "Prepare helper agent/sub-agent handoff and
|
|
1052
|
+
"context.actionDetail.taskExecuteRun": "Prepare helper agent/sub-agent task handoff and start the task: {task}. (TODO becomes DOING)",
|
|
1053
|
+
"context.actionDetail.taskExecuteContinue": "Prepare helper agent/sub-agent handoff and wrap up the in-progress task: {task}. (Share outcome/verification, then mark it DONE)",
|
|
1054
|
+
"context.actionDetail.taskExecuteComplete": "Mark the current task as complete: {task}. (Change DOING to DONE)",
|
|
1053
1055
|
"context.actionDetail.reviewFixCommit": "Create a review-fix commit with resolved feedback summary",
|
|
1054
1056
|
"context.actionDetail.prePrReviewRun": "Run the pre-PR review via a helper agent/sub-agent and prepare `review-trace.json`",
|
|
1055
1057
|
"context.actionDetail.prePrReviewRecord": "Record pre-PR review evidence into decisions.md and tasks.md",
|
|
1056
|
-
"context.actionDetail.codeReviewRun": "
|
|
1058
|
+
"context.actionDetail.codeReviewRun": "Check PR review comments, then use a helper agent/sub-agent for the follow-up fixes and evidence summary",
|
|
1057
1059
|
"context.actionDetail.prCreate": "Create PR and sync PR fields in tasks.md",
|
|
1058
1060
|
"context.actionDetail.prCreateRequiredSequence": "Complete PR 2-step flow: prepare draft + OK, then create and sync",
|
|
1059
1061
|
"context.actionDetail.prCreatePrepareFromDoc": "Refine pr.md draft and set Status to Ready",
|
|
@@ -3553,6 +3555,7 @@ function resolvePrePrReviewPolicy(workflow) {
|
|
|
3553
3555
|
function getPrePrReviewPrompt(lang, skills, fallbackText) {
|
|
3554
3556
|
if (lang === "ko") {
|
|
3555
3557
|
return `PR \uC0DD\uC131 \uC804 \uC0AC\uC804 \uCF54\uB4DC\uB9AC\uBDF0\uB97C \uC9C4\uD589\uD558\uC138\uC694.
|
|
3558
|
+
0. \uAC19\uC740 feature/pre-PR \uB9AC\uBDF0\uB97C \uB2F4\uB2F9\uD558\uB358 \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8\uAC00 \uC774\uBBF8 \uC788\uC73C\uBA74 \uC0C8\uB85C \uB9CC\uB4E4\uC9C0 \uB9D0\uACE0 \uC7AC\uC0AC\uC6A9\uD558\uC138\uC694. \uAE30\uBCF8\uC740 \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8 1\uAC1C\uC785\uB2C8\uB2E4.
|
|
3556
3559
|
1. \`spec.md\`, \`plan.md\`, \`tasks.md\`\uB97C \uC77D\uACE0 feature \uBAA9\uD45C/\uBC94\uC704/\uC644\uB8CC \uAE30\uC900\uC744 \uBA3C\uC800 \uC694\uC57D\uD558\uC138\uC694.
|
|
3557
3560
|
2. \uB9AC\uBDF0 \uBC94\uC704\uB97C \uBD84\uB9AC\uD574 \uD655\uC778\uD558\uC138\uC694.
|
|
3558
3561
|
- main \uAE30\uC900: 'git diff --name-only $(git merge-base HEAD origin/main)..HEAD'
|
|
@@ -3561,11 +3564,14 @@ function getPrePrReviewPrompt(lang, skills, fallbackText) {
|
|
|
3561
3564
|
4. \uD655\uC778\uB41C \uAC01 \uD30C\uC77C\uC5D0 \uB300\uD574 risk, security, perf, maintainability \uD3C9\uAC00\uC640 \uAD6C\uCCB4\uC801\uC778 fileLine \uC704\uCE58\uAC00 \uD3EC\uD568\uB41C 'review-trace.json' \uC99D\uAC70 \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uC138\uC694.
|
|
3562
3565
|
5. \uAE30\uBCF8 \uBCA0\uC774\uC2A4\uB77C\uC778\uC740 '${fallbackText}'\uC774\uBA70, 'create-pr' \uBB38\uC11C\uC758 'Pre-PR \uAE30\uBCF8 \uCCB4\uD06C\uB9AC\uC2A4\uD2B8' \uC139\uC158\uC744 \uC218\uD589\uD558\uC138\uC694.
|
|
3563
3566
|
6. \uC6B0\uC120\uC21C\uC704 \uC2A4\uD0AC: ${skills.length > 0 ? skills.join(", ") : "\uC5C6\uC74C"} \uB85C \uC2EC\uD654 \uAC80\uD1A0\uB97C \uC9C4\uD589\uD558\uC138\uC694.
|
|
3564
|
-
7. \uCD94\uAC00 \uAC80\uC99D\uC774 \uAF2D \uD544\uC694\uD560 \uB54C\uB9CC audit/\uD0C0\uAE43 \uBA85\uB839\uC744 \uC2E4\uD589\uD558\
|
|
3565
|
-
8. \
|
|
3566
|
-
9. \
|
|
3567
|
+
7. \uCD94\uAC00 \uAC80\uC99D\uC774 \uAF2D \uD544\uC694\uD560 \uB54C\uB9CC audit/\uD0C0\uAE43 \uBA85\uB839\uC744 \uC2E4\uD589\uD558\uC138\uC694. \uBCC4\uB3C4 \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8 \uCD94\uAC00 \uC0DD\uC131\uB3C4 \uAF2D \uD544\uC694\uD560 \uB54C\uB9CC \uD558\uC138\uC694.
|
|
3568
|
+
8. \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8 \uD55C\uB3C4\uC5D0 \uAC78\uB9AC\uBA74 \uBA54\uC778 \uC5D0\uC774\uC804\uD2B8\uC5D0\uC11C \uB9AC\uBDF0\uB97C \uC774\uC5B4\uAC00\uACE0, \uC774\uBBF8 \uC218\uC9D1\uD55C \uACB0\uACFC\uB9CC \uC815\uB9AC\uD574\uB3C4 \uB429\uB2C8\uB2E4.
|
|
3569
|
+
9. \uC2E4\uD589\uD55C \uBA85\uB839\uC774 \uC788\uC73C\uBA74 \`commandsExecuted\`\uC5D0 \uAE30\uB85D\uD558\uC138\uC694.
|
|
3570
|
+
10. \uC9C0\uC801\uC0AC\uD56D\uC774 \uB0A8\uC544 \uC788\uC73C\uBA74 \uBA3C\uC800 'npx lee-spec-kit pre-pr-review <feature> --evidence review-trace.json --decision changes_requested' \uB85C \uAE30\uB85D\uD558\uC138\uC694. \uB2E8, \`workflow.prePrReview.evidenceMode=any\` \uC774\uACE0 \uC2E4\uD589 \uC99D\uAC70 \uAC15\uC81C\uAC00 \uC5C6\uC73C\uBA74 \`--evidence\` \uC5C6\uC774 \uC9C1\uC811 \uAE30\uB85D\uD574\uB3C4 \uB429\uB2C8\uB2E4.
|
|
3571
|
+
11. \uC218\uC815/\uC7AC\uAC80\uC99D \uD6C4 \uCD5C\uC885 \uC2B9\uC778 \uC2DC\uC810\uC5D0 'npx lee-spec-kit pre-pr-review <feature> --decision approve' \uB97C \uC2E4\uD589\uD558\uC138\uC694. \`path_required\` \uC815\uCC45\uC77C \uB54C\uB9CC \`--evidence review-trace.json\` \uC744 \uD568\uAED8 \uBD99\uC774\uC138\uC694.`;
|
|
3567
3572
|
}
|
|
3568
3573
|
return `Conduct a pre-PR code review.
|
|
3574
|
+
0. Reuse the existing helper/sub-agent for this feature review if one already exists. Default to a single helper agent.
|
|
3569
3575
|
1. Read \`spec.md\`, \`plan.md\`, and \`tasks.md\` first, then summarize the feature goal, scope, and done criteria.
|
|
3570
3576
|
2. Split and check the review scope.
|
|
3571
3577
|
- Main scope: 'git diff --name-only $(git merge-base HEAD origin/main)..HEAD'
|
|
@@ -3574,15 +3580,17 @@ function getPrePrReviewPrompt(lang, skills, fallbackText) {
|
|
|
3574
3580
|
4. Generate a 'review-trace.json' file for all changed files, including \`findingCount\`, \`blockingFindings\`, evaluations for risk, security, perf, maintainability, and specific fileLine locators.
|
|
3575
3581
|
5. The baseline is '${fallbackText}'. Always perform the 'Pre-PR Core Checklist' section of the 'create-pr' document.
|
|
3576
3582
|
6. Priority skills: ${skills.length > 0 ? skills.join(", ") : "None"} for deeper technical review.
|
|
3577
|
-
7. Run extra audit/targeted verification only when the review needs more evidence
|
|
3578
|
-
8. If
|
|
3579
|
-
9.
|
|
3583
|
+
7. Run extra audit/targeted verification only when the review truly needs more evidence. Spawn additional helper agents only when necessary.
|
|
3584
|
+
8. If helper-agent quota is exhausted, continue the review in the main agent and just keep the evidence consistent.
|
|
3585
|
+
9. Record commands in \`commandsExecuted\` only when you actually ran them.
|
|
3586
|
+
10. If unresolved findings remain, first record them with 'npx lee-spec-kit pre-pr-review <feature> --evidence review-trace.json --decision changes_requested'. When \`workflow.prePrReview.evidenceMode=any\` and execution evidence is not enforced, direct record mode without \`--evidence\` is also valid.
|
|
3587
|
+
11. After fixes and re-validation, run 'npx lee-spec-kit pre-pr-review <feature> --decision approve' for final pre-PR approval. Add \`--evidence review-trace.json\` only when the active evidence policy requires a path.`;
|
|
3580
3588
|
}
|
|
3581
3589
|
function getCodeReviewPrompt(lang) {
|
|
3582
3590
|
if (lang === "ko") {
|
|
3583
|
-
return `\uB9AC\uBDF0 \uCF54\uBA58\uD2B8\uB97C \uD655\uC778/\uBD84\uC11D\uD55C \uB4A4 \uD544\uC694\uD55C \uC218\uC815\uC744 \uC9C4\uD589\uD558\uC138\uC694. PR \uC0C1\uD0DC\uB294 Review\uB97C \uC720\uC9C0\uD558\uACE0 'PR \uB9AC\uBDF0 Evidence/Decision'\uC744 \uCD5C\uC2E0\uC73C\uB85C \uAE30\uB85D\uD558\uC138\uC694. \uC6D0\uACA9 \uBC18\uC601(push)\uC740 \uBA85\uC2DC\uC801\uC778 \uBA38\uC9C0 \uC2B9\uC778(\uB77C\uBCA8) \uD6C4, \uB85C\uCEEC \uBE0C\uB79C\uCE58\uAC00 upstream\uBCF4\uB2E4 \uC55E\uC120 \uACBD\uC6B0\uC5D0\uB9CC \uC9C4\uD589\uD558\uC138\uC694.`;
|
|
3591
|
+
return `\uB9AC\uBDF0 \uCF54\uBA58\uD2B8\uB97C \uD655\uC778/\uBD84\uC11D\uD55C \uB4A4 \uD544\uC694\uD55C \uC218\uC815\uC744 \uC9C4\uD589\uD558\uC138\uC694. \uAE30\uC874 review \uB2F4\uB2F9 \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8\uAC00 \uC788\uC73C\uBA74 \uC7AC\uC0AC\uC6A9\uD558\uACE0, \uAE30\uBCF8\uC740 1\uAC1C\uB9CC \uC0AC\uC6A9\uD558\uC138\uC694. \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8 \uD55C\uB3C4\uC5D0 \uAC78\uB9AC\uBA74 \uBA54\uC778 \uC5D0\uC774\uC804\uD2B8\uC5D0\uC11C \uC774\uC5B4\uAC00\uC138\uC694. PR \uC0C1\uD0DC\uB294 Review\uB97C \uC720\uC9C0\uD558\uACE0 'PR \uB9AC\uBDF0 Evidence/Decision'\uC744 \uCD5C\uC2E0\uC73C\uB85C \uAE30\uB85D\uD558\uC138\uC694. \uC6D0\uACA9 \uBC18\uC601(push)\uC740 \uBA85\uC2DC\uC801\uC778 \uBA38\uC9C0 \uC2B9\uC778(\uB77C\uBCA8) \uD6C4, \uB85C\uCEEC \uBE0C\uB79C\uCE58\uAC00 upstream\uBCF4\uB2E4 \uC55E\uC120 \uACBD\uC6B0\uC5D0\uB9CC \uC9C4\uD589\uD558\uC138\uC694.`;
|
|
3584
3592
|
}
|
|
3585
|
-
return `Review and analyze comments, then make necessary fixes. Keep PR status as Review and record the latest 'PR Review Evidence/Decision'. Push changes only after explicit approval (label) and only if the local branch is ahead of upstream.`;
|
|
3593
|
+
return `Review and analyze comments, then make necessary fixes. Reuse the existing review helper agent if one already exists, and default to a single helper agent. If helper-agent quota is exhausted, continue in the main agent. Keep PR status as Review and record the latest 'PR Review Evidence/Decision'. Push changes only after explicit approval (label) and only if the local branch is ahead of upstream.`;
|
|
3586
3594
|
}
|
|
3587
3595
|
|
|
3588
3596
|
// src/utils/context/steps.ts
|
|
@@ -3694,6 +3702,13 @@ function buildTaskRunCommandArgs(feature, taskId) {
|
|
|
3694
3702
|
}
|
|
3695
3703
|
return commandArgs;
|
|
3696
3704
|
}
|
|
3705
|
+
function buildTaskCompleteCommandArgs(feature, taskId) {
|
|
3706
|
+
const commandArgs = ["task-complete", feature.folderName, "--task", taskId];
|
|
3707
|
+
if (feature.type && feature.type !== "single") {
|
|
3708
|
+
commandArgs.push("--component", feature.type);
|
|
3709
|
+
}
|
|
3710
|
+
return commandArgs;
|
|
3711
|
+
}
|
|
3697
3712
|
function buildCodeReviewRunCommandArgs(feature) {
|
|
3698
3713
|
const commandArgs = ["code-review-run", feature.folderName];
|
|
3699
3714
|
if (feature.type && feature.type !== "single") {
|
|
@@ -3769,6 +3784,14 @@ function resolveProjectCommitTopic(feature) {
|
|
|
3769
3784
|
const topic = withoutTaskId || normalizeCommitTopicText(feature.folderName);
|
|
3770
3785
|
return toShellSafeCommitTopic(topic);
|
|
3771
3786
|
}
|
|
3787
|
+
function resolveTaskUiLabel(task) {
|
|
3788
|
+
if (!task) return "T-unknown task";
|
|
3789
|
+
const id = task.id?.trim();
|
|
3790
|
+
const title = task.title.trim();
|
|
3791
|
+
const normalizedTitle = id ? title.replace(new RegExp(`^${id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s+`), "") : title;
|
|
3792
|
+
if (id) return `${id} - ${normalizedTitle || title}`;
|
|
3793
|
+
return title || "T-unknown task";
|
|
3794
|
+
}
|
|
3772
3795
|
function getReviewFixCommitGuidance(feature, lang, options) {
|
|
3773
3796
|
const prePr = !!options?.prePr;
|
|
3774
3797
|
if (prePr) {
|
|
@@ -3841,7 +3864,7 @@ function countDoneTransitionsInLatestTasksCommit(ctx, feature) {
|
|
|
3841
3864
|
if (!diff.trim()) return 0;
|
|
3842
3865
|
const removedByTask = /* @__PURE__ */ new Map();
|
|
3843
3866
|
const addedByTask = /* @__PURE__ */ new Map();
|
|
3844
|
-
const
|
|
3867
|
+
const parseTaskLine3 = (line) => {
|
|
3845
3868
|
const match = line.match(
|
|
3846
3869
|
/^\s*-\s*\[(TODO|DOING|DONE|REVIEW)\]\s+(.+?)\s*$/i
|
|
3847
3870
|
);
|
|
@@ -3856,7 +3879,7 @@ function countDoneTransitionsInLatestTasksCommit(ctx, feature) {
|
|
|
3856
3879
|
for (const line of diff.split("\n")) {
|
|
3857
3880
|
if (line.startsWith("---") || line.startsWith("+++")) continue;
|
|
3858
3881
|
if (line.startsWith("-")) {
|
|
3859
|
-
const parsed =
|
|
3882
|
+
const parsed = parseTaskLine3(line.slice(1));
|
|
3860
3883
|
if (!parsed) continue;
|
|
3861
3884
|
const existing = removedByTask.get(parsed.key) || /* @__PURE__ */ new Set();
|
|
3862
3885
|
existing.add(parsed.status);
|
|
@@ -3864,7 +3887,7 @@ function countDoneTransitionsInLatestTasksCommit(ctx, feature) {
|
|
|
3864
3887
|
continue;
|
|
3865
3888
|
}
|
|
3866
3889
|
if (line.startsWith("+")) {
|
|
3867
|
-
const parsed =
|
|
3890
|
+
const parsed = parseTaskLine3(line.slice(1));
|
|
3868
3891
|
if (!parsed) continue;
|
|
3869
3892
|
const existing = addedByTask.get(parsed.key) || /* @__PURE__ */ new Set();
|
|
3870
3893
|
existing.add(parsed.status);
|
|
@@ -4065,11 +4088,14 @@ function getStepDefinitions(ctx) {
|
|
|
4065
4088
|
operationType: "local",
|
|
4066
4089
|
requiresUserCheck: true,
|
|
4067
4090
|
taskExecutePhase: "complete",
|
|
4068
|
-
uiDetailKey: "context.actionDetail.
|
|
4091
|
+
uiDetailKey: "context.actionDetail.taskExecuteComplete",
|
|
4092
|
+
uiDetailParams: {
|
|
4093
|
+
task: resolveTaskUiLabel(f.activeTask)
|
|
4094
|
+
},
|
|
4069
4095
|
scope: "docs",
|
|
4070
4096
|
cwd: f.git.docsGitCwd,
|
|
4071
4097
|
cmd: buildSelfCliCommand(
|
|
4072
|
-
|
|
4098
|
+
buildTaskCompleteCommandArgs(
|
|
4073
4099
|
f,
|
|
4074
4100
|
f.activeTask?.id || `T-${f.folderName}-active`
|
|
4075
4101
|
)
|
|
@@ -4188,6 +4214,9 @@ ${tr(lang, "messages", "taskCommitGateWarnProceed", {
|
|
|
4188
4214
|
requiresUserCheck: true,
|
|
4189
4215
|
taskExecutePhase: "start",
|
|
4190
4216
|
uiDetailKey: "context.actionDetail.taskExecuteRun",
|
|
4217
|
+
uiDetailParams: {
|
|
4218
|
+
task: resolveTaskUiLabel(f.nextTodoTask)
|
|
4219
|
+
},
|
|
4191
4220
|
scope: "docs",
|
|
4192
4221
|
cwd: f.git.docsGitCwd,
|
|
4193
4222
|
cmd: buildSelfCliCommand(
|
|
@@ -4348,7 +4377,7 @@ ${tr(lang, "messages", "prePrReviewDecisionReconfirm", {
|
|
|
4348
4377
|
const isCodeReviewNeedEvidence = (f) => isCodeReviewCurrent(f) && f.pr.status === "Review" && workflowPolicy.requireReview && !isCodeReviewNeedEvidenceField(f) && !f.prReview.evidenceProvided;
|
|
4349
4378
|
const isCodeReviewNeedDecisionField = (f) => isCodeReviewCurrent(f) && f.pr.status === "Review" && workflowPolicy.requireReview && !isCodeReviewNeedEvidenceField(f) && f.prReview.evidenceProvided && !f.docs.prReviewDecisionFieldExists;
|
|
4350
4379
|
const isCodeReviewNeedDecision = (f) => isCodeReviewCurrent(f) && f.pr.status === "Review" && workflowPolicy.requireReview && !isCodeReviewNeedEvidenceField(f) && f.prReview.evidenceProvided && !isCodeReviewNeedDecisionField(f) && !f.prReview.decisionProvided;
|
|
4351
|
-
const isCodeReviewRun = (f) => isCodeReviewCurrent(f) && f.pr.status === "Review" && workflowPolicy.requireReview && !isCodeReviewNeedEvidenceField(f) && !f.prReview.evidenceProvided && !f.prReview.decisionProvided;
|
|
4380
|
+
const isCodeReviewRun = (f) => isCodeReviewCurrent(f) && f.pr.status === "Review" && workflowPolicy.requireReview && (f.git.projectBranchAhead || 0) === 0 && !isCodeReviewNeedEvidenceField(f) && !f.prReview.evidenceProvided && !f.prReview.decisionProvided;
|
|
4352
4381
|
const isCodeReviewFinalize = (f) => isCodeReviewCurrent(f) && !isCodeReviewSyncApproved(f) && (!workflowPolicy.requireReview || f.pr.status === "Review" && !isCodeReviewNeedEvidenceField(f) && !isCodeReviewNeedEvidence(f) && !isCodeReviewNeedDecisionField(f) && !isCodeReviewNeedDecision(f) && f.prReview.evidenceProvided && f.prReview.decisionProvided);
|
|
4353
4382
|
const isCodeReviewRequestReview = (f) => isCodeReviewCurrent(f) && !!f.pr.status && f.pr.status !== "Review";
|
|
4354
4383
|
const getCodeReviewRunActions = (f) => [
|
|
@@ -4733,9 +4762,9 @@ ${tr(lang, "messages", "prePrReviewDecisionReconfirm", {
|
|
|
4733
4762
|
actions: (f) => getTaskExecuteFinalizeActions(f)
|
|
4734
4763
|
},
|
|
4735
4764
|
{
|
|
4736
|
-
id: "
|
|
4737
|
-
phase: "
|
|
4738
|
-
owner: "
|
|
4765
|
+
id: "task_complete",
|
|
4766
|
+
phase: "finalize",
|
|
4767
|
+
owner: "main",
|
|
4739
4768
|
category: "task_execute",
|
|
4740
4769
|
when: (f) => isTaskExecuteCurrent(f) && !!f.activeTask,
|
|
4741
4770
|
actions: (f) => getTaskExecuteRunningActions(f)
|
|
@@ -5192,7 +5221,7 @@ function applyApprovalPolicy(step, actions, approval, currentSubstatePhase) {
|
|
|
5192
5221
|
function applyTaskExecutePhaseCheck(action, requiresUserCheck, policy, explicitlyRequired = false, currentSubstatePhase) {
|
|
5193
5222
|
if (policy !== "start_only") return requiresUserCheck;
|
|
5194
5223
|
if (action.category !== "task_execute") return requiresUserCheck;
|
|
5195
|
-
const isCompletionPhase = currentSubstatePhase === "running" || !currentSubstatePhase && action.taskExecutePhase === "complete";
|
|
5224
|
+
const isCompletionPhase = currentSubstatePhase === "running" || currentSubstatePhase === "finalize" || !currentSubstatePhase && action.taskExecutePhase === "complete";
|
|
5196
5225
|
if (!isCompletionPhase) return requiresUserCheck;
|
|
5197
5226
|
if (explicitlyRequired) return requiresUserCheck;
|
|
5198
5227
|
return false;
|
|
@@ -8130,11 +8159,11 @@ function annotateActions(actions) {
|
|
|
8130
8159
|
}
|
|
8131
8160
|
function getActionSummary(action, lang) {
|
|
8132
8161
|
if (action.uiSummaryKey) {
|
|
8133
|
-
const localized = tr(lang, "cli", action.uiSummaryKey);
|
|
8162
|
+
const localized = tr(lang, "cli", action.uiSummaryKey, action.uiDetailParams);
|
|
8134
8163
|
if (localized !== `cli.${action.uiSummaryKey}`) return localized;
|
|
8135
8164
|
}
|
|
8136
8165
|
if (action.uiDetailKey) {
|
|
8137
|
-
const localized = tr(lang, "cli", action.uiDetailKey);
|
|
8166
|
+
const localized = tr(lang, "cli", action.uiDetailKey, action.uiDetailParams);
|
|
8138
8167
|
if (localized !== `cli.${action.uiDetailKey}`) return localized;
|
|
8139
8168
|
}
|
|
8140
8169
|
const detailKey = action.category ? ACTION_DETAIL_KEY_BY_CATEGORY[action.category] : void 0;
|
|
@@ -8159,7 +8188,7 @@ function toOneLine(text) {
|
|
|
8159
8188
|
}
|
|
8160
8189
|
function buildActionDetail(action, lang) {
|
|
8161
8190
|
if (action.uiDetailKey) {
|
|
8162
|
-
const localized = tr(lang, "cli", action.uiDetailKey);
|
|
8191
|
+
const localized = tr(lang, "cli", action.uiDetailKey, action.uiDetailParams);
|
|
8163
8192
|
if (localized !== `cli.${action.uiDetailKey}`) return localized;
|
|
8164
8193
|
}
|
|
8165
8194
|
const formatBranchCreateDetail = (command) => {
|
|
@@ -8257,7 +8286,7 @@ function toActionOptions(actions, lang) {
|
|
|
8257
8286
|
const summary = getActionSummary(action, lang);
|
|
8258
8287
|
const detail = buildActionDetail(action, lang);
|
|
8259
8288
|
const requiresRequestText = action.category === "user_request_replan";
|
|
8260
|
-
const replyExample = requiresRequestText ? `${label}, <your request>` :
|
|
8289
|
+
const replyExample = requiresRequestText ? `${label}, <your request>` : label;
|
|
8261
8290
|
return {
|
|
8262
8291
|
label,
|
|
8263
8292
|
summary,
|
|
@@ -8282,7 +8311,8 @@ function buildActionSnapshot(actionOptions) {
|
|
|
8282
8311
|
operationType: action.operationType,
|
|
8283
8312
|
requiresUserCheck: !!action.requiresUserCheck,
|
|
8284
8313
|
uiSummaryKey: action.uiSummaryKey,
|
|
8285
|
-
uiDetailKey: action.uiDetailKey
|
|
8314
|
+
uiDetailKey: action.uiDetailKey,
|
|
8315
|
+
uiDetailParams: action.uiDetailParams ? JSON.stringify(action.uiDetailParams) : void 0
|
|
8286
8316
|
};
|
|
8287
8317
|
}
|
|
8288
8318
|
return {
|
|
@@ -8293,7 +8323,8 @@ function buildActionSnapshot(actionOptions) {
|
|
|
8293
8323
|
operationType: action.operationType,
|
|
8294
8324
|
requiresUserCheck: !!action.requiresUserCheck,
|
|
8295
8325
|
uiSummaryKey: action.uiSummaryKey,
|
|
8296
|
-
uiDetailKey: action.uiDetailKey
|
|
8326
|
+
uiDetailKey: action.uiDetailKey,
|
|
8327
|
+
uiDetailParams: action.uiDetailParams ? JSON.stringify(action.uiDetailParams) : void 0
|
|
8297
8328
|
};
|
|
8298
8329
|
});
|
|
8299
8330
|
}
|
|
@@ -8915,6 +8946,9 @@ function toCompactActionOption(option) {
|
|
|
8915
8946
|
if (option.action.taskExecutePhase) {
|
|
8916
8947
|
base.taskExecutePhase = option.action.taskExecutePhase;
|
|
8917
8948
|
}
|
|
8949
|
+
if (option.action.uiDetailParams) {
|
|
8950
|
+
base.uiDetailParams = option.action.uiDetailParams;
|
|
8951
|
+
}
|
|
8918
8952
|
if (option.action.type === "command") {
|
|
8919
8953
|
base.scope = option.action.scope;
|
|
8920
8954
|
base.cwd = option.action.cwd;
|
|
@@ -9205,7 +9239,11 @@ async function runApprovedOption(state, config, lang, featureName, selectionOpti
|
|
|
9205
9239
|
approval,
|
|
9206
9240
|
state.actionOptions.map((o) => o.label)
|
|
9207
9241
|
);
|
|
9208
|
-
|
|
9242
|
+
const replanOptions = state.actionOptions.filter(
|
|
9243
|
+
(option) => option.action.category === "user_request_replan"
|
|
9244
|
+
);
|
|
9245
|
+
const implicitReplanRequest = approval.trim();
|
|
9246
|
+
parsedLabel = parsedApproval?.label ?? (replanOptions.length > 0 && implicitReplanRequest ? replanOptions[0].label : null);
|
|
9209
9247
|
if (!parsedLabel) {
|
|
9210
9248
|
throw createCliError(
|
|
9211
9249
|
"INVALID_APPROVAL",
|
|
@@ -9249,7 +9287,7 @@ async function runApprovedOption(state, config, lang, featureName, selectionOpti
|
|
|
9249
9287
|
}
|
|
9250
9288
|
const selectedAction = freshSelected.action;
|
|
9251
9289
|
if (selectedAction.category === "user_request_replan") {
|
|
9252
|
-
const requestText = parsedApproval?.requestText?.trim();
|
|
9290
|
+
const requestText = (parsedApproval?.requestText?.trim() || (parsedApproval ? "" : implicitReplanRequest)).trim();
|
|
9253
9291
|
if (!requestText) {
|
|
9254
9292
|
throw createCliError(
|
|
9255
9293
|
"INVALID_APPROVAL",
|
|
@@ -12409,6 +12447,12 @@ function sanitizeDraftMetadataValue(raw) {
|
|
|
12409
12447
|
if (/^\(.+\)$/.test(value)) return void 0;
|
|
12410
12448
|
return value;
|
|
12411
12449
|
}
|
|
12450
|
+
function sanitizeDraftTitleValue(raw) {
|
|
12451
|
+
const value = sanitizeDraftMetadataValue(raw);
|
|
12452
|
+
if (!value) return void 0;
|
|
12453
|
+
const normalized = value.replace(/`/g, "").replace(/\*\*(.*?)\*\*/g, "$1").replace(/\[(.*?)\]\((.*?)\)/g, "$1").replace(/\s+/g, " ").trim();
|
|
12454
|
+
return normalized || void 0;
|
|
12455
|
+
}
|
|
12412
12456
|
function parseWorkflowDraftStatus(raw) {
|
|
12413
12457
|
const value = (raw || "").trim();
|
|
12414
12458
|
if (!value) return void 0;
|
|
@@ -12420,7 +12464,7 @@ function parseWorkflowDraftMetadata(content) {
|
|
|
12420
12464
|
const status = parseWorkflowDraftStatus(
|
|
12421
12465
|
extractDraftMetadataValue(content, ["Status", "\uC0C1\uD0DC"])
|
|
12422
12466
|
);
|
|
12423
|
-
const title =
|
|
12467
|
+
const title = sanitizeDraftTitleValue(
|
|
12424
12468
|
extractDraftMetadataValue(content, ["Title", "\uC81C\uBAA9", "PR Title", "PR \uC81C\uBAA9"])
|
|
12425
12469
|
);
|
|
12426
12470
|
const labels = sanitizeDraftMetadataValue(
|
|
@@ -15899,6 +15943,9 @@ async function runPrePrReviewRun(featureName, options) {
|
|
|
15899
15943
|
fallback: policy.fallback,
|
|
15900
15944
|
handoffOnly: true,
|
|
15901
15945
|
advancesWorkflow: false,
|
|
15946
|
+
reuseKey: `pre-pr:${featureRef}`,
|
|
15947
|
+
suggestedParallelism: 1,
|
|
15948
|
+
fallbackToMainAgentWhenQuotaExceeded: true,
|
|
15902
15949
|
nextStepRequirement: "generate_review_trace_then_record",
|
|
15903
15950
|
evidenceFile: "review-trace.json",
|
|
15904
15951
|
prompt,
|
|
@@ -15920,6 +15967,18 @@ async function runPrePrReviewRun(featureName, options) {
|
|
|
15920
15967
|
config.lang === "ko" ? "\uC774 \uBA85\uB839\uC740 \uB9AC\uBDF0 handoff\uB9CC \uC900\uBE44\uD569\uB2C8\uB2E4. review-trace.json\uC744 \uC9C1\uC811 \uC0DD\uC131\uD558\uAC70\uB098 \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC0C1\uD0DC\uB97C \uBC14\uB85C \uB118\uAE30\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4." : "This command only prepares the review handoff. It does not generate review-trace.json or advance workflow state by itself."
|
|
15921
15968
|
)
|
|
15922
15969
|
);
|
|
15970
|
+
console.log(
|
|
15971
|
+
chalk8.gray(
|
|
15972
|
+
config.lang === "ko" ? "- \uAE30\uC874 pre-PR \uB9AC\uBDF0 \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8\uAC00 \uC788\uC73C\uBA74 \uC7AC\uC0AC\uC6A9\uD558\uACE0, \uAE30\uBCF8\uC740 1\uAC1C\uB9CC \uC0AC\uC6A9\uD558\uC138\uC694." : "- Reuse the existing pre-PR helper agent if one already exists; default to a single helper agent."
|
|
15973
|
+
)
|
|
15974
|
+
);
|
|
15975
|
+
console.log(
|
|
15976
|
+
chalk8.gray(
|
|
15977
|
+
config.lang === "ko" ? "- \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8 \uD55C\uB3C4\uC5D0 \uAC78\uB9AC\uBA74 \uBA54\uC778 \uC5D0\uC774\uC804\uD2B8\uC5D0\uC11C \uB9AC\uBDF0\uB97C \uC774\uC5B4\uAC00\uC138\uC694." : "- If helper-agent quota is exhausted, continue the review in the main agent."
|
|
15978
|
+
)
|
|
15979
|
+
);
|
|
15980
|
+
console.log(`Reuse key: pre-pr:${featureRef}`);
|
|
15981
|
+
console.log(`Suggested parallelism: 1`);
|
|
15923
15982
|
console.log(`Evidence file: review-trace.json`);
|
|
15924
15983
|
console.log(`Record changes requested: ${changesRequestedCommand}`);
|
|
15925
15984
|
console.log(`Record approval: ${approveCommand}`);
|
|
@@ -16103,18 +16162,20 @@ async function runPrePrReview(featureName, options) {
|
|
|
16103
16162
|
function buildCodeReviewRunPrompt(input) {
|
|
16104
16163
|
if (input.lang === "ko") {
|
|
16105
16164
|
return [
|
|
16106
|
-
"PR \uB9AC\uBDF0 \
|
|
16165
|
+
"PR \uB9AC\uBDF0 \uCF54\uBA58\uD2B8\uB97C \uD655\uC778\uD558\uACE0 \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8\uB85C \uC218\uC815 \uC791\uC5C5\uC744 \uC9C4\uD589\uD558\uC138\uC694.",
|
|
16107
16166
|
`- Feature: ${input.featureRef}`,
|
|
16108
16167
|
`- ${input.basePrompt}`,
|
|
16109
|
-
"- \uB9AC\uBDF0 \uCF54\uBA58\uD2B8 \
|
|
16168
|
+
"- \uC0AC\uB78C/CodeRabbit\uC774 \uB0A8\uAE34 \uB9AC\uBDF0 \uCF54\uBA58\uD2B8\uB97C \uAC80\uD1A0\uD558\uACE0 \uD544\uC694\uD55C \uCF54\uB4DC/\uBB38\uC11C \uC218\uC815\uC744 \uC9C4\uD589\uD558\uC138\uC694.",
|
|
16169
|
+
"- \uC218\uC815 \uB0B4\uC6A9\uACFC \uAC80\uD1A0 \uACB0\uACFC\uB97C \uBC18\uC601\uD55C \uB4A4 `tasks.md`\uC758 `PR Review Evidence/Decision`\uC744 \uCD5C\uC2E0\uC73C\uB85C \uAE30\uB85D\uD558\uC138\uC694.",
|
|
16110
16170
|
"- \uAD00\uB828 \uC218\uC815\uC774 \uC0DD\uAE30\uBA74 \uCF54\uB4DC/\uBB38\uC11C \uBCC0\uACBD\uC744 \uC815\uB9AC\uD558\uACE0, push/merge\uB294 \uBA54\uC778 \uC5D0\uC774\uC804\uD2B8 \uCD5C\uC885 \uC0C1\uD0DC\uC5D0\uC11C\uB9CC \uC9C4\uD589\uD558\uC138\uC694."
|
|
16111
16171
|
].join("\n");
|
|
16112
16172
|
}
|
|
16113
16173
|
return [
|
|
16114
|
-
"
|
|
16174
|
+
"Review PR comments and use a helper agent/sub-agent for the follow-up fixes.",
|
|
16115
16175
|
`- Feature: ${input.featureRef}`,
|
|
16116
16176
|
`- ${input.basePrompt}`,
|
|
16117
|
-
"-
|
|
16177
|
+
"- Check human/CodeRabbit review comments and make the required code/docs changes.",
|
|
16178
|
+
"- Update `PR Review Evidence` and `PR Review Decision` in `tasks.md` after applying the fixes and summarizing the outcome.",
|
|
16118
16179
|
"- If review fixes are needed, keep code/docs changes ready for the main-agent finalize state. Push/merge stays in the main agent."
|
|
16119
16180
|
].join("\n");
|
|
16120
16181
|
}
|
|
@@ -16150,6 +16211,9 @@ async function runCodeReviewRun(featureName, options) {
|
|
|
16150
16211
|
owner: "subagent",
|
|
16151
16212
|
handoffOnly: true,
|
|
16152
16213
|
advancesWorkflow: false,
|
|
16214
|
+
reuseKey: `code-review:${feature.folderName}`,
|
|
16215
|
+
suggestedParallelism: 1,
|
|
16216
|
+
fallbackToMainAgentWhenQuotaExceeded: true,
|
|
16153
16217
|
nextMainState: "code_review_finalize",
|
|
16154
16218
|
tasksPath: path12.join(feature.path, "tasks.md"),
|
|
16155
16219
|
decisionsPath: path12.join(feature.path, "decisions.md"),
|
|
@@ -16164,11 +16228,18 @@ async function runCodeReviewRun(featureName, options) {
|
|
|
16164
16228
|
console.log();
|
|
16165
16229
|
console.log(
|
|
16166
16230
|
chalk8.yellow(
|
|
16167
|
-
config.lang === "ko" ? "\uC774 \uBA85\uB839\uC740 PR \uB9AC\uBDF0 handoff\uB9CC \uC900\uBE44\uD569\uB2C8\uB2E4. \
|
|
16231
|
+
config.lang === "ko" ? "\uC774 \uBA85\uB839\uC740 PR \uB9AC\uBDF0 \uCF54\uBA58\uD2B8 \uB300\uC751\uC6A9 handoff\uB9CC \uC900\uBE44\uD569\uB2C8\uB2E4. \uCF54\uBA58\uD2B8\uB97C \uC9C1\uC811 \uC77D\uC5B4\uC624\uAC70\uB098 evidence/decision\uC744 \uC790\uB3D9 \uAE30\uB85D\uD558\uC9C0 \uC54A\uC73C\uBA70, \uC0C1\uD0DC\uB3C4 \uBC14\uB85C \uB118\uAE30\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4." : "This command only prepares a handoff for addressing PR review comments. It does not fetch comments automatically, record review evidence/decision, or advance workflow state by itself."
|
|
16168
16232
|
)
|
|
16169
16233
|
);
|
|
16170
16234
|
console.log(chalk8.gray(`- substate: ${payload.substateId}`));
|
|
16171
16235
|
console.log(chalk8.gray(`- owner: ${payload.owner}`));
|
|
16236
|
+
console.log(chalk8.gray(`- reuse key: ${payload.reuseKey}`));
|
|
16237
|
+
console.log(chalk8.gray(`- suggested parallelism: ${payload.suggestedParallelism}`));
|
|
16238
|
+
console.log(
|
|
16239
|
+
chalk8.gray(
|
|
16240
|
+
`- quota fallback: ${payload.fallbackToMainAgentWhenQuotaExceeded ? "continue in main agent" : "none"}`
|
|
16241
|
+
)
|
|
16242
|
+
);
|
|
16172
16243
|
console.log(chalk8.gray(`- next main state: ${payload.nextMainState}`));
|
|
16173
16244
|
console.log(chalk8.gray(`- tasks.md: ${payload.tasksPath}`));
|
|
16174
16245
|
console.log(chalk8.gray(`- decisions.md: ${payload.decisionsPath}`));
|
|
@@ -16420,9 +16491,10 @@ function parseTaskLine(line) {
|
|
|
16420
16491
|
function buildTaskRunPrompt(input) {
|
|
16421
16492
|
const shared = [
|
|
16422
16493
|
"Read `spec.md`, `plan.md`, and `tasks.md` before editing code.",
|
|
16423
|
-
"
|
|
16424
|
-
"
|
|
16494
|
+
"Reuse the existing helper/sub-agent for this task if one already exists. Default to a single helper agent.",
|
|
16495
|
+
"Use additional helper agents only when parallel analysis is clearly worth the extra slot cost.",
|
|
16425
16496
|
"Keep one writer for overlapping files; do not let multiple sub-agents edit the same files concurrently.",
|
|
16497
|
+
"If helper-agent quota is exhausted, continue the task in the main agent instead of blocking progress.",
|
|
16426
16498
|
"Update the assigned task status and verification notes in `tasks.md` before leaving this task.",
|
|
16427
16499
|
"Mark the task `DONE` only after code changes and verification are complete."
|
|
16428
16500
|
];
|
|
@@ -16433,9 +16505,10 @@ function buildTaskRunPrompt(input) {
|
|
|
16433
16505
|
`- Task: ${input.taskId} ${input.title}`,
|
|
16434
16506
|
input.mode === "start" ? "- \uC774 \uBA85\uB839\uC740 `tasks.md`\uC758 \uD604\uC7AC task\uB97C `DOING`\uC73C\uB85C \uBC14\uAFB8\uACE0, \uC774\uD6C4 \uAD6C\uD604 handoff prompt\uB97C \uC900\uBE44\uD569\uB2C8\uB2E4." : "- \uC774 \uBA85\uB839\uC740 \uC9C4\uD589 \uC911 task\uC758 \uAD6C\uD604 handoff prompt\uB97C \uB2E4\uC2DC \uC900\uBE44\uD569\uB2C8\uB2E4.",
|
|
16435
16507
|
"- \uBA3C\uC800 `spec.md`, `plan.md`, `tasks.md`\uB97C \uC77D\uACE0 \uBC94\uC704\uC640 \uC644\uB8CC \uAE30\uC900\uC744 \uC815\uB9AC\uD558\uC138\uC694.",
|
|
16436
|
-
"- \
|
|
16437
|
-
"- \uC601\uD5A5 \uBC94\uC704 \uBD84\uC11D, \uD14C\uC2A4\uD2B8 \uC704\uCE58 \uD0D0\uC0C9, \uAE30\uC874 \uD328\uD134 \uC870\uC0AC\
|
|
16508
|
+
"- \uAE30\uC874\uC5D0 \uC774 task\uB97C \uB9E1\uB358 \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8\uAC00 \uC788\uC73C\uBA74 \uC7AC\uC0AC\uC6A9\uD558\uACE0, \uAE30\uBCF8\uC740 1\uAC1C\uB9CC \uC0AC\uC6A9\uD558\uC138\uC694.",
|
|
16509
|
+
"- \uC601\uD5A5 \uBC94\uC704 \uBD84\uC11D, \uD14C\uC2A4\uD2B8 \uC704\uCE58 \uD0D0\uC0C9, \uAE30\uC874 \uD328\uD134 \uC870\uC0AC\uAC00 \uC815\uB9D0 \uB3C5\uB9BD\uC801\uC77C \uB54C\uB9CC \uCD94\uAC00 \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8\uB97C \uC0AC\uC6A9\uD558\uC138\uC694.",
|
|
16438
16510
|
"- \uAC19\uC740 \uD30C\uC77C\uAD70\uC744 \uC218\uC815\uD558\uB294 \uC791\uC131\uC790\uB294 \uD55C \uBA85\uB9CC \uB450\uC138\uC694.",
|
|
16511
|
+
"- \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8 \uD55C\uB3C4\uC5D0 \uAC78\uB9AC\uBA74 \uBA54\uC778 \uC5D0\uC774\uC804\uD2B8\uC5D0\uC11C \uAD6C\uD604\uC744 \uC774\uC5B4\uAC00\uC138\uC694.",
|
|
16439
16512
|
"- \uC774 task\uB97C \uB9C8\uCE58\uAE30 \uC804 `tasks.md`\uC5D0 \uC0C1\uD0DC\uC640 \uAC80\uC99D \uBA54\uBAA8\uB97C \uBC18\uC601\uD558\uC138\uC694.",
|
|
16440
16513
|
"- \uCF54\uB4DC \uBCC0\uACBD\uACFC \uAC80\uC99D\uC774 \uB05D\uB0AC\uC744 \uB54C\uB9CC task\uB97C `DONE`\uC73C\uB85C \uD45C\uC2DC\uD558\uC138\uC694."
|
|
16441
16514
|
].join("\n");
|
|
@@ -16534,7 +16607,11 @@ async function runTaskRun(featureName, options) {
|
|
|
16534
16607
|
mode,
|
|
16535
16608
|
substateId: mode === "start" ? "task_run" : "task_running",
|
|
16536
16609
|
owner: "subagent",
|
|
16537
|
-
|
|
16610
|
+
handoffOnly: true,
|
|
16611
|
+
reuseKey: `task:${feature.folderName}:${resolvedTask.taskId}`,
|
|
16612
|
+
suggestedParallelism: 1,
|
|
16613
|
+
fallbackToMainAgentWhenQuotaExceeded: true,
|
|
16614
|
+
nextMainState: "task_complete",
|
|
16538
16615
|
tasksUpdated,
|
|
16539
16616
|
tasksPath,
|
|
16540
16617
|
prompt,
|
|
@@ -16548,6 +16625,13 @@ async function runTaskRun(featureName, options) {
|
|
|
16548
16625
|
console.log();
|
|
16549
16626
|
console.log(chalk8.gray(`- substate: ${payload.substateId}`));
|
|
16550
16627
|
console.log(chalk8.gray(`- owner: ${payload.owner}`));
|
|
16628
|
+
console.log(chalk8.gray(`- reuse key: ${payload.reuseKey}`));
|
|
16629
|
+
console.log(chalk8.gray(`- suggested parallelism: ${payload.suggestedParallelism}`));
|
|
16630
|
+
console.log(
|
|
16631
|
+
chalk8.gray(
|
|
16632
|
+
`- quota fallback: ${payload.fallbackToMainAgentWhenQuotaExceeded ? "continue in main agent" : "none"}`
|
|
16633
|
+
)
|
|
16634
|
+
);
|
|
16551
16635
|
console.log(chalk8.gray(`- next main state: ${payload.nextMainState}`));
|
|
16552
16636
|
if (tasksUpdated) {
|
|
16553
16637
|
console.log();
|
|
@@ -16583,6 +16667,146 @@ function taskRunCommand(program2) {
|
|
|
16583
16667
|
}
|
|
16584
16668
|
});
|
|
16585
16669
|
}
|
|
16670
|
+
function parseTaskLine2(line) {
|
|
16671
|
+
const match = line.match(
|
|
16672
|
+
/^\s*-\s*\[(TODO|DOING|DONE|REVIEW)\]\[[^\]]+\](?:\[[^\]]+\])*\s+(T-[A-Za-z0-9-]+)\s+(.+?)\s*$/
|
|
16673
|
+
);
|
|
16674
|
+
if (!match) return null;
|
|
16675
|
+
return {
|
|
16676
|
+
index: -1,
|
|
16677
|
+
raw: line,
|
|
16678
|
+
status: match[1],
|
|
16679
|
+
taskId: match[2],
|
|
16680
|
+
title: match[3]
|
|
16681
|
+
};
|
|
16682
|
+
}
|
|
16683
|
+
function setTaskStatus2(line, nextStatus) {
|
|
16684
|
+
return line.raw.replace(
|
|
16685
|
+
/^\s*-\s*\[(TODO|DOING|DONE|REVIEW)\]/,
|
|
16686
|
+
`- [${nextStatus}]`
|
|
16687
|
+
);
|
|
16688
|
+
}
|
|
16689
|
+
async function resolveTaskCompleteContext(featureName, options) {
|
|
16690
|
+
const config = await getConfig(process.cwd());
|
|
16691
|
+
if (!config) {
|
|
16692
|
+
throw createCliError(
|
|
16693
|
+
"CONFIG_NOT_FOUND",
|
|
16694
|
+
"No lee-spec-kit config found in this workspace."
|
|
16695
|
+
);
|
|
16696
|
+
}
|
|
16697
|
+
const ctx = await createCliContext({ cwd: process.cwd() });
|
|
16698
|
+
const state = await resolveContextSelection(ctx, featureName, {
|
|
16699
|
+
component: resolveComponentOption(options.component)
|
|
16700
|
+
});
|
|
16701
|
+
if (state.status !== "single_matched" || !state.matchedFeature) {
|
|
16702
|
+
throw createCliError(
|
|
16703
|
+
"CONTEXT_SELECTION_REQUIRED",
|
|
16704
|
+
"task-complete requires a single matched feature. Pass <feature-name> explicitly."
|
|
16705
|
+
);
|
|
16706
|
+
}
|
|
16707
|
+
return {
|
|
16708
|
+
config,
|
|
16709
|
+
feature: state.matchedFeature
|
|
16710
|
+
};
|
|
16711
|
+
}
|
|
16712
|
+
async function runTaskComplete(featureName, options) {
|
|
16713
|
+
const { feature } = await resolveTaskCompleteContext(featureName, options);
|
|
16714
|
+
const tasksPath = path12.join(feature.path, "tasks.md");
|
|
16715
|
+
if (!await fs.pathExists(tasksPath)) {
|
|
16716
|
+
throw createCliError(
|
|
16717
|
+
"PRECONDITION_FAILED",
|
|
16718
|
+
`tasks.md not found for feature: ${feature.folderName}`
|
|
16719
|
+
);
|
|
16720
|
+
}
|
|
16721
|
+
const content = await fs.readFile(tasksPath, "utf-8");
|
|
16722
|
+
const lines = content.split("\n");
|
|
16723
|
+
const requestedTaskId = options.task?.trim() || feature.activeTask?.id || feature.nextTodoTask?.id;
|
|
16724
|
+
if (!requestedTaskId) {
|
|
16725
|
+
throw createCliError(
|
|
16726
|
+
"PRECONDITION_FAILED",
|
|
16727
|
+
"No active task is available for task-complete."
|
|
16728
|
+
);
|
|
16729
|
+
}
|
|
16730
|
+
const resolvedTask = lines.map((line, index) => {
|
|
16731
|
+
const parsed = parseTaskLine2(line);
|
|
16732
|
+
return parsed ? { ...parsed, index } : null;
|
|
16733
|
+
}).find((entry) => entry?.taskId === requestedTaskId);
|
|
16734
|
+
if (!resolvedTask) {
|
|
16735
|
+
throw createCliError(
|
|
16736
|
+
"INVALID_ARGUMENT",
|
|
16737
|
+
`Task "${requestedTaskId}" was not found in tasks.md.`
|
|
16738
|
+
);
|
|
16739
|
+
}
|
|
16740
|
+
if (resolvedTask.status === "DONE") {
|
|
16741
|
+
throw createCliError(
|
|
16742
|
+
"PRECONDITION_FAILED",
|
|
16743
|
+
`Task "${requestedTaskId}" is already DONE.`
|
|
16744
|
+
);
|
|
16745
|
+
}
|
|
16746
|
+
if (resolvedTask.status !== "DOING" && resolvedTask.status !== "REVIEW") {
|
|
16747
|
+
throw createCliError(
|
|
16748
|
+
"PRECONDITION_FAILED",
|
|
16749
|
+
`Task "${requestedTaskId}" must be DOING/REVIEW before marking it DONE.`
|
|
16750
|
+
);
|
|
16751
|
+
}
|
|
16752
|
+
lines[resolvedTask.index] = setTaskStatus2(resolvedTask, "DONE");
|
|
16753
|
+
await fs.writeFile(tasksPath, lines.join("\n"), "utf-8");
|
|
16754
|
+
const payload = {
|
|
16755
|
+
status: "ok",
|
|
16756
|
+
reasonCode: "TASK_COMPLETED",
|
|
16757
|
+
feature: feature.folderName,
|
|
16758
|
+
taskId: resolvedTask.taskId,
|
|
16759
|
+
title: resolvedTask.title,
|
|
16760
|
+
previousStatus: resolvedTask.status,
|
|
16761
|
+
nextStatus: "DONE",
|
|
16762
|
+
substateId: "task_complete",
|
|
16763
|
+
owner: "main",
|
|
16764
|
+
nextMainState: "task_finalize",
|
|
16765
|
+
tasksUpdated: true,
|
|
16766
|
+
tasksPath,
|
|
16767
|
+
recordedAt: getLocalDateString()
|
|
16768
|
+
};
|
|
16769
|
+
if (options.json) {
|
|
16770
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
16771
|
+
return;
|
|
16772
|
+
}
|
|
16773
|
+
console.log(
|
|
16774
|
+
chalk8.green(
|
|
16775
|
+
`Marked task ${resolvedTask.taskId} as DONE for ${feature.folderName}.`
|
|
16776
|
+
)
|
|
16777
|
+
);
|
|
16778
|
+
console.log(chalk8.gray(`- tasks.md updated: ${tasksPath}`));
|
|
16779
|
+
console.log(chalk8.gray(`- status: ${resolvedTask.status} -> DONE`));
|
|
16780
|
+
console.log(chalk8.gray(`- next main state: ${payload.nextMainState}`));
|
|
16781
|
+
}
|
|
16782
|
+
function taskCompleteCommand(program2) {
|
|
16783
|
+
program2.command("task-complete [feature-name]").description("Mark the active DOING/REVIEW task as DONE").option("--component <component>", "Component name for multi projects").option("--task <task-id>", "Explicit task id to mark DONE").option("--json", "Output JSON").action(
|
|
16784
|
+
async (featureName, options) => {
|
|
16785
|
+
try {
|
|
16786
|
+
await runTaskComplete(featureName, options);
|
|
16787
|
+
} catch (error) {
|
|
16788
|
+
const config = await getConfig(process.cwd());
|
|
16789
|
+
const lang = config?.lang ?? DEFAULT_LANG;
|
|
16790
|
+
const cliError = toCliError(error);
|
|
16791
|
+
const suggestions = getCliErrorSuggestions(cliError.code, lang);
|
|
16792
|
+
if (options.json) {
|
|
16793
|
+
console.log(
|
|
16794
|
+
JSON.stringify({
|
|
16795
|
+
status: "error",
|
|
16796
|
+
reasonCode: cliError.code,
|
|
16797
|
+
error: cliError.message,
|
|
16798
|
+
suggestions
|
|
16799
|
+
})
|
|
16800
|
+
);
|
|
16801
|
+
} else {
|
|
16802
|
+
console.error(chalk8.red(`[${cliError.code}] ${cliError.message}`));
|
|
16803
|
+
printCliErrorSuggestions(suggestions, lang);
|
|
16804
|
+
}
|
|
16805
|
+
process.exitCode = 1;
|
|
16806
|
+
}
|
|
16807
|
+
}
|
|
16808
|
+
);
|
|
16809
|
+
}
|
|
16586
16810
|
function isBannerDisabled() {
|
|
16587
16811
|
const v = (process.env.LEE_SPEC_KIT_NO_BANNER || "").trim();
|
|
16588
16812
|
return v === "1";
|
|
@@ -16766,6 +16990,7 @@ onboardCommand(program);
|
|
|
16766
16990
|
prePrReviewCommand(program);
|
|
16767
16991
|
codeReviewRunCommand(program);
|
|
16768
16992
|
taskRunCommand(program);
|
|
16993
|
+
taskCompleteCommand(program);
|
|
16769
16994
|
requirementsCommand(program);
|
|
16770
16995
|
await program.parseAsync();
|
|
16771
16996
|
//# sourceMappingURL=index.js.map
|