lee-spec-kit 0.6.35 → 0.6.37
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 +191 -43
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -597,6 +597,8 @@ var koMessages = {
|
|
|
597
597
|
projectCommitUpdate: 'cd "{projectGitCwd}" && (git diff --cached --quiet && echo "\uC2A4\uD14C\uC774\uC9D5\uB41C \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uC774\uBC88 \uD0DC\uC2A4\uD06C\uC5D0\uC11C \uC218\uC815\uD55C \uD30C\uC77C\uB9CC \uC120\uD0DD\uD574 git add [files] \uD6C4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694." && exit 1 || git commit -m "feat({folderName}): {commitTopic}")',
|
|
598
598
|
reviewFixCommitIssueGuidance: "PR \uB9AC\uBDF0 \uC218\uC815 \uCEE4\uBC0B\uC744 \uC9C4\uD589\uD558\uC138\uC694. \uB9AC\uBDF0 \uBC18\uC601 \uD30C\uC77C\uB9CC \uC2A4\uD14C\uC774\uC9D5\uD55C \uB4A4 `fix(#{issueNumber}): <review-fix-summary>` \uD615\uC2DD\uC73C\uB85C \uCEE4\uBC0B\uD558\uC138\uC694. `<review-fix-summary>`\uC5D0\uB294 \uC774\uBC88 \uCEE4\uBC0B\uC5D0\uC11C \uC2E4\uC81C\uB85C \uD574\uACB0\uD55C \uB9AC\uBDF0 \uD56D\uBAA9 \uC694\uC57D\uC744 \uC791\uC131\uD558\uC138\uC694. (\uD0DC\uC2A4\uD06C \uC81C\uBAA9 \uC7AC\uC0AC\uC6A9 \uAE08\uC9C0)",
|
|
599
599
|
reviewFixCommitGuidance: "PR \uB9AC\uBDF0 \uC218\uC815 \uCEE4\uBC0B\uC744 \uC9C4\uD589\uD558\uC138\uC694. \uB9AC\uBDF0 \uBC18\uC601 \uD30C\uC77C\uB9CC \uC2A4\uD14C\uC774\uC9D5\uD55C \uB4A4 `fix(review): <review-fix-summary>` \uD615\uC2DD\uC73C\uB85C \uCEE4\uBC0B\uD558\uC138\uC694. `<review-fix-summary>`\uC5D0\uB294 \uC774\uBC88 \uCEE4\uBC0B\uC5D0\uC11C \uC2E4\uC81C\uB85C \uD574\uACB0\uD55C \uB9AC\uBDF0 \uD56D\uBAA9 \uC694\uC57D\uC744 \uC791\uC131\uD558\uC138\uC694. (\uD0DC\uC2A4\uD06C \uC81C\uBAA9 \uC7AC\uC0AC\uC6A9 \uAE08\uC9C0)",
|
|
600
|
+
prePrFixCommitIssueGuidance: "pre-PR \uB9AC\uBDF0 \uC9C0\uC801\uC0AC\uD56D \uC218\uC815 \uCEE4\uBC0B\uC744 \uC9C4\uD589\uD558\uC138\uC694. pre-PR \uC218\uC815 \uD30C\uC77C\uB9CC \uC2A4\uD14C\uC774\uC9D5\uD55C \uB4A4 `fix(#{issueNumber}): <pre-pr-fix-summary>` \uD615\uC2DD\uC73C\uB85C \uCEE4\uBC0B\uD558\uC138\uC694. `<pre-pr-fix-summary>`\uC5D0\uB294 pre-PR\uC5D0\uC11C \uD574\uACB0\uD55C \uC9C0\uC801\uC0AC\uD56D\uC744 \uC791\uC131\uD558\uC138\uC694.",
|
|
601
|
+
prePrFixCommitGuidance: "pre-PR \uB9AC\uBDF0 \uC9C0\uC801\uC0AC\uD56D \uC218\uC815 \uCEE4\uBC0B\uC744 \uC9C4\uD589\uD558\uC138\uC694. pre-PR \uC218\uC815 \uD30C\uC77C\uB9CC \uC2A4\uD14C\uC774\uC9D5\uD55C \uB4A4 `fix(pre-pr): <pre-pr-fix-summary>` \uD615\uC2DD\uC73C\uB85C \uCEE4\uBC0B\uD558\uC138\uC694. `<pre-pr-fix-summary>`\uC5D0\uB294 pre-PR\uC5D0\uC11C \uD574\uACB0\uD55C \uC9C0\uC801\uC0AC\uD56D\uC744 \uC791\uC131\uD558\uC138\uC694.",
|
|
600
602
|
standaloneNeedsProjectRoot: "standalone \uBAA8\uB4DC\uC5D0\uC11C\uB294 projectRoot \uC124\uC815\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. (npx lee-spec-kit config --project-root ...)",
|
|
601
603
|
createBranch: 'cd "{projectGitCwd}" && mkdir -p .worktrees && (git worktree add ".worktrees/feat-{issueNumber}-{slug}" "feat/{issueNumber}-{slug}" || git worktree add -b "feat/{issueNumber}-{slug}" ".worktrees/feat-{issueNumber}-{slug}") && WT="{projectGitCwd}/.worktrees/feat-{issueNumber}-{slug}" && for f in .env .env.local .env.development .env.development.local .env.test .env.test.local .env.production .env.production.local; do [ -f "{projectGitCwd}/$f" ] && [ ! -e "$WT/$f" ] && cp "{projectGitCwd}/$f" "$WT/$f" || true; done && echo "worktree: {projectGitCwd}/.worktrees/feat-{issueNumber}-{slug}"',
|
|
602
604
|
moveToExistingWorktree: '\uD574\uB2F9 feature\uC6A9 worktree\uAC00 \uC774\uBBF8 \uC788\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 `cd "{worktreePath}"`\uB85C \uC774\uB3D9\uD55C \uB4A4 context\uB97C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.',
|
|
@@ -618,6 +620,7 @@ var koMessages = {
|
|
|
618
620
|
prePrReviewRun: "\uCF54\uB4DC \uB9AC\uBDF0 \uC5D0\uC774\uC804\uD2B8\uB97C \uC2E4\uD589\uD574 \uBE44\uC5B4\uC788\uC9C0 \uC54A\uC740 `commandsExecuted`\uB97C \uD3EC\uD568\uD55C `review-trace.json`\uC744 \uC0DD\uC131\uD55C \uB4A4, `pre-pr-review --evidence review-trace.json`\uC73C\uB85C \uB9AC\uBDF0 \uACB0\uACFC\uB97C \uAE30\uB85D\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
|
|
619
621
|
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`/\uC2E4\uD589 \uBA85\uB839(`commandsExecuted`)\uC744 \uAE30\uB85D\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
|
|
620
622
|
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)",
|
|
623
|
+
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)",
|
|
621
624
|
prePrReviewDecisionReconfirm: "\uD604\uC7AC `PR \uC804 \uB9AC\uBDF0 Decision`\uC774 `{decision}`\uC785\uB2C8\uB2E4. \uC9C0\uC801\uC0AC\uD56D\uC744 \uBC18\uC601\uD55C \uB4A4 \uC774\uC804 \uC0C1\uD0DC \uC7AC\uC0AC\uC6A9\uC744 \uB9C9\uAE30 \uC704\uD574 \uBA85\uC2DC\uC801\uC73C\uB85C Decision\uC744 \uC9C0\uC815\uD574 \uC7AC\uC2E4\uD589\uD558\uC138\uC694: `{command}` (\uD655\uC778 \uD544\uC694)",
|
|
622
625
|
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)",
|
|
623
626
|
prReviewEvidenceMissing: "tasks.md\uC758 `PR \uB9AC\uBDF0 Evidence`\uAC00 \uBE44\uC5B4\uC788\uAC70\uB098 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. `\uC694\uC57D: ...`(\uB610\uB294 `summary: ...`) \uD615\uC2DD\uC73C\uB85C \uAE30\uB85D\uD558\uAC70\uB098 `PR Review Log`(\uB610\uB294 `PR \uB9AC\uBDF0 \uB85C\uADF8`)\uC758 `Summary`/`Decision`\uC774 \uC788\uB294 \uD30C\uC77C \uACBD\uB85C\uB97C \uC9C0\uC815\uD558\uC138\uC694. (\uD655\uC778 \uD544\uC694)",
|
|
@@ -1139,6 +1142,8 @@ var enMessages = {
|
|
|
1139
1142
|
projectCommitUpdate: 'cd "{projectGitCwd}" && (git diff --cached --quiet && echo "No staged files. Stage only files changed in this task with git add [files], then run again." && exit 1 || git commit -m "feat({folderName}): {commitTopic}")',
|
|
1140
1143
|
reviewFixCommitIssueGuidance: "Commit PR review fixes. Stage only review-fix files, then commit with `fix(#{issueNumber}): <review-fix-summary>`. `<review-fix-summary>` must describe review comments resolved in this commit (do not reuse task titles).",
|
|
1141
1144
|
reviewFixCommitGuidance: "Commit PR review fixes. Stage only review-fix files, then commit with `fix(review): <review-fix-summary>`. `<review-fix-summary>` must describe review comments resolved in this commit (do not reuse task titles).",
|
|
1145
|
+
prePrFixCommitIssueGuidance: "Commit fixes requested by pre-PR review. Stage only pre-PR fix files, then commit with `fix(#{issueNumber}): <pre-pr-fix-summary>`. `<pre-pr-fix-summary>` must describe findings resolved from pre-PR review.",
|
|
1146
|
+
prePrFixCommitGuidance: "Commit fixes requested by pre-PR review. Stage only pre-PR fix files, then commit with `fix(pre-pr): <pre-pr-fix-summary>`. `<pre-pr-fix-summary>` must describe findings resolved from pre-PR review.",
|
|
1142
1147
|
standaloneNeedsProjectRoot: "Standalone mode requires projectRoot. (npx lee-spec-kit config --project-root ...)",
|
|
1143
1148
|
createBranch: 'cd "{projectGitCwd}" && mkdir -p .worktrees && (git worktree add ".worktrees/feat-{issueNumber}-{slug}" "feat/{issueNumber}-{slug}" || git worktree add -b "feat/{issueNumber}-{slug}" ".worktrees/feat-{issueNumber}-{slug}") && WT="{projectGitCwd}/.worktrees/feat-{issueNumber}-{slug}" && for f in .env .env.local .env.development .env.development.local .env.test .env.test.local .env.production .env.production.local; do [ -f "{projectGitCwd}/$f" ] && [ ! -e "$WT/$f" ] && cp "{projectGitCwd}/$f" "$WT/$f" || true; done && echo "worktree: {projectGitCwd}/.worktrees/feat-{issueNumber}-{slug}"',
|
|
1144
1149
|
moveToExistingWorktree: 'A matching feature worktree already exists. Move first: `cd "{worktreePath}"`, then re-run context.',
|
|
@@ -1160,6 +1165,7 @@ var enMessages = {
|
|
|
1160
1165
|
prePrReviewRun: "Run the code review agent and generate `review-trace.json` with non-empty `commandsExecuted`, then execute `pre-pr-review --evidence review-trace.json` to record findings. (CHECK required)",
|
|
1161
1166
|
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`, `Tests Run`, and real executed commands (`commandsExecuted`). (CHECK required)",
|
|
1162
1167
|
prePrReviewDecisionMissing: "tasks.md `Pre-PR Decision` is empty/placeholder or missing decision format. Record it as `decision: ...` (or `\uACB0\uC815: ...`). (CHECK required)",
|
|
1168
|
+
prePrReviewFixRequired: "Current `Pre-PR Decision` is `{decision}`. Apply the requested fixes from pre-PR findings before moving to PR creation. (CHECK required)",
|
|
1163
1169
|
prePrReviewDecisionReconfirm: "Current `Pre-PR Decision` is `{decision}`. After fixing findings, rerun pre-PR review with an explicit decision to avoid replaying the prior state: `{command}` (CHECK required)",
|
|
1164
1170
|
prReviewEvidenceFieldMissing: "tasks.md is missing the `PR Review Evidence` field. Add `- **PR Review Evidence**: -` and continue. (CHECK required)",
|
|
1165
1171
|
prReviewEvidenceMissing: "tasks.md `PR Review Evidence` is empty/invalid. Use `summary: ...` (or `\uC694\uC57D: ...`), or point to a file containing `PR Review Log` with non-placeholder `Summary` and `Decision`. (CHECK required)",
|
|
@@ -3349,7 +3355,8 @@ function getPrePrReviewPrompt(lang, skills, fallbackText) {
|
|
|
3349
3355
|
3. \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. \uC794\uC5EC \uC704\uD5D8(residualRisks)\uACFC \uC2E4\uD589\uD55C \uBA85\uB839\uC5B4(commandsExecuted)\uB3C4 \uD3EC\uD568\uD558\uC138\uC694.
|
|
3350
3356
|
4. \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.
|
|
3351
3357
|
5. \uC6B0\uC120\uC21C\uC704 \uC2A4\uD0AC: ${skills.length > 0 ? skills.join(", ") : "\uC5C6\uC74C"} \uB85C \uC2EC\uD654 \uAC80\uD1A0\uB97C \uC9C4\uD589\uD558\uC138\uC694.
|
|
3352
|
-
\
|
|
3358
|
+
6. \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\uACE0 \uCF54\uB4DC\uB97C \uC218\uC815\uD558\uC138\uC694.
|
|
3359
|
+
7. \uC218\uC815/\uC7AC\uAC80\uC99D \uD6C4 \uCD5C\uC885 \uC2B9\uC778 \uC2DC\uC810\uC5D0 'npx lee-spec-kit pre-pr-review <feature> --evidence review-trace.json --decision approve' \uB97C \uC2E4\uD589\uD558\uC138\uC694.`;
|
|
3353
3360
|
}
|
|
3354
3361
|
return `Conduct a pre-PR code review.
|
|
3355
3362
|
1. Run automated analyzers (e.g., vitest, biome check, pnpm audit).
|
|
@@ -3359,7 +3366,8 @@ function getPrePrReviewPrompt(lang, skills, fallbackText) {
|
|
|
3359
3366
|
3. Generate a 'review-trace.json' file for all changed files, including evaluations for risk, security, perf, maintainability, and specific fileLine locators. Also include residualRisks and commandsExecuted array.
|
|
3360
3367
|
4. The baseline is '${fallbackText}'. Always perform the 'Pre-PR Core Checklist' section of the 'create-pr' document.
|
|
3361
3368
|
5. Priority skills: ${skills.length > 0 ? skills.join(", ") : "None"} for deeper technical review.
|
|
3362
|
-
|
|
3369
|
+
6. If unresolved findings remain, first record them with 'npx lee-spec-kit pre-pr-review <feature> --evidence review-trace.json --decision changes_requested' and apply code fixes.
|
|
3370
|
+
7. After fixes and re-validation, run 'npx lee-spec-kit pre-pr-review <feature> --evidence review-trace.json --decision approve' for final pre-PR approval.`;
|
|
3363
3371
|
}
|
|
3364
3372
|
function getCodeReviewPrompt(lang) {
|
|
3365
3373
|
if (lang === "ko") {
|
|
@@ -3384,6 +3392,9 @@ function isPrMetadataConfigured(feature) {
|
|
|
3384
3392
|
function isReviewIterationPhase(feature, workflowPolicy) {
|
|
3385
3393
|
return workflowPolicy.requirePr && workflowPolicy.requireReview && isPrMetadataConfigured(feature) && !!feature.pr.link && feature.pr.status === "Review";
|
|
3386
3394
|
}
|
|
3395
|
+
function isPrePrFixIterationPhase(feature, workflowPolicy, prePrReviewPolicy) {
|
|
3396
|
+
return prePrReviewPolicy.enabled && workflowPolicy.requirePr && feature.prePrReview.status === "Done" && !!feature.prePrReview.decisionOutcome && feature.prePrReview.decisionOutcome !== "approve" && (!isPrMetadataConfigured(feature) || !feature.pr.link);
|
|
3397
|
+
}
|
|
3387
3398
|
function isPrePrReviewSatisfied(feature, prePrReviewPolicy) {
|
|
3388
3399
|
if (!prePrReviewPolicy.enabled) return true;
|
|
3389
3400
|
if (!feature.docs.prePrReviewFieldExists || feature.prePrReview.status !== "Done") {
|
|
@@ -3460,6 +3471,7 @@ function buildPrePrReviewCommandArgs(feature, evidencePath, decision) {
|
|
|
3460
3471
|
}
|
|
3461
3472
|
function resolvePrePrReviewEvidencePath(feature) {
|
|
3462
3473
|
const docsRoot = feature.git.docsGitCwd;
|
|
3474
|
+
const docsParent = path12.dirname(docsRoot);
|
|
3463
3475
|
const candidates = [];
|
|
3464
3476
|
const explicit = (feature.prePrReview.evidence || "").trim();
|
|
3465
3477
|
if (explicit && explicit !== "-") {
|
|
@@ -3467,8 +3479,16 @@ function resolvePrePrReviewEvidencePath(feature) {
|
|
|
3467
3479
|
candidates.push(explicit);
|
|
3468
3480
|
} else {
|
|
3469
3481
|
candidates.push(path12.resolve(docsRoot, explicit));
|
|
3482
|
+
candidates.push(path12.resolve(docsParent, explicit));
|
|
3470
3483
|
candidates.push(path12.resolve(process.cwd(), explicit));
|
|
3471
3484
|
candidates.push(path12.resolve(feature.path, explicit));
|
|
3485
|
+
const normalizedExplicit = explicit.replace(/\\/g, "/");
|
|
3486
|
+
if (normalizedExplicit.startsWith("docs/")) {
|
|
3487
|
+
const withoutDocsPrefix = normalizedExplicit.slice("docs/".length);
|
|
3488
|
+
if (withoutDocsPrefix) {
|
|
3489
|
+
candidates.push(path12.resolve(docsRoot, withoutDocsPrefix));
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3472
3492
|
}
|
|
3473
3493
|
}
|
|
3474
3494
|
candidates.push(path12.resolve(process.cwd(), "review-trace.json"));
|
|
@@ -3501,6 +3521,17 @@ function resolveProjectCommitTopic(feature) {
|
|
|
3501
3521
|
const topic = withoutTaskId || normalizeCommitTopicText(feature.folderName);
|
|
3502
3522
|
return toShellSafeCommitTopic(topic);
|
|
3503
3523
|
}
|
|
3524
|
+
function getReviewFixCommitGuidance(feature, lang, options) {
|
|
3525
|
+
const prePr = !!options?.prePr;
|
|
3526
|
+
if (prePr) {
|
|
3527
|
+
return feature.issueNumber ? tr(lang, "messages", "prePrFixCommitIssueGuidance", {
|
|
3528
|
+
issueNumber: feature.issueNumber
|
|
3529
|
+
}) : tr(lang, "messages", "prePrFixCommitGuidance");
|
|
3530
|
+
}
|
|
3531
|
+
return feature.issueNumber ? tr(lang, "messages", "reviewFixCommitIssueGuidance", {
|
|
3532
|
+
issueNumber: feature.issueNumber
|
|
3533
|
+
}) : tr(lang, "messages", "reviewFixCommitGuidance");
|
|
3534
|
+
}
|
|
3504
3535
|
function resolveManagedWorktreeCleanupPaths(projectGitCwd) {
|
|
3505
3536
|
if (!projectGitCwd) return null;
|
|
3506
3537
|
const normalized = path12.resolve(projectGitCwd);
|
|
@@ -4013,7 +4044,16 @@ function getStepDefinitions(ctx) {
|
|
|
4013
4044
|
];
|
|
4014
4045
|
}
|
|
4015
4046
|
if (f.git.projectHasUncommittedChanges) {
|
|
4016
|
-
|
|
4047
|
+
const reviewIterationPhase = isReviewIterationPhase(
|
|
4048
|
+
f,
|
|
4049
|
+
workflowPolicy
|
|
4050
|
+
);
|
|
4051
|
+
const prePrFixIterationPhase = isPrePrFixIterationPhase(
|
|
4052
|
+
f,
|
|
4053
|
+
workflowPolicy,
|
|
4054
|
+
prePrReviewPolicy
|
|
4055
|
+
);
|
|
4056
|
+
if (reviewIterationPhase || prePrFixIterationPhase) {
|
|
4017
4057
|
if (!f.git.projectGitCwd) {
|
|
4018
4058
|
return [
|
|
4019
4059
|
{
|
|
@@ -4032,11 +4072,8 @@ function getStepDefinitions(ctx) {
|
|
|
4032
4072
|
type: "instruction",
|
|
4033
4073
|
category: "review_fix_commit",
|
|
4034
4074
|
requiresUserCheck: true,
|
|
4035
|
-
message: f
|
|
4036
|
-
|
|
4037
|
-
issueNumber: f.issueNumber
|
|
4038
|
-
}) : tr(lang, "messages", "reviewFixCommitGuidance", {
|
|
4039
|
-
projectGitCwd: f.git.projectGitCwd
|
|
4075
|
+
message: getReviewFixCommitGuidance(f, lang, {
|
|
4076
|
+
prePr: prePrFixIterationPhase
|
|
4040
4077
|
})
|
|
4041
4078
|
}
|
|
4042
4079
|
];
|
|
@@ -4262,7 +4299,16 @@ ${tr(lang, "messages", "taskCommitGateWarnProceed", {
|
|
|
4262
4299
|
}
|
|
4263
4300
|
];
|
|
4264
4301
|
}
|
|
4265
|
-
|
|
4302
|
+
const reviewIterationPhase = isReviewIterationPhase(
|
|
4303
|
+
f,
|
|
4304
|
+
workflowPolicy
|
|
4305
|
+
);
|
|
4306
|
+
const prePrFixIterationPhase = isPrePrFixIterationPhase(
|
|
4307
|
+
f,
|
|
4308
|
+
workflowPolicy,
|
|
4309
|
+
prePrReviewPolicy
|
|
4310
|
+
);
|
|
4311
|
+
if (reviewIterationPhase || prePrFixIterationPhase) {
|
|
4266
4312
|
if (!f.git.projectGitCwd) {
|
|
4267
4313
|
return [
|
|
4268
4314
|
{
|
|
@@ -4277,11 +4323,8 @@ ${tr(lang, "messages", "taskCommitGateWarnProceed", {
|
|
|
4277
4323
|
type: "instruction",
|
|
4278
4324
|
category: "review_fix_commit",
|
|
4279
4325
|
requiresUserCheck: true,
|
|
4280
|
-
message: f
|
|
4281
|
-
|
|
4282
|
-
issueNumber: f.issueNumber
|
|
4283
|
-
}) : tr(lang, "messages", "reviewFixCommitGuidance", {
|
|
4284
|
-
projectGitCwd: f.git.projectGitCwd
|
|
4326
|
+
message: getReviewFixCommitGuidance(f, lang, {
|
|
4327
|
+
prePr: prePrFixIterationPhase
|
|
4285
4328
|
})
|
|
4286
4329
|
}
|
|
4287
4330
|
];
|
|
@@ -4338,33 +4381,41 @@ ${tr(lang, "messages", "taskCommitGateWarnProceed", {
|
|
|
4338
4381
|
}
|
|
4339
4382
|
];
|
|
4340
4383
|
}
|
|
4341
|
-
|
|
4342
|
-
|
|
4384
|
+
if (f.prePrReview.decisionOutcome && f.prePrReview.decisionOutcome !== "approve") {
|
|
4385
|
+
const rerunEvidencePath = resolvePrePrReviewEvidencePath(f) || "review-trace.json";
|
|
4386
|
+
const rerunCommand = buildSelfCliCommand(
|
|
4387
|
+
buildPrePrReviewCommandArgs(f, rerunEvidencePath, "approve")
|
|
4388
|
+
);
|
|
4343
4389
|
return [
|
|
4344
4390
|
{
|
|
4345
4391
|
type: "instruction",
|
|
4346
|
-
category: "
|
|
4392
|
+
category: "review_fix_commit",
|
|
4347
4393
|
requiresUserCheck: true,
|
|
4348
|
-
message:
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4394
|
+
message: `${tr(lang, "messages", "prePrReviewFixRequired", {
|
|
4395
|
+
decision: f.prePrReview.decisionOutcome
|
|
4396
|
+
})}
|
|
4397
|
+
${getReviewFixCommitGuidance(f, lang, {
|
|
4398
|
+
prePr: true
|
|
4399
|
+
})}
|
|
4400
|
+
${tr(lang, "messages", "prePrReviewDecisionReconfirm", {
|
|
4401
|
+
decision: f.prePrReview.decisionOutcome,
|
|
4402
|
+
command: rerunCommand
|
|
4403
|
+
})}`
|
|
4353
4404
|
}
|
|
4354
4405
|
];
|
|
4355
4406
|
}
|
|
4356
|
-
|
|
4407
|
+
const evidencePath = resolvePrePrReviewEvidencePath(f);
|
|
4408
|
+
if (!evidencePath) {
|
|
4357
4409
|
return [
|
|
4358
4410
|
{
|
|
4359
4411
|
type: "instruction",
|
|
4360
4412
|
category: "pre_pr_review",
|
|
4361
4413
|
requiresUserCheck: true,
|
|
4362
|
-
message:
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
})
|
|
4414
|
+
message: getPrePrReviewPrompt(
|
|
4415
|
+
lang,
|
|
4416
|
+
prePrReviewPolicy.skills,
|
|
4417
|
+
prePrReviewPolicy.fallback
|
|
4418
|
+
)
|
|
4368
4419
|
}
|
|
4369
4420
|
];
|
|
4370
4421
|
}
|
|
@@ -5317,11 +5368,14 @@ function hasPrePrReviewLogQuality(content, options) {
|
|
|
5317
5368
|
if (!hasValidReviewLogEntries(decisionEntries)) continue;
|
|
5318
5369
|
const findingsEntries = collectStructuredReviewEntries(section, [
|
|
5319
5370
|
"Findings",
|
|
5371
|
+
"Findings (Changed Files)",
|
|
5320
5372
|
"\uC9C0\uC801\uC0AC\uD56D",
|
|
5321
|
-
"\uC9C0\uC801 \uC0AC\uD56D"
|
|
5373
|
+
"\uC9C0\uC801 \uC0AC\uD56D",
|
|
5374
|
+
"\uC9C0\uC801\uC0AC\uD56D (\uBCC0\uACBD \uD30C\uC77C)",
|
|
5375
|
+
"\uC9C0\uC801 \uC0AC\uD56D (\uBCC0\uACBD \uD30C\uC77C)"
|
|
5322
5376
|
]);
|
|
5323
5377
|
const hasActionableFindings = findingsEntries.map((entry) => entry.trim()).some(
|
|
5324
|
-
(entry) => entry.length > 0 && !isReviewDraftPlaceholder(entry) && !isPlaceholderReviewEvidence(entry) && /\S+:\d+/.test(entry)
|
|
5378
|
+
(entry) => entry.length > 0 && !isReviewDraftPlaceholder(entry) && !isPlaceholderReviewEvidence(entry) && (/\S+:\d+/.test(entry) || /\b[Ll]ines?\s+\d+/.test(entry))
|
|
5325
5379
|
);
|
|
5326
5380
|
const hasExplicitZeroFindings = findingsEntries.some(
|
|
5327
5381
|
(entry) => isExplicitZeroFindingsEntry(entry)
|
|
@@ -5340,14 +5394,15 @@ function hasPrePrReviewLogQuality(content, options) {
|
|
|
5340
5394
|
"\uC2E4\uD589 \uD14C\uC2A4\uD2B8",
|
|
5341
5395
|
"\uD14C\uC2A4\uD2B8 \uC2E4\uD589"
|
|
5342
5396
|
]);
|
|
5343
|
-
|
|
5397
|
+
const commandsEntries = collectStructuredReviewEntries(section, [
|
|
5398
|
+
"Commands Executed",
|
|
5399
|
+
"Executed Commands",
|
|
5400
|
+
"\uC2E4\uD589 \uBA85\uB839\uC5B4",
|
|
5401
|
+
"\uC2E4\uD589 \uBA85\uB839"
|
|
5402
|
+
]);
|
|
5403
|
+
const hasTestsRunEntries = hasValidReviewLogEntries(testsRunEntries) || hasValidReviewLogEntries(commandsEntries);
|
|
5404
|
+
if (!hasTestsRunEntries) continue;
|
|
5344
5405
|
if (requireCommandsExecuted) {
|
|
5345
|
-
const commandsEntries = collectStructuredReviewEntries(section, [
|
|
5346
|
-
"Commands Executed",
|
|
5347
|
-
"Executed Commands",
|
|
5348
|
-
"\uC2E4\uD589 \uBA85\uB839\uC5B4",
|
|
5349
|
-
"\uC2E4\uD589 \uBA85\uB839"
|
|
5350
|
-
]);
|
|
5351
5406
|
const hasCommandsExecuted = commandsEntries.map((entry) => entry.trim()).some(
|
|
5352
5407
|
(entry) => entry.length > 0 && !isReviewDraftPlaceholder(entry) && !isPlaceholderReviewEvidence(entry) && !isNoCommandsPlaceholder(entry)
|
|
5353
5408
|
);
|
|
@@ -5392,6 +5447,13 @@ function resolveLocalEvidencePathCandidates(rawValue, context) {
|
|
|
5392
5447
|
candidates.add(path12.resolve(context.featurePath, evidencePath));
|
|
5393
5448
|
candidates.add(path12.resolve(context.docsDir, evidencePath));
|
|
5394
5449
|
candidates.add(path12.resolve(path12.dirname(context.docsDir), evidencePath));
|
|
5450
|
+
const normalizedEvidencePath = evidencePath.replace(/\\/g, "/");
|
|
5451
|
+
if (normalizedEvidencePath.startsWith("docs/")) {
|
|
5452
|
+
const withoutDocsPrefix = normalizedEvidencePath.slice("docs/".length);
|
|
5453
|
+
if (withoutDocsPrefix) {
|
|
5454
|
+
candidates.add(path12.resolve(context.docsDir, withoutDocsPrefix));
|
|
5455
|
+
}
|
|
5456
|
+
}
|
|
5395
5457
|
}
|
|
5396
5458
|
return [...candidates];
|
|
5397
5459
|
}
|
|
@@ -11976,9 +12038,49 @@ function extractMarkdownByHeadings(content, headings, levels) {
|
|
|
11976
12038
|
}
|
|
11977
12039
|
return lines.slice(start, end).join("\n");
|
|
11978
12040
|
}
|
|
12041
|
+
function removeMarkdownByHeadings(content, headings, levels) {
|
|
12042
|
+
const targets = new Set(headings.map((heading) => normalizeHeading(heading)));
|
|
12043
|
+
const lines = content.split("\n");
|
|
12044
|
+
const levelSet = new Set(levels);
|
|
12045
|
+
let start = -1;
|
|
12046
|
+
let startLevel = 0;
|
|
12047
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12048
|
+
const match = lines[i].match(/^\s*(#{2,6})\s+(.+?)\s*$/);
|
|
12049
|
+
if (!match) continue;
|
|
12050
|
+
const level = match[1].length;
|
|
12051
|
+
if (!levelSet.has(level)) continue;
|
|
12052
|
+
if (!targets.has(normalizeHeading(match[2]))) continue;
|
|
12053
|
+
start = i;
|
|
12054
|
+
startLevel = level;
|
|
12055
|
+
break;
|
|
12056
|
+
}
|
|
12057
|
+
if (start < 0) return content;
|
|
12058
|
+
let end = lines.length;
|
|
12059
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
12060
|
+
const heading = lines[i].match(/^\s*(#{2,6})\s+(.+?)\s*$/);
|
|
12061
|
+
if (!heading) continue;
|
|
12062
|
+
const level = heading[1].length;
|
|
12063
|
+
if (level <= startLevel) {
|
|
12064
|
+
end = i;
|
|
12065
|
+
break;
|
|
12066
|
+
}
|
|
12067
|
+
}
|
|
12068
|
+
const next = [...lines.slice(0, start), ...lines.slice(end)].join("\n");
|
|
12069
|
+
const hasTrailingNewline = /\n$/.test(content);
|
|
12070
|
+
const normalized = next.replace(/\n{3,}/g, "\n\n").trimEnd();
|
|
12071
|
+
if (!normalized) return "";
|
|
12072
|
+
return hasTrailingNewline ? `${normalized}
|
|
12073
|
+
` : normalized;
|
|
12074
|
+
}
|
|
11979
12075
|
function extractMarkdownSection(content, headings) {
|
|
11980
12076
|
return extractMarkdownByHeadings(content, headings, [2]);
|
|
11981
12077
|
}
|
|
12078
|
+
function stripIssueDraftMetadataSection(content) {
|
|
12079
|
+
return stripWorkflowDraftMetadataSection(content);
|
|
12080
|
+
}
|
|
12081
|
+
function stripWorkflowDraftMetadataSection(content) {
|
|
12082
|
+
return removeMarkdownByHeadings(content, ["Metadata", "\uBA54\uD0C0\uB370\uC774\uD130"], [2]);
|
|
12083
|
+
}
|
|
11982
12084
|
function isTemplateLine(line) {
|
|
11983
12085
|
const trimmed = line.trim();
|
|
11984
12086
|
if (!trimmed) return true;
|
|
@@ -12985,8 +13087,20 @@ function githubCommand(program2) {
|
|
|
12985
13087
|
kindLabel: tg(config.lang, "kindIssue"),
|
|
12986
13088
|
lang: config.lang
|
|
12987
13089
|
});
|
|
12988
|
-
const body = preparedBody.body;
|
|
12989
|
-
|
|
13090
|
+
const body = stripIssueDraftMetadataSection(preparedBody.body);
|
|
13091
|
+
let bodyFile = preparedBody.bodyFile;
|
|
13092
|
+
if (options.create && body !== preparedBody.body) {
|
|
13093
|
+
const sanitizedBodyFile = toBodyFilePath(
|
|
13094
|
+
void 0,
|
|
13095
|
+
"issue",
|
|
13096
|
+
config.docsDir,
|
|
13097
|
+
`${feature.type}-issue-sanitized`,
|
|
13098
|
+
config.lang
|
|
13099
|
+
);
|
|
13100
|
+
await fs.ensureDir(path12.dirname(sanitizedBodyFile));
|
|
13101
|
+
await fs.writeFile(sanitizedBodyFile, body, "utf-8");
|
|
13102
|
+
bodyFile = sanitizedBodyFile;
|
|
13103
|
+
}
|
|
12990
13104
|
const title = options.title?.trim() || (preparedBody.source === "workflow-ready" ? preparedBody.draftMetadata?.title : void 0) || defaultTitle;
|
|
12991
13105
|
const labels = parseLabels(
|
|
12992
13106
|
optionLabels || (preparedBody.source === "workflow-ready" ? preparedBody.draftMetadata?.labels : void 0),
|
|
@@ -13193,8 +13307,22 @@ function githubCommand(program2) {
|
|
|
13193
13307
|
kindLabel: tg(config.lang, "kindPr"),
|
|
13194
13308
|
lang: config.lang
|
|
13195
13309
|
});
|
|
13196
|
-
let body =
|
|
13310
|
+
let body = stripWorkflowDraftMetadataSection(
|
|
13311
|
+
preparedBody.body
|
|
13312
|
+
);
|
|
13197
13313
|
let bodyFile = preparedBody.bodyFile;
|
|
13314
|
+
if (options.create && body !== preparedBody.body) {
|
|
13315
|
+
const sanitizedBodyFile = toBodyFilePath(
|
|
13316
|
+
void 0,
|
|
13317
|
+
"pr",
|
|
13318
|
+
config.docsDir,
|
|
13319
|
+
`${feature.type}-pr-sanitized`,
|
|
13320
|
+
config.lang
|
|
13321
|
+
);
|
|
13322
|
+
await fs.ensureDir(path12.dirname(sanitizedBodyFile));
|
|
13323
|
+
await fs.writeFile(sanitizedBodyFile, body, "utf-8");
|
|
13324
|
+
bodyFile = sanitizedBodyFile;
|
|
13325
|
+
}
|
|
13198
13326
|
const title = options.title?.trim() || (preparedBody.source === "workflow-ready" ? preparedBody.draftMetadata?.title : void 0) || defaultTitle;
|
|
13199
13327
|
const labels = parseLabels(
|
|
13200
13328
|
optionLabels || (preparedBody.source === "workflow-ready" ? preparedBody.draftMetadata?.labels : void 0),
|
|
@@ -14606,7 +14734,24 @@ function getPreferredKeys(lang) {
|
|
|
14606
14734
|
}
|
|
14607
14735
|
function buildReportContent(input) {
|
|
14608
14736
|
const skills = input.skills.length > 0 ? input.skills.join(", ") : "code-review-excellence";
|
|
14609
|
-
const
|
|
14737
|
+
const normalizedCommands = input.evidence.commandsExecuted.map((entry) => normalizeShellLikeCommand(entry)).filter(Boolean);
|
|
14738
|
+
const commandsRun = normalizedCommands.length > 0 ? normalizedCommands.map((c) => ` - \`${c}\``).join("\n") : " - None specified";
|
|
14739
|
+
const testCommandTokens = [
|
|
14740
|
+
"test",
|
|
14741
|
+
"vitest",
|
|
14742
|
+
"jest",
|
|
14743
|
+
"playwright",
|
|
14744
|
+
"cypress",
|
|
14745
|
+
"tsc",
|
|
14746
|
+
"biome check",
|
|
14747
|
+
"eslint",
|
|
14748
|
+
"audit"
|
|
14749
|
+
];
|
|
14750
|
+
const testsRunCommands = normalizedCommands.filter((entry) => {
|
|
14751
|
+
const lowered = entry.toLowerCase();
|
|
14752
|
+
return testCommandTokens.some((token) => lowered.includes(token));
|
|
14753
|
+
});
|
|
14754
|
+
const testsRun = (testsRunCommands.length > 0 ? testsRunCommands : normalizedCommands).map((entry) => ` - \`${entry}\` -> executed`).join("\n");
|
|
14610
14755
|
let filesSection = "";
|
|
14611
14756
|
if (input.evidence.files.length === 0) {
|
|
14612
14757
|
filesSection = " - 0 findings";
|
|
@@ -14631,6 +14776,9 @@ function buildReportContent(input) {
|
|
|
14631
14776
|
- **Commands Executed**:
|
|
14632
14777
|
${commandsRun}
|
|
14633
14778
|
|
|
14779
|
+
- **Tests Run**:
|
|
14780
|
+
${testsRun || " - Not recorded"}
|
|
14781
|
+
|
|
14634
14782
|
- **Residual Risks**:
|
|
14635
14783
|
- ${input.evidence.residualRisks}
|
|
14636
14784
|
|
|
@@ -14643,7 +14791,7 @@ ${mainScopeFiles}
|
|
|
14643
14791
|
- **Worktree Changed Files**:
|
|
14644
14792
|
${worktreeScopeFiles}
|
|
14645
14793
|
|
|
14646
|
-
- **Findings
|
|
14794
|
+
- **Findings**:
|
|
14647
14795
|
${filesSection}
|
|
14648
14796
|
|
|
14649
14797
|
- **Trace**: pre-pr-review command executed and synced with tasks.md
|