@urateam/core 0.1.0
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/__tests__/assembler.test.d.ts +2 -0
- package/dist/__tests__/assembler.test.d.ts.map +1 -0
- package/dist/__tests__/assembler.test.js +63 -0
- package/dist/__tests__/assembler.test.js.map +1 -0
- package/dist/__tests__/auth-check.test.d.ts +2 -0
- package/dist/__tests__/auth-check.test.d.ts.map +1 -0
- package/dist/__tests__/auth-check.test.js +88 -0
- package/dist/__tests__/auth-check.test.js.map +1 -0
- package/dist/__tests__/auto-merge.test.d.ts +15 -0
- package/dist/__tests__/auto-merge.test.d.ts.map +1 -0
- package/dist/__tests__/auto-merge.test.js +428 -0
- package/dist/__tests__/auto-merge.test.js.map +1 -0
- package/dist/__tests__/bec89-unified-schema.test.d.ts +2 -0
- package/dist/__tests__/bec89-unified-schema.test.d.ts.map +1 -0
- package/dist/__tests__/bec89-unified-schema.test.js +235 -0
- package/dist/__tests__/bec89-unified-schema.test.js.map +1 -0
- package/dist/__tests__/conflict-detector.test.d.ts +2 -0
- package/dist/__tests__/conflict-detector.test.d.ts.map +1 -0
- package/dist/__tests__/conflict-detector.test.js +206 -0
- package/dist/__tests__/conflict-detector.test.js.map +1 -0
- package/dist/__tests__/coordination.test.d.ts +2 -0
- package/dist/__tests__/coordination.test.d.ts.map +1 -0
- package/dist/__tests__/coordination.test.js +257 -0
- package/dist/__tests__/coordination.test.js.map +1 -0
- package/dist/__tests__/db-postgres.test.d.ts +14 -0
- package/dist/__tests__/db-postgres.test.d.ts.map +1 -0
- package/dist/__tests__/db-postgres.test.js +289 -0
- package/dist/__tests__/db-postgres.test.js.map +1 -0
- package/dist/__tests__/db.test.d.ts +2 -0
- package/dist/__tests__/db.test.d.ts.map +1 -0
- package/dist/__tests__/db.test.js +182 -0
- package/dist/__tests__/db.test.js.map +1 -0
- package/dist/__tests__/deep-review.test.d.ts +2 -0
- package/dist/__tests__/deep-review.test.d.ts.map +1 -0
- package/dist/__tests__/deep-review.test.js +322 -0
- package/dist/__tests__/deep-review.test.js.map +1 -0
- package/dist/__tests__/devcontainer.test.d.ts +2 -0
- package/dist/__tests__/devcontainer.test.d.ts.map +1 -0
- package/dist/__tests__/devcontainer.test.js +89 -0
- package/dist/__tests__/devcontainer.test.js.map +1 -0
- package/dist/__tests__/distributed-lock.test.d.ts +18 -0
- package/dist/__tests__/distributed-lock.test.d.ts.map +1 -0
- package/dist/__tests__/distributed-lock.test.js +237 -0
- package/dist/__tests__/distributed-lock.test.js.map +1 -0
- package/dist/__tests__/e2e-pipeline.test.d.ts +25 -0
- package/dist/__tests__/e2e-pipeline.test.d.ts.map +1 -0
- package/dist/__tests__/e2e-pipeline.test.js +517 -0
- package/dist/__tests__/e2e-pipeline.test.js.map +1 -0
- package/dist/__tests__/error-classifier.test.d.ts +2 -0
- package/dist/__tests__/error-classifier.test.d.ts.map +1 -0
- package/dist/__tests__/error-classifier.test.js +33 -0
- package/dist/__tests__/error-classifier.test.js.map +1 -0
- package/dist/__tests__/executor-integration.test.d.ts +11 -0
- package/dist/__tests__/executor-integration.test.d.ts.map +1 -0
- package/dist/__tests__/executor-integration.test.js +246 -0
- package/dist/__tests__/executor-integration.test.js.map +1 -0
- package/dist/__tests__/executor-issue-id.test.d.ts +13 -0
- package/dist/__tests__/executor-issue-id.test.d.ts.map +1 -0
- package/dist/__tests__/executor-issue-id.test.js +211 -0
- package/dist/__tests__/executor-issue-id.test.js.map +1 -0
- package/dist/__tests__/executor.test.d.ts +2 -0
- package/dist/__tests__/executor.test.d.ts.map +1 -0
- package/dist/__tests__/executor.test.js +164 -0
- package/dist/__tests__/executor.test.js.map +1 -0
- package/dist/__tests__/extract-handoff.test.d.ts +2 -0
- package/dist/__tests__/extract-handoff.test.d.ts.map +1 -0
- package/dist/__tests__/extract-handoff.test.js +131 -0
- package/dist/__tests__/extract-handoff.test.js.map +1 -0
- package/dist/__tests__/fail-on-auto-commit.test.d.ts +2 -0
- package/dist/__tests__/fail-on-auto-commit.test.d.ts.map +1 -0
- package/dist/__tests__/fail-on-auto-commit.test.js +156 -0
- package/dist/__tests__/fail-on-auto-commit.test.js.map +1 -0
- package/dist/__tests__/fixtures/webhook-comment.json +5 -0
- package/dist/__tests__/fixtures/webhook-state-change.json +15 -0
- package/dist/__tests__/force-push-agent-branches.test.d.ts +12 -0
- package/dist/__tests__/force-push-agent-branches.test.d.ts.map +1 -0
- package/dist/__tests__/force-push-agent-branches.test.js +348 -0
- package/dist/__tests__/force-push-agent-branches.test.js.map +1 -0
- package/dist/__tests__/github-webhook.test.d.ts +2 -0
- package/dist/__tests__/github-webhook.test.d.ts.map +1 -0
- package/dist/__tests__/github-webhook.test.js +370 -0
- package/dist/__tests__/github-webhook.test.js.map +1 -0
- package/dist/__tests__/gitlab.test.d.ts +28 -0
- package/dist/__tests__/gitlab.test.d.ts.map +1 -0
- package/dist/__tests__/gitlab.test.js +241 -0
- package/dist/__tests__/gitlab.test.js.map +1 -0
- package/dist/__tests__/integration/auto-commit.test.d.ts +2 -0
- package/dist/__tests__/integration/auto-commit.test.d.ts.map +1 -0
- package/dist/__tests__/integration/auto-commit.test.js +207 -0
- package/dist/__tests__/integration/auto-commit.test.js.map +1 -0
- package/dist/__tests__/integration/bec99-cross-worktree-guard.test.d.ts +10 -0
- package/dist/__tests__/integration/bec99-cross-worktree-guard.test.d.ts.map +1 -0
- package/dist/__tests__/integration/bec99-cross-worktree-guard.test.js +183 -0
- package/dist/__tests__/integration/bec99-cross-worktree-guard.test.js.map +1 -0
- package/dist/__tests__/integration/reproduce-bec99.test.d.ts +32 -0
- package/dist/__tests__/integration/reproduce-bec99.test.d.ts.map +1 -0
- package/dist/__tests__/integration/reproduce-bec99.test.js +243 -0
- package/dist/__tests__/integration/reproduce-bec99.test.js.map +1 -0
- package/dist/__tests__/integration/vitest-changed.test.d.ts +10 -0
- package/dist/__tests__/integration/vitest-changed.test.d.ts.map +1 -0
- package/dist/__tests__/integration/vitest-changed.test.js +128 -0
- package/dist/__tests__/integration/vitest-changed.test.js.map +1 -0
- package/dist/__tests__/license.test.d.ts +2 -0
- package/dist/__tests__/license.test.d.ts.map +1 -0
- package/dist/__tests__/license.test.js +53 -0
- package/dist/__tests__/license.test.js.map +1 -0
- package/dist/__tests__/mcp-resolver.test.d.ts +2 -0
- package/dist/__tests__/mcp-resolver.test.d.ts.map +1 -0
- package/dist/__tests__/mcp-resolver.test.js +65 -0
- package/dist/__tests__/mcp-resolver.test.js.map +1 -0
- package/dist/__tests__/migrator.test.d.ts +2 -0
- package/dist/__tests__/migrator.test.d.ts.map +1 -0
- package/dist/__tests__/migrator.test.js +300 -0
- package/dist/__tests__/migrator.test.js.map +1 -0
- package/dist/__tests__/notifier-discord.test.d.ts +2 -0
- package/dist/__tests__/notifier-discord.test.d.ts.map +1 -0
- package/dist/__tests__/notifier-discord.test.js +166 -0
- package/dist/__tests__/notifier-discord.test.js.map +1 -0
- package/dist/__tests__/notifier-slack.test.d.ts +2 -0
- package/dist/__tests__/notifier-slack.test.d.ts.map +1 -0
- package/dist/__tests__/notifier-slack.test.js +157 -0
- package/dist/__tests__/notifier-slack.test.js.map +1 -0
- package/dist/__tests__/notifier.test.d.ts +2 -0
- package/dist/__tests__/notifier.test.d.ts.map +1 -0
- package/dist/__tests__/notifier.test.js +207 -0
- package/dist/__tests__/notifier.test.js.map +1 -0
- package/dist/__tests__/pipeline-config.test.d.ts +2 -0
- package/dist/__tests__/pipeline-config.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline-config.test.js +143 -0
- package/dist/__tests__/pipeline-config.test.js.map +1 -0
- package/dist/__tests__/pipeline-runner.test.d.ts +2 -0
- package/dist/__tests__/pipeline-runner.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline-runner.test.js +359 -0
- package/dist/__tests__/pipeline-runner.test.js.map +1 -0
- package/dist/__tests__/pm-approvals-n1.repro.test.d.ts +9 -0
- package/dist/__tests__/pm-approvals-n1.repro.test.d.ts.map +1 -0
- package/dist/__tests__/pm-approvals-n1.repro.test.js +175 -0
- package/dist/__tests__/pm-approvals-n1.repro.test.js.map +1 -0
- package/dist/__tests__/pm-approvals.test.d.ts +2 -0
- package/dist/__tests__/pm-approvals.test.d.ts.map +1 -0
- package/dist/__tests__/pm-approvals.test.js +162 -0
- package/dist/__tests__/pm-approvals.test.js.map +1 -0
- package/dist/__tests__/pm-budget.test.d.ts +2 -0
- package/dist/__tests__/pm-budget.test.d.ts.map +1 -0
- package/dist/__tests__/pm-budget.test.js +65 -0
- package/dist/__tests__/pm-budget.test.js.map +1 -0
- package/dist/__tests__/pm-conflict.test.d.ts +2 -0
- package/dist/__tests__/pm-conflict.test.d.ts.map +1 -0
- package/dist/__tests__/pm-conflict.test.js +87 -0
- package/dist/__tests__/pm-conflict.test.js.map +1 -0
- package/dist/__tests__/pm-promote.test.d.ts +2 -0
- package/dist/__tests__/pm-promote.test.d.ts.map +1 -0
- package/dist/__tests__/pm-promote.test.js +82 -0
- package/dist/__tests__/pm-promote.test.js.map +1 -0
- package/dist/__tests__/pm-recover.test.d.ts +2 -0
- package/dist/__tests__/pm-recover.test.d.ts.map +1 -0
- package/dist/__tests__/pm-recover.test.js +100 -0
- package/dist/__tests__/pm-recover.test.js.map +1 -0
- package/dist/__tests__/pm-scheduler.test.d.ts +2 -0
- package/dist/__tests__/pm-scheduler.test.d.ts.map +1 -0
- package/dist/__tests__/pm-scheduler.test.js +112 -0
- package/dist/__tests__/pm-scheduler.test.js.map +1 -0
- package/dist/__tests__/pm-slack-interface.test.d.ts +2 -0
- package/dist/__tests__/pm-slack-interface.test.d.ts.map +1 -0
- package/dist/__tests__/pm-slack-interface.test.js +372 -0
- package/dist/__tests__/pm-slack-interface.test.js.map +1 -0
- package/dist/__tests__/pm-slack.test.d.ts +2 -0
- package/dist/__tests__/pm-slack.test.d.ts.map +1 -0
- package/dist/__tests__/pm-slack.test.js +83 -0
- package/dist/__tests__/pm-slack.test.js.map +1 -0
- package/dist/__tests__/pm-triage.test.d.ts +2 -0
- package/dist/__tests__/pm-triage.test.d.ts.map +1 -0
- package/dist/__tests__/pm-triage.test.js +198 -0
- package/dist/__tests__/pm-triage.test.js.map +1 -0
- package/dist/__tests__/pm-types.test.d.ts +2 -0
- package/dist/__tests__/pm-types.test.d.ts.map +1 -0
- package/dist/__tests__/pm-types.test.js +76 -0
- package/dist/__tests__/pm-types.test.js.map +1 -0
- package/dist/__tests__/pr-automerge.test.d.ts +18 -0
- package/dist/__tests__/pr-automerge.test.d.ts.map +1 -0
- package/dist/__tests__/pr-automerge.test.js +645 -0
- package/dist/__tests__/pr-automerge.test.js.map +1 -0
- package/dist/__tests__/pr-description.test.d.ts +2 -0
- package/dist/__tests__/pr-description.test.d.ts.map +1 -0
- package/dist/__tests__/pr-description.test.js +728 -0
- package/dist/__tests__/pr-description.test.js.map +1 -0
- package/dist/__tests__/prompt-injection.test.d.ts +2 -0
- package/dist/__tests__/prompt-injection.test.d.ts.map +1 -0
- package/dist/__tests__/prompt-injection.test.js +446 -0
- package/dist/__tests__/prompt-injection.test.js.map +1 -0
- package/dist/__tests__/ralph-gate.test.d.ts +19 -0
- package/dist/__tests__/ralph-gate.test.d.ts.map +1 -0
- package/dist/__tests__/ralph-gate.test.js +593 -0
- package/dist/__tests__/ralph-gate.test.js.map +1 -0
- package/dist/__tests__/ralph-review-fix-regression.test.d.ts +18 -0
- package/dist/__tests__/ralph-review-fix-regression.test.d.ts.map +1 -0
- package/dist/__tests__/ralph-review-fix-regression.test.js +306 -0
- package/dist/__tests__/ralph-review-fix-regression.test.js.map +1 -0
- package/dist/__tests__/ralph.test.d.ts +2 -0
- package/dist/__tests__/ralph.test.d.ts.map +1 -0
- package/dist/__tests__/ralph.test.js +96 -0
- package/dist/__tests__/ralph.test.js.map +1 -0
- package/dist/__tests__/recover-stuck.test.d.ts +8 -0
- package/dist/__tests__/recover-stuck.test.d.ts.map +1 -0
- package/dist/__tests__/recover-stuck.test.js +399 -0
- package/dist/__tests__/recover-stuck.test.js.map +1 -0
- package/dist/__tests__/repo.test.d.ts +2 -0
- package/dist/__tests__/repo.test.d.ts.map +1 -0
- package/dist/__tests__/repo.test.js +295 -0
- package/dist/__tests__/repo.test.js.map +1 -0
- package/dist/__tests__/repro-bec58-n-plus-one.test.d.ts +2 -0
- package/dist/__tests__/repro-bec58-n-plus-one.test.d.ts.map +1 -0
- package/dist/__tests__/repro-bec58-n-plus-one.test.js +187 -0
- package/dist/__tests__/repro-bec58-n-plus-one.test.js.map +1 -0
- package/dist/__tests__/reproduce-bec113-pagination-warning.test.d.ts +16 -0
- package/dist/__tests__/reproduce-bec113-pagination-warning.test.d.ts.map +1 -0
- package/dist/__tests__/reproduce-bec113-pagination-warning.test.js +226 -0
- package/dist/__tests__/reproduce-bec113-pagination-warning.test.js.map +1 -0
- package/dist/__tests__/reproduce-bec43-updatedat.test.d.ts +2 -0
- package/dist/__tests__/reproduce-bec43-updatedat.test.d.ts.map +1 -0
- package/dist/__tests__/reproduce-bec43-updatedat.test.js +76 -0
- package/dist/__tests__/reproduce-bec43-updatedat.test.js.map +1 -0
- package/dist/__tests__/reproduce-bec48-distributed-race.test.d.ts +18 -0
- package/dist/__tests__/reproduce-bec48-distributed-race.test.d.ts.map +1 -0
- package/dist/__tests__/reproduce-bec48-distributed-race.test.js +178 -0
- package/dist/__tests__/reproduce-bec48-distributed-race.test.js.map +1 -0
- package/dist/__tests__/reproduce-bec62.test.d.ts +2 -0
- package/dist/__tests__/reproduce-bec62.test.d.ts.map +1 -0
- package/dist/__tests__/reproduce-bec62.test.js +86 -0
- package/dist/__tests__/reproduce-bec62.test.js.map +1 -0
- package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.d.ts +13 -0
- package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.d.ts.map +1 -0
- package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.js +220 -0
- package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.js.map +1 -0
- package/dist/__tests__/review-feedback.test.d.ts +2 -0
- package/dist/__tests__/review-feedback.test.d.ts.map +1 -0
- package/dist/__tests__/review-feedback.test.js +383 -0
- package/dist/__tests__/review-feedback.test.js.map +1 -0
- package/dist/__tests__/sanitizer.test.d.ts +2 -0
- package/dist/__tests__/sanitizer.test.d.ts.map +1 -0
- package/dist/__tests__/sanitizer.test.js +162 -0
- package/dist/__tests__/sanitizer.test.js.map +1 -0
- package/dist/__tests__/security.test.d.ts +2 -0
- package/dist/__tests__/security.test.d.ts.map +1 -0
- package/dist/__tests__/security.test.js +52 -0
- package/dist/__tests__/security.test.js.map +1 -0
- package/dist/__tests__/server.test.d.ts +2 -0
- package/dist/__tests__/server.test.d.ts.map +1 -0
- package/dist/__tests__/server.test.js +61 -0
- package/dist/__tests__/server.test.js.map +1 -0
- package/dist/__tests__/slack-alerts.test.d.ts +2 -0
- package/dist/__tests__/slack-alerts.test.d.ts.map +1 -0
- package/dist/__tests__/slack-alerts.test.js +214 -0
- package/dist/__tests__/slack-alerts.test.js.map +1 -0
- package/dist/__tests__/stage-models.test.d.ts +14 -0
- package/dist/__tests__/stage-models.test.d.ts.map +1 -0
- package/dist/__tests__/stage-models.test.js +244 -0
- package/dist/__tests__/stage-models.test.js.map +1 -0
- package/dist/__tests__/start-todo.test.d.ts +2 -0
- package/dist/__tests__/start-todo.test.d.ts.map +1 -0
- package/dist/__tests__/start-todo.test.js +175 -0
- package/dist/__tests__/start-todo.test.js.map +1 -0
- package/dist/__tests__/tech-stack.test.d.ts +2 -0
- package/dist/__tests__/tech-stack.test.d.ts.map +1 -0
- package/dist/__tests__/tech-stack.test.js +75 -0
- package/dist/__tests__/tech-stack.test.js.map +1 -0
- package/dist/__tests__/templates.test.d.ts +2 -0
- package/dist/__tests__/templates.test.d.ts.map +1 -0
- package/dist/__tests__/templates.test.js +161 -0
- package/dist/__tests__/templates.test.js.map +1 -0
- package/dist/__tests__/test-quality.test.d.ts +2 -0
- package/dist/__tests__/test-quality.test.d.ts.map +1 -0
- package/dist/__tests__/test-quality.test.js +329 -0
- package/dist/__tests__/test-quality.test.js.map +1 -0
- package/dist/__tests__/token-budget.test.d.ts +2 -0
- package/dist/__tests__/token-budget.test.d.ts.map +1 -0
- package/dist/__tests__/token-budget.test.js +198 -0
- package/dist/__tests__/token-budget.test.js.map +1 -0
- package/dist/__tests__/types.test.d.ts +2 -0
- package/dist/__tests__/types.test.d.ts.map +1 -0
- package/dist/__tests__/types.test.js +156 -0
- package/dist/__tests__/types.test.js.map +1 -0
- package/dist/__tests__/validate.test.d.ts +2 -0
- package/dist/__tests__/validate.test.d.ts.map +1 -0
- package/dist/__tests__/validate.test.js +128 -0
- package/dist/__tests__/validate.test.js.map +1 -0
- package/dist/__tests__/webhook-handler.test.d.ts +2 -0
- package/dist/__tests__/webhook-handler.test.d.ts.map +1 -0
- package/dist/__tests__/webhook-handler.test.js +286 -0
- package/dist/__tests__/webhook-handler.test.js.map +1 -0
- package/dist/__tests__/webhook.test.d.ts +2 -0
- package/dist/__tests__/webhook.test.d.ts.map +1 -0
- package/dist/__tests__/webhook.test.js +58 -0
- package/dist/__tests__/webhook.test.js.map +1 -0
- package/dist/db/client.d.ts +56 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +201 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/index.d.ts +4 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +4 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrations/postgres/001_initial_schema.sql +78 -0
- package/dist/db/migrations/postgres/002_pg_timestamps.sql +78 -0
- package/dist/db/migrations/postgres/003_retry_count.sql +10 -0
- package/dist/db/migrations/postgres/004_review_feedback.sql +20 -0
- package/dist/db/migrations/postgres/005_auto_merge.sql +15 -0
- package/dist/db/migrations/sqlite/001_initial_schema.sql +78 -0
- package/dist/db/migrations/sqlite/002_retry_count.sql +5 -0
- package/dist/db/migrations/sqlite/003_review_feedback.sql +7 -0
- package/dist/db/migrations/sqlite/004_auto_merge.sql +6 -0
- package/dist/db/migrator.d.ts +51 -0
- package/dist/db/migrator.d.ts.map +1 -0
- package/dist/db/migrator.js +188 -0
- package/dist/db/migrator.js.map +1 -0
- package/dist/db/schema.d.ts +1114 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +129 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/entrypoint.d.ts +2 -0
- package/dist/entrypoint.d.ts.map +1 -0
- package/dist/entrypoint.js +113 -0
- package/dist/entrypoint.js.map +1 -0
- package/dist/executor/agent-config.d.ts +10 -0
- package/dist/executor/agent-config.d.ts.map +1 -0
- package/dist/executor/agent-config.js +81 -0
- package/dist/executor/agent-config.js.map +1 -0
- package/dist/executor/agent-stream.d.ts +65 -0
- package/dist/executor/agent-stream.d.ts.map +1 -0
- package/dist/executor/agent-stream.js +101 -0
- package/dist/executor/agent-stream.js.map +1 -0
- package/dist/executor/auth-check.d.ts +10 -0
- package/dist/executor/auth-check.d.ts.map +1 -0
- package/dist/executor/auth-check.js +52 -0
- package/dist/executor/auth-check.js.map +1 -0
- package/dist/executor/deep-review.d.ts +61 -0
- package/dist/executor/deep-review.d.ts.map +1 -0
- package/dist/executor/deep-review.js +308 -0
- package/dist/executor/deep-review.js.map +1 -0
- package/dist/executor/executor.d.ts +27 -0
- package/dist/executor/executor.d.ts.map +1 -0
- package/dist/executor/executor.js +168 -0
- package/dist/executor/executor.js.map +1 -0
- package/dist/executor/extract-handoff.d.ts +14 -0
- package/dist/executor/extract-handoff.d.ts.map +1 -0
- package/dist/executor/extract-handoff.js +80 -0
- package/dist/executor/extract-handoff.js.map +1 -0
- package/dist/executor/handoff.d.ts +24 -0
- package/dist/executor/handoff.d.ts.map +1 -0
- package/dist/executor/handoff.js +63 -0
- package/dist/executor/handoff.js.map +1 -0
- package/dist/executor/index.d.ts +8 -0
- package/dist/executor/index.d.ts.map +1 -0
- package/dist/executor/index.js +8 -0
- package/dist/executor/index.js.map +1 -0
- package/dist/executor/mcp-resolver.d.ts +29 -0
- package/dist/executor/mcp-resolver.d.ts.map +1 -0
- package/dist/executor/mcp-resolver.js +80 -0
- package/dist/executor/mcp-resolver.js.map +1 -0
- package/dist/executor/permissions.d.ts +11 -0
- package/dist/executor/permissions.d.ts.map +1 -0
- package/dist/executor/permissions.js +32 -0
- package/dist/executor/permissions.js.map +1 -0
- package/dist/executor/profiles.d.ts +5 -0
- package/dist/executor/profiles.d.ts.map +1 -0
- package/dist/executor/profiles.js +35 -0
- package/dist/executor/profiles.js.map +1 -0
- package/dist/executor/prompt/assembler.d.ts +10 -0
- package/dist/executor/prompt/assembler.d.ts.map +1 -0
- package/dist/executor/prompt/assembler.js +28 -0
- package/dist/executor/prompt/assembler.js.map +1 -0
- package/dist/executor/prompt/index.d.ts +5 -0
- package/dist/executor/prompt/index.d.ts.map +1 -0
- package/dist/executor/prompt/index.js +5 -0
- package/dist/executor/prompt/index.js.map +1 -0
- package/dist/executor/prompt/sanitizer.d.ts +25 -0
- package/dist/executor/prompt/sanitizer.d.ts.map +1 -0
- package/dist/executor/prompt/sanitizer.js +81 -0
- package/dist/executor/prompt/sanitizer.js.map +1 -0
- package/dist/executor/prompt/schema-mapper.d.ts +7 -0
- package/dist/executor/prompt/schema-mapper.d.ts.map +1 -0
- package/dist/executor/prompt/schema-mapper.js +59 -0
- package/dist/executor/prompt/schema-mapper.js.map +1 -0
- package/dist/executor/prompt/templates.d.ts +31 -0
- package/dist/executor/prompt/templates.d.ts.map +1 -0
- package/dist/executor/prompt/templates.js +283 -0
- package/dist/executor/prompt/templates.js.map +1 -0
- package/dist/executor/ralph.d.ts +19 -0
- package/dist/executor/ralph.d.ts.map +1 -0
- package/dist/executor/ralph.js +112 -0
- package/dist/executor/ralph.js.map +1 -0
- package/dist/executor/test-quality.d.ts +117 -0
- package/dist/executor/test-quality.d.ts.map +1 -0
- package/dist/executor/test-quality.js +261 -0
- package/dist/executor/test-quality.js.map +1 -0
- package/dist/executor/validate.d.ts +15 -0
- package/dist/executor/validate.d.ts.map +1 -0
- package/dist/executor/validate.js +124 -0
- package/dist/executor/validate.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/license.d.ts +18 -0
- package/dist/license.d.ts.map +1 -0
- package/dist/license.js +44 -0
- package/dist/license.js.map +1 -0
- package/dist/logger.d.ts +43 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +91 -0
- package/dist/logger.js.map +1 -0
- package/dist/notifier/composite.d.ts +13 -0
- package/dist/notifier/composite.d.ts.map +1 -0
- package/dist/notifier/composite.js +28 -0
- package/dist/notifier/composite.js.map +1 -0
- package/dist/notifier/discord.d.ts +14 -0
- package/dist/notifier/discord.d.ts.map +1 -0
- package/dist/notifier/discord.js +105 -0
- package/dist/notifier/discord.js.map +1 -0
- package/dist/notifier/index.d.ts +6 -0
- package/dist/notifier/index.d.ts.map +1 -0
- package/dist/notifier/index.js +6 -0
- package/dist/notifier/index.js.map +1 -0
- package/dist/notifier/linear.d.ts +28 -0
- package/dist/notifier/linear.d.ts.map +1 -0
- package/dist/notifier/linear.js +138 -0
- package/dist/notifier/linear.js.map +1 -0
- package/dist/notifier/slack-alerts.d.ts +62 -0
- package/dist/notifier/slack-alerts.d.ts.map +1 -0
- package/dist/notifier/slack-alerts.js +184 -0
- package/dist/notifier/slack-alerts.js.map +1 -0
- package/dist/notifier/slack.d.ts +14 -0
- package/dist/notifier/slack.d.ts.map +1 -0
- package/dist/notifier/slack.js +146 -0
- package/dist/notifier/slack.js.map +1 -0
- package/dist/pipeline/automerge.d.ts +44 -0
- package/dist/pipeline/automerge.d.ts.map +1 -0
- package/dist/pipeline/automerge.js +135 -0
- package/dist/pipeline/automerge.js.map +1 -0
- package/dist/pipeline/config.d.ts +5 -0
- package/dist/pipeline/config.d.ts.map +1 -0
- package/dist/pipeline/config.js +68 -0
- package/dist/pipeline/config.js.map +1 -0
- package/dist/pipeline/distributed-lock.d.ts +50 -0
- package/dist/pipeline/distributed-lock.d.ts.map +1 -0
- package/dist/pipeline/distributed-lock.js +114 -0
- package/dist/pipeline/distributed-lock.js.map +1 -0
- package/dist/pipeline/error-classifier.d.ts +9 -0
- package/dist/pipeline/error-classifier.d.ts.map +1 -0
- package/dist/pipeline/error-classifier.js +25 -0
- package/dist/pipeline/error-classifier.js.map +1 -0
- package/dist/pipeline/index.d.ts +9 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +9 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/pr-description.d.ts +35 -0
- package/dist/pipeline/pr-description.d.ts.map +1 -0
- package/dist/pipeline/pr-description.js +52 -0
- package/dist/pipeline/pr-description.js.map +1 -0
- package/dist/pipeline/queue.d.ts +7 -0
- package/dist/pipeline/queue.d.ts.map +1 -0
- package/dist/pipeline/queue.js +39 -0
- package/dist/pipeline/queue.js.map +1 -0
- package/dist/pipeline/router.d.ts +6 -0
- package/dist/pipeline/router.d.ts.map +1 -0
- package/dist/pipeline/router.js +19 -0
- package/dist/pipeline/router.js.map +1 -0
- package/dist/pipeline/runner.d.ts +142 -0
- package/dist/pipeline/runner.d.ts.map +1 -0
- package/dist/pipeline/runner.js +1848 -0
- package/dist/pipeline/runner.js.map +1 -0
- package/dist/pm/actions/approval-helpers.d.ts +11 -0
- package/dist/pm/actions/approval-helpers.d.ts.map +1 -0
- package/dist/pm/actions/approval-helpers.js +34 -0
- package/dist/pm/actions/approval-helpers.js.map +1 -0
- package/dist/pm/actions/cancel.d.ts +11 -0
- package/dist/pm/actions/cancel.d.ts.map +1 -0
- package/dist/pm/actions/cancel.js +68 -0
- package/dist/pm/actions/cancel.js.map +1 -0
- package/dist/pm/actions/deprioritize.d.ts +12 -0
- package/dist/pm/actions/deprioritize.d.ts.map +1 -0
- package/dist/pm/actions/deprioritize.js +55 -0
- package/dist/pm/actions/deprioritize.js.map +1 -0
- package/dist/pm/actions/promote.d.ts +11 -0
- package/dist/pm/actions/promote.d.ts.map +1 -0
- package/dist/pm/actions/promote.js +78 -0
- package/dist/pm/actions/promote.js.map +1 -0
- package/dist/pm/actions/recover-stuck.d.ts +42 -0
- package/dist/pm/actions/recover-stuck.d.ts.map +1 -0
- package/dist/pm/actions/recover-stuck.js +143 -0
- package/dist/pm/actions/recover-stuck.js.map +1 -0
- package/dist/pm/actions/recover.d.ts +18 -0
- package/dist/pm/actions/recover.d.ts.map +1 -0
- package/dist/pm/actions/recover.js +56 -0
- package/dist/pm/actions/recover.js.map +1 -0
- package/dist/pm/actions/resolve-approvals.d.ts +17 -0
- package/dist/pm/actions/resolve-approvals.d.ts.map +1 -0
- package/dist/pm/actions/resolve-approvals.js +92 -0
- package/dist/pm/actions/resolve-approvals.js.map +1 -0
- package/dist/pm/actions/start-todo.d.ts +28 -0
- package/dist/pm/actions/start-todo.d.ts.map +1 -0
- package/dist/pm/actions/start-todo.js +117 -0
- package/dist/pm/actions/start-todo.js.map +1 -0
- package/dist/pm/actions/triage.d.ts +13 -0
- package/dist/pm/actions/triage.d.ts.map +1 -0
- package/dist/pm/actions/triage.js +109 -0
- package/dist/pm/actions/triage.js.map +1 -0
- package/dist/pm/budget.d.ts +9 -0
- package/dist/pm/budget.d.ts.map +1 -0
- package/dist/pm/budget.js +62 -0
- package/dist/pm/budget.js.map +1 -0
- package/dist/pm/call-claude.d.ts +3 -0
- package/dist/pm/call-claude.d.ts.map +1 -0
- package/dist/pm/call-claude.js +37 -0
- package/dist/pm/call-claude.js.map +1 -0
- package/dist/pm/conflict-detector.d.ts +42 -0
- package/dist/pm/conflict-detector.d.ts.map +1 -0
- package/dist/pm/conflict-detector.js +116 -0
- package/dist/pm/conflict-detector.js.map +1 -0
- package/dist/pm/conflict.d.ts +20 -0
- package/dist/pm/conflict.d.ts.map +1 -0
- package/dist/pm/conflict.js +63 -0
- package/dist/pm/conflict.js.map +1 -0
- package/dist/pm/coordination.d.ts +50 -0
- package/dist/pm/coordination.d.ts.map +1 -0
- package/dist/pm/coordination.js +163 -0
- package/dist/pm/coordination.js.map +1 -0
- package/dist/pm/linear-helpers.d.ts +2 -0
- package/dist/pm/linear-helpers.d.ts.map +1 -0
- package/dist/pm/linear-helpers.js +16 -0
- package/dist/pm/linear-helpers.js.map +1 -0
- package/dist/pm/scheduler.d.ts +47 -0
- package/dist/pm/scheduler.d.ts.map +1 -0
- package/dist/pm/scheduler.js +346 -0
- package/dist/pm/scheduler.js.map +1 -0
- package/dist/pm/slack-helpers.d.ts +2 -0
- package/dist/pm/slack-helpers.d.ts.map +1 -0
- package/dist/pm/slack-helpers.js +24 -0
- package/dist/pm/slack-helpers.js.map +1 -0
- package/dist/pm/slack-interface.d.ts +133 -0
- package/dist/pm/slack-interface.d.ts.map +1 -0
- package/dist/pm/slack-interface.js +641 -0
- package/dist/pm/slack-interface.js.map +1 -0
- package/dist/pm/slack.d.ts +18 -0
- package/dist/pm/slack.d.ts.map +1 -0
- package/dist/pm/slack.js +144 -0
- package/dist/pm/slack.js.map +1 -0
- package/dist/pm/types.d.ts +99 -0
- package/dist/pm/types.d.ts.map +1 -0
- package/dist/pm/types.js +17 -0
- package/dist/pm/types.js.map +1 -0
- package/dist/repo/config.d.ts +35 -0
- package/dist/repo/config.d.ts.map +1 -0
- package/dist/repo/config.js +72 -0
- package/dist/repo/config.js.map +1 -0
- package/dist/repo/devcontainer.d.ts +33 -0
- package/dist/repo/devcontainer.d.ts.map +1 -0
- package/dist/repo/devcontainer.js +90 -0
- package/dist/repo/devcontainer.js.map +1 -0
- package/dist/repo/git.d.ts +185 -0
- package/dist/repo/git.d.ts.map +1 -0
- package/dist/repo/git.js +586 -0
- package/dist/repo/git.js.map +1 -0
- package/dist/repo/github.d.ts +56 -0
- package/dist/repo/github.d.ts.map +1 -0
- package/dist/repo/github.js +164 -0
- package/dist/repo/github.js.map +1 -0
- package/dist/repo/gitlab.d.ts +47 -0
- package/dist/repo/gitlab.d.ts.map +1 -0
- package/dist/repo/gitlab.js +91 -0
- package/dist/repo/gitlab.js.map +1 -0
- package/dist/repo/index.d.ts +7 -0
- package/dist/repo/index.d.ts.map +1 -0
- package/dist/repo/index.js +5 -0
- package/dist/repo/index.js.map +1 -0
- package/dist/repo/tech-stack.d.ts +13 -0
- package/dist/repo/tech-stack.d.ts.map +1 -0
- package/dist/repo/tech-stack.js +112 -0
- package/dist/repo/tech-stack.js.map +1 -0
- package/dist/security/index.d.ts +3 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +3 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/review-checklist.d.ts +9 -0
- package/dist/security/review-checklist.d.ts.map +1 -0
- package/dist/security/review-checklist.js +46 -0
- package/dist/security/review-checklist.js.map +1 -0
- package/dist/security/sandbox.d.ts +7 -0
- package/dist/security/sandbox.d.ts.map +1 -0
- package/dist/security/sandbox.js +31 -0
- package/dist/security/sandbox.js.map +1 -0
- package/dist/server.d.ts +48 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +90 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +1230 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +225 -0
- package/dist/types.js.map +1 -0
- package/dist/webhook/github-handler.d.ts +39 -0
- package/dist/webhook/github-handler.d.ts.map +1 -0
- package/dist/webhook/github-handler.js +439 -0
- package/dist/webhook/github-handler.js.map +1 -0
- package/dist/webhook/handler.d.ts +16 -0
- package/dist/webhook/handler.d.ts.map +1 -0
- package/dist/webhook/handler.js +171 -0
- package/dist/webhook/handler.js.map +1 -0
- package/dist/webhook/index.d.ts +5 -0
- package/dist/webhook/index.d.ts.map +1 -0
- package/dist/webhook/index.js +5 -0
- package/dist/webhook/index.js.map +1 -0
- package/dist/webhook/parser.d.ts +18 -0
- package/dist/webhook/parser.d.ts.map +1 -0
- package/dist/webhook/parser.js +30 -0
- package/dist/webhook/parser.js.map +1 -0
- package/dist/webhook/signature.d.ts +2 -0
- package/dist/webhook/signature.d.ts.map +1 -0
- package/dist/webhook/signature.js +14 -0
- package/dist/webhook/signature.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,728 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { generatePRDescription } from "../pipeline/pr-description.js";
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- test file uses partial handoff objects
|
|
4
|
+
/**
|
|
5
|
+
* Test the PR description enrichment feature (BEC-83 / BEC-109).
|
|
6
|
+
*
|
|
7
|
+
* These tests verify that auto-generated PR descriptions include:
|
|
8
|
+
* - Summary section from handoff.summary
|
|
9
|
+
* - Changes section with bulleted list of filesChanged
|
|
10
|
+
* - Test plan section with test files
|
|
11
|
+
* - Fallback content when optional fields unavailable
|
|
12
|
+
* - Exact template order: Summary → Changes → Test plan → Issue link
|
|
13
|
+
*
|
|
14
|
+
* Tests use the actual generatePRDescription() function from production code.
|
|
15
|
+
*/
|
|
16
|
+
describe("PR Description Enrichment (BEC-83)", () => {
|
|
17
|
+
// =========================================================================
|
|
18
|
+
// 1. Summary Section
|
|
19
|
+
// =========================================================================
|
|
20
|
+
describe("Summary section", () => {
|
|
21
|
+
it("populates Summary from handoff.summary", () => {
|
|
22
|
+
const handoff = {
|
|
23
|
+
summary: "Added user authentication with JWT tokens and bcrypt hashing.",
|
|
24
|
+
filesChanged: [],
|
|
25
|
+
approach: "Used passport.js middleware",
|
|
26
|
+
context: "Authentication was missing",
|
|
27
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
28
|
+
};
|
|
29
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-123" });
|
|
30
|
+
expect(body).toContain("## Summary");
|
|
31
|
+
expect(body).toContain("Added user authentication with JWT tokens and bcrypt hashing.");
|
|
32
|
+
});
|
|
33
|
+
it("uses fallback 'No summary available.' when handoff is undefined", () => {
|
|
34
|
+
const body = generatePRDescription({ handoff: undefined, issueId: "BEC-123" });
|
|
35
|
+
expect(body).toContain("## Summary");
|
|
36
|
+
expect(body).toContain("No summary available.");
|
|
37
|
+
});
|
|
38
|
+
it("renders empty summary when handoff.summary is an empty string", () => {
|
|
39
|
+
const handoff = {
|
|
40
|
+
summary: "",
|
|
41
|
+
filesChanged: [],
|
|
42
|
+
approach: "test",
|
|
43
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
44
|
+
tokenBudget: { remaining: 1000, used: 100, totalBudget: 1100 },
|
|
45
|
+
};
|
|
46
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-123" });
|
|
47
|
+
expect(body).toContain("## Summary");
|
|
48
|
+
// Empty string summary renders with just the header and blank line
|
|
49
|
+
expect(body).toMatch(/## Summary\n\n/);
|
|
50
|
+
});
|
|
51
|
+
it("handles multi-line summaries correctly", () => {
|
|
52
|
+
const handoff = {
|
|
53
|
+
summary: `Implemented database migrations for user schema.
|
|
54
|
+
- Added users table with unique email constraint
|
|
55
|
+
- Created indexes for faster queries`,
|
|
56
|
+
filesChanged: ["src/migrations/001_users.ts"],
|
|
57
|
+
approach: "Used Drizzle ORM",
|
|
58
|
+
context: "Schema needed updates",
|
|
59
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
60
|
+
};
|
|
61
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-456" });
|
|
62
|
+
expect(body).toContain("## Summary");
|
|
63
|
+
expect(body).toContain("Implemented database migrations for user schema.");
|
|
64
|
+
expect(body).toContain("- Added users table with unique email constraint");
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
// =========================================================================
|
|
68
|
+
// 2. Changes Section
|
|
69
|
+
// =========================================================================
|
|
70
|
+
describe("Changes section", () => {
|
|
71
|
+
it("includes bulleted list of all filesChanged", () => {
|
|
72
|
+
const handoff = {
|
|
73
|
+
summary: "Updated auth flow",
|
|
74
|
+
filesChanged: [
|
|
75
|
+
"src/auth.ts",
|
|
76
|
+
"src/auth.test.ts",
|
|
77
|
+
"src/types/auth.ts",
|
|
78
|
+
"src/middleware/auth-check.ts",
|
|
79
|
+
],
|
|
80
|
+
approach: "Refactored",
|
|
81
|
+
context: "Security update",
|
|
82
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
83
|
+
};
|
|
84
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-789" });
|
|
85
|
+
expect(body).toContain("## Changes");
|
|
86
|
+
expect(body).toContain("- `src/auth.ts`");
|
|
87
|
+
expect(body).toContain("- `src/auth.test.ts`");
|
|
88
|
+
expect(body).toContain("- `src/types/auth.ts`");
|
|
89
|
+
expect(body).toContain("- `src/middleware/auth-check.ts`");
|
|
90
|
+
});
|
|
91
|
+
it("uses fallback 'No file changes recorded.' when filesChanged is empty", () => {
|
|
92
|
+
const handoff = {
|
|
93
|
+
summary: "No changes needed",
|
|
94
|
+
filesChanged: [],
|
|
95
|
+
approach: "test",
|
|
96
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
97
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
98
|
+
};
|
|
99
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-111" });
|
|
100
|
+
expect(body).toContain("## Changes");
|
|
101
|
+
expect(body).toContain("No file changes recorded.");
|
|
102
|
+
});
|
|
103
|
+
it("uses fallback 'No file changes recorded.' when handoff is undefined", () => {
|
|
104
|
+
const body = generatePRDescription({ handoff: undefined, issueId: "BEC-222" });
|
|
105
|
+
expect(body).toContain("## Changes");
|
|
106
|
+
expect(body).toContain("No file changes recorded.");
|
|
107
|
+
});
|
|
108
|
+
it("properly escapes backticks in file paths", () => {
|
|
109
|
+
const handoff = {
|
|
110
|
+
summary: "Updated config",
|
|
111
|
+
filesChanged: ["src/components/Button.tsx", "src/styles/button.css"],
|
|
112
|
+
approach: "test",
|
|
113
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
114
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
115
|
+
};
|
|
116
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-333" });
|
|
117
|
+
expect(body).toContain("- `src/components/Button.tsx`");
|
|
118
|
+
expect(body).toContain("- `src/styles/button.css`");
|
|
119
|
+
});
|
|
120
|
+
it("handles deeply nested file paths", () => {
|
|
121
|
+
const handoff = {
|
|
122
|
+
summary: "Deep refactor",
|
|
123
|
+
filesChanged: [
|
|
124
|
+
"packages/core/src/executor/stages/implement/handler.ts",
|
|
125
|
+
"packages/core/src/__tests__/executor.test.ts",
|
|
126
|
+
],
|
|
127
|
+
approach: "test",
|
|
128
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
129
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
130
|
+
};
|
|
131
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-444" });
|
|
132
|
+
expect(body).toContain("- `packages/core/src/executor/stages/implement/handler.ts`");
|
|
133
|
+
expect(body).toContain("- `packages/core/src/__tests__/executor.test.ts`");
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
// =========================================================================
|
|
137
|
+
// 3. Test Plan Section
|
|
138
|
+
// =========================================================================
|
|
139
|
+
describe("Test plan section", () => {
|
|
140
|
+
it("lists test files when filesChanged includes .test.ts files", () => {
|
|
141
|
+
const handoff = {
|
|
142
|
+
summary: "Added feature",
|
|
143
|
+
filesChanged: [
|
|
144
|
+
"src/feature.ts",
|
|
145
|
+
"src/feature.test.ts",
|
|
146
|
+
"src/helper.ts",
|
|
147
|
+
"src/helper.test.ts",
|
|
148
|
+
],
|
|
149
|
+
approach: "test",
|
|
150
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
151
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
152
|
+
};
|
|
153
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-555" });
|
|
154
|
+
expect(body).toContain("## Test plan");
|
|
155
|
+
expect(body).toContain("- `src/feature.test.ts`");
|
|
156
|
+
expect(body).toContain("- `src/helper.test.ts`");
|
|
157
|
+
// Verify that test files appear in the test plan section, not the changes section
|
|
158
|
+
const testPlanStart = body.indexOf("## Test plan");
|
|
159
|
+
const issueLink = body.indexOf("Resolves");
|
|
160
|
+
const testPlanSection = body.substring(testPlanStart, issueLink);
|
|
161
|
+
expect(testPlanSection).toContain("- `src/feature.test.ts`");
|
|
162
|
+
expect(testPlanSection).toContain("- `src/helper.test.ts`");
|
|
163
|
+
// Non-test files should appear in Changes section, not Test plan section
|
|
164
|
+
expect(testPlanSection).not.toContain("- `src/feature.ts`");
|
|
165
|
+
expect(testPlanSection).not.toContain("- `src/helper.ts`");
|
|
166
|
+
});
|
|
167
|
+
it("identifies .test.jsx files as test files", () => {
|
|
168
|
+
const handoff = {
|
|
169
|
+
summary: "React component",
|
|
170
|
+
filesChanged: ["src/Button.jsx", "src/Button.test.jsx"],
|
|
171
|
+
approach: "test",
|
|
172
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
173
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
174
|
+
};
|
|
175
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-666" });
|
|
176
|
+
expect(body).toContain("## Test plan");
|
|
177
|
+
expect(body).toContain("- `src/Button.test.jsx`");
|
|
178
|
+
});
|
|
179
|
+
it("identifies .spec.ts files as test files", () => {
|
|
180
|
+
const handoff = {
|
|
181
|
+
summary: "Angular service",
|
|
182
|
+
filesChanged: ["src/app.service.ts", "src/app.service.spec.ts"],
|
|
183
|
+
approach: "test",
|
|
184
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
185
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
186
|
+
};
|
|
187
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-777" });
|
|
188
|
+
expect(body).toContain("## Test plan");
|
|
189
|
+
expect(body).toContain("- `src/app.service.spec.ts`");
|
|
190
|
+
});
|
|
191
|
+
it("identifies __tests__ directory files as test files", () => {
|
|
192
|
+
const handoff = {
|
|
193
|
+
summary: "Updated utils",
|
|
194
|
+
filesChanged: [
|
|
195
|
+
"src/utils.ts",
|
|
196
|
+
"src/__tests__/utils.test.ts",
|
|
197
|
+
"src/__tests__/integration/utils.test.ts",
|
|
198
|
+
],
|
|
199
|
+
approach: "test",
|
|
200
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
201
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
202
|
+
};
|
|
203
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-888" });
|
|
204
|
+
expect(body).toContain("## Test plan");
|
|
205
|
+
expect(body).toContain("- `src/__tests__/utils.test.ts`");
|
|
206
|
+
expect(body).toContain("- `src/__tests__/integration/utils.test.ts`");
|
|
207
|
+
});
|
|
208
|
+
it("uses fallback 'No test changes' when no test files present", () => {
|
|
209
|
+
const handoff = {
|
|
210
|
+
summary: "Documentation only",
|
|
211
|
+
filesChanged: ["README.md", "docs/guide.md"],
|
|
212
|
+
approach: "test",
|
|
213
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
214
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
215
|
+
};
|
|
216
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-999" });
|
|
217
|
+
expect(body).toContain("## Test plan");
|
|
218
|
+
expect(body).toContain("No test changes");
|
|
219
|
+
});
|
|
220
|
+
it("uses fallback 'No test changes' when handoff is undefined", () => {
|
|
221
|
+
const body = generatePRDescription({ handoff: undefined, issueId: "BEC-101" });
|
|
222
|
+
expect(body).toContain("## Test plan");
|
|
223
|
+
expect(body).toContain("No test changes");
|
|
224
|
+
});
|
|
225
|
+
it("identifies files in test-related directories (tests/, specs/)", () => {
|
|
226
|
+
const handoff = {
|
|
227
|
+
summary: "Feature update",
|
|
228
|
+
filesChanged: [
|
|
229
|
+
"src/feature.ts",
|
|
230
|
+
"tests/feature.test.ts",
|
|
231
|
+
"specs/feature.spec.ts",
|
|
232
|
+
],
|
|
233
|
+
approach: "test",
|
|
234
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
235
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
236
|
+
};
|
|
237
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-202" });
|
|
238
|
+
expect(body).toContain("## Test plan");
|
|
239
|
+
expect(body).toContain("- `tests/feature.test.ts`");
|
|
240
|
+
expect(body).toContain("- `specs/feature.spec.ts`");
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
// =========================================================================
|
|
244
|
+
// 4. Issue Link Section
|
|
245
|
+
// =========================================================================
|
|
246
|
+
describe("Issue link section", () => {
|
|
247
|
+
it("includes 'Resolves' link with issue identifier", () => {
|
|
248
|
+
const handoff = {
|
|
249
|
+
summary: "Test",
|
|
250
|
+
filesChanged: [],
|
|
251
|
+
approach: "test",
|
|
252
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
253
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
254
|
+
};
|
|
255
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-303" });
|
|
256
|
+
expect(body).toContain("Resolves BEC-303");
|
|
257
|
+
});
|
|
258
|
+
it("includes 'Resolves' link even when handoff is undefined", () => {
|
|
259
|
+
const body = generatePRDescription({ handoff: undefined, issueId: "BEC-404" });
|
|
260
|
+
expect(body).toContain("Resolves BEC-404");
|
|
261
|
+
});
|
|
262
|
+
it("appears as the last section in PR body", () => {
|
|
263
|
+
const handoff = {
|
|
264
|
+
summary: "Test summary",
|
|
265
|
+
filesChanged: ["file1.ts"],
|
|
266
|
+
approach: "test",
|
|
267
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
268
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
269
|
+
};
|
|
270
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-505" });
|
|
271
|
+
expect(body.endsWith("Resolves BEC-505")).toBe(true);
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
// =========================================================================
|
|
275
|
+
// 5. Template Order and Structure
|
|
276
|
+
// =========================================================================
|
|
277
|
+
describe("Template order and structure", () => {
|
|
278
|
+
it("follows exact order: Summary → Changes → Test plan → Issue link", () => {
|
|
279
|
+
const handoff = {
|
|
280
|
+
summary: "Summary text",
|
|
281
|
+
filesChanged: ["src/test.ts", "src/test.test.ts"],
|
|
282
|
+
approach: "test",
|
|
283
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
284
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
285
|
+
};
|
|
286
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-606" });
|
|
287
|
+
const summaryIndex = body.indexOf("## Summary");
|
|
288
|
+
const changesIndex = body.indexOf("## Changes");
|
|
289
|
+
const testPlanIndex = body.indexOf("## Test plan");
|
|
290
|
+
const resolvesIndex = body.indexOf("Resolves");
|
|
291
|
+
expect(summaryIndex).toBeLessThan(changesIndex);
|
|
292
|
+
expect(changesIndex).toBeLessThan(testPlanIndex);
|
|
293
|
+
expect(testPlanIndex).toBeLessThan(resolvesIndex);
|
|
294
|
+
});
|
|
295
|
+
it("separates sections with double newlines (paragraph breaks)", () => {
|
|
296
|
+
const handoff = {
|
|
297
|
+
summary: "Test",
|
|
298
|
+
filesChanged: ["file.ts"],
|
|
299
|
+
approach: "test",
|
|
300
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
301
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
302
|
+
};
|
|
303
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-707" });
|
|
304
|
+
// Sections should be separated by \n\n
|
|
305
|
+
expect(body).toMatch(/## Summary\n.*\n\n## Changes/s);
|
|
306
|
+
expect(body).toMatch(/## Changes\n.*\n\n## Test plan/s);
|
|
307
|
+
expect(body).toMatch(/## Test plan\n.*\n\nResolves/s);
|
|
308
|
+
});
|
|
309
|
+
it("handles draft PR status correctly in body", () => {
|
|
310
|
+
const handoff = {
|
|
311
|
+
summary: "Test",
|
|
312
|
+
filesChanged: [],
|
|
313
|
+
approach: "test",
|
|
314
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
315
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
316
|
+
};
|
|
317
|
+
const body = generatePRDescription({
|
|
318
|
+
handoff,
|
|
319
|
+
issueId: "BEC-808",
|
|
320
|
+
shouldDraft: true,
|
|
321
|
+
ralphSatisfied: false,
|
|
322
|
+
unresolvedBlockingFindings: [],
|
|
323
|
+
ralphGaps: [{ criterion: "test" }],
|
|
324
|
+
});
|
|
325
|
+
expect(body).toContain("> **Draft PR**");
|
|
326
|
+
expect(body).toContain("RALPH found 1 unmet acceptance criteria");
|
|
327
|
+
});
|
|
328
|
+
it("includes blocking review findings count in draft status", () => {
|
|
329
|
+
const handoff = {
|
|
330
|
+
summary: "Test",
|
|
331
|
+
filesChanged: [],
|
|
332
|
+
approach: "test",
|
|
333
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
334
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
335
|
+
};
|
|
336
|
+
const blockingFindings = [
|
|
337
|
+
{ type: "blocking", message: "test 1" },
|
|
338
|
+
{ type: "blocking", message: "test 2" },
|
|
339
|
+
];
|
|
340
|
+
const body = generatePRDescription({
|
|
341
|
+
handoff,
|
|
342
|
+
issueId: "BEC-909",
|
|
343
|
+
shouldDraft: true,
|
|
344
|
+
ralphSatisfied: true,
|
|
345
|
+
unresolvedBlockingFindings: blockingFindings,
|
|
346
|
+
ralphGaps: [],
|
|
347
|
+
});
|
|
348
|
+
expect(body).toContain("> **Draft PR**");
|
|
349
|
+
expect(body).toContain("2 blocking review findings remain");
|
|
350
|
+
});
|
|
351
|
+
it("includes agent commits section when agentCommits are provided", () => {
|
|
352
|
+
const handoff = {
|
|
353
|
+
summary: "Test",
|
|
354
|
+
filesChanged: ["src/feature.ts"],
|
|
355
|
+
approach: "test",
|
|
356
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
357
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
358
|
+
};
|
|
359
|
+
const body = generatePRDescription({
|
|
360
|
+
handoff,
|
|
361
|
+
issueId: "BEC-910",
|
|
362
|
+
agentCommits: ["feat: add new feature", "fix: correct edge case"],
|
|
363
|
+
});
|
|
364
|
+
expect(body).toContain("## Commits");
|
|
365
|
+
expect(body).toContain("- feat: add new feature");
|
|
366
|
+
expect(body).toContain("- fix: correct edge case");
|
|
367
|
+
});
|
|
368
|
+
it("omits Commits section when all commits are auto-committed", () => {
|
|
369
|
+
const handoff = {
|
|
370
|
+
summary: "Test",
|
|
371
|
+
filesChanged: ["src/feature.ts"],
|
|
372
|
+
approach: "test",
|
|
373
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
374
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
375
|
+
};
|
|
376
|
+
const body = generatePRDescription({
|
|
377
|
+
handoff,
|
|
378
|
+
issueId: "BEC-911",
|
|
379
|
+
agentCommits: ["Auto-commit (auto-committed)", "Another (auto-committed)"],
|
|
380
|
+
});
|
|
381
|
+
expect(body).not.toContain("## Commits");
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
// =========================================================================
|
|
385
|
+
// 6. Fallback Behavior
|
|
386
|
+
// =========================================================================
|
|
387
|
+
describe("Fallback behavior", () => {
|
|
388
|
+
it("handles completely empty handoff gracefully", () => {
|
|
389
|
+
const handoff = {
|
|
390
|
+
summary: "",
|
|
391
|
+
filesChanged: [],
|
|
392
|
+
approach: "test",
|
|
393
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
394
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
395
|
+
};
|
|
396
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-010" });
|
|
397
|
+
expect(body).toContain("## Summary");
|
|
398
|
+
expect(body).toContain("## Changes");
|
|
399
|
+
expect(body).toContain("No file changes recorded.");
|
|
400
|
+
expect(body).toContain("## Test plan");
|
|
401
|
+
expect(body).toContain("No test changes");
|
|
402
|
+
expect(body).toContain("Resolves BEC-010");
|
|
403
|
+
// Verify all sections are present
|
|
404
|
+
expect(body).toMatch(/## Summary[\s\S]*## Changes[\s\S]*## Test plan[\s\S]*Resolves/);
|
|
405
|
+
});
|
|
406
|
+
it("generates valid markdown when all fields are present", () => {
|
|
407
|
+
const handoff = {
|
|
408
|
+
summary: "Comprehensive update with tests and documentation.",
|
|
409
|
+
filesChanged: [
|
|
410
|
+
"src/main.ts",
|
|
411
|
+
"src/utils.ts",
|
|
412
|
+
"src/utils.test.ts",
|
|
413
|
+
"src/helper.test.ts",
|
|
414
|
+
"docs/api.md",
|
|
415
|
+
],
|
|
416
|
+
approach: "Strategic refactor",
|
|
417
|
+
context: "Performance improvements",
|
|
418
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
419
|
+
};
|
|
420
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-111" });
|
|
421
|
+
// Verify markdown structure
|
|
422
|
+
expect(body).toMatch(/^## Summary\n/);
|
|
423
|
+
expect(body).toContain("## Changes");
|
|
424
|
+
expect(body).toContain("## Test plan");
|
|
425
|
+
expect(body).toContain("Resolves BEC-111");
|
|
426
|
+
// Verify code blocks are properly formatted
|
|
427
|
+
expect(body).toContain("- `src/main.ts`");
|
|
428
|
+
expect(body).toContain("- `src/utils.test.ts`");
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
// =========================================================================
|
|
432
|
+
// 7. Edge Cases
|
|
433
|
+
// =========================================================================
|
|
434
|
+
describe("Edge cases", () => {
|
|
435
|
+
it("handles single file in changes section", () => {
|
|
436
|
+
const handoff = {
|
|
437
|
+
summary: "Single file change",
|
|
438
|
+
filesChanged: ["src/single.ts"],
|
|
439
|
+
approach: "test",
|
|
440
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
441
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
442
|
+
};
|
|
443
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-212" });
|
|
444
|
+
expect(body).toContain("## Changes");
|
|
445
|
+
expect(body).toContain("- `src/single.ts`");
|
|
446
|
+
});
|
|
447
|
+
it("handles large number of files", () => {
|
|
448
|
+
const filesChanged = Array.from({ length: 50 }, (_, i) => `src/file${i}.ts`);
|
|
449
|
+
const handoff = {
|
|
450
|
+
summary: "Large refactor",
|
|
451
|
+
filesChanged,
|
|
452
|
+
approach: "test",
|
|
453
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
454
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
455
|
+
};
|
|
456
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-313" });
|
|
457
|
+
expect(body).toContain("## Changes");
|
|
458
|
+
for (let i = 0; i < 50; i++) {
|
|
459
|
+
expect(body).toContain(`- \`src/file${i}.ts\``);
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
it("handles files with special characters in names", () => {
|
|
463
|
+
const handoff = {
|
|
464
|
+
summary: "Update",
|
|
465
|
+
filesChanged: [
|
|
466
|
+
"src/my-component.tsx",
|
|
467
|
+
"src/my_helper.ts",
|
|
468
|
+
"src/const.CONSTANT.ts",
|
|
469
|
+
],
|
|
470
|
+
approach: "test",
|
|
471
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
472
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
473
|
+
};
|
|
474
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-414" });
|
|
475
|
+
expect(body).toContain("- `src/my-component.tsx`");
|
|
476
|
+
expect(body).toContain("- `src/my_helper.ts`");
|
|
477
|
+
expect(body).toContain("- `src/const.CONSTANT.ts`");
|
|
478
|
+
});
|
|
479
|
+
it("handles summary with special markdown characters", () => {
|
|
480
|
+
const handoff = {
|
|
481
|
+
summary: "Fixed `bug` in **login** flow. See PR #123 for details.",
|
|
482
|
+
filesChanged: [],
|
|
483
|
+
approach: "test",
|
|
484
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
485
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
486
|
+
};
|
|
487
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-515" });
|
|
488
|
+
expect(body).toContain("Fixed `bug` in **login** flow. See PR #123 for details.");
|
|
489
|
+
});
|
|
490
|
+
it("handles multiple test file extensions (tsx, jsx, spec.ts)", () => {
|
|
491
|
+
const handoff = {
|
|
492
|
+
summary: "Mixed tests",
|
|
493
|
+
filesChanged: [
|
|
494
|
+
"src/Button.tsx",
|
|
495
|
+
"src/Button.test.tsx",
|
|
496
|
+
"src/Form.jsx",
|
|
497
|
+
"src/Form.test.jsx",
|
|
498
|
+
"src/service.ts",
|
|
499
|
+
"src/service.spec.ts",
|
|
500
|
+
],
|
|
501
|
+
approach: "test",
|
|
502
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
503
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
504
|
+
};
|
|
505
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-616" });
|
|
506
|
+
expect(body).toContain("## Test plan");
|
|
507
|
+
expect(body).toContain("- `src/Button.test.tsx`");
|
|
508
|
+
expect(body).toContain("- `src/Form.test.jsx`");
|
|
509
|
+
expect(body).toContain("- `src/service.spec.ts`");
|
|
510
|
+
});
|
|
511
|
+
it("ignores non-test files even if 'test' appears in path", () => {
|
|
512
|
+
const handoff = {
|
|
513
|
+
summary: "Update",
|
|
514
|
+
filesChanged: [
|
|
515
|
+
"src/components/test-utils.ts", // NOT a test file
|
|
516
|
+
"src/components/test-utils.test.ts", // IS a test file
|
|
517
|
+
],
|
|
518
|
+
approach: "test",
|
|
519
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
520
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
521
|
+
};
|
|
522
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-717" });
|
|
523
|
+
const testPlanSection = body.split("## Test plan")[1].split("\n\nResolves")[0];
|
|
524
|
+
// Should only contain the actual test file
|
|
525
|
+
expect(testPlanSection).toContain("- `src/components/test-utils.test.ts`");
|
|
526
|
+
// Non-test file should not be listed in test plan
|
|
527
|
+
expect(testPlanSection).not.toContain("test-utils.ts`\n");
|
|
528
|
+
});
|
|
529
|
+
});
|
|
530
|
+
// =========================================================================
|
|
531
|
+
// 8. Acceptance Criteria Verification
|
|
532
|
+
// =========================================================================
|
|
533
|
+
describe("Acceptance Criteria (BEC-83)", () => {
|
|
534
|
+
it("✓ PR descriptions include Summary section from handoff.summary (2-3 sentences)", () => {
|
|
535
|
+
const handoff = {
|
|
536
|
+
summary: "Implemented OAuth2 authentication flow with Google and GitHub providers.",
|
|
537
|
+
filesChanged: ["src/auth/oauth.ts"],
|
|
538
|
+
approach: "test",
|
|
539
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
540
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
541
|
+
};
|
|
542
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-83" });
|
|
543
|
+
expect(body).toContain("## Summary");
|
|
544
|
+
expect(body).toContain("Implemented OAuth2 authentication flow");
|
|
545
|
+
expect(body.split("## Summary")[1].split("##")[0]).toContain("Implemented OAuth2 authentication flow");
|
|
546
|
+
});
|
|
547
|
+
it("✓ PR descriptions include Changes section with all filesChanged", () => {
|
|
548
|
+
const handoff = {
|
|
549
|
+
summary: "Test",
|
|
550
|
+
filesChanged: ["src/auth.ts", "src/routes/auth.ts", "src/types.ts"],
|
|
551
|
+
approach: "test",
|
|
552
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
553
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
554
|
+
};
|
|
555
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-83" });
|
|
556
|
+
expect(body).toContain("## Changes");
|
|
557
|
+
expect(body).toContain("- `src/auth.ts`");
|
|
558
|
+
expect(body).toContain("- `src/routes/auth.ts`");
|
|
559
|
+
expect(body).toContain("- `src/types.ts`");
|
|
560
|
+
});
|
|
561
|
+
it("✓ PR descriptions include Test plan section", () => {
|
|
562
|
+
const handoff = {
|
|
563
|
+
summary: "Test",
|
|
564
|
+
filesChanged: ["src/feature.ts", "src/feature.test.ts"],
|
|
565
|
+
approach: "test",
|
|
566
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
567
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
568
|
+
};
|
|
569
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-83" });
|
|
570
|
+
expect(body).toContain("## Test plan");
|
|
571
|
+
expect(body).toContain("- `src/feature.test.ts`");
|
|
572
|
+
});
|
|
573
|
+
it("✓ PR descriptions include 'Resolves {issueIdentifier}'", () => {
|
|
574
|
+
const handoff = {
|
|
575
|
+
summary: "Test",
|
|
576
|
+
filesChanged: [],
|
|
577
|
+
approach: "test",
|
|
578
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
579
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
580
|
+
};
|
|
581
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-83" });
|
|
582
|
+
expect(body).toContain("Resolves BEC-83");
|
|
583
|
+
});
|
|
584
|
+
it("✓ PR body follows exact template order: Summary → Changes → Test plan → Issue link", () => {
|
|
585
|
+
const handoff = {
|
|
586
|
+
summary: "Test summary",
|
|
587
|
+
filesChanged: ["src/file.ts", "src/file.test.ts"],
|
|
588
|
+
approach: "test",
|
|
589
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
590
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
591
|
+
};
|
|
592
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-83" });
|
|
593
|
+
const sections = body.match(/## Summary|## Changes|## Test plan|Resolves/g);
|
|
594
|
+
expect(sections).toEqual([
|
|
595
|
+
"## Summary",
|
|
596
|
+
"## Changes",
|
|
597
|
+
"## Test plan",
|
|
598
|
+
"Resolves",
|
|
599
|
+
]);
|
|
600
|
+
});
|
|
601
|
+
it("✓ Pipeline runner uses handoff artifact to populate all fields", () => {
|
|
602
|
+
// Verify that generatePRDescription uses handoff?.summary and handoff?.filesChanged
|
|
603
|
+
const handoff = {
|
|
604
|
+
summary: "Custom summary from handoff",
|
|
605
|
+
filesChanged: ["custom/file.ts"],
|
|
606
|
+
approach: "test",
|
|
607
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
608
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
609
|
+
};
|
|
610
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-83" });
|
|
611
|
+
expect(body).toContain("Custom summary from handoff");
|
|
612
|
+
expect(body).toContain("- `custom/file.ts`");
|
|
613
|
+
});
|
|
614
|
+
it("✓ PR creation succeeds with fallback content when optional fields unavailable", () => {
|
|
615
|
+
const body = generatePRDescription({ handoff: undefined, issueId: "BEC-83" });
|
|
616
|
+
expect(body).toContain("## Summary");
|
|
617
|
+
expect(body).toContain("No summary available."); // Only when handoff is undefined
|
|
618
|
+
expect(body).toContain("## Changes");
|
|
619
|
+
expect(body).toContain("No file changes recorded.");
|
|
620
|
+
expect(body).toContain("## Test plan");
|
|
621
|
+
expect(body).toContain("No test changes");
|
|
622
|
+
expect(body).toContain("Resolves BEC-83");
|
|
623
|
+
// Verify structure is intact
|
|
624
|
+
expect(body).toMatch(/## Summary[\s\S]*## Changes[\s\S]*## Test plan[\s\S]*Resolves/);
|
|
625
|
+
});
|
|
626
|
+
it("✓ PR descriptions created for all pipeline-generated PRs (100% coverage)", () => {
|
|
627
|
+
// Test multiple scenarios to ensure all PRs get descriptions
|
|
628
|
+
// Scenario 1: With full handoff
|
|
629
|
+
const body1 = generatePRDescription({
|
|
630
|
+
handoff: {
|
|
631
|
+
summary: "Feature",
|
|
632
|
+
filesChanged: ["file.ts"],
|
|
633
|
+
approach: "test",
|
|
634
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
635
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
636
|
+
},
|
|
637
|
+
issueId: "BEC-1",
|
|
638
|
+
});
|
|
639
|
+
expect(body1.includes("## Summary") && body1.includes("Resolves BEC-1")).toBe(true);
|
|
640
|
+
// Scenario 2: With undefined handoff (should still have full PR body)
|
|
641
|
+
const body2 = generatePRDescription({ handoff: undefined, issueId: "BEC-2" });
|
|
642
|
+
expect(body2.includes("## Summary") && body2.includes("Resolves BEC-2")).toBe(true);
|
|
643
|
+
// Scenario 3: With draft status
|
|
644
|
+
const body3 = generatePRDescription({
|
|
645
|
+
handoff: {
|
|
646
|
+
summary: "Draft feature",
|
|
647
|
+
filesChanged: [],
|
|
648
|
+
approach: "test",
|
|
649
|
+
context: { issueIntent: "test", constraints: [], assumptions: [] },
|
|
650
|
+
tokenBudget: { contextTokensUsed: 10000, recommendedMaxTurns: 10 },
|
|
651
|
+
},
|
|
652
|
+
issueId: "BEC-3",
|
|
653
|
+
shouldDraft: true,
|
|
654
|
+
ralphSatisfied: false,
|
|
655
|
+
unresolvedBlockingFindings: [],
|
|
656
|
+
ralphGaps: [{ criterion: "test" }],
|
|
657
|
+
});
|
|
658
|
+
expect(body3.includes("## Summary") &&
|
|
659
|
+
body3.includes("> **Draft PR**") &&
|
|
660
|
+
body3.includes("Resolves BEC-3")).toBe(true);
|
|
661
|
+
});
|
|
662
|
+
});
|
|
663
|
+
// =========================================================================
|
|
664
|
+
// 9. Integration: verifies createPRViaCli receives non-empty body (BEC-109)
|
|
665
|
+
// =========================================================================
|
|
666
|
+
describe("Integration: generatePRDescription output for createPRViaCli (BEC-109)", () => {
|
|
667
|
+
it("produces a non-empty body with Summary, Changes, and Test plan sections", () => {
|
|
668
|
+
const handoff = {
|
|
669
|
+
summary: "Wired PR description generation into runner.ts createPR calls.",
|
|
670
|
+
filesChanged: [
|
|
671
|
+
"packages/core/src/pipeline/pr-description.ts",
|
|
672
|
+
"packages/core/src/pipeline/runner.ts",
|
|
673
|
+
"packages/core/src/__tests__/pr-description.test.ts",
|
|
674
|
+
],
|
|
675
|
+
approach: "Extracted inline PR body logic into generatePRDescription()",
|
|
676
|
+
context: { issueIntent: "BEC-109", constraints: [], assumptions: [] },
|
|
677
|
+
tokenBudget: { contextTokensUsed: 50000, recommendedMaxTurns: 10 },
|
|
678
|
+
};
|
|
679
|
+
const body = generatePRDescription({ handoff, issueId: "BEC-109" });
|
|
680
|
+
// Non-empty
|
|
681
|
+
expect(body.length).toBeGreaterThan(0);
|
|
682
|
+
// Required sections present
|
|
683
|
+
expect(body).toContain("## Summary");
|
|
684
|
+
expect(body).toContain("## Changes");
|
|
685
|
+
expect(body).toContain("## Test plan");
|
|
686
|
+
// Section content is meaningful
|
|
687
|
+
expect(body).toContain("Wired PR description generation");
|
|
688
|
+
expect(body).toContain("- `packages/core/src/pipeline/pr-description.ts`");
|
|
689
|
+
expect(body).toContain("- `packages/core/src/__tests__/pr-description.test.ts`");
|
|
690
|
+
// Issue link
|
|
691
|
+
expect(body).toContain("Resolves BEC-109");
|
|
692
|
+
});
|
|
693
|
+
it("body passed to createPRViaCli contains all required sections for a typical run", () => {
|
|
694
|
+
// Simulate what runner.ts does: call generatePRDescription then pass body to createPRViaCli
|
|
695
|
+
const handoff = {
|
|
696
|
+
summary: "Added authentication middleware with JWT validation.",
|
|
697
|
+
filesChanged: [
|
|
698
|
+
"src/middleware/auth.ts",
|
|
699
|
+
"src/middleware/auth.test.ts",
|
|
700
|
+
"src/routes/api.ts",
|
|
701
|
+
],
|
|
702
|
+
approach: "Implemented using jsonwebtoken library",
|
|
703
|
+
context: { issueIntent: "auth", constraints: [], assumptions: [] },
|
|
704
|
+
tokenBudget: { contextTokensUsed: 20000, recommendedMaxTurns: 10 },
|
|
705
|
+
};
|
|
706
|
+
const body = generatePRDescription({
|
|
707
|
+
handoff,
|
|
708
|
+
issueId: "BEC-42",
|
|
709
|
+
shouldDraft: false,
|
|
710
|
+
ralphSatisfied: true,
|
|
711
|
+
ralphGaps: [],
|
|
712
|
+
unresolvedBlockingFindings: [],
|
|
713
|
+
agentCommits: ["feat(auth): add JWT middleware", "test(auth): add unit tests"],
|
|
714
|
+
});
|
|
715
|
+
// Verify body is non-empty and has all required sections
|
|
716
|
+
expect(body.length).toBeGreaterThan(50);
|
|
717
|
+
expect(body).toContain("## Summary");
|
|
718
|
+
expect(body).toContain("## Changes");
|
|
719
|
+
expect(body).toContain("## Test plan");
|
|
720
|
+
expect(body).toContain("Resolves BEC-42");
|
|
721
|
+
// This body would be passed as the `body` param to createPRViaCli()
|
|
722
|
+
// Verify it would produce a valid gh CLI call (non-empty, no undefined)
|
|
723
|
+
expect(body).not.toContain("undefined");
|
|
724
|
+
expect(body.trim().length).toBeGreaterThan(0);
|
|
725
|
+
});
|
|
726
|
+
});
|
|
727
|
+
});
|
|
728
|
+
//# sourceMappingURL=pr-description.test.js.map
|