lee-spec-kit 0.6.38 → 0.6.40

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 CHANGED
@@ -8,7 +8,7 @@ import chalk8 from 'chalk';
8
8
  import { spawn, spawnSync, execFileSync, execSync } from 'child_process';
9
9
  import os from 'os';
10
10
  import { createHash, randomUUID } from 'crypto';
11
- import fs10 from 'fs';
11
+ import fs9 from 'fs';
12
12
  import { Buffer as Buffer$1 } from 'buffer';
13
13
 
14
14
  var getFilename = () => fileURLToPath(import.meta.url);
@@ -215,6 +215,7 @@ var koCli = {
215
215
  "doctor.issue.tasksEmpty": "tasks.md\uC5D0 \uD0DC\uC2A4\uD06C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
216
216
  "doctor.issue.tasksDocStatusUnset": "tasks.md\uC758 \uBB38\uC11C \uC0C1\uD0DC(Doc Status)\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. (Draft/Review/Approved \uC911 \uD558\uB098\uB85C \uC124\uC815\uD558\uC138\uC694.)",
217
217
  "doctor.issue.tasksDocStatusMissing": "tasks.md\uC5D0 \uBB38\uC11C \uC0C1\uD0DC(Doc Status) \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. `- **\uBB38\uC11C \uC0C1\uD0DC**: -`\uC640 `\uAC12: Draft | Review | Approved`\uB97C \uCD94\uAC00\uD558\uC138\uC694.",
218
+ "doctor.issue.tasksPrdTagUnknown": "tasks.md\uC5D0 \uC815\uC758\uB418\uC9C0 \uC54A\uC740 PRD \uD0DC\uADF8\uAC00 \uC788\uC2B5\uB2C8\uB2E4: {ids}{extra}. tasks.md\uC5D0\uC11C PRD-FR-001 \uAC19\uC740 ID\uB97C \uC784\uC758\uB85C \uB9CC\uB4E4\uC9C0 \uB9D0\uACE0, \uBA3C\uC800 docs/prd \uB610\uB294 \uC0C1\uC704 \uC694\uAD6C\uC0AC\uD56D \uBB38\uC11C\uC5D0 ID\uB97C backfill\uD55C \uB4A4 spec.md `PRD Refs`\uC640 tasks \uD0DC\uADF8\uB97C \uD568\uAED8 \uB9DE\uCD94\uC138\uC694.",
218
219
  "doctor.issue.duplicateFeatureId": "\uC911\uBCF5 Feature ID \uAC10\uC9C0: {id} ({count}\uAC1C)",
219
220
  "doctor.issue.missingFeatureId": "Feature \uD3F4\uB354\uBA85\uC774 F001-... \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4. (ID\uB97C \uCD94\uCD9C\uD560 \uC218 \uC5C6\uC74C)",
220
221
  "init.selectLangPrompt": "\uBB38\uC11C \uC5B8\uC5B4\uB97C \uC120\uD0DD\uD558\uC138\uC694:",
@@ -469,15 +470,15 @@ var koContext = {
469
470
  "context.autoRunUnavailable": "\uD604\uC7AC \uCEE8\uD14D\uC2A4\uD2B8\uC5D0\uC11C\uB294 \uC790\uB3D9 \uC2E4\uD589\uC744 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
470
471
  "context.autoRunSummary": "config \uAE30\uC900\uC73C\uB85C \uC2B9\uC778 \uD544\uC694 \uCE74\uD14C\uACE0\uB9AC \uC804\uAE4C\uC9C0 \uC5F0\uC18D \uC2E4\uD589\uD558\uC138\uC694: {categories}",
471
472
  "context.autoRunCommandHint": "\uC790\uB3D9 \uC2E4\uD589 \uBA85\uB839(config \uAC8C\uC774\uD2B8): {command}",
472
- "context.subAgentOrchestrationHint": "\uBA54\uC778 \uC5D0\uC774\uC804\uD2B8 \uC624\uCF00\uC2A4\uD2B8\uB808\uC774\uC158: \uAC00\uB2A5\uD558\uBA74 `matchedFeature.currentSubstateOwner`\uB97C \uC6B0\uC120 \uC0AC\uC6A9\uD558\uC138\uC694. main \uC18C\uC720 \uC0C1\uD0DC\uB294 \uBA54\uC778\uC5D0\uC11C \uCC98\uB9AC\uD558\uACE0, subagent \uC18C\uC720 command \uC0C1\uD0DC\uB9CC \uC704\uC784\uD558\uBA70, \uC7A5\uC2DC\uAC04 category\uB294 \uB808\uAC70\uC2DC fallback\uC73C\uB85C\uB9CC \uC0AC\uC6A9\uD558\uC138\uC694.",
473
+ "context.subAgentOrchestrationHint": "\uBA54\uC778 \uC5D0\uC774\uC804\uD2B8\uAC00 \uC804\uCCB4 \uD750\uB984\uACFC \uC2B9\uC778\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4. \uD604\uC7AC \uB2E8\uACC4\uC758 owner\uAC00 `subagent`\uBA74 \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8\uC5D0 \uB9E1\uAE30\uACE0, `main`\uC774\uBA74 \uBA54\uC778\uC5D0\uC11C \uC9C4\uD589\uD558\uC138\uC694.",
473
474
  "context.commandDetail.branchCreateWithWorktree": "({scope}) worktree {worktree}\uB97C \uC0AC\uC6A9\uD574 \uBE0C\uB79C\uCE58 {branch}\uB97C \uC0DD\uC131\uD558\uAC70\uB098 \uC7AC\uC0AC\uC6A9\uD558\uC138\uC694",
474
475
  "context.commandDetail.branchCreateWithBranch": "({scope}) \uBE0C\uB79C\uCE58 {branch}\uC6A9 worktree\uB97C \uC0DD\uC131\uD558\uAC70\uB098 \uC7AC\uC0AC\uC6A9\uD558\uC138\uC694",
475
476
  "context.commandDetail.branchCreateGeneric": "({scope}) feature \uBE0C\uB79C\uCE58\uC6A9 worktree\uB97C \uC0DD\uC131\uD558\uAC70\uB098 \uC7AC\uC0AC\uC6A9\uD558\uC138\uC694",
476
477
  "context.commandDetail.codeReviewMergeAfterOk": "({scope}) \uBA85\uC2DC\uC801 \uC2B9\uC778 \uD6C4 PR\uC744 \uBA38\uC9C0\uD558\uC138\uC694",
477
478
  "context.commandDetail.codeReviewPushFix": "({scope}) \uB9AC\uBDF0 \uC218\uC815 \uCEE4\uBC0B\uC744 push\uD558\uC138\uC694",
478
- "context.commandDetail.prePrReviewRun": "({scope}) \uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uC2E4\uD589\uC6A9 Pre-PR \uB9AC\uBDF0 handoff\uB97C \uC2DC\uC791\uD558\uC138\uC694",
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",
479
480
  "context.commandDetail.prePrReviewRecord": "({scope}) Pre-PR \uB9AC\uBDF0 evidence\uB97C decisions.md\uC640 tasks.md\uC5D0 \uAE30\uB85D\uD558\uC138\uC694",
480
- "context.commandDetail.codeReviewRun": "({scope}) \uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uC2E4\uD589\uC6A9 PR \uB9AC\uBDF0 handoff\uB97C \uC2DC\uC791\uD558\uC138\uC694",
481
+ "context.commandDetail.codeReviewRun": "({scope}) \uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent)\uB85C PR \uB9AC\uBDF0\uB97C \uC2E4\uD589\uD574 evidence/\uC218\uC815 \uC694\uC57D\uC744 \uC900\uBE44\uD558\uC138\uC694",
481
482
  "context.actionSummary.runDocsCommand": "\uBB38\uC11C \uC791\uC5C5 \uBA85\uB839\uC744 \uC2E4\uD589\uD558\uC138\uC694",
482
483
  "context.actionSummary.runProjectCommand": "\uD504\uB85C\uC81D\uD2B8 \uC791\uC5C5 \uBA85\uB839\uC744 \uC2E4\uD589\uD558\uC138\uC694",
483
484
  "context.actionDetail.featureFolder": "Feature \uD3F4\uB354\uC640 \uAE30\uBCF8 \uBB38\uC11C \uACE8\uACA9\uC744 \uC900\uBE44\uD558\uC138\uC694",
@@ -495,12 +496,12 @@ var koContext = {
495
496
  "context.actionDetail.issueCreatePrepareFromDoc": "issue.md \uCD08\uC548\uC744 \uBCF4\uC644\uD558\uACE0 \uC0C1\uD0DC\uB97C Ready\uB85C \uC124\uC815\uD558\uC138\uC694",
496
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",
497
498
  "context.actionDetail.taskExecute": "\uD604\uC7AC \uD0DC\uC2A4\uD06C\uB97C \uC9C4\uD589\uD558\uC138\uC694",
498
- "context.actionDetail.taskExecuteRun": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uAD6C\uD604\uC6A9 task \uC2E4\uD589 handoff\uB97C \uC2DC\uC791\uD558\uC138\uC694",
499
- "context.actionDetail.taskExecuteContinue": "\uC9C4\uD589 \uC911\uC778 task \uC2E4\uD589\uC744 \uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 handoff\uB85C \uC774\uC5B4\uAC00\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 \uC774\uC5B4\uAC00\uC138\uC694",
500
501
  "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",
501
- "context.actionDetail.prePrReviewRun": "PR \uC804 \uB9AC\uBDF0\uB97C \uC218\uD589\uD558\uACE0 review-trace.json evidence\uB97C \uC0DD\uC131\uD558\uC138\uC694",
502
+ "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",
502
503
  "context.actionDetail.prePrReviewRecord": "PR \uC804 \uB9AC\uBDF0 evidence\uB97C decisions.md\uC640 tasks.md\uC5D0 \uAE30\uB85D\uD558\uC138\uC694",
503
- "context.actionDetail.codeReviewRun": "PR \uB9AC\uBDF0\uB97C \uC218\uD589\uD558\uACE0 \uB9AC\uBDF0 evidence/\uC218\uC815 \uC694\uC57D\uC744 \uC900\uBE44\uD558\uC138\uC694",
504
+ "context.actionDetail.codeReviewRun": "\uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8(sub-agent)\uB85C PR \uB9AC\uBDF0\uB97C \uC2E4\uD589\uD574 evidence/\uC218\uC815 \uC694\uC57D\uC744 \uC900\uBE44\uD558\uC138\uC694",
504
505
  "context.actionDetail.prCreate": "PR\uC744 \uC0DD\uC131\uD558\uACE0 tasks \uAE30.md\uC758 PR \uC815\uBCF4\uB97C \uB9DE\uCD94\uC138\uC694",
505
506
  "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",
506
507
  "context.actionDetail.prCreatePrepareFromDoc": "pr.md \uCD08\uC548\uC744 \uBCF4\uC644\uD558\uACE0 \uC0C1\uD0DC\uB97C Ready\uB85C \uC124\uC815\uD558\uC138\uC694",
@@ -623,7 +624,7 @@ var koMessages = {
623
624
  taskCommitGateReasonMismatchLastDone: "\uCD5C\uADFC \uD504\uB85C\uC81D\uD2B8 \uCF54\uB4DC \uCEE4\uBC0B\uC774 \uC9C1\uC804 \uC644\uB8CC \uD0DC\uC2A4\uD06C\uC640 \uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4",
624
625
  prLegacyAsk: "tasks.md\uC5D0 PR/PR \uC0C1\uD0DC \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uD15C\uD50C\uB9BF\uC744 \uCD5C\uC2E0 \uD3EC\uB9F7\uC73C\uB85C \uC5C5\uB370\uC774\uD2B8\uD560\uAE4C\uC694? (\uD655\uC778 \uD544\uC694)",
625
626
  prePrReviewFieldMissing: "tasks.md\uC5D0 `PR \uC804 \uB9AC\uBDF0` \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. `- **PR \uC804 \uB9AC\uBDF0**: Pending | Done` \uD56D\uBAA9\uC744 \uCD94\uAC00\uD558\uACE0 \uB2E4\uC2DC context\uB97C \uC2E4\uD589\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
626
- prePrReviewRun: "\uCF54\uB4DC \uB9AC\uBDF0 \uC5D0\uC774\uC804\uD2B8\uB97C \uC2E4\uD589\uD574 `spec.md`/`plan.md`/`tasks.md` \uB300\uBE44 \uAD6C\uD604 \uC801\uD569\uC131\uC744 \uAC80\uD1A0\uD558\uACE0, `Summary`/`Feature Intent Summary`/`Implementation Fit`/`Missing Cases`/`Spec Alignment Checked`/`Finding Count`/`Blocking Findings`/`Findings`/`Residual Risks`\uAC00 \uD3EC\uD568\uB41C `review-trace.json`\uC744 \uC0DD\uC131\uD55C \uB4A4 `pre-pr-review`\uB85C \uB9AC\uBDF0 \uACB0\uACFC\uB97C \uAE30\uB85D\uD558\uC138\uC694. \uD604\uC7AC evidence \uC815\uCC45\uC774 \uACBD\uB85C\uB97C \uC694\uAD6C\uD560 \uB54C\uB9CC `--evidence review-trace.json`\uC744 \uD568\uAED8 \uC0AC\uC6A9\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
627
+ prePrReviewRun: "\uCF54\uB4DC \uB9AC\uBDF0 \uC5D0\uC774\uC804\uD2B8\uB97C \uC2E4\uD589\uD574 `spec.md`/`plan.md`/`tasks.md` \uB300\uBE44 \uAD6C\uD604 \uC801\uD569\uC131\uC744 \uAC80\uD1A0\uD558\uACE0, `Summary`/`Feature Intent Summary`/`Implementation Fit`/`Missing Cases`/`Spec Alignment Checked`/`Finding Count`/`Blocking Findings`/`Findings`/`Residual Risks`\uAC00 \uD3EC\uD568\uB41C `review-trace.json`\uC744 \uC0DD\uC131\uD55C \uB4A4 `pre-pr-review`\uB85C \uB9AC\uBDF0 \uACB0\uACFC\uB97C \uAE30\uB85D\uD558\uC138\uC694. `pre-pr-review-run` \uC790\uCCB4\uB294 evidence\uB97C \uC0DD\uC131\uD558\uAC70\uB098 \uC0C1\uD0DC\uB97C \uBC14\uB85C \uB118\uAE30\uC9C0 \uC54A\uC73C\uBA70, \uD604\uC7AC evidence \uC815\uCC45\uC774 \uACBD\uB85C\uB97C \uC694\uAD6C\uD560 \uB54C\uB9CC `--evidence review-trace.json`\uC744 \uD568\uAED8 \uC0AC\uC6A9\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
627
628
  prePrReviewEvidenceMissing: "tasks.md\uC758 `PR \uC804 \uB9AC\uBDF0 Evidence`\uAC00 \uBE44\uC5B4\uC788\uAC70\uB098 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC2E4\uC81C \uD30C\uC77C \uACBD\uB85C\uC640 `Pre-PR Review Log`(\uB610\uB294 `PR \uC804 \uB9AC\uBDF0 \uB85C\uADF8`)\uC5D0 placeholder\uAC00 \uC544\uB2CC `Summary`/`Feature Intent Summary`/`Implementation Fit`/`Missing Cases`/`Spec Alignment Checked`/`Finding Count`/`Blocking Findings`/`Decision`/`Findings`(\uB610\uB294 \uBA85\uC2DC\uC801 `0 findings`)/`Residual Risks`\uB97C \uAE30\uB85D\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
628
629
  prePrReviewDecisionMissing: "tasks.md\uC758 `PR \uC804 \uB9AC\uBDF0 Decision`\uC774 \uBE44\uC5B4\uC788\uAC70\uB098 \uACB0\uC815 \uD615\uC2DD\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. `\uACB0\uC815: ...`(\uB610\uB294 `decision: ...`) \uD615\uC2DD\uC73C\uB85C \uAE30\uB85D\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
629
630
  prePrReviewFixRequired: "\uD604\uC7AC `PR \uC804 \uB9AC\uBDF0 Decision`\uC774 `{decision}`\uC785\uB2C8\uB2E4. PR \uC0DD\uC131 \uB2E8\uACC4\uB85C \uC774\uB3D9\uD558\uAE30 \uC804\uC5D0 pre-PR \uC9C0\uC801\uC0AC\uD56D\uC744 \uCF54\uB4DC\uC5D0 \uBC18\uC601\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
@@ -766,6 +767,7 @@ var enCli = {
766
767
  "doctor.issue.tasksEmpty": "tasks.md has no tasks.",
767
768
  "doctor.issue.tasksDocStatusUnset": "tasks.md Doc Status is not set. (Set it to Draft, Review, or Approved.)",
768
769
  "doctor.issue.tasksDocStatusMissing": "tasks.md is missing the Doc Status field. Add `- **Doc Status**: -` and `Values: Draft | Review | Approved`.",
770
+ "doctor.issue.tasksPrdTagUnknown": "tasks.md uses PRD tags with no matching source definition: {ids}{extra}. Do not invent IDs like PRD-FR-001 in tasks.md. Backfill IDs in docs/prd or the upstream requirements doc first, then align spec.md `PRD Refs` and task tags.",
769
771
  "doctor.issue.duplicateFeatureId": "Duplicate Feature ID detected: {id} ({count})",
770
772
  "doctor.issue.missingFeatureId": "Feature folder name is not in F001-... format. (Cannot extract ID)",
771
773
  "init.selectLangPrompt": "Select docs language:",
@@ -1020,15 +1022,15 @@ var enContext = {
1020
1022
  "context.autoRunUnavailable": "Auto-run is not available in the current context.",
1021
1023
  "context.autoRunSummary": "Run continuously by config until approval-required categories appear: {categories}",
1022
1024
  "context.autoRunCommandHint": "Auto-run command (config-based gate): {command}",
1023
- "context.subAgentOrchestrationHint": "Main-agent orchestration: prefer `matchedFeature.currentSubstateOwner` when present. Keep main-owned states in the main agent, delegate subagent-owned command states, and use long-running categories only as a legacy fallback.",
1025
+ "context.subAgentOrchestrationHint": "The main agent manages overall flow and approvals. If the current state owner is `subagent`, hand execution to a helper agent; if it is `main`, keep it in the main agent.",
1024
1026
  "context.commandDetail.branchCreateWithWorktree": "({scope}) create or reuse worktree {worktree} for branch {branch}",
1025
1027
  "context.commandDetail.branchCreateWithBranch": "({scope}) create or reuse worktree for branch {branch}",
1026
1028
  "context.commandDetail.branchCreateGeneric": "({scope}) create or reuse feature branch worktree",
1027
1029
  "context.commandDetail.codeReviewMergeAfterOk": "({scope}) merge PR after explicit OK",
1028
1030
  "context.commandDetail.codeReviewPushFix": "({scope}) push review-fix commits",
1029
- "context.commandDetail.prePrReviewRun": "({scope}) launch pre-PR review handoff for sub-agent execution",
1031
+ "context.commandDetail.prePrReviewRun": "({scope}) run the pre-PR review via a helper agent/sub-agent and prepare `review-trace.json`",
1030
1032
  "context.commandDetail.prePrReviewRecord": "({scope}) record pre-PR review evidence into decisions.md + tasks.md",
1031
- "context.commandDetail.codeReviewRun": "({scope}) launch PR review handoff for sub-agent execution",
1033
+ "context.commandDetail.codeReviewRun": "({scope}) run the PR review via a helper agent/sub-agent and prepare evidence/fix summary",
1032
1034
  "context.actionSummary.runDocsCommand": "Run docs command",
1033
1035
  "context.actionSummary.runProjectCommand": "Run project command",
1034
1036
  "context.actionDetail.featureFolder": "Prepare feature folder and baseline docs",
@@ -1046,12 +1048,12 @@ var enContext = {
1046
1048
  "context.actionDetail.issueCreatePrepareFromDoc": "Refine issue.md draft and set Status to Ready",
1047
1049
  "context.actionDetail.issueCreateFromDoc": "Create GitHub Issue from ready issue.md and sync Issue",
1048
1050
  "context.actionDetail.taskExecute": "Proceed with the current task",
1049
- "context.actionDetail.taskExecuteRun": "Launch task execution handoff for sub-agent implementation",
1050
- "context.actionDetail.taskExecuteContinue": "Continue in-progress task execution via sub-agent handoff",
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 continue the in-progress task",
1051
1053
  "context.actionDetail.reviewFixCommit": "Create a review-fix commit with resolved feedback summary",
1052
- "context.actionDetail.prePrReviewRun": "Run pre-PR review and generate review-trace.json evidence",
1054
+ "context.actionDetail.prePrReviewRun": "Run the pre-PR review via a helper agent/sub-agent and prepare `review-trace.json`",
1053
1055
  "context.actionDetail.prePrReviewRecord": "Record pre-PR review evidence into decisions.md and tasks.md",
1054
- "context.actionDetail.codeReviewRun": "Run PR review and prepare review evidence/fix summary",
1056
+ "context.actionDetail.codeReviewRun": "Run the PR review via a helper agent/sub-agent and prepare evidence/fix summary",
1055
1057
  "context.actionDetail.prCreate": "Create PR and sync PR fields in tasks.md",
1056
1058
  "context.actionDetail.prCreateRequiredSequence": "Complete PR 2-step flow: prepare draft + OK, then create and sync",
1057
1059
  "context.actionDetail.prCreatePrepareFromDoc": "Refine pr.md draft and set Status to Ready",
@@ -1174,7 +1176,7 @@ var enMessages = {
1174
1176
  taskCommitGateReasonMismatchLastDone: "The latest project code commit does not match the last completed task",
1175
1177
  prLegacyAsk: "tasks.md is missing PR/PR Status fields. Update to the latest template format? (CHECK required)",
1176
1178
  prePrReviewFieldMissing: "tasks.md is missing the `Pre-PR Review` field. Add `- **Pre-PR Review**: Pending | Done` and run context again. (CHECK required)",
1177
- prePrReviewRun: "Run the code review agent, compare the implementation against `spec.md`/`plan.md`/`tasks.md`, and generate `review-trace.json` with `Summary`, `Feature Intent Summary`, `Implementation Fit`, `Missing Cases`, `Spec Alignment Checked`, `Finding Count`, `Blocking Findings`, `Findings`, and `Residual Risks`. Then record findings with `pre-pr-review`; use `--evidence review-trace.json` when the active evidence policy requires a path. (CHECK required)",
1179
+ prePrReviewRun: "Run the code review agent, compare the implementation against `spec.md`/`plan.md`/`tasks.md`, and generate `review-trace.json` with `Summary`, `Feature Intent Summary`, `Implementation Fit`, `Missing Cases`, `Spec Alignment Checked`, `Finding Count`, `Blocking Findings`, `Findings`, and `Residual Risks`. Then record findings with `pre-pr-review`; `pre-pr-review-run` itself does not generate evidence or advance state, and you should use `--evidence review-trace.json` only when the active evidence policy requires a path. (CHECK required)",
1178
1180
  prePrReviewEvidenceMissing: "tasks.md `Pre-PR Evidence` is empty/invalid. Point to a real file and include a `Pre-PR Review Log` section with non-placeholder `Summary`, `Feature Intent Summary`, `Implementation Fit`, `Missing Cases`, `Spec Alignment Checked`, `Finding Count`, `Blocking Findings`, `Decision`, `Findings` (or explicit `0 findings`), and `Residual Risks`. (CHECK required)",
1179
1181
  prePrReviewDecisionMissing: "tasks.md `Pre-PR Decision` is empty/placeholder or missing decision format. Record it as `decision: ...` (or `\uACB0\uC815: ...`). (CHECK required)",
1180
1182
  prePrReviewFixRequired: "Current `Pre-PR Decision` is `{decision}`. Apply the requested fixes from pre-PR findings before moving to PR creation. (CHECK required)",
@@ -3699,19 +3701,35 @@ function buildCodeReviewRunCommandArgs(feature) {
3699
3701
  }
3700
3702
  return commandArgs;
3701
3703
  }
3704
+ function isNonEmptyStringValue(value) {
3705
+ return typeof value === "string" && value.trim().length > 0;
3706
+ }
3707
+ function isNonNegativeIntegerValue(value) {
3708
+ return Number.isInteger(value) && Number(value) >= 0;
3709
+ }
3710
+ function isLikelyCurrentPrePrReviewEvidence(evidencePath, feature) {
3711
+ try {
3712
+ const raw = fs9.readFileSync(evidencePath, "utf-8");
3713
+ const parsed = JSON.parse(raw);
3714
+ const evidenceFeature = (parsed.feature || "").toString().trim();
3715
+ if (evidenceFeature && evidenceFeature !== feature.folderName) {
3716
+ return false;
3717
+ }
3718
+ return isNonEmptyStringValue(parsed.summary) && isNonEmptyStringValue(parsed.featureIntentSummary) && isNonEmptyStringValue(parsed.implementationFit) && isNonEmptyStringValue(parsed.missingCases) && typeof parsed.specAlignmentChecked === "boolean" && isNonNegativeIntegerValue(parsed.findingCount) && isNonNegativeIntegerValue(parsed.blockingFindings) && Array.isArray(parsed.files);
3719
+ } catch {
3720
+ return false;
3721
+ }
3722
+ }
3702
3723
  function resolvePrePrReviewEvidencePath(feature) {
3703
3724
  const docsRoot = feature.git.docsGitCwd;
3704
- const docsParent = path12.dirname(docsRoot);
3705
3725
  const candidates = [];
3706
3726
  const explicit = (feature.prePrReview.evidence || "").trim();
3707
3727
  if (explicit && explicit !== "-") {
3708
3728
  if (path12.isAbsolute(explicit)) {
3709
3729
  candidates.push(explicit);
3710
3730
  } else {
3711
- candidates.push(path12.resolve(docsRoot, explicit));
3712
- candidates.push(path12.resolve(docsParent, explicit));
3713
- candidates.push(path12.resolve(process.cwd(), explicit));
3714
3731
  candidates.push(path12.resolve(feature.path, explicit));
3732
+ candidates.push(path12.resolve(docsRoot, explicit));
3715
3733
  const normalizedExplicit = explicit.replace(/\\/g, "/");
3716
3734
  if (normalizedExplicit.startsWith("docs/")) {
3717
3735
  const withoutDocsPrefix = normalizedExplicit.slice("docs/".length);
@@ -3721,16 +3739,16 @@ function resolvePrePrReviewEvidencePath(feature) {
3721
3739
  }
3722
3740
  }
3723
3741
  }
3724
- candidates.push(path12.resolve(process.cwd(), "review-trace.json"));
3725
- candidates.push(path12.join(docsRoot, "review-trace.json"));
3726
3742
  candidates.push(path12.join(feature.path, "review-trace.json"));
3743
+ candidates.push(path12.join(docsRoot, "review-trace.json"));
3727
3744
  const seen = /* @__PURE__ */ new Set();
3728
3745
  for (const candidate of candidates) {
3729
3746
  const abs = path12.resolve(candidate);
3730
3747
  if (seen.has(abs)) continue;
3731
3748
  seen.add(abs);
3732
- if (!fs10.existsSync(abs)) continue;
3749
+ if (!fs9.existsSync(abs)) continue;
3733
3750
  if (!abs.toLowerCase().endsWith(".json")) continue;
3751
+ if (!isLikelyCurrentPrePrReviewEvidence(abs, feature)) continue;
3734
3752
  const rel = path12.relative(docsRoot, abs).replace(/\\/g, "/");
3735
3753
  if (rel && !rel.startsWith("../")) {
3736
3754
  return rel;
@@ -6032,7 +6050,7 @@ function resolveExistingExpectedWorktreePath(projectGitCwd, issueNumber, slug, f
6032
6050
  slug,
6033
6051
  folderName
6034
6052
  )) {
6035
- if (!fs10.existsSync(candidate)) continue;
6053
+ if (!fs9.existsSync(candidate)) continue;
6036
6054
  return candidate;
6037
6055
  }
6038
6056
  return void 0;
@@ -6062,7 +6080,7 @@ function resolveFeatureWorktreePath(ctx, projectGitCwd, issueNumber, slug, folde
6062
6080
  slug,
6063
6081
  folderName
6064
6082
  )) {
6065
- if (!fs10.existsSync(candidate)) continue;
6083
+ if (!fs9.existsSync(candidate)) continue;
6066
6084
  const branchName = getCurrentBranch(ctx, candidate);
6067
6085
  if (!expectedBranchesSet.has(branchName)) continue;
6068
6086
  return {
@@ -10090,6 +10108,108 @@ function printChecklist(f, stepDefinitions) {
10090
10108
  console.log(` ${mark} ${definition.step}. ${label} ${detail}`);
10091
10109
  });
10092
10110
  }
10111
+ var PRD_REQUIREMENT_ID_RE = /\bPRD-(?:FR|US|NFR)-\d+\b/gi;
10112
+ function isPrdRequirementId(value) {
10113
+ return /^PRD-(?:FR|US|NFR)-\d+$/i.test(value.trim());
10114
+ }
10115
+ function isNonPrdTag(value) {
10116
+ const trimmed = value.trim();
10117
+ return /^NON[-_ ]?PRD$/i.test(trimmed);
10118
+ }
10119
+ function normalizeRelPath2(value) {
10120
+ return value.replace(/\\/g, "/").replace(/^\.\/+/, "");
10121
+ }
10122
+ function extractTitleAfterId(line, id) {
10123
+ const idx = line.indexOf(id);
10124
+ if (idx < 0) return void 0;
10125
+ const after = line.slice(idx + id.length);
10126
+ const cleaned = after.replace(/^[\s::\-–—)\]]+/, "").trim();
10127
+ return cleaned ? cleaned : void 0;
10128
+ }
10129
+ async function scanPrdRequirements(fsAdapter, docsDir) {
10130
+ const prdDir = path12.join(docsDir, "prd");
10131
+ const files = await walkFiles(fsAdapter, prdDir, {
10132
+ extensions: [".md"],
10133
+ ignoreDirs: [".git", "node_modules", "dist", "tmp"]
10134
+ });
10135
+ const definitions = /* @__PURE__ */ new Map();
10136
+ const duplicates = [];
10137
+ for (const filePath of files) {
10138
+ if (path12.basename(filePath).toLowerCase() === "readme.md") {
10139
+ continue;
10140
+ }
10141
+ let content = "";
10142
+ try {
10143
+ content = await fsAdapter.readFile(filePath, "utf-8");
10144
+ } catch {
10145
+ continue;
10146
+ }
10147
+ const relFile = normalizeRelPath2(path12.relative(docsDir, filePath));
10148
+ const lines = content.split(/\r?\n/);
10149
+ let inCodeBlock = false;
10150
+ for (let i = 0; i < lines.length; i += 1) {
10151
+ const line = lines[i] || "";
10152
+ if (/^\s*(```|~~~)/.test(line)) {
10153
+ inCodeBlock = !inCodeBlock;
10154
+ continue;
10155
+ }
10156
+ if (inCodeBlock) continue;
10157
+ const ids = [...line.matchAll(PRD_REQUIREMENT_ID_RE)].map(
10158
+ (match) => (match[0] || "").toUpperCase()
10159
+ );
10160
+ if (ids.length === 0) continue;
10161
+ for (const id of ids) {
10162
+ const def = {
10163
+ id,
10164
+ title: extractTitleAfterId(line, id),
10165
+ file: relFile,
10166
+ line: i + 1
10167
+ };
10168
+ const existing = definitions.get(id);
10169
+ if (existing) {
10170
+ duplicates.push(def);
10171
+ continue;
10172
+ }
10173
+ definitions.set(id, def);
10174
+ }
10175
+ }
10176
+ }
10177
+ return { definitions, duplicates, filesScanned: files.length };
10178
+ }
10179
+ function parseTaskLines(content) {
10180
+ const out = [];
10181
+ const lines = content.split(/\r?\n/);
10182
+ let inCodeBlock = false;
10183
+ for (let i = 0; i < lines.length; i += 1) {
10184
+ const line = lines[i] || "";
10185
+ if (/^\s*(```|~~~)/.test(line)) {
10186
+ inCodeBlock = !inCodeBlock;
10187
+ continue;
10188
+ }
10189
+ if (inCodeBlock) continue;
10190
+ const match = line.match(
10191
+ /^\s*-\s*\[([A-Z]+)\]((?:\[[^\]]+\])*)\s*(.+?)\s*$/
10192
+ );
10193
+ if (!match) continue;
10194
+ const status = (match[1] || "").trim().toUpperCase();
10195
+ const tagsPart = match[2] || "";
10196
+ const title = (match[3] || "").trim();
10197
+ if (!title) continue;
10198
+ if (status !== "TODO" && status !== "DOING" && status !== "DONE" && status !== "REVIEW") {
10199
+ continue;
10200
+ }
10201
+ const tags = [...tagsPart.matchAll(/\[([^\]]+)\]/g)].map((m) => (m[1] || "").trim()).filter(Boolean);
10202
+ out.push({
10203
+ status,
10204
+ tags,
10205
+ title,
10206
+ line: i + 1
10207
+ });
10208
+ }
10209
+ return out;
10210
+ }
10211
+
10212
+ // src/commands/doctor.ts
10093
10213
  var FIXABLE_ISSUE_CODES = /* @__PURE__ */ new Set([
10094
10214
  "placeholder_left",
10095
10215
  "spec_status_unset",
@@ -10346,6 +10466,10 @@ async function checkDocsStructure(config, cwd) {
10346
10466
  }
10347
10467
  async function checkFeatures(config, cwd, features, decisionsPlaceholderMode) {
10348
10468
  const issues = [];
10469
+ const { definitions: prdDefinitions } = await scanPrdRequirements(
10470
+ fs,
10471
+ config.docsDir
10472
+ );
10349
10473
  if (features.length === 0) {
10350
10474
  issues.push({
10351
10475
  level: "warn",
@@ -10427,6 +10551,24 @@ async function checkFeatures(config, cwd, features, decisionsPlaceholderMode) {
10427
10551
  path: formatPath(cwd, path12.join(f.path, "tasks.md"))
10428
10552
  });
10429
10553
  }
10554
+ if (f.docs.tasksExists) {
10555
+ const tasksPath = path12.join(f.path, "tasks.md");
10556
+ const tasksContent = await fs.readFile(tasksPath, "utf-8");
10557
+ const unknownPrdTags = [...new Set(
10558
+ parseTaskLines(tasksContent).flatMap((task) => task.tags).filter((tag) => isPrdRequirementId(tag)).map((tag) => tag.trim().toUpperCase()).filter((tag) => !prdDefinitions.has(tag))
10559
+ )].sort();
10560
+ if (unknownPrdTags.length > 0) {
10561
+ issues.push({
10562
+ level: "warn",
10563
+ code: "tasks_prd_tag_unknown",
10564
+ message: tr(config.lang, "cli", "doctor.issue.tasksPrdTagUnknown", {
10565
+ ids: unknownPrdTags.slice(0, 5).join(", "),
10566
+ extra: unknownPrdTags.length > 5 ? ` (+${unknownPrdTags.length - 5} more)` : ""
10567
+ }),
10568
+ path: formatPath(cwd, tasksPath)
10569
+ });
10570
+ }
10571
+ }
10430
10572
  if (f.docs.tasksExists && !f.docs.tasksDocStatusFieldExists && !isInitialTemplateState) {
10431
10573
  issues.push({
10432
10574
  level: "warn",
@@ -15644,6 +15786,9 @@ async function runPrePrReviewRun(featureName, options) {
15644
15786
  feature: featureRef,
15645
15787
  skills: policy.skills,
15646
15788
  fallback: policy.fallback,
15789
+ handoffOnly: true,
15790
+ advancesWorkflow: false,
15791
+ nextStepRequirement: "generate_review_trace_then_record",
15647
15792
  evidenceFile: "review-trace.json",
15648
15793
  prompt,
15649
15794
  recordCommands: {
@@ -15659,6 +15804,11 @@ async function runPrePrReviewRun(featureName, options) {
15659
15804
  }
15660
15805
  console.log(prompt);
15661
15806
  console.log();
15807
+ console.log(
15808
+ chalk8.yellow(
15809
+ 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."
15810
+ )
15811
+ );
15662
15812
  console.log(`Evidence file: review-trace.json`);
15663
15813
  console.log(`Record changes requested: ${changesRequestedCommand}`);
15664
15814
  console.log(`Record approval: ${approveCommand}`);
@@ -15887,6 +16037,8 @@ async function runCodeReviewRun(featureName, options) {
15887
16037
  feature: feature.folderName,
15888
16038
  substateId: "code_review_run",
15889
16039
  owner: "subagent",
16040
+ handoffOnly: true,
16041
+ advancesWorkflow: false,
15890
16042
  nextMainState: "code_review_finalize",
15891
16043
  tasksPath: path12.join(feature.path, "tasks.md"),
15892
16044
  decisionsPath: path12.join(feature.path, "decisions.md"),
@@ -15899,6 +16051,11 @@ async function runCodeReviewRun(featureName, options) {
15899
16051
  }
15900
16052
  console.log(prompt);
15901
16053
  console.log();
16054
+ console.log(
16055
+ chalk8.yellow(
16056
+ config.lang === "ko" ? "\uC774 \uBA85\uB839\uC740 PR \uB9AC\uBDF0 handoff\uB9CC \uC900\uBE44\uD569\uB2C8\uB2E4. \uB9AC\uBDF0 evidence/decision\uC744 \uC9C1\uC811 \uAE30\uB85D\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 PR review handoff. It does not record review evidence/decision or advance workflow state by itself."
16057
+ )
16058
+ );
15902
16059
  console.log(chalk8.gray(`- substate: ${payload.substateId}`));
15903
16060
  console.log(chalk8.gray(`- owner: ${payload.owner}`));
15904
16061
  console.log(chalk8.gray(`- next main state: ${payload.nextMainState}`));
@@ -15933,105 +16090,6 @@ function codeReviewRunCommand(program2) {
15933
16090
  }
15934
16091
  );
15935
16092
  }
15936
- var PRD_REQUIREMENT_ID_RE = /\bPRD-(?:FR|US|NFR)-\d+\b/gi;
15937
- function isPrdRequirementId(value) {
15938
- return /^PRD-(?:FR|US|NFR)-\d+$/i.test(value.trim());
15939
- }
15940
- function isNonPrdTag(value) {
15941
- const trimmed = value.trim();
15942
- return /^NON[-_ ]?PRD$/i.test(trimmed);
15943
- }
15944
- function normalizeRelPath2(value) {
15945
- return value.replace(/\\/g, "/").replace(/^\.\/+/, "");
15946
- }
15947
- function extractTitleAfterId(line, id) {
15948
- const idx = line.indexOf(id);
15949
- if (idx < 0) return void 0;
15950
- const after = line.slice(idx + id.length);
15951
- const cleaned = after.replace(/^[\s::\-–—)\]]+/, "").trim();
15952
- return cleaned ? cleaned : void 0;
15953
- }
15954
- async function scanPrdRequirements(fsAdapter, docsDir) {
15955
- const prdDir = path12.join(docsDir, "prd");
15956
- const files = await walkFiles(fsAdapter, prdDir, {
15957
- extensions: [".md"],
15958
- ignoreDirs: [".git", "node_modules", "dist", "tmp"]
15959
- });
15960
- const definitions = /* @__PURE__ */ new Map();
15961
- const duplicates = [];
15962
- for (const filePath of files) {
15963
- let content = "";
15964
- try {
15965
- content = await fsAdapter.readFile(filePath, "utf-8");
15966
- } catch {
15967
- continue;
15968
- }
15969
- const relFile = normalizeRelPath2(path12.relative(docsDir, filePath));
15970
- const lines = content.split(/\r?\n/);
15971
- let inCodeBlock = false;
15972
- for (let i = 0; i < lines.length; i += 1) {
15973
- const line = lines[i] || "";
15974
- if (/^\s*(```|~~~)/.test(line)) {
15975
- inCodeBlock = !inCodeBlock;
15976
- continue;
15977
- }
15978
- if (inCodeBlock) continue;
15979
- const ids = [...line.matchAll(PRD_REQUIREMENT_ID_RE)].map(
15980
- (match) => (match[0] || "").toUpperCase()
15981
- );
15982
- if (ids.length === 0) continue;
15983
- for (const id of ids) {
15984
- const def = {
15985
- id,
15986
- title: extractTitleAfterId(line, id),
15987
- file: relFile,
15988
- line: i + 1
15989
- };
15990
- const existing = definitions.get(id);
15991
- if (existing) {
15992
- duplicates.push(def);
15993
- continue;
15994
- }
15995
- definitions.set(id, def);
15996
- }
15997
- }
15998
- }
15999
- return { definitions, duplicates, filesScanned: files.length };
16000
- }
16001
- function parseTaskLines(content) {
16002
- const out = [];
16003
- const lines = content.split(/\r?\n/);
16004
- let inCodeBlock = false;
16005
- for (let i = 0; i < lines.length; i += 1) {
16006
- const line = lines[i] || "";
16007
- if (/^\s*(```|~~~)/.test(line)) {
16008
- inCodeBlock = !inCodeBlock;
16009
- continue;
16010
- }
16011
- if (inCodeBlock) continue;
16012
- const match = line.match(
16013
- /^\s*-\s*\[([A-Z]+)\]((?:\[[^\]]+\])*)\s*(.+?)\s*$/
16014
- );
16015
- if (!match) continue;
16016
- const status = (match[1] || "").trim().toUpperCase();
16017
- const tagsPart = match[2] || "";
16018
- const title = (match[3] || "").trim();
16019
- if (!title) continue;
16020
- if (status !== "TODO" && status !== "DOING" && status !== "DONE" && status !== "REVIEW") {
16021
- continue;
16022
- }
16023
- const tags = [...tagsPart.matchAll(/\[([^\]]+)\]/g)].map((m) => (m[1] || "").trim()).filter(Boolean);
16024
- out.push({
16025
- status,
16026
- tags,
16027
- title,
16028
- line: i + 1
16029
- });
16030
- }
16031
- return out;
16032
- }
16033
-
16034
- // src/commands/requirements.ts
16035
16093
  function getRequirementState(tasks) {
16036
16094
  if (tasks.total === 0) return "UNTRACKED";
16037
16095
  if (tasks.done === tasks.total) return "DONE";
@@ -16236,7 +16294,7 @@ async function runRequirements(options) {
16236
16294
  }
16237
16295
  function parseTaskLine(line) {
16238
16296
  const match = line.match(
16239
- /^\s*-\s*\[(TODO|DOING|DONE|REVIEW)\]\[([^\]]+)\]\s+(T-[A-Za-z0-9-]+)\s+(.+?)\s*$/
16297
+ /^\s*-\s*\[(TODO|DOING|DONE|REVIEW)\]\[([^\]]+)\](?:\[[^\]]+\])*\s+(T-[A-Za-z0-9-]+)\s+(.+?)\s*$/
16240
16298
  );
16241
16299
  if (!match) return null;
16242
16300
  return {
@@ -16259,9 +16317,10 @@ function buildTaskRunPrompt(input) {
16259
16317
  ];
16260
16318
  if (input.lang === "ko") {
16261
16319
  return [
16262
- `${input.mode === "start" ? "\uC0C8 task \uC2E4\uD589\uC744 \uC2DC\uC791\uD558\uC138\uC694." : "\uC9C4\uD589 \uC911\uC778 task \uC2E4\uD589\uC744 \uC774\uC5B4\uAC00\uC138\uC694."}`,
16320
+ `${input.mode === "start" ? "\uC0C8 task \uC2E4\uD589\uC6A9 handoff\uB97C \uC900\uBE44\uD558\uC138\uC694." : "\uC9C4\uD589 \uC911\uC778 task handoff\uB97C \uC774\uC5B4\uAC00\uC138\uC694."}`,
16263
16321
  `- Feature: ${input.featureRef}`,
16264
16322
  `- Task: ${input.taskId} ${input.title}`,
16323
+ 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.",
16265
16324
  "- \uBA3C\uC800 `spec.md`, `plan.md`, `tasks.md`\uB97C \uC77D\uACE0 \uBC94\uC704\uC640 \uC644\uB8CC \uAE30\uC900\uC744 \uC815\uB9AC\uD558\uC138\uC694.",
16266
16325
  "- \uCF54\uB4DC \uBD84\uC11D\uACFC \uD0D0\uC0C9 \uC791\uC5C5\uC740 \uAE30\uBCF8\uC801\uC73C\uB85C \uC11C\uBE0C\uC5D0\uC774\uC804\uD2B8\uB97C \uC0AC\uC6A9\uD558\uC138\uC694.",
16267
16326
  "- \uC601\uD5A5 \uBC94\uC704 \uBD84\uC11D, \uD14C\uC2A4\uD2B8 \uC704\uCE58 \uD0D0\uC0C9, \uAE30\uC874 \uD328\uD134 \uC870\uC0AC\uCC98\uB7FC \uB3C5\uB9BD\uC801\uC778 \uBD84\uC11D\uC740 \uBCD1\uB82C\uB85C \uC218\uD589\uD558\uC138\uC694.",
@@ -16271,9 +16330,10 @@ function buildTaskRunPrompt(input) {
16271
16330
  ].join("\n");
16272
16331
  }
16273
16332
  return [
16274
- input.mode === "start" ? "Start this task execution." : "Continue this in-progress task execution.",
16333
+ input.mode === "start" ? "Prepare the handoff for this task execution." : "Prepare the handoff for this in-progress task.",
16275
16334
  `- Feature: ${input.featureRef}`,
16276
16335
  `- Task: ${input.taskId} ${input.title}`,
16336
+ `- ${input.mode === "start" ? "This command marks the current task as DOING in tasks.md, then prepares the implementation handoff prompt." : "This command prepares the implementation handoff prompt again for the in-progress task."}`,
16277
16337
  ...shared.map((line) => `- ${line}`)
16278
16338
  ].join("\n");
16279
16339
  }
@@ -16385,7 +16445,9 @@ async function runTaskRun(featureName, options) {
16385
16445
  }
16386
16446
  }
16387
16447
  function taskRunCommand(program2) {
16388
- program2.command("task-run [feature-name]").description("Prepare and start a task execution handoff for sub-agent work").option("--component <component>", "Component name for multi projects").option("--task <task-id>", "Explicit task id to execute").option("--json", "Output JSON").action(async (featureName, options) => {
16448
+ program2.command("task-run [feature-name]").description(
16449
+ "Prepare task execution handoff for sub-agent work (marks TODO tasks as DOING)"
16450
+ ).option("--component <component>", "Component name for multi projects").option("--task <task-id>", "Explicit task id to execute").option("--json", "Output JSON").action(async (featureName, options) => {
16389
16451
  try {
16390
16452
  await runTaskRun(featureName, options);
16391
16453
  } catch (error) {