lee-spec-kit 0.6.28 → 0.6.29

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
@@ -186,7 +186,7 @@ var ko = {
186
186
  "context.actionDetail.tasksWriteImprove": "tasks.md\uB97C \uBCF4\uC644\uD558\uACE0 \uBB38\uC11C \uC0C1\uD0DC\uB97C \uC815\uB82C\uD558\uC138\uC694",
187
187
  "context.actionDetail.tasksApprove": "tasks.md\uB97C \uC2B9\uC778\uD569\uB2C8\uB2E4",
188
188
  "context.actionDetail.issueCreate": "\uC774\uC288\uB97C \uC0DD\uC131\uD558\uACE0 tasks.md\uC758 \uC774\uC288 \uC815\uBCF4\uB97C \uB9DE\uCD94\uC138\uC694",
189
- "context.actionDetail.issueCreateAndWrite": "\uC774\uC288 \uCD08\uC548\uC744 \uBCF4\uC644\uD558\uACE0 \uC2B9\uC778(OK) \uD6C4 \uC774\uC288\uB97C \uC0DD\uC131\uD574 \uBC88\uD638\uB97C \uB3D9\uAE30\uD654\uD558\uC138\uC694",
189
+ "context.actionDetail.issueCreateAndWrite": "\uC774\uC288 \uCD08\uC548\uC744 \uBCF4\uC644\uD558\uACE0 \uB77C\uBCA8 \uC2B9\uC778(`A` \uB610\uB294 `A OK`) \uD6C4 \uC774\uC288\uB97C \uC0DD\uC131\uD574 \uBC88\uD638\uB97C \uB3D9\uAE30\uD654\uD558\uC138\uC694",
190
190
  "context.actionDetail.issueCreatePrepareFromDoc": "issue.md \uCD08\uC548\uC744 \uBCF4\uC644\uD558\uACE0 \uC0C1\uD0DC\uB97C Ready\uB85C \uC124\uC815\uD558\uC138\uC694",
191
191
  "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",
192
192
  "context.actionDetail.taskExecute": "\uD604\uC7AC \uD0DC\uC2A4\uD06C\uB97C \uC9C4\uD589\uD558\uC138\uC694",
@@ -504,8 +504,8 @@ var ko = {
504
504
  tasksImprove: "tasks.md\uB97C \uBCF4\uC644\uD558\uACE0 \uBB38\uC11C \uC0C1\uD0DC\uB97C Review\uB85C \uBCC0\uACBD\uD558\uC138\uC694.",
505
505
  tasksApproval: "tasks.md \uB0B4\uC6A9\uC744 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uACF5\uC720\uD558\uACE0 \uC9C4\uD589 \uC2B9\uC778(`A` \uB610\uB294 `A OK` \uD615\uC2DD)\uC744 \uBC1B\uC73C\uC138\uC694. (\uC2B9\uC778 \uD6C4 \uBB38\uC11C \uC0C1\uD0DC\uB97C Approved\uB85C \uBCC0\uACBD)",
506
506
  docsCommitPlanning: 'cd "{docsGitCwd}" && git add "{featurePath}" && git commit -m "docs(planning): {folderName} \uAE30\uD68D \uBB38\uC11C"',
507
- issueCreateAndWrite: "\uC774\uC288 \uBCF8\uBB38 \uD15C\uD50C\uB9BF\uC744 \uC0DD\uC131\uD574 \uBAA9\uD45C/\uC644\uB8CC \uAE30\uC900\uC744 \uAC80\uD1A0\xB7\uBCF4\uC644\uD558\uACE0, \uC0AC\uC6A9\uC790 \uC2B9\uC778(OK) \uD6C4 \uC774\uC288\uB97C \uC0DD\uC131\uD558\uC138\uC694. \uC774\uD6C4 tasks.md\uC758 \uC774\uC288 \uBC88\uD638\uB97C \uCC44\uC6B0\uACE0 \uBB38\uC11C \uCEE4\uBC0B\uC744 \uC900\uBE44\uD558\uC138\uC694.",
508
- issuePrepareFromDoc: "`issue.md`\uB97C \uAE30\uC900\uC73C\uB85C \uC774\uC288 \uC81C\uBAA9/\uBCF8\uBB38/\uB77C\uBCA8 \uCD08\uC548\uC744 \uBCF4\uC644\uD558\uACE0 \uC0AC\uC6A9\uC790 \uC2B9\uC778(OK)\uC744 \uBC1B\uC544 \uC0C1\uD0DC\uB97C `Ready`\uB85C \uBCC0\uACBD\uD558\uC138\uC694.",
507
+ issueCreateAndWrite: "\uC774\uC288 \uBCF8\uBB38 \uD15C\uD50C\uB9BF\uC744 \uC0DD\uC131\uD574 \uBAA9\uD45C/\uC644\uB8CC \uAE30\uC900\uC744 \uAC80\uD1A0\xB7\uBCF4\uC644\uD558\uACE0, \uB77C\uBCA8 \uC2B9\uC778(`A` \uB610\uB294 `A OK`) \uD6C4 \uC774\uC288\uB97C \uC0DD\uC131\uD558\uC138\uC694. \uC774\uD6C4 tasks.md\uC758 \uC774\uC288 \uBC88\uD638\uB97C \uCC44\uC6B0\uACE0 \uBB38\uC11C \uCEE4\uBC0B\uC744 \uC900\uBE44\uD558\uC138\uC694.",
508
+ issuePrepareFromDoc: "`issue.md`\uB97C \uAE30\uC900\uC73C\uB85C \uC774\uC288 \uC81C\uBAA9/\uBCF8\uBB38/\uB77C\uBCA8 \uCD08\uC548\uC744 \uBCF4\uC644\uD558\uACE0 \uB77C\uBCA8 \uC2B9\uC778(`A` \uB610\uB294 `A OK`)\uC744 \uBC1B\uC544 \uC0C1\uD0DC\uB97C `Ready`\uB85C \uBCC0\uACBD\uD558\uC138\uC694.",
509
509
  issueCreateFromDoc: "`issue.md` \uC0C1\uD0DC\uAC00 `Ready`\uC774\uBA74 GitHub Issue\uB97C \uC0DD\uC131\uD558\uACE0, \uC0DD\uC131\uB41C \uC774\uC288 \uBC88\uD638\uB97C `tasks.md`\uC5D0 \uBC18\uC601\uD558\uC138\uC694.",
510
510
  docsCommitIssueUpdate: 'cd "{docsGitCwd}" && git add "{featurePath}" && git commit -m "docs(#{issueNumber}): {folderName} \uBB38\uC11C \uC5C5\uB370\uC774\uD2B8"',
511
511
  docsCommitUpdate: 'cd "{docsGitCwd}" && git add "{featurePath}" && git commit -m "docs: {folderName} \uBB38\uC11C \uC5C5\uB370\uC774\uD2B8"',
@@ -529,7 +529,7 @@ var ko = {
529
529
  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",
530
530
  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)",
531
531
  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)",
532
- 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`)\uC758 `Summary`/`Decision`\uC744 \uAE30\uB85D\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
532
+ 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`/`Decision`/`Findings`(\uB610\uB294 \uBA85\uC2DC\uC801 `0 findings`)/`Residual Risks`/`Tests Run`\uC744 \uAE30\uB85D\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
533
533
  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)",
534
534
  prePrReviewRun: "PR \uC0DD\uC131 \uC804 \uC0AC\uC804 \uCF54\uB4DC\uB9AC\uBDF0\uB97C \uC9C4\uD589\uD558\uC138\uC694. \uAE30\uBCF8 \uBCA0\uC774\uC2A4\uB77C\uC778\uC740 `{fallback}`\uC774\uBA70, `create-pr` \uBB38\uC11C\uC758 `Pre-PR \uAE30\uBCF8 \uCCB4\uD06C\uB9AC\uC2A4\uD2B8` \uC139\uC158\uC744 \uD56D\uC0C1 \uC218\uD589\uD558\uC138\uC694. \uC6B0\uC120\uC21C\uC704 \uC2A4\uD0AC: {skills} (\uC124\uCE58\uB41C \uB354 \uC801\uD569\uD55C \uC2A4\uD0AC\uC774 \uC788\uB2E4\uBA74 \uBA3C\uC800 \uC81C\uC548 \uD6C4 \uC0AC\uC6A9)\uB85C \uCD94\uAC00 \uC2EC\uD654 \uAC80\uD1A0\uB97C \uC9C4\uD589\uD558\uC138\uC694. \uC644\uB8CC \uD6C4 `PR \uC804 \uB9AC\uBDF0`\uB97C Done\uC73C\uB85C \uC5C5\uB370\uC774\uD2B8\uD558\uC138\uC694.",
535
535
  prReviewEvidenceFieldMissing: "tasks.md\uC5D0 `PR \uB9AC\uBDF0 Evidence` \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. `- **PR \uB9AC\uBDF0 Evidence**: -` \uD56D\uBAA9\uC744 \uCD94\uAC00\uD558\uACE0 \uB2E4\uC2DC \uC9C4\uD589\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
@@ -588,7 +588,7 @@ var ko = {
588
588
  workflowPrRemoteChecksPending: "\uC6D0\uACA9 PR \uCCB4\uD06C \uB300\uAE30\uAC00 {count}\uAC74 \uAC10\uC9C0\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uCCB4\uD06C \uC644\uB8CC \uD6C4 \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694.",
589
589
  workflowPrePrReviewMissing: "\uC644\uB8CC \uC0C1\uD0DC\uC774\uC9C0\uB9CC `PR \uC804 \uB9AC\uBDF0` \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. (tasks.md\uC5D0 `- **PR \uC804 \uB9AC\uBDF0**: Pending | Done`\uC744 \uCD94\uAC00\uD558\uC138\uC694.)",
590
590
  workflowPrePrReviewNotDone: "\uC644\uB8CC \uC0C1\uD0DC\uC774\uC9C0\uB9CC `PR \uC804 \uB9AC\uBDF0`\uAC00 Done\uC774 \uC544\uB2D9\uB2C8\uB2E4. (\uC0AC\uC804 \uCF54\uB4DC\uB9AC\uBDF0 \uD6C4 Done\uC73C\uB85C \uC5C5\uB370\uC774\uD2B8\uD558\uC138\uC694.)",
591
- workflowPrePrEvidenceMissing: "\uC644\uB8CC \uC0C1\uD0DC\uC774\uC9C0\uB9CC `PR \uC804 \uB9AC\uBDF0 Evidence`\uAC00 \uBE44\uC5B4\uC788\uAC70\uB098 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. (`Pre-PR Review Log`/`PR \uC804 \uB9AC\uBDF0 \uB85C\uADF8`\uC758 `Summary`/`Decision`\uC774 \uC788\uB294 \uC2E4\uC81C \uACBD\uB85C\uB97C \uAE30\uB85D\uD558\uC138\uC694.)",
591
+ workflowPrePrEvidenceMissing: "\uC644\uB8CC \uC0C1\uD0DC\uC774\uC9C0\uB9CC `PR \uC804 \uB9AC\uBDF0 Evidence`\uAC00 \uBE44\uC5B4\uC788\uAC70\uB098 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. (`Pre-PR Review Log`/`PR \uC804 \uB9AC\uBDF0 \uB85C\uADF8`\uC5D0 placeholder\uAC00 \uC544\uB2CC `Summary`/`Decision`/`Findings`(\uB610\uB294 \uBA85\uC2DC\uC801 `0 findings`)/`Residual Risks`/`Tests Run`\uC774 \uC788\uB294 \uC2E4\uC81C \uACBD\uB85C\uB97C \uAE30\uB85D\uD558\uC138\uC694.)",
592
592
  workflowPrePrDecisionMissing: "\uC644\uB8CC \uC0C1\uD0DC\uC774\uC9C0\uB9CC `PR \uC804 \uB9AC\uBDF0 Decision`\uC774 \uBE44\uC5B4\uC788\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. (`decision: approve|changes_requested|blocked ...` \uD615\uC2DD)",
593
593
  workflowPrePrDecisionNotApproved: "\uC644\uB8CC \uC0C1\uD0DC\uC774\uC9C0\uB9CC `PR \uC804 \uB9AC\uBDF0 Decision`\uC774 `{outcome}`\uC785\uB2C8\uB2E4. \uB9AC\uBDF0 \uB9AC\uC2A4\uD06C\uB97C \uD574\uC18C\uD55C \uB4A4 pre-pr-review\uB97C \uC7AC\uC2E4\uD589\uD574 `approve`\uB85C \uB9DE\uCD94\uC138\uC694."
594
594
  }
@@ -1015,8 +1015,8 @@ var en = {
1015
1015
  tasksImprove: "Improve tasks.md and change Doc Status to Review.",
1016
1016
  tasksApproval: "Share tasks.md with the user and get progress approval (`A` or `A OK` format). (Then set Doc Status to Approved)",
1017
1017
  docsCommitPlanning: 'cd "{docsGitCwd}" && git add "{featurePath}" && git commit -m "docs(planning): {folderName} planning docs"',
1018
- issueCreateAndWrite: "Generate the issue body template, refine goals/completion criteria, get explicit user OK, create the issue, then update issue number in tasks.md and prepare a docs commit.",
1019
- issuePrepareFromDoc: "Use `issue.md` to refine issue title/body/labels draft, get explicit user OK, then set status to `Ready`.",
1018
+ issueCreateAndWrite: "Generate the issue body template, refine goals/completion criteria, get label approval (`A` or `A OK`), create the issue, then update issue number in tasks.md and prepare a docs commit.",
1019
+ issuePrepareFromDoc: "Use `issue.md` to refine issue title/body/labels draft, get label approval (`A` or `A OK`), then set status to `Ready`.",
1020
1020
  issueCreateFromDoc: "When `issue.md` status is `Ready`, create the GitHub Issue and sync the created issue number into `tasks.md`.",
1021
1021
  docsCommitIssueUpdate: 'cd "{docsGitCwd}" && git add "{featurePath}" && git commit -m "docs(#{issueNumber}): {folderName} docs update"',
1022
1022
  docsCommitUpdate: 'cd "{docsGitCwd}" && git add "{featurePath}" && git commit -m "docs: {folderName} docs update"',
@@ -1040,7 +1040,7 @@ var en = {
1040
1040
  taskCommitGateReasonMismatchLastDone: "The latest project code commit does not match the last completed task",
1041
1041
  prLegacyAsk: "tasks.md is missing PR/PR Status fields. Update to the latest template format? (CHECK required)",
1042
1042
  prePrReviewFieldMissing: "tasks.md is missing the `Pre-PR Review` field. Add `- **Pre-PR Review**: Pending | Done` and run context again. (CHECK required)",
1043
- 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` and `Decision`. (CHECK required)",
1043
+ 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`, `Decision`, `Findings` (or explicit `0 findings`), `Residual Risks`, and `Tests Run`. (CHECK required)",
1044
1044
  prePrReviewDecisionMissing: "tasks.md `Pre-PR Decision` is empty/placeholder or missing decision format. Record it as `decision: ...` (or `\uACB0\uC815: ...`). (CHECK required)",
1045
1045
  prePrReviewRun: "Run a pre-PR code review before creating the PR. Always execute the `{fallback}` baseline by following the `Pre-PR Baseline Checklist` section in the `create-pr` doc. Then use preferred skills ({skills}) for deeper review (if a better installed skill fits this change, propose it first). After completing it, set `Pre-PR Review` to Done in tasks.md.",
1046
1046
  prReviewEvidenceFieldMissing: "tasks.md is missing the `PR Review Evidence` field. Add `- **PR Review Evidence**: -` and continue. (CHECK required)",
@@ -1099,7 +1099,7 @@ var en = {
1099
1099
  workflowPrRemoteChecksPending: "Remote PR has {count} pending check(s). Wait for checks to complete, then re-check.",
1100
1100
  workflowPrePrReviewMissing: "Implementation is done but `Pre-PR Review` is missing. (Add `- **Pre-PR Review**: Pending | Done` in tasks.md.)",
1101
1101
  workflowPrePrReviewNotDone: "Implementation is done but `Pre-PR Review` is not Done. (Run pre-PR review, then update it to Done.)",
1102
- workflowPrePrEvidenceMissing: "Implementation is done but `Pre-PR Evidence` is empty/invalid. (Point to an existing file and include `Pre-PR Review Log` with non-placeholder `Summary` and `Decision`.)",
1102
+ workflowPrePrEvidenceMissing: "Implementation is done but `Pre-PR Evidence` is empty/invalid. (Point to an existing file and include `Pre-PR Review Log` with non-placeholder `Summary`, `Decision`, `Findings` (or explicit `0 findings`), `Residual Risks`, and `Tests Run`.)",
1103
1103
  workflowPrePrDecisionMissing: "Implementation is done but `Pre-PR Decision` is empty/invalid. (Use `decision: approve|changes_requested|blocked ...`.)",
1104
1104
  workflowPrePrDecisionNotApproved: "Implementation is done but `Pre-PR Decision` is `{outcome}`. Resolve review risks and re-run pre-PR review until decision becomes `approve`."
1105
1105
  }
@@ -4699,17 +4699,62 @@ function hasReviewLogQuality(content, headerRegex, summaryKeys, decisionKeys) {
4699
4699
  }
4700
4700
  return false;
4701
4701
  }
4702
+ function isExplicitZeroFindingsEntry(value) {
4703
+ const trimmed = value.trim().toLowerCase();
4704
+ if (!trimmed) return false;
4705
+ return /^0+\s*findings?\b/.test(trimmed) || /^no\s+findings?\b/.test(trimmed) || /^findings?\s*[::]\s*0+\b/.test(trimmed) || /^지적\s*사항?\s*[::]?\s*0+\b/.test(trimmed) || /^지적\s*없음\b/.test(trimmed);
4706
+ }
4707
+ function hasPrePrReviewLogQuality(content) {
4708
+ const sections = splitReviewLogSections(content, PRE_PR_REVIEW_LOG_HEADER);
4709
+ for (const section of sections) {
4710
+ const summaryEntries = collectStructuredReviewEntries(section, [
4711
+ "Summary",
4712
+ "\uC694\uC57D",
4713
+ "Note",
4714
+ "\uB178\uD2B8"
4715
+ ]);
4716
+ if (!hasValidReviewLogEntries(summaryEntries)) continue;
4717
+ const decisionEntries = collectStructuredReviewEntries(section, [
4718
+ "Decision",
4719
+ "\uACB0\uC815"
4720
+ ]);
4721
+ if (!hasValidReviewLogEntries(decisionEntries)) continue;
4722
+ const findingsEntries = collectStructuredReviewEntries(section, [
4723
+ "Findings",
4724
+ "\uC9C0\uC801\uC0AC\uD56D",
4725
+ "\uC9C0\uC801 \uC0AC\uD56D"
4726
+ ]);
4727
+ const hasActionableFindings = findingsEntries.map((entry) => entry.trim()).some(
4728
+ (entry) => entry.length > 0 && !isReviewDraftPlaceholder(entry) && !isPlaceholderReviewEvidence(entry) && /\S+:\d+/.test(entry)
4729
+ );
4730
+ const hasExplicitZeroFindings = findingsEntries.some(
4731
+ (entry) => isExplicitZeroFindingsEntry(entry)
4732
+ );
4733
+ if (!hasActionableFindings && !hasExplicitZeroFindings) continue;
4734
+ const residualRiskEntries = collectStructuredReviewEntries(section, [
4735
+ "Residual Risks",
4736
+ "Residual Risk",
4737
+ "\uC794\uC5EC \uB9AC\uC2A4\uD06C",
4738
+ "\uC794\uC5EC \uC704\uD5D8"
4739
+ ]);
4740
+ if (!hasValidReviewLogEntries(residualRiskEntries)) continue;
4741
+ const testsRunEntries = collectStructuredReviewEntries(section, [
4742
+ "Tests Run",
4743
+ "Test Run",
4744
+ "\uC2E4\uD589 \uD14C\uC2A4\uD2B8",
4745
+ "\uD14C\uC2A4\uD2B8 \uC2E4\uD589"
4746
+ ]);
4747
+ if (!hasValidReviewLogEntries(testsRunEntries)) continue;
4748
+ return true;
4749
+ }
4750
+ return false;
4751
+ }
4702
4752
  var PRE_PR_REVIEW_LOG_HEADER = /^##\s+(?:Pre-PR Review Log|PR 전 리뷰 로그)\b.*$/gim;
4703
4753
  var PR_REVIEW_LOG_HEADER = /^##\s+(?:PR Review Log|PR 리뷰 로그)\b.*$/gim;
4704
4754
  async function hasPrePrReviewLogEvidence(candidatePath) {
4705
4755
  try {
4706
4756
  const content = await fs17.readFile(candidatePath, "utf-8");
4707
- return hasReviewLogQuality(
4708
- content,
4709
- PRE_PR_REVIEW_LOG_HEADER,
4710
- ["Summary", "\uC694\uC57D", "Note", "\uB178\uD2B8"],
4711
- ["Decision", "\uACB0\uC815"]
4712
- );
4757
+ return hasPrePrReviewLogQuality(content);
4713
4758
  } catch {
4714
4759
  return false;
4715
4760
  }
@@ -6862,7 +6907,7 @@ function getApprovalSessionId() {
6862
6907
  if (explicit) return explicit;
6863
6908
  const terminalSession = (process.env.TERM_SESSION_ID || process.env.WT_SESSION || process.env.TMUX_PANE || "").trim();
6864
6909
  if (terminalSession) return terminalSession;
6865
- return `ppid:${process.ppid}`;
6910
+ return "";
6866
6911
  }
6867
6912
  function getApprovalTicketPaths(config) {
6868
6913
  return {
@@ -7004,7 +7049,7 @@ async function consumeApprovalTicket(config, token, expected) {
7004
7049
  "Approval ticket expired. Run `context` again and re-approve."
7005
7050
  );
7006
7051
  }
7007
- if (record.sessionId !== sessionId) {
7052
+ if (record.sessionId && record.sessionId !== sessionId) {
7008
7053
  throw createCliError(
7009
7054
  "INVALID_APPROVAL",
7010
7055
  "Approval ticket session mismatch. Re-run `context` in the current session and approve again."
@@ -7198,17 +7243,17 @@ var LONG_RUNNING_DELEGATION_CATEGORIES = [
7198
7243
  "review_fix_commit",
7199
7244
  "pre_pr_review"
7200
7245
  ];
7201
- function shouldDelegateCurrentAction(actionOptions, autoRunAvailable) {
7246
+ function shouldDelegateCurrentAction(actionOptions) {
7202
7247
  const primaryCategory = actionOptions[0]?.action?.category || null;
7203
7248
  const longRunningSet = new Set(LONG_RUNNING_DELEGATION_CATEGORIES);
7204
- const shouldDelegate = autoRunAvailable || !!primaryCategory && longRunningSet.has(primaryCategory);
7249
+ const shouldDelegate = !!primaryCategory && longRunningSet.has(primaryCategory);
7205
7250
  return {
7206
7251
  shouldDelegate,
7207
7252
  category: primaryCategory
7208
7253
  };
7209
7254
  }
7210
7255
  function buildAgentOrchestrationPolicy(actionOptions, autoRunAvailable) {
7211
- const delegation = shouldDelegateCurrentAction(actionOptions, autoRunAvailable);
7256
+ const delegation = shouldDelegateCurrentAction(actionOptions);
7212
7257
  return {
7213
7258
  mode: "main_orchestrates_subagent_execution",
7214
7259
  delegationPolicy: "prefer_main_delegate_long_running_fallback_main",
@@ -7217,6 +7262,7 @@ function buildAgentOrchestrationPolicy(actionOptions, autoRunAvailable) {
7217
7262
  fallbackToMainAgentWhenSubAgentUnavailable: true,
7218
7263
  longRunningCategories: [...LONG_RUNNING_DELEGATION_CATEGORIES],
7219
7264
  currentActionShouldDelegate: delegation.shouldDelegate,
7265
+ autoRunShouldDelegate: autoRunAvailable,
7220
7266
  currentActionCategory: delegation.category,
7221
7267
  mainAgentResponsibilities: [
7222
7268
  "Keep user conversation state and approval boundaries",
@@ -8224,10 +8270,7 @@ async function runContext(featureName, options) {
8224
8270
  }
8225
8271
  const actionOptions = state.actionOptions;
8226
8272
  const hasCommandOption = actionOptions.some((option) => option.action.type === "command");
8227
- const longRunningDelegation = shouldDelegateCurrentAction(
8228
- actionOptions,
8229
- autoRunPlan.available
8230
- );
8273
+ const longRunningDelegation = shouldDelegateCurrentAction(actionOptions);
8231
8274
  console.log(chalk6.green(chalk6.bold("\u{1F449} Next Options (Atomic):")));
8232
8275
  let hasDocsCommand = false;
8233
8276
  actionOptions.forEach((option) => {
@@ -11485,6 +11528,54 @@ ${mermaidSection}
11485
11528
  - **Spec**: \`${bodyPaths.specPath}\`
11486
11529
  - **Tasks**: \`${bodyPaths.tasksPath}\`${closes}`;
11487
11530
  }
11531
+ function stripMarkdownCodeContexts(body) {
11532
+ const lines = body.split("\n");
11533
+ const out = [];
11534
+ let inFence = false;
11535
+ let fenceChar = "";
11536
+ let fenceLength = 0;
11537
+ for (const line of lines) {
11538
+ const fenceStartMatch = line.match(/^\s*(`{3,}|~{3,})/);
11539
+ if (fenceStartMatch) {
11540
+ const marker = fenceStartMatch[1];
11541
+ const markerChar = marker[0];
11542
+ const markerLength = marker.length;
11543
+ if (!inFence) {
11544
+ inFence = true;
11545
+ fenceChar = markerChar;
11546
+ fenceLength = markerLength;
11547
+ continue;
11548
+ }
11549
+ if (markerChar === fenceChar && markerLength >= fenceLength) {
11550
+ inFence = false;
11551
+ fenceChar = "";
11552
+ fenceLength = 0;
11553
+ }
11554
+ continue;
11555
+ }
11556
+ if (inFence) continue;
11557
+ out.push(line.replace(/`[^`\n]*`/g, ""));
11558
+ }
11559
+ return out.join("\n");
11560
+ }
11561
+ function hasIssueClosingKeyword(body, issueNumber) {
11562
+ if (!issueNumber) return false;
11563
+ const cleaned = stripMarkdownCodeContexts(body);
11564
+ const issue = escapeRegExp3(issueNumber);
11565
+ const closeKeywordRegex = new RegExp(
11566
+ `\\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\\b\\s*(?:[a-zA-Z0-9_.-]+\\/)?#\\s*${issue}\\b`,
11567
+ "i"
11568
+ );
11569
+ return closeKeywordRegex.test(cleaned);
11570
+ }
11571
+ function ensureIssueClosingLine(body, issueNumber) {
11572
+ if (!issueNumber) return body;
11573
+ if (hasIssueClosingKeyword(body, issueNumber)) return body;
11574
+ const trimmed = body.trimEnd();
11575
+ const separator = trimmed.length > 0 ? "\n\n" : "";
11576
+ return `${trimmed}${separator}Closes #${issueNumber}
11577
+ `;
11578
+ }
11488
11579
  function getRequiredIssueSections(lang) {
11489
11580
  return getGithubDraftRequiredSections("issue", lang);
11490
11581
  }
@@ -11938,8 +12029,8 @@ function githubCommand(program2) {
11938
12029
  kindLabel: tg(config.lang, "kindPr"),
11939
12030
  lang: config.lang
11940
12031
  });
11941
- const body = preparedBody.body;
11942
- const bodyFile = preparedBody.bodyFile;
12032
+ let body = preparedBody.body;
12033
+ let bodyFile = preparedBody.bodyFile;
11943
12034
  const title = options.title?.trim() || (preparedBody.source === "workflow-ready" ? preparedBody.draftMetadata?.title : void 0) || defaultTitle;
11944
12035
  const labels = parseLabels(
11945
12036
  optionLabels || (preparedBody.source === "workflow-ready" ? preparedBody.draftMetadata?.labels : void 0),
@@ -11954,6 +12045,18 @@ function githubCommand(program2) {
11954
12045
  let syncChanged = false;
11955
12046
  const pushDocsSync = shouldPushDocsSync(config);
11956
12047
  if (options.create) {
12048
+ const normalizedBody = ensureIssueClosingLine(body, feature.issueNumber);
12049
+ if (normalizedBody !== body) {
12050
+ body = normalizedBody;
12051
+ const fallbackBodyFile = defaultBodyFile;
12052
+ if (preparedBody.source === "generated") {
12053
+ await fs17.writeFile(bodyFile, body, "utf-8");
12054
+ } else {
12055
+ await fs17.ensureDir(path23.dirname(fallbackBodyFile));
12056
+ await fs17.writeFile(fallbackBodyFile, body, "utf-8");
12057
+ bodyFile = fallbackBodyFile;
12058
+ }
12059
+ }
11957
12060
  const projectGitCwd = resolveGithubProjectCwd(config, feature);
11958
12061
  ensureNoTodoPlaceholders(body, tg(config.lang, "kindPr"), config.lang);
11959
12062
  ensurePrArtifacts(body, artifactPolicy, config.lang);
@@ -12983,6 +13086,12 @@ function buildReportContent(input) {
12983
13086
  - **Skills**: ${skills}
12984
13087
  - **Decision**: ${input.decision}
12985
13088
  - **Summary**: ${input.note}
13089
+ - **Findings**:
13090
+ - TODO: <file:line | severity: low|medium|high | fix: required|optional | note: ...> OR 0 findings
13091
+ - **Residual Risks**:
13092
+ - TODO: residual risk assessment after review
13093
+ - **Tests Run**:
13094
+ - TODO: commands/results verified during pre-PR review
12986
13095
  - **Evidence**:
12987
13096
  - TODO: review comments/paths/tests verified during pre-PR review
12988
13097
  - **Trace**: pre-pr-review command executed and synced with tasks.md