dorfl 0.1.1 → 0.2.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/advance-ci-template.d.ts +3 -3
- package/dist/advance-ci-template.js +1 -1
- package/dist/advance-ci-template.js.map +1 -1
- package/dist/advance-classify.d.ts +5 -5
- package/dist/advance-classify.d.ts.map +1 -1
- package/dist/advance-classify.js +4 -4
- package/dist/advance-drivers.d.ts +8 -8
- package/dist/advance-drivers.d.ts.map +1 -1
- package/dist/advance-drivers.js +20 -8
- package/dist/advance-drivers.js.map +1 -1
- package/dist/advance-isolated.d.ts +3 -3
- package/dist/advance-isolated.d.ts.map +1 -1
- package/dist/advance-isolated.js +1 -1
- package/dist/advance-lifecycle-template.d.ts +2 -2
- package/dist/advance-lifecycle-template.d.ts.map +1 -1
- package/dist/advance-lifecycle-template.js +85 -13
- package/dist/advance-lifecycle-template.js.map +1 -1
- package/dist/advance-loop-driver.d.ts +3 -3
- package/dist/advance-loop-driver.d.ts.map +1 -1
- package/dist/advance-loop-driver.js +1 -1
- package/dist/advance-treeless-publish.d.ts +24 -1
- package/dist/advance-treeless-publish.d.ts.map +1 -1
- package/dist/advance-treeless-publish.js +41 -0
- package/dist/advance-treeless-publish.js.map +1 -1
- package/dist/advance.d.ts +69 -17
- package/dist/advance.d.ts.map +1 -1
- package/dist/advance.js +409 -102
- package/dist/advance.js.map +1 -1
- package/dist/advancing-lock.d.ts +31 -3
- package/dist/advancing-lock.d.ts.map +1 -1
- package/dist/advancing-lock.js +55 -5
- package/dist/advancing-lock.js.map +1 -1
- package/dist/agent-launch.d.ts +12 -0
- package/dist/agent-launch.d.ts.map +1 -1
- package/dist/agent-launch.js +22 -12
- package/dist/agent-launch.js.map +1 -1
- package/dist/agent-stop.d.ts +40 -2
- package/dist/agent-stop.d.ts.map +1 -1
- package/dist/agent-stop.js +30 -2
- package/dist/agent-stop.js.map +1 -1
- package/dist/apply-decide.d.ts +19 -5
- package/dist/apply-decide.d.ts.map +1 -1
- package/dist/apply-decide.js +38 -9
- package/dist/apply-decide.js.map +1 -1
- package/dist/apply-merge-action.d.ts +20 -8
- package/dist/apply-merge-action.d.ts.map +1 -1
- package/dist/apply-merge-action.js +44 -9
- package/dist/apply-merge-action.js.map +1 -1
- package/dist/apply-persist.d.ts +62 -31
- package/dist/apply-persist.d.ts.map +1 -1
- package/dist/apply-persist.js +173 -44
- package/dist/apply-persist.js.map +1 -1
- package/dist/apply-stuck-action.d.ts +151 -0
- package/dist/apply-stuck-action.d.ts.map +1 -0
- package/dist/apply-stuck-action.js +125 -0
- package/dist/apply-stuck-action.js.map +1 -0
- package/dist/brand.d.ts +12 -1
- package/dist/brand.d.ts.map +1 -1
- package/dist/brand.js +2 -1
- package/dist/brand.js.map +1 -1
- package/dist/buildable-body.d.ts +14 -14
- package/dist/buildable-body.js +9 -9
- package/dist/claim-cas.d.ts +3 -3
- package/dist/claim-cas.js +1 -1
- package/dist/claim-cas.js.map +1 -1
- package/dist/cli-spinner.d.ts +1 -1
- package/dist/cli-spinner.js +1 -1
- package/dist/cli.d.ts +10 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +385 -128
- package/dist/cli.js.map +1 -1
- package/dist/close-job-template.d.ts +3 -3
- package/dist/close-job-template.js +9 -9
- package/dist/close-job.d.ts +8 -8
- package/dist/close-job.js +25 -25
- package/dist/close-job.js.map +1 -1
- package/dist/complete.d.ts +9 -6
- package/dist/complete.d.ts.map +1 -1
- package/dist/complete.js +99 -45
- package/dist/complete.js.map +1 -1
- package/dist/concurrency.d.ts +1 -1
- package/dist/concurrency.js +1 -1
- package/dist/config.d.ts +86 -40
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +61 -9
- package/dist/config.js.map +1 -1
- package/dist/continue-branch.d.ts +1 -1
- package/dist/continue-branch.d.ts.map +1 -1
- package/dist/continue-branch.js +23 -1
- package/dist/continue-branch.js.map +1 -1
- package/dist/cwd-section.js +1 -1
- package/dist/cwd-section.js.map +1 -1
- package/dist/decision-engine.d.ts +39 -11
- package/dist/decision-engine.d.ts.map +1 -1
- package/dist/decision-engine.js +10 -6
- package/dist/decision-engine.js.map +1 -1
- package/dist/do-autopick.d.ts +6 -6
- package/dist/do-autopick.d.ts.map +1 -1
- package/dist/do-autopick.js +16 -6
- package/dist/do-autopick.js.map +1 -1
- package/dist/do-config.d.ts +4 -4
- package/dist/do-config.js +3 -3
- package/dist/do-config.js.map +1 -1
- package/dist/do-remote-auto.d.ts +2 -2
- package/dist/do-remote-auto.js +1 -1
- package/dist/do.d.ts +74 -81
- package/dist/do.d.ts.map +1 -1
- package/dist/do.js +439 -50
- package/dist/do.js.map +1 -1
- package/dist/drop-source.d.ts +2 -2
- package/dist/env-config.d.ts.map +1 -1
- package/dist/env-config.js +19 -11
- package/dist/env-config.js.map +1 -1
- package/dist/failure-cause.d.ts +3 -2
- package/dist/failure-cause.d.ts.map +1 -1
- package/dist/failure-cause.js +28 -1
- package/dist/failure-cause.js.map +1 -1
- package/dist/format.d.ts +6 -6
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +13 -30
- package/dist/format.js.map +1 -1
- package/dist/frontmatter.d.ts +28 -15
- package/dist/frontmatter.d.ts.map +1 -1
- package/dist/frontmatter.js +38 -24
- package/dist/frontmatter.js.map +1 -1
- package/dist/gc.d.ts +65 -6
- package/dist/gc.d.ts.map +1 -1
- package/dist/gc.js +126 -9
- package/dist/gc.js.map +1 -1
- package/dist/github.d.ts +14 -0
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +73 -0
- package/dist/github.js.map +1 -1
- package/dist/harness.d.ts +25 -0
- package/dist/harness.d.ts.map +1 -1
- package/dist/harness.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/install-ci-branch-protection.d.ts +133 -39
- package/dist/install-ci-branch-protection.d.ts.map +1 -1
- package/dist/install-ci-branch-protection.js +191 -49
- package/dist/install-ci-branch-protection.js.map +1 -1
- package/dist/install-ci-capabilities/advance-lifecycle.d.ts +1 -1
- package/dist/install-ci-capabilities/advance-lifecycle.js +1 -1
- package/dist/install-ci-capabilities/close-job.d.ts +1 -1
- package/dist/install-ci-capabilities/close-job.js +1 -1
- package/dist/install-ci-capabilities/example-noop.d.ts +1 -1
- package/dist/install-ci-capabilities/example-noop.js +1 -1
- package/dist/install-ci-capabilities/intake.d.ts +2 -2
- package/dist/install-ci-capabilities/intake.js +2 -2
- package/dist/install-ci-capabilities/verify.d.ts +1 -1
- package/dist/install-ci-capabilities/verify.js +1 -1
- package/dist/install-ci-core.d.ts +24 -4
- package/dist/install-ci-core.d.ts.map +1 -1
- package/dist/install-ci-core.js +12 -5
- package/dist/install-ci-core.js.map +1 -1
- package/dist/install-ci-github.d.ts +33 -1
- package/dist/install-ci-github.d.ts.map +1 -1
- package/dist/install-ci-github.js +74 -1
- package/dist/install-ci-github.js.map +1 -1
- package/dist/install-ci.d.ts +1 -1
- package/dist/install-ci.js +4 -4
- package/dist/install-ci.js.map +1 -1
- package/dist/install-skills.d.ts +123 -0
- package/dist/install-skills.d.ts.map +1 -0
- package/dist/install-skills.js +100 -0
- package/dist/install-skills.js.map +1 -0
- package/dist/intake-event.d.ts +6 -6
- package/dist/intake-event.js +6 -6
- package/dist/intake-marker.d.ts +3 -3
- package/dist/intake-marker.d.ts.map +1 -1
- package/dist/intake-triage.d.ts +1 -1
- package/dist/intake-triage.js +2 -2
- package/dist/intake-trigger-template.d.ts +8 -8
- package/dist/intake-trigger-template.d.ts.map +1 -1
- package/dist/intake-trigger-template.js +17 -17
- package/dist/intake-trigger-template.js.map +1 -1
- package/dist/intake.d.ts +65 -52
- package/dist/intake.d.ts.map +1 -1
- package/dist/intake.js +92 -76
- package/dist/intake.js.map +1 -1
- package/dist/integration-core.d.ts +27 -24
- package/dist/integration-core.d.ts.map +1 -1
- package/dist/integration-core.js +191 -77
- package/dist/integration-core.js.map +1 -1
- package/dist/integrator.d.ts +1 -1
- package/dist/integrator.d.ts.map +1 -1
- package/dist/integrator.js +19 -3
- package/dist/integrator.js.map +1 -1
- package/dist/isolation.d.ts +4 -4
- package/dist/isolation.d.ts.map +1 -1
- package/dist/isolation.js +9 -0
- package/dist/isolation.js.map +1 -1
- package/dist/issue-provider.d.ts +4 -4
- package/dist/issue-provider.js +1 -1
- package/dist/item-lock.d.ts +216 -149
- package/dist/item-lock.d.ts.map +1 -1
- package/dist/item-lock.js +345 -270
- package/dist/item-lock.js.map +1 -1
- package/dist/item-path.d.ts +2 -2
- package/dist/item-path.js +2 -2
- package/dist/ledger-lint.d.ts +9 -9
- package/dist/ledger-lint.js +9 -9
- package/dist/ledger-read.d.ts +57 -57
- package/dist/ledger-read.d.ts.map +1 -1
- package/dist/ledger-read.js +24 -24
- package/dist/ledger-read.js.map +1 -1
- package/dist/ledger-write.d.ts +33 -28
- package/dist/ledger-write.d.ts.map +1 -1
- package/dist/ledger-write.js +100 -122
- package/dist/ledger-write.js.map +1 -1
- package/dist/lifecycle-gather.d.ts +18 -1
- package/dist/lifecycle-gather.d.ts.map +1 -1
- package/dist/lifecycle-gather.js +23 -17
- package/dist/lifecycle-gather.js.map +1 -1
- package/dist/lifecycle-pools.d.ts +44 -7
- package/dist/lifecycle-pools.d.ts.map +1 -1
- package/dist/lifecycle-pools.js +27 -7
- package/dist/lifecycle-pools.js.map +1 -1
- package/dist/merge-question-surfacer.d.ts +18 -4
- package/dist/merge-question-surfacer.d.ts.map +1 -1
- package/dist/merge-question-surfacer.js +20 -5
- package/dist/merge-question-surfacer.js.map +1 -1
- package/dist/migrate-stuck-locks.d.ts +129 -0
- package/dist/migrate-stuck-locks.d.ts.map +1 -0
- package/dist/migrate-stuck-locks.js +355 -0
- package/dist/migrate-stuck-locks.js.map +1 -0
- package/dist/mint-adr.js +4 -4
- package/dist/mirror-pool-scan.d.ts +2 -2
- package/dist/mirror-pool-scan.js +3 -3
- package/dist/mirror-pool-scan.js.map +1 -1
- package/dist/needs-attention.d.ts +304 -27
- package/dist/needs-attention.d.ts.map +1 -1
- package/dist/needs-attention.js +542 -67
- package/dist/needs-attention.js.map +1 -1
- package/dist/orphan-sidecar.d.ts +10 -6
- package/dist/orphan-sidecar.d.ts.map +1 -1
- package/dist/orphan-sidecar.js +35 -2
- package/dist/orphan-sidecar.js.map +1 -1
- package/dist/pi-harness.d.ts +16 -0
- package/dist/pi-harness.d.ts.map +1 -1
- package/dist/pi-harness.js +82 -2
- package/dist/pi-harness.js.map +1 -1
- package/dist/placement.d.ts +8 -8
- package/dist/placement.js +3 -3
- package/dist/prd-to-spec.d.ts.map +1 -1
- package/dist/prd-to-spec.js +9 -5
- package/dist/prd-to-spec.js.map +1 -1
- package/dist/prompt.d.ts +16 -19
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +17 -19
- package/dist/prompt.js.map +1 -1
- package/dist/protocol/CLAIM-PROTOCOL.md +17 -10
- package/dist/protocol/REVIEW-PROTOCOL.md +4 -1
- package/dist/protocol/SURFACE-PROTOCOL.md +16 -2
- package/dist/protocol/TASKING-PROTOCOL.md +3 -1
- package/dist/protocol/WORK-CONTRACT.md +22 -18
- package/dist/protocol/task-template.md +1 -1
- package/dist/readiness.d.ts +1 -1
- package/dist/reap-branches.d.ts +12 -9
- package/dist/reap-branches.d.ts.map +1 -1
- package/dist/reap-branches.js +25 -7
- package/dist/reap-branches.js.map +1 -1
- package/dist/recover-isolated.d.ts +12 -0
- package/dist/recover-isolated.d.ts.map +1 -1
- package/dist/recover-isolated.js +6 -1
- package/dist/recover-isolated.js.map +1 -1
- package/dist/repo-config.d.ts +23 -2
- package/dist/repo-config.d.ts.map +1 -1
- package/dist/repo-config.js +64 -18
- package/dist/repo-config.js.map +1 -1
- package/dist/repo-mirror.d.ts.map +1 -1
- package/dist/repo-mirror.js +18 -2
- package/dist/repo-mirror.js.map +1 -1
- package/dist/review-gate.d.ts +3 -3
- package/dist/review-gate.d.ts.map +1 -1
- package/dist/review-gate.js +11 -10
- package/dist/review-gate.js.map +1 -1
- package/dist/review-verdict.d.ts +2 -2
- package/dist/review-verdict.d.ts.map +1 -1
- package/dist/review-verdict.js +2 -2
- package/dist/review-verdict.js.map +1 -1
- package/dist/run.d.ts +2 -2
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +58 -23
- package/dist/run.js.map +1 -1
- package/dist/scan.d.ts +26 -17
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +29 -15
- package/dist/scan.js.map +1 -1
- package/dist/select-order.d.ts +1 -1
- package/dist/select-priority.d.ts +14 -14
- package/dist/select-priority.d.ts.map +1 -1
- package/dist/select-priority.js +5 -5
- package/dist/select-priority.js.map +1 -1
- package/dist/sidecar-apply.js +1 -1
- package/dist/sidecar-apply.js.map +1 -1
- package/dist/sidecar.d.ts +47 -12
- package/dist/sidecar.d.ts.map +1 -1
- package/dist/sidecar.js +84 -4
- package/dist/sidecar.js.map +1 -1
- package/dist/skills/answer-questions/SKILL.md +89 -0
- package/dist/skills/capture-signal/SKILL.md +52 -0
- package/dist/skills/convert-from-prd-to-spec/SKILL.md +90 -0
- package/dist/skills/drive-tasks/SKILL.md +218 -0
- package/dist/skills/from-idea/SKILL.md +83 -0
- package/dist/skills/merge-prs/SKILL.md +70 -0
- package/dist/skills/orchestrate/SKILL.md +101 -0
- package/dist/skills/promote/SKILL.md +35 -0
- package/dist/skills/review/SKILL.md +16 -0
- package/dist/skills/setup/SKILL.md +258 -0
- package/dist/skills/setup/protocol/ADR-FORMAT.md +47 -0
- package/dist/skills/setup/protocol/CLAIM-PROTOCOL.md +224 -0
- package/dist/skills/setup/protocol/REVIEW-PROTOCOL.md +122 -0
- package/dist/skills/setup/protocol/SURFACE-PROTOCOL.md +135 -0
- package/dist/skills/setup/protocol/TASKING-PROTOCOL.md +124 -0
- package/dist/skills/setup/protocol/WORK-CONTRACT.md +280 -0
- package/dist/skills/setup/protocol/spec-template.md +71 -0
- package/dist/skills/setup/protocol/task-template.md +65 -0
- package/dist/skills/surface-questions/SKILL.md +16 -0
- package/dist/skills/to-spec/SKILL.md +34 -0
- package/dist/skills/to-task/SKILL.md +19 -0
- package/dist/skills/triage-observations/SKILL.md +78 -0
- package/dist/skills/work/SKILL.md +51 -0
- package/dist/slug-namespace.d.ts +6 -6
- package/dist/slug-namespace.js +8 -8
- package/dist/slug-namespace.js.map +1 -1
- package/dist/spec-complete.d.ts.map +1 -1
- package/dist/spec-complete.js +4 -5
- package/dist/spec-complete.js.map +1 -1
- package/dist/start.d.ts +1 -1
- package/dist/start.d.ts.map +1 -1
- package/dist/start.js +54 -60
- package/dist/start.js.map +1 -1
- package/dist/status.d.ts +3 -3
- package/dist/status.js +4 -4
- package/dist/status.js.map +1 -1
- package/dist/surface-gate.d.ts +2 -2
- package/dist/surface-gate.d.ts.map +1 -1
- package/dist/surface-gate.js +10 -3
- package/dist/surface-gate.js.map +1 -1
- package/dist/surface-persist.d.ts +2 -2
- package/dist/surface-persist.d.ts.map +1 -1
- package/dist/surface-persist.js +1 -1
- package/dist/surface-persist.js.map +1 -1
- package/dist/tasker-review-loop.d.ts +11 -10
- package/dist/tasker-review-loop.d.ts.map +1 -1
- package/dist/tasker-review-loop.js +8 -8
- package/dist/tasker-review-loop.js.map +1 -1
- package/dist/tasking-eligibility.d.ts +21 -21
- package/dist/tasking-eligibility.d.ts.map +1 -1
- package/dist/tasking-eligibility.js +10 -10
- package/dist/tasking-lock.d.ts +10 -10
- package/dist/tasking-lock.d.ts.map +1 -1
- package/dist/tasking-lock.js +69 -49
- package/dist/tasking-lock.js.map +1 -1
- package/dist/tasking.d.ts +73 -39
- package/dist/tasking.d.ts.map +1 -1
- package/dist/tasking.js +309 -95
- package/dist/tasking.js.map +1 -1
- package/dist/triage-gate.d.ts +1 -1
- package/dist/triage-persist.d.ts +15 -11
- package/dist/triage-persist.d.ts.map +1 -1
- package/dist/triage-persist.js +48 -18
- package/dist/triage-persist.js.map +1 -1
- package/dist/vendor/incur/agents.d.ts +58 -0
- package/dist/vendor/incur/agents.d.ts.map +1 -0
- package/dist/vendor/incur/agents.js +343 -0
- package/dist/vendor/incur/agents.js.map +1 -0
- package/dist/verify-workflow-template.d.ts +1 -1
- package/dist/verify-workflow-template.js +3 -3
- package/dist/watch-session.d.ts +11 -3
- package/dist/watch-session.d.ts.map +1 -1
- package/dist/watch-session.js +94 -7
- package/dist/watch-session.js.map +1 -1
- package/dist/work-layout.d.ts +15 -9
- package/dist/work-layout.d.ts.map +1 -1
- package/dist/work-layout.js +14 -9
- package/dist/work-layout.js.map +1 -1
- package/dist/workspace.d.ts +2 -2
- package/package.json +2 -2
- package/src/advance-ci-template.ts +4 -4
- package/src/advance-classify.ts +5 -5
- package/src/advance-drivers.ts +26 -13
- package/src/advance-isolated.ts +3 -3
- package/src/advance-lifecycle-template.ts +98 -13
- package/src/advance-loop-driver.ts +3 -3
- package/src/advance-treeless-publish.ts +46 -1
- package/src/advance.ts +495 -115
- package/src/advancing-lock.ts +102 -7
- package/src/agent-launch.ts +37 -12
- package/src/agent-stop.ts +60 -2
- package/src/apply-decide.ts +38 -9
- package/src/apply-merge-action.ts +49 -11
- package/src/apply-persist.ts +236 -62
- package/src/apply-stuck-action.ts +260 -0
- package/src/brand.ts +14 -2
- package/src/buildable-body.ts +14 -14
- package/src/claim-cas.ts +4 -4
- package/src/cli-spinner.ts +1 -1
- package/src/cli.ts +472 -141
- package/src/close-job-template.ts +9 -9
- package/src/close-job.ts +26 -26
- package/src/complete.ts +121 -63
- package/src/concurrency.ts +1 -1
- package/src/config.ts +143 -49
- package/src/continue-branch.ts +23 -1
- package/src/cwd-section.ts +1 -1
- package/src/decision-engine.ts +57 -19
- package/src/do-autopick.ts +21 -10
- package/src/do-config.ts +7 -7
- package/src/do-remote-auto.ts +2 -2
- package/src/do.ts +558 -85
- package/src/drop-source.ts +2 -2
- package/src/env-config.ts +19 -11
- package/src/failure-cause.ts +30 -1
- package/src/format.ts +13 -33
- package/src/frontmatter.ts +55 -35
- package/src/gc.ts +172 -9
- package/src/github.ts +78 -0
- package/src/harness.ts +25 -0
- package/src/index.ts +10 -0
- package/src/install-ci-branch-protection.ts +283 -58
- package/src/install-ci-capabilities/advance-lifecycle.ts +1 -1
- package/src/install-ci-capabilities/close-job.ts +1 -1
- package/src/install-ci-capabilities/example-noop.ts +1 -1
- package/src/install-ci-capabilities/intake.ts +2 -2
- package/src/install-ci-capabilities/verify.ts +1 -1
- package/src/install-ci-core.ts +34 -7
- package/src/install-ci-github.ts +87 -1
- package/src/install-ci.ts +4 -4
- package/src/install-skills.ts +166 -0
- package/src/intake-event.ts +6 -6
- package/src/intake-marker.ts +3 -3
- package/src/intake-triage.ts +2 -2
- package/src/intake-trigger-template.ts +18 -18
- package/src/intake.ts +138 -103
- package/src/integration-core.ts +234 -100
- package/src/integrator.ts +22 -9
- package/src/isolation.ts +13 -4
- package/src/issue-provider.ts +4 -4
- package/src/item-lock.ts +505 -361
- package/src/item-path.ts +2 -2
- package/src/ledger-lint.ts +9 -9
- package/src/ledger-read.ts +81 -81
- package/src/ledger-write.ts +137 -152
- package/src/lifecycle-gather.ts +45 -22
- package/src/lifecycle-pools.ts +71 -13
- package/src/merge-question-surfacer.ts +32 -8
- package/src/migrate-stuck-locks.ts +451 -0
- package/src/mint-adr.ts +4 -4
- package/src/mirror-pool-scan.ts +5 -5
- package/src/needs-attention.ts +877 -104
- package/src/orphan-sidecar.ts +49 -8
- package/src/pi-harness.ts +82 -2
- package/src/placement.ts +8 -8
- package/src/prd-to-spec.ts +13 -5
- package/src/prompt.ts +20 -25
- package/src/readiness.ts +1 -1
- package/src/reap-branches.ts +38 -14
- package/src/recover-isolated.ts +18 -1
- package/src/repo-config.ts +66 -17
- package/src/repo-mirror.ts +23 -1
- package/src/review-gate.ts +12 -11
- package/src/review-verdict.ts +3 -3
- package/src/run.ts +69 -23
- package/src/scan.ts +36 -22
- package/src/select-order.ts +1 -1
- package/src/select-priority.ts +15 -15
- package/src/sidecar-apply.ts +1 -1
- package/src/sidecar.ts +141 -14
- package/src/slug-namespace.ts +10 -10
- package/src/spec-complete.ts +4 -5
- package/src/start.ts +57 -63
- package/src/status.ts +7 -7
- package/src/surface-gate.ts +12 -5
- package/src/surface-persist.ts +3 -3
- package/src/tasker-review-loop.ts +18 -17
- package/src/tasking-eligibility.ts +21 -21
- package/src/tasking-lock.ts +75 -60
- package/src/tasking.ts +381 -135
- package/src/triage-gate.ts +1 -1
- package/src/triage-persist.ts +71 -27
- package/src/vendor/incur/LICENSE +21 -0
- package/src/vendor/incur/README.md +19 -0
- package/src/vendor/incur/agents.ts +392 -0
- package/src/verify-workflow-template.ts +3 -3
- package/src/watch-session.ts +102 -7
- package/src/work-layout.ts +14 -9
- package/src/workspace.ts +2 -2
package/src/intake.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {existsSync, mkdirSync, readFileSync, writeFileSync} from 'node:fs';
|
|
2
2
|
import {dirname, join} from 'node:path';
|
|
3
3
|
import {runAsync, type RunResult} from './git.js';
|
|
4
|
-
import {workFolderRel, workItemRel} from './work-layout.js';
|
|
4
|
+
import {workFolderRel, workFolderPrefix, workItemRel} from './work-layout.js';
|
|
5
5
|
import {paramCase} from './brand.js';
|
|
6
6
|
import {
|
|
7
7
|
performIntegration,
|
|
@@ -48,7 +48,7 @@ import {triageIntake, type IntakeTriageDecision} from './intake-triage.js';
|
|
|
48
48
|
import {renderTaskBody, renderSpecBody} from './buildable-body.js';
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
|
-
* **`intake <N>`** (
|
|
51
|
+
* **`intake <N>`** (spec `issue-intake`, task `intake-tracer-slice-outcome`): the
|
|
52
52
|
* KEYSTONE of the issue front-door. A new, GATE-FREE command — explicit invocation
|
|
53
53
|
* IS the authorization (precedent: `explicit-do-prd-not-gated-by-autoslice`), so
|
|
54
54
|
* `autoTask`/`autoBuild` config does NOT apply — that reads a GitHub issue + its
|
|
@@ -62,24 +62,24 @@ import {renderTaskBody, renderSpecBody} from './buildable-body.js';
|
|
|
62
62
|
* prompt's JUDGEMENT is NOT unit-tested (like the review prompt's is not); only the
|
|
63
63
|
* dispatch is.
|
|
64
64
|
*
|
|
65
|
-
* The dispatcher implements the FULL four-outcome decision table (
|
|
65
|
+
* The dispatcher implements the FULL four-outcome decision table (spec
|
|
66
66
|
* `issue-intake` — the source of truth):
|
|
67
67
|
* - **ASK** (not clear enough to act on): `postIssueComment` the next clarifying
|
|
68
68
|
* question; emit NOTHING; STOP.
|
|
69
69
|
* - **TASK** (clear AND fits ONE tracer-bullet task): write
|
|
70
|
-
* `work/backlog/<slug>.md` (`covers: []`, NO `
|
|
70
|
+
* `work/backlog/<slug>.md` (`covers: []`, NO `spec:`) carrying `issue: N` (the
|
|
71
71
|
* lone-task closure link, NOT `Fixes #N`), integrate via {@link
|
|
72
72
|
* performIntegration} (default `propose`).
|
|
73
|
-
* - **
|
|
74
|
-
* which is NEVER bounced): write the
|
|
75
|
-
* axes the verdict carried), integrate, STOP (tasking is the separate `do
|
|
73
|
+
* - **SPEC** (clear AND coherent but >1 task — INCLUDING a coupled-but-SMALL pair,
|
|
74
|
+
* which is NEVER bounced): write the spec file (`work/specs/ready/<slug>.md`) with `issue: N` (+ the gate
|
|
75
|
+
* axes the verdict carried), integrate, STOP (tasking is the separate `do spec:`
|
|
76
76
|
* step).
|
|
77
77
|
* - **BOUNCE** (genuinely UNRELATED concerns — no shared vision): the bounce is
|
|
78
78
|
* TERMINAL (the asks are unrelated and must be re-filed), so intake CLOSES the
|
|
79
79
|
* issue ATOMICALLY — the "file separate issues" text as the closing comment +
|
|
80
80
|
* `reason: not planned` (the honest GitHub-native signal) in ONE `closeIssue`
|
|
81
81
|
* call; emit NOTHING. Intake closes on BOUNCE (as not planned); NEVER on
|
|
82
|
-
* task/
|
|
82
|
+
* task/spec (CI's close-job closes those via the `issue:` field) / ask.
|
|
83
83
|
*
|
|
84
84
|
* The per-outcome integration KNOBS, the processing LOCK, and event-classification
|
|
85
85
|
* are LATER tasks and are NOT built here (default `propose` is fine here).
|
|
@@ -92,10 +92,10 @@ import {renderTaskBody, renderSpecBody} from './buildable-body.js';
|
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
94
|
* The four outcomes the decision prompt classifies an issue into (the decision
|
|
95
|
-
* table). EXPAND step (
|
|
95
|
+
* table). EXPAND step (spec
|
|
96
96
|
* `prd-to-spec-vocabulary-cutover-and-migration-command`): the `spec` outcome
|
|
97
97
|
* names the "clear + coherent but >1 task" classification (a parent SPEC). HARD
|
|
98
|
-
* CUTOVER (contract step): the legacy
|
|
98
|
+
* CUTOVER (contract step): the legacy ''prd'' outcome token is GONE — the prompt
|
|
99
99
|
* emits `spec` and the parser rejects any other token.
|
|
100
100
|
*/
|
|
101
101
|
export type IntakeOutcome = 'ask' | 'task' | 'spec' | 'bounce';
|
|
@@ -122,7 +122,7 @@ export interface IntakeVerdict {
|
|
|
122
122
|
/**
|
|
123
123
|
* The drafted task BODY (`task` outcome) — the markdown AFTER the frontmatter
|
|
124
124
|
* (the `## What to build` / `## Acceptance criteria` / `## Prompt` sections). The
|
|
125
|
-
* dispatcher writes the frontmatter (slug/title/`covers: []`, NO `
|
|
125
|
+
* dispatcher writes the frontmatter (slug/title/`covers: []`, NO `spec:`) carrying
|
|
126
126
|
* the lone-task `issue: N` closure link itself; the agent never writes
|
|
127
127
|
* git-visible files.
|
|
128
128
|
*/
|
|
@@ -151,7 +151,7 @@ export interface IntakeVerdict {
|
|
|
151
151
|
specBody?: string;
|
|
152
152
|
/**
|
|
153
153
|
* The spec's gate axes (`spec` outcome) AS THE PROMPT JUDGED THEM — surfaced onto
|
|
154
|
-
* the emitted spec frontmatter (
|
|
154
|
+
* the emitted spec frontmatter (spec `issue-intake` US #8: "the emitted artifact
|
|
155
155
|
* carries … its own gate axes"). Both omitted (undeclared) by default; the prompt
|
|
156
156
|
* sets `specHumanOnly: true` when a human should drive the TASKING and/or
|
|
157
157
|
* `specNeedsAnswers: true` when open questions remain.
|
|
@@ -186,16 +186,16 @@ export interface IntakeResult {
|
|
|
186
186
|
outcome: IntakeRunOutcome;
|
|
187
187
|
/** The issue number acted on. */
|
|
188
188
|
issueNumber: number;
|
|
189
|
-
/** The slug of the emitted artifact (task OR
|
|
189
|
+
/** The slug of the emitted artifact (task OR spec outcome). */
|
|
190
190
|
emittedSlug?: string;
|
|
191
|
-
/** Repo-relative path of the emitted artifact (task OR
|
|
191
|
+
/** Repo-relative path of the emitted artifact (task OR spec outcome). */
|
|
192
192
|
emitted?: string;
|
|
193
193
|
/** True iff a comment was posted on the issue (ask / bounce outcomes). */
|
|
194
194
|
commented?: boolean;
|
|
195
195
|
/**
|
|
196
196
|
* True iff the ISSUE was closed (the BOUNCE outcome — a terminal bounce closes
|
|
197
197
|
* the issue atomically as `not planned`). Additive (mirrors {@link commented}),
|
|
198
|
-
* so CI / callers can observe the close. Never set on ask/task/
|
|
198
|
+
* so CI / callers can observe the close. Never set on ask/task/spec.
|
|
199
199
|
*/
|
|
200
200
|
closed?: boolean;
|
|
201
201
|
/** Human-readable summary of the terminal condition. */
|
|
@@ -253,10 +253,10 @@ export interface PerformIntakeOptions {
|
|
|
253
253
|
/** The HOST-ONLY sessions root for the pi session file. */
|
|
254
254
|
sessionsDir?: string;
|
|
255
255
|
/**
|
|
256
|
-
* The PER-OUTCOME integration modes (
|
|
256
|
+
* The PER-OUTCOME integration modes (spec `issue-intake` US #9) the emitted artifact integrates
|
|
257
257
|
* THROUGH the shared core with. Because `intake` decides the artifact TYPE at
|
|
258
258
|
* RUNTIME, the mode is keyed per type: an emitted task integrates with
|
|
259
|
-
* `integration.task`, an emitted
|
|
259
|
+
* `integration.task`, an emitted spec with `integration.spec` (`propose` =
|
|
260
260
|
* push the `work/<slug>` branch + open a PR, NO `main` touch; `merge` = land on
|
|
261
261
|
* `main`). The CLI resolves this from the granular + aggregate flags via
|
|
262
262
|
* {@link resolveIntakeIntegrationModes}; ask/bounce emit nothing, so the modes
|
|
@@ -266,8 +266,8 @@ export interface PerformIntakeOptions {
|
|
|
266
266
|
/**
|
|
267
267
|
* **The ORIGIN-TRUST verdict, passed IN** (task
|
|
268
268
|
* `untrusted-origin-forces-build-propose`; the `--origin-trust <trusted|untrusted>`
|
|
269
|
-
* CLI flag). `intake` STAMPS `origin: issue` + this `originTrust` onto every
|
|
270
|
-
* task it emits, so the author-trust signal SURVIVES the
|
|
269
|
+
* CLI flag). `intake` STAMPS `origin: issue` + this `originTrust` onto every spec/
|
|
270
|
+
* task it emits, so the author-trust signal SURVIVES the spec/task merge
|
|
271
271
|
* boundary (a landed-on-main artifact otherwise erases how it was born, the
|
|
272
272
|
* laundering gap). `intake` does NOT resolve trust itself: the verdict is CI's
|
|
273
273
|
* POLICY, computed in the `intake.yml` shell from the SAME `author_association`
|
|
@@ -285,7 +285,7 @@ export interface PerformIntakeOptions {
|
|
|
285
285
|
*/
|
|
286
286
|
noPR?: boolean;
|
|
287
287
|
/**
|
|
288
|
-
* **The per-repo
|
|
288
|
+
* **The per-repo SPEC-PLACEMENT default, passed IN** (spec
|
|
289
289
|
* `staging-pool-position-gate-and-trust-model` US #2/#5, task
|
|
290
290
|
* `pre-prd-staging-pool-split-and-untrusted-prd-placement`). The resolved
|
|
291
291
|
* per-repo default landing for `intake`-authored prds (`pre-proposed` =
|
|
@@ -293,8 +293,8 @@ export interface PerformIntakeOptions {
|
|
|
293
293
|
* into the shared placement resolver (`src/placement.ts`). The resolver
|
|
294
294
|
* overlays an EXPLICIT operator flag ({@link explicitSpecsLandIn}, top) and
|
|
295
295
|
* the UNTRUSTED-ORIGIN force (`originTrust: untrusted` ⇒ staging) on top.
|
|
296
|
-
* Unset ⇒ the resolver's built-in floor applies (`staging` = `
|
|
297
|
-
* the conservative landing). The
|
|
296
|
+
* Unset ⇒ the resolver's built-in floor applies (`staging` = `specs/proposed/`,
|
|
297
|
+
* the conservative landing). The SPEC TWIN of `tasksLandIn` on the tasker
|
|
298
298
|
* path — one resolver, two lifecycles.
|
|
299
299
|
*/
|
|
300
300
|
specsLandIn?: SpecsLandIn;
|
|
@@ -325,6 +325,19 @@ export interface PerformIntakeOptions {
|
|
|
325
325
|
* must not act as the bot. Absent ⇒ ambient (today's behaviour).
|
|
326
326
|
*/
|
|
327
327
|
identity?: Identity;
|
|
328
|
+
/**
|
|
329
|
+
* **The cross-job merge-serialiser CAS-retry cap** (config `mergeRetries`, spec
|
|
330
|
+
* `land-time-reverify-and-parallel-merge-ceiling` Story 5 / Applied Answer q1
|
|
331
|
+
* (a)). Threaded VERBATIM into the shared integrate core so a wide-matrix CI's
|
|
332
|
+
* raised cap reaches intake's task/spec emit land tail too (task
|
|
333
|
+
* `thread-merge-retries-cross-task-and-ratify-default`). Resolved ONCE at the
|
|
334
|
+
* entry point (the CLI) through the env + per-repo layers of the gate-family
|
|
335
|
+
* precedence chain — the `intake` command has NO `--merge-retries` flag today
|
|
336
|
+
* (the flag layer legitimately does not apply here; intake is
|
|
337
|
+
* unattended-CI-first, env + per-repo cover the need). Unset ⇒ the engine's
|
|
338
|
+
* `DEFAULT_MERGE_RETRIES = 1000` (byte-for-byte unchanged).
|
|
339
|
+
*/
|
|
340
|
+
mergeRetries?: number;
|
|
328
341
|
/** Environment for child git/agent processes (the AGENT-launch ambient env). */
|
|
329
342
|
env?: NodeJS.ProcessEnv;
|
|
330
343
|
/** Sink for human-readable progress notes. */
|
|
@@ -334,15 +347,15 @@ export interface PerformIntakeOptions {
|
|
|
334
347
|
const DEFAULT_ARBITER = 'origin';
|
|
335
348
|
|
|
336
349
|
/**
|
|
337
|
-
* **The STAGED-prds dir** (
|
|
350
|
+
* **The STAGED-prds dir** (spec `staging-pool-position-gate-and-trust-model`,
|
|
338
351
|
* task `pre-prd-staging-pool-split-and-untrusted-prd-placement`, governing
|
|
339
352
|
* ADR `placement-is-runner-deterministic-humanonly-is-agent-judgement`). When
|
|
340
353
|
* the runner-deterministic placement resolver picks the staging side for an
|
|
341
|
-
* `intake`-authored
|
|
342
|
-
* `work/
|
|
343
|
-
* the tasking candidate POOL (`work/
|
|
344
|
-
* ({@link promoteFromPreSpec} in `needs-attention.ts`) moves an approved
|
|
345
|
-
* `
|
|
354
|
+
* `intake`-authored spec, the runner writes the spec file HERE instead of in
|
|
355
|
+
* `work/specs/ready/`. An item born in `specs/proposed/` is durable + readable but NOT in
|
|
356
|
+
* the tasking candidate POOL (`work/specs/ready/` is the pool). A runner/human-owned promotion
|
|
357
|
+
* ({@link promoteFromPreSpec} in `needs-attention.ts`) moves an approved spec
|
|
358
|
+
* `specs/proposed/ → specs/ready/` to make it taskable.
|
|
346
359
|
*/
|
|
347
360
|
export const STAGED_SPECS_DIR = workFolderRel('specs-proposed');
|
|
348
361
|
|
|
@@ -377,19 +390,19 @@ function specLandingToSide(
|
|
|
377
390
|
|
|
378
391
|
/**
|
|
379
392
|
* The emitted artifact TYPE `intake` decides at RUNTIME — a `task` verdict emits
|
|
380
|
-
* `work/backlog/<slug>.md`, a `
|
|
393
|
+
* `work/backlog/<slug>.md`, a `spec` verdict emits the spec file (`work/specs/ready/<slug>.md`). The two
|
|
381
394
|
* granular flag axes (`--merge-task`/`--propose-task` vs `--merge-spec`/
|
|
382
395
|
* `--propose-spec`) are keyed on this. (ask/bounce emit NOTHING, so the modes are
|
|
383
396
|
* no-ops for them.)
|
|
384
397
|
*/
|
|
385
398
|
export type IntakeArtifactType = 'task' | 'spec';
|
|
386
|
-
// prd → spec
|
|
387
|
-
//
|
|
399
|
+
// ''prd'' → `spec` HARD CUTOVER: `'spec'` is the ONLY spec artifact type value; the
|
|
400
|
+
// legacy ''prd'' alias is GONE (the contract task removed it).
|
|
388
401
|
|
|
389
402
|
/**
|
|
390
|
-
* The PER-OUTCOME integration mode FLAG SET (
|
|
403
|
+
* The PER-OUTCOME integration mode FLAG SET (spec `issue-intake` US #9). Because
|
|
391
404
|
* `intake` decides the artifact TYPE at runtime, a single `--merge`/`--propose`
|
|
392
|
-
* cannot express a type-conditional policy ("merge a
|
|
405
|
+
* cannot express a type-conditional policy ("merge a spec but propose a task") —
|
|
393
406
|
* hence the four GRANULAR per-type flags layered over the two AGGREGATES:
|
|
394
407
|
*
|
|
395
408
|
* - **granular:** `--merge-spec`/`--propose-spec` apply iff the outcome is a spec;
|
|
@@ -400,9 +413,9 @@ export type IntakeArtifactType = 'task' | 'spec';
|
|
|
400
413
|
* author-trust) is CI's POLICY, authored in `runner-in-ci` — NOT here.
|
|
401
414
|
*/
|
|
402
415
|
export interface IntakeIntegrationFlags {
|
|
403
|
-
/** Aggregate: merge BOTH a task and a
|
|
416
|
+
/** Aggregate: merge BOTH a task and a spec (the broad knob, overridden per type). */
|
|
404
417
|
merge?: boolean;
|
|
405
|
-
/** Aggregate: propose BOTH a task and a
|
|
418
|
+
/** Aggregate: propose BOTH a task and a spec. */
|
|
406
419
|
propose?: boolean;
|
|
407
420
|
/** Granular: merge a spec (overrides the aggregate for the spec outcome). */
|
|
408
421
|
mergeSpec?: boolean;
|
|
@@ -419,7 +432,7 @@ export interface IntakeIntegrationModes {
|
|
|
419
432
|
/** The mode an EMITTED task integrates with. */
|
|
420
433
|
task: IntegrationMode;
|
|
421
434
|
/**
|
|
422
|
-
* The mode an EMITTED spec integrates with. `spec` is the CANONICAL key (
|
|
435
|
+
* The mode an EMITTED spec integrates with. `spec` is the CANONICAL key (spec →
|
|
423
436
|
* spec cutover); the user-facing `--merge-spec`/`--propose-spec` flags that FEED
|
|
424
437
|
* it carry the same `spec` spelling (the cli-flag rename landed in batch 4f).
|
|
425
438
|
*/
|
|
@@ -453,10 +466,10 @@ function granularFromFlags(
|
|
|
453
466
|
}
|
|
454
467
|
|
|
455
468
|
/**
|
|
456
|
-
* The PURE per-outcome integration mode resolution (
|
|
469
|
+
* The PURE per-outcome integration mode resolution (spec `issue-intake` US #9 —
|
|
457
470
|
* the canonical table). Given ONLY the flag set, resolve BOTH per-type modes in
|
|
458
471
|
* one eager pass (so a usage error is caught before the runtime verdict is even
|
|
459
|
-
* known). The rules, all decided in the
|
|
472
|
+
* known). The rules, all decided in the spec:
|
|
460
473
|
*
|
|
461
474
|
* - **unset ⇒ propose for BOTH** (conservative default; matches `do`).
|
|
462
475
|
* - **aggregates:** `--merge` ⇒ merge both; `--propose` ⇒ propose both (this axis
|
|
@@ -574,7 +587,7 @@ export async function performIntake(
|
|
|
574
587
|
return {exitCode: 1, outcome: 'usage-error', issueNumber, message};
|
|
575
588
|
}
|
|
576
589
|
|
|
577
|
-
// 2. ACQUIRE the `processing` LOCK (
|
|
590
|
+
// 2. ACQUIRE the `processing` LOCK (spec `issue-intake` US #10): a TRANSIENT concurrency mutex
|
|
578
591
|
// that serialises two concurrent runs on the SAME issue. Read the labels; if
|
|
579
592
|
// the lock is ALREADY present, BACK OFF (do nothing — another run owns it). The
|
|
580
593
|
// winner ADDS the label and proceeds; the label is REMOVED on finish (success
|
|
@@ -815,12 +828,12 @@ async function decideAndDispatch(
|
|
|
815
828
|
return {exitCode: 1, outcome: 'agent-failed', issueNumber, message};
|
|
816
829
|
}
|
|
817
830
|
|
|
818
|
-
// DISPATCH on the verdict — the FULL four-outcome decision table (
|
|
831
|
+
// DISPATCH on the verdict — the FULL four-outcome decision table (spec
|
|
819
832
|
// `issue-intake`). The agent only DRAFTED the verdict; the runner owns every
|
|
820
833
|
// git/seam side-effect below (the in-band boundary): the write + integrate
|
|
821
|
-
// (task/
|
|
834
|
+
// (task/spec) and the `postIssueComment` (ask/bounce).
|
|
822
835
|
//
|
|
823
|
-
// PER-OUTCOME integration (
|
|
836
|
+
// PER-OUTCOME integration (spec `issue-intake` US #9): the resolved mode is keyed on the runtime
|
|
824
837
|
// artifact TYPE — a `task` verdict integrates with the task mode, a `spec`
|
|
825
838
|
// verdict with the spec mode. Unset ⇒ propose for both. ask/bounce never
|
|
826
839
|
// integrate, so the modes are no-ops for them.
|
|
@@ -837,6 +850,9 @@ async function decideAndDispatch(
|
|
|
837
850
|
cwd,
|
|
838
851
|
arbiter,
|
|
839
852
|
integration: modes.task,
|
|
853
|
+
// The resolved cross-job CAS-retry cap (config `mergeRetries`) — threaded so
|
|
854
|
+
// intake's lone-task emit lands under the same per-repo cap the build path uses.
|
|
855
|
+
mergeRetries: options.mergeRetries,
|
|
840
856
|
// The origin-trust STAMP, passed IN (not resolved here): the emitted task
|
|
841
857
|
// carries `origin: issue` + this verdict so the becomes-code checkpoint is
|
|
842
858
|
// not laundered. Unset ⇒ unstamped (a local intake ⇒ human/trusted).
|
|
@@ -855,7 +871,7 @@ async function decideAndDispatch(
|
|
|
855
871
|
note,
|
|
856
872
|
});
|
|
857
873
|
// The `spec` outcome is the parent-spec verdict; it dispatches through
|
|
858
|
-
// `modes.spec`. HARD CUTOVER: the legacy
|
|
874
|
+
// `modes.spec`. HARD CUTOVER: the legacy ''prd'' outcome case is GONE.
|
|
859
875
|
case 'spec':
|
|
860
876
|
return dispatchSpec({
|
|
861
877
|
verdict,
|
|
@@ -863,7 +879,10 @@ async function decideAndDispatch(
|
|
|
863
879
|
cwd,
|
|
864
880
|
arbiter,
|
|
865
881
|
integration: modes.spec,
|
|
866
|
-
//
|
|
882
|
+
// The resolved cross-job CAS-retry cap (config `mergeRetries`) — threaded so
|
|
883
|
+
// intake's spec emit lands under the same per-repo cap the build path uses.
|
|
884
|
+
mergeRetries: options.mergeRetries,
|
|
885
|
+
// Same origin-trust stamp on the spec outcome (propagated onto its tasks
|
|
867
886
|
// later by the tasker). Passed IN; not resolved here.
|
|
868
887
|
originTrust: options.originTrust,
|
|
869
888
|
noPR: options.noPR,
|
|
@@ -871,7 +890,7 @@ async function decideAndDispatch(
|
|
|
871
890
|
// `pre-prd-staging-pool-split-and-untrusted-prd-placement`): the
|
|
872
891
|
// configured-default + explicit-flag rungs, fed into the SHARED placement
|
|
873
892
|
// resolver alongside the `originTrust` stamp above. The resolver decides
|
|
874
|
-
// `
|
|
893
|
+
// `specs/proposed/` (staging) vs `specs/ready/` (the tasking pool); `intake` never
|
|
875
894
|
// places itself.
|
|
876
895
|
specsLandIn: options.specsLandIn,
|
|
877
896
|
explicitSpecsLandIn: options.explicitSpecsLandIn,
|
|
@@ -931,7 +950,7 @@ async function decideAndDispatch(
|
|
|
931
950
|
*
|
|
932
951
|
* - **ask** (non-terminal): `postIssueComment` the drafted question, emit NOTHING,
|
|
933
952
|
* and LEAVE THE ISSUE OPEN — it waits for the thread to be answered (a later run
|
|
934
|
-
* resumes from it). The task/
|
|
953
|
+
* resumes from it). The task/spec path also never closes (CI's close-job does,
|
|
935
954
|
* via the `issue:` field). Intake closes ONLY on BOUNCE.
|
|
936
955
|
* - **bounce** (TERMINAL): the asks are unrelated and must be re-filed, so an OPEN
|
|
937
956
|
* issue is a dishonest "still in play" signal. Intake CLOSES the issue
|
|
@@ -1028,7 +1047,7 @@ async function dispatchComment(params: {
|
|
|
1028
1047
|
|
|
1029
1048
|
/**
|
|
1030
1049
|
* DISPATCH the `task` outcome: derive a content-derived slug, write
|
|
1031
|
-
* `work/backlog/<slug>.md` (`covers: []`, NO `
|
|
1050
|
+
* `work/backlog/<slug>.md` (`covers: []`, NO `spec:`) carrying `issue: N` (the
|
|
1032
1051
|
* lone-task closure link, NOT `Fixes #N`), and integrate via {@link
|
|
1033
1052
|
* performIntegration}. The runner owns the git: it onboards a
|
|
1034
1053
|
* `work/<slug>` branch off fresh `<arbiter>/main`, then the lifecycle `stage`
|
|
@@ -1041,6 +1060,8 @@ async function dispatchTask(params: {
|
|
|
1041
1060
|
cwd: string;
|
|
1042
1061
|
arbiter: string;
|
|
1043
1062
|
integration: IntegrationMode;
|
|
1063
|
+
/** The resolved cross-job CAS-retry cap (undefined ⇒ engine default). */
|
|
1064
|
+
mergeRetries: number | undefined;
|
|
1044
1065
|
/** The origin-trust stamp passed IN (unset ⇒ emit unstamped ⇒ human/trusted). */
|
|
1045
1066
|
originTrust: OriginTrust | undefined;
|
|
1046
1067
|
noPR: boolean | undefined;
|
|
@@ -1063,6 +1084,7 @@ async function dispatchTask(params: {
|
|
|
1063
1084
|
cwd,
|
|
1064
1085
|
arbiter,
|
|
1065
1086
|
integration,
|
|
1087
|
+
mergeRetries,
|
|
1066
1088
|
originTrust,
|
|
1067
1089
|
noPR,
|
|
1068
1090
|
providerInstance,
|
|
@@ -1074,7 +1096,7 @@ async function dispatchTask(params: {
|
|
|
1074
1096
|
note,
|
|
1075
1097
|
} = params;
|
|
1076
1098
|
|
|
1077
|
-
// A content-derived slug — NEVER a counter (
|
|
1099
|
+
// A content-derived slug — NEVER a counter (spec `issue-intake` US #8). Prefer the drafted
|
|
1078
1100
|
// `taskSlug`, else derive from the drafted title; sanitise either through
|
|
1079
1101
|
// `paramCase` so the filename + frontmatter slug are well-formed.
|
|
1080
1102
|
const slug = resolveSlug(verdict);
|
|
@@ -1089,7 +1111,7 @@ async function dispatchTask(params: {
|
|
|
1089
1111
|
|
|
1090
1112
|
// BOUNDED INTERNAL REVIEW (observation
|
|
1091
1113
|
// `intake-lone-task-skips-adversarial-review-the-prd-path-gets`, rulings A/B/C):
|
|
1092
|
-
// the `do
|
|
1114
|
+
// the `do spec:` path gets `runTaskReviewLoop`; the lone-TASK path got NOTHING.
|
|
1093
1115
|
// AFTER the `task` verdict and BEFORE the write/integrate, run a bounded (3-round,
|
|
1094
1116
|
// HARD-CAPPED) adversarial self-review on the SINGLE drafted task. It mutates the
|
|
1095
1117
|
// candidate body IN MEMORY (no `work/backlog/` write pre-convergence). A launch/
|
|
@@ -1185,6 +1207,12 @@ async function dispatchTask(params: {
|
|
|
1185
1207
|
// EXPLICITLY-chosen mode proceeds as-is: a future `--merge-task` lands on main
|
|
1186
1208
|
// (`merge` IS the auto-land mode, never downgraded).
|
|
1187
1209
|
mode: integration,
|
|
1210
|
+
// The cross-job merge-serialiser CAS-retry cap (config `mergeRetries`) — the
|
|
1211
|
+
// git-alone floor of the cross-job land queue, resolved through the gate-
|
|
1212
|
+
// family precedence chain in the CLI and threaded here so intake's lone-task
|
|
1213
|
+
// emit lands under the same per-repo cap the build path uses. Unset ⇒ the
|
|
1214
|
+
// engine default (byte-for-byte unchanged).
|
|
1215
|
+
mergeRetries,
|
|
1188
1216
|
noPR,
|
|
1189
1217
|
providerInstance,
|
|
1190
1218
|
type: 'feat',
|
|
@@ -1217,8 +1245,8 @@ async function dispatchTask(params: {
|
|
|
1217
1245
|
}
|
|
1218
1246
|
|
|
1219
1247
|
/**
|
|
1220
|
-
* DISPATCH the `spec` outcome (
|
|
1221
|
-
*
|
|
1248
|
+
* DISPATCH the `spec` outcome (the SOLE parent-spec outcome after the HARD CUTOVER;
|
|
1249
|
+
* the legacy ''prd'' outcome token is GONE): derive a content-derived slug, write the spec file
|
|
1222
1250
|
* (`work/specs/ready/<slug>.md`) carrying `issue: N` (the loop-closure linkage the
|
|
1223
1251
|
* close JOB reaches via `task.spec: → spec issue:`; on a fanned spec the number
|
|
1224
1252
|
* lives ONLY on the spec — a fanned task uses `spec:`, NOT its own `issue:`, which
|
|
@@ -1234,6 +1262,8 @@ async function dispatchSpec(params: {
|
|
|
1234
1262
|
cwd: string;
|
|
1235
1263
|
arbiter: string;
|
|
1236
1264
|
integration: IntegrationMode;
|
|
1265
|
+
/** The resolved cross-job CAS-retry cap (undefined ⇒ engine default). */
|
|
1266
|
+
mergeRetries: number | undefined;
|
|
1237
1267
|
/** The origin-trust stamp passed IN (unset ⇒ emit unstamped ⇒ human/trusted). */
|
|
1238
1268
|
originTrust: OriginTrust | undefined;
|
|
1239
1269
|
noPR: boolean | undefined;
|
|
@@ -1255,6 +1285,7 @@ async function dispatchSpec(params: {
|
|
|
1255
1285
|
cwd,
|
|
1256
1286
|
arbiter,
|
|
1257
1287
|
integration,
|
|
1288
|
+
mergeRetries,
|
|
1258
1289
|
originTrust,
|
|
1259
1290
|
noPR,
|
|
1260
1291
|
specsLandIn,
|
|
@@ -1266,7 +1297,7 @@ async function dispatchSpec(params: {
|
|
|
1266
1297
|
note,
|
|
1267
1298
|
} = params;
|
|
1268
1299
|
|
|
1269
|
-
// A content-derived slug — NEVER a counter (
|
|
1300
|
+
// A content-derived slug — NEVER a counter (spec `issue-intake` US #8). Prefer the drafted
|
|
1270
1301
|
// `specSlug`, else derive from the drafted title.
|
|
1271
1302
|
const slug = resolveSpecSlug(verdict);
|
|
1272
1303
|
if (slug === '') {
|
|
@@ -1279,7 +1310,7 @@ async function dispatchSpec(params: {
|
|
|
1279
1310
|
// RUNNER-DETERMINISTIC PLACEMENT (task
|
|
1280
1311
|
// `pre-prd-staging-pool-split-and-untrusted-prd-placement`, governing ADR
|
|
1281
1312
|
// `placement-is-runner-deterministic-humanonly-is-agent-judgement`). Resolve
|
|
1282
|
-
// which folder the runner writes the intake-authored
|
|
1313
|
+
// which folder the runner writes the intake-authored spec into BEFORE handing
|
|
1283
1314
|
// it to the shared integrate band: the SAME precedence chain the tasker uses
|
|
1284
1315
|
// (`explicit > untrusted-origin ⇒ staging > specsLandIn > built-in (staging)`),
|
|
1285
1316
|
// the SAME shared resolver — only the lifecycle SLOTS differ. The agent
|
|
@@ -1317,16 +1348,20 @@ async function dispatchSpec(params: {
|
|
|
1317
1348
|
slug,
|
|
1318
1349
|
source: 'in-progress',
|
|
1319
1350
|
recovering: false,
|
|
1320
|
-
// An intake-emitted
|
|
1351
|
+
// An intake-emitted spec has no `verify` floor of its own (it is a new spec,
|
|
1321
1352
|
// not a build), exactly as the task branch + the tasking transition skip it.
|
|
1322
1353
|
skipVerify: true,
|
|
1323
1354
|
mode: integration,
|
|
1355
|
+
// The cross-job merge-serialiser CAS-retry cap (config `mergeRetries`) — same
|
|
1356
|
+
// rationale as the lone-task emit above; threaded so intake's spec emit lands
|
|
1357
|
+
// under the same per-repo cap. Unset ⇒ the engine default (byte-for-byte).
|
|
1358
|
+
mergeRetries,
|
|
1324
1359
|
noPR,
|
|
1325
1360
|
providerInstance,
|
|
1326
1361
|
type: 'feat',
|
|
1327
1362
|
lifecycle: {
|
|
1328
|
-
// The emitted
|
|
1329
|
-
// race as the task path: `stage()` writes the
|
|
1363
|
+
// The emitted spec IS the title source. Pass the DRAFTED title EXPLICITLY (same
|
|
1364
|
+
// race as the task path: `stage()` writes the spec file AFTER the title
|
|
1330
1365
|
// read). `titlePath` stays set but is IGNORED while `title` is present.
|
|
1331
1366
|
titlePath: join(cwd, relPath),
|
|
1332
1367
|
title: verdict.specTitle ?? slug,
|
|
@@ -1384,9 +1419,9 @@ async function integrationToIntakeResult(
|
|
|
1384
1419
|
core.integration?.mode === 'merge'
|
|
1385
1420
|
? 'landed it on the arbiter main'
|
|
1386
1421
|
: 'opened a PR carrying it (main untouched)';
|
|
1387
|
-
// Both a lone task and a
|
|
1388
|
-
// closes its own issue; a
|
|
1389
|
-
// task/
|
|
1422
|
+
// Both a lone task and a spec carry `issue: N` as their closure link (the task
|
|
1423
|
+
// closes its own issue; a spec is reached via `task.spec: → spec issue:`). On the
|
|
1424
|
+
// task/spec path `intake` never closes the issue (CI's close-job does, via the
|
|
1390
1425
|
// `issue:` field; intake closes ONLY on BOUNCE) and emits no `Fixes #N` (a
|
|
1391
1426
|
// deferred GitHub-only optimisation).
|
|
1392
1427
|
const link = `issue: ${issueNumber}`;
|
|
@@ -1456,7 +1491,7 @@ async function integrationToIntakeResult(
|
|
|
1456
1491
|
* `commit` (the additive {@link IntegrateResult.commit}) in merge. A degraded
|
|
1457
1492
|
* propose (no `url`) or a failed merge-tip read (no `commit`) simply OMITS the
|
|
1458
1493
|
* link — the comment still confirms what was created (the artifact is safe on the
|
|
1459
|
-
* branch/main regardless). No
|
|
1494
|
+
* branch/main regardless). No spec link beyond the slug.
|
|
1460
1495
|
* - carries the FULL intake MARKER via the SHARED {@link stampIntakeMarker} helper
|
|
1461
1496
|
* (`kind=created slug=<slug> seen=<id>,…`) so the triage's `already-terminal`
|
|
1462
1497
|
* branch consumes it — the comment cannot re-trigger intake.
|
|
@@ -1497,7 +1532,7 @@ export function composeIntakeCompletionComment(params: {
|
|
|
1497
1532
|
* does, via the `issue:` field); this comment changes NO issue state.
|
|
1498
1533
|
* - LINKS the artifact by INTEGRATION MODE: the PR `url` in propose, the landed
|
|
1499
1534
|
* `commit` (the additive {@link IntegrateResult.commit} this task surfaces) in
|
|
1500
|
-
* merge. No
|
|
1535
|
+
* merge. No spec link beyond the slug.
|
|
1501
1536
|
* - carries the FULL intake MARKER via the SHARED {@link stampIntakeMarker} helper
|
|
1502
1537
|
* (`kind=created slug=<slug> seen=<id>,…`). `kind=created` is TERMINAL, so the
|
|
1503
1538
|
* triage's `already-terminal` branch then treats the issue as already-transformed
|
|
@@ -1558,7 +1593,7 @@ async function postCompletionComment(params: {
|
|
|
1558
1593
|
}
|
|
1559
1594
|
|
|
1560
1595
|
/**
|
|
1561
|
-
* Resolve a content-derived slug from the verdict — NEVER a counter (
|
|
1596
|
+
* Resolve a content-derived slug from the verdict — NEVER a counter (spec `issue-intake` US #8).
|
|
1562
1597
|
* Prefer the drafted `taskSlug`, else derive from the drafted title; both go
|
|
1563
1598
|
* through `paramCase` (the brand case-transform) so the result is a clean
|
|
1564
1599
|
* lowercase-`-`-joined slug. An empty result (no slug AND no title) signals the
|
|
@@ -1573,7 +1608,7 @@ function resolveSlug(verdict: IntakeVerdict): string {
|
|
|
1573
1608
|
}
|
|
1574
1609
|
|
|
1575
1610
|
/**
|
|
1576
|
-
* Resolve a content-derived slug for the spec outcome — NEVER a counter (
|
|
1611
|
+
* Resolve a content-derived slug for the spec outcome — NEVER a counter (spec `issue-intake` US #8).
|
|
1577
1612
|
* Prefer the drafted `specSlug`, else derive from the drafted spec title; both go
|
|
1578
1613
|
* through `paramCase`. An empty result signals the caller to refuse.
|
|
1579
1614
|
*/
|
|
@@ -1587,13 +1622,13 @@ function resolveSpecSlug(verdict: IntakeVerdict): string {
|
|
|
1587
1622
|
|
|
1588
1623
|
/**
|
|
1589
1624
|
* Render the backlog task file: the frontmatter (`title`/`slug`/`covers: []`, NO
|
|
1590
|
-
* `
|
|
1625
|
+
* `spec:` — its own source of truth, spec `issue-intake` decision table) carrying the lone-task
|
|
1591
1626
|
* `issue: N` closure link + the drafted body. The task closes its source issue
|
|
1592
1627
|
* via its `issue:` field (the provider-agnostic link a FUTURE CI close-job reads
|
|
1593
1628
|
* from folder + field state); it carries NO `Fixes #N` (a deferred GitHub-only
|
|
1594
1629
|
* optimisation, structurally unplaceable on the `--merge` path). The number is
|
|
1595
|
-
* the task's own closure path — `issue:` XOR `
|
|
1596
|
-
* `
|
|
1630
|
+
* the task's own closure path — `issue:` XOR `spec:`; a lone task never carries a
|
|
1631
|
+
* `spec:` (spec `issue-intake` decision table). When the agent drafted no body, a thin default
|
|
1597
1632
|
* scaffold keeps the file a valid task.
|
|
1598
1633
|
*/
|
|
1599
1634
|
export function renderBacklogTask(params: {
|
|
@@ -1623,7 +1658,7 @@ export function renderBacklogTask(params: {
|
|
|
1623
1658
|
const frontmatter = lines.join('\n');
|
|
1624
1659
|
// The drafted body (agent-authored, headings and all) is wrapped VERBATIM.
|
|
1625
1660
|
// Only the empty-body DEFAULT SCAFFOLD is sourced from the shared section
|
|
1626
|
-
// skeleton owner (`renderTaskBody`,
|
|
1661
|
+
// skeleton owner (`renderTaskBody`, spec
|
|
1627
1662
|
// `centralize-buildable-task-renderer-shared-by-intake-and-promotion` US #2),
|
|
1628
1663
|
// so intake's fallback and promotion's body cannot drift on section
|
|
1629
1664
|
// names/order. The shared renderer ends its body with a trailing newline (its
|
|
@@ -1642,16 +1677,16 @@ export function renderBacklogTask(params: {
|
|
|
1642
1677
|
}
|
|
1643
1678
|
|
|
1644
1679
|
/**
|
|
1645
|
-
* Render the emitted
|
|
1646
|
-
* `issue: N` + the gate axes the prompt JUDGED) followed by the drafted
|
|
1647
|
-
* For a FANNED
|
|
1648
|
-
* the N fanned tasks, which reach it via `task.
|
|
1649
|
-
* task carries `
|
|
1650
|
-
* one that puts `issue:` on a task). The close JOB reaches the
|
|
1651
|
-
* `task.
|
|
1680
|
+
* Render the emitted spec file: the frontmatter (`title`/`slug` + the loop-closure
|
|
1681
|
+
* `issue: N` + the gate axes the prompt JUDGED) followed by the drafted spec body.
|
|
1682
|
+
* For a FANNED spec the `issue: N` lives ONLY on the spec — never duplicated across
|
|
1683
|
+
* the N fanned tasks, which reach it via `task.spec: → spec issue:` (a fanned
|
|
1684
|
+
* task carries `spec:`, NOT its own `issue:`; the lone-task outcome is the only
|
|
1685
|
+
* one that puts `issue:` on a task). The close JOB reaches the spec's number via
|
|
1686
|
+
* `task.spec: → spec issue:`. The gate axes (`humanOnly`/`needsAnswers`) are emitted ONLY when the
|
|
1652
1687
|
* verdict declared them `true` — an omitted axis is `undefined` (undeclared), the
|
|
1653
1688
|
* same convention `frontmatter.ts` parses. When the agent drafted no body, a thin
|
|
1654
|
-
* default scaffold keeps the file a valid
|
|
1689
|
+
* default scaffold keeps the file a valid spec that `do spec:` can later task.
|
|
1655
1690
|
*/
|
|
1656
1691
|
export function renderSpec(params: {
|
|
1657
1692
|
slug: string;
|
|
@@ -1682,7 +1717,7 @@ export function renderSpec(params: {
|
|
|
1682
1717
|
if (originTrust !== undefined) {
|
|
1683
1718
|
lines.push('origin: issue', `originTrust: ${originTrust}`);
|
|
1684
1719
|
}
|
|
1685
|
-
// Surface the gate axes AS THE PROMPT JUDGED THEM (
|
|
1720
|
+
// Surface the gate axes AS THE PROMPT JUDGED THEM (spec `issue-intake` US #8). Only emit a `true`
|
|
1686
1721
|
// axis — an undeclared axis stays absent (parsed as `undefined`).
|
|
1687
1722
|
if (humanOnly === true) {
|
|
1688
1723
|
lines.push('humanOnly: true');
|
|
@@ -1692,11 +1727,11 @@ export function renderSpec(params: {
|
|
|
1692
1727
|
}
|
|
1693
1728
|
lines.push('---');
|
|
1694
1729
|
const frontmatter = lines.join('\n');
|
|
1695
|
-
// As with `renderBacklogTask`: the drafted
|
|
1730
|
+
// As with `renderBacklogTask`: the drafted SPEC body is wrapped VERBATIM; only
|
|
1696
1731
|
// the empty-body DEFAULT SCAFFOLD is sourced from the shared section skeleton
|
|
1697
|
-
// owner (`renderSpecBody` with `solution` + `userStories`,
|
|
1732
|
+
// owner (`renderSpecBody` with `solution` + `userStories`, spec
|
|
1698
1733
|
// `centralize-buildable-task-renderer-shared-by-intake-and-promotion` US #2),
|
|
1699
|
-
// so intake's
|
|
1734
|
+
// so intake's SPEC fallback and promotion's SPEC body cannot drift. `trimEnd()`
|
|
1700
1735
|
// drops the renderer's trailing blank line so intake's single trailing `\n`
|
|
1701
1736
|
// (owned by the join below) keeps the bytes identical to the pre-rewire literal.
|
|
1702
1737
|
const drafted =
|
|
@@ -1704,7 +1739,7 @@ export function renderSpec(params: {
|
|
|
1704
1739
|
? body.trim()
|
|
1705
1740
|
: renderSpecBody({
|
|
1706
1741
|
problemStatement: `Transformed from issue #${issueNumber}: ${title}`,
|
|
1707
|
-
solution: '(to be detailed; this
|
|
1742
|
+
solution: '(to be detailed; this spec needs tasking via `do spec:`).',
|
|
1708
1743
|
userStories: `1. As a user, I want issue #${issueNumber} addressed.`,
|
|
1709
1744
|
}).trimEnd();
|
|
1710
1745
|
return `${frontmatter}\n\n${drafted}\n`;
|
|
@@ -1737,7 +1772,7 @@ async function stageIntakeContent(params: {
|
|
|
1737
1772
|
* `intake-` PRODUCER prefix keeps this short-lived "create the item" branch
|
|
1738
1773
|
* DISTINCT from the later build branch (`work/task-<slug>`) for the same slug
|
|
1739
1774
|
* — the firing `intake` × `do task:` collision the observation traced. The
|
|
1740
|
-
* task-emit path passes `'task'`, the
|
|
1775
|
+
* task-emit path passes `'task'`, the spec-emit path `'spec'`. A pre-existing
|
|
1741
1776
|
* local branch (a re-run) is force-recreated off fresh main.
|
|
1742
1777
|
*/
|
|
1743
1778
|
async function switchToWorkBranch(
|
|
@@ -1782,7 +1817,7 @@ async function runDecision(
|
|
|
1782
1817
|
if (options.decide) {
|
|
1783
1818
|
return options.decide({cwd, issue, comments, prompt, env: options.env});
|
|
1784
1819
|
}
|
|
1785
|
-
// PRODUCTION: launch the harness with the decision
|
|
1820
|
+
// PRODUCTION: launch the harness with the decision spec, then PARSE the verdict
|
|
1786
1821
|
// the agent emitted out of its ANSWER channel (`launched.output`) — the SAME wire
|
|
1787
1822
|
// the review gate runs (launch → `parseReviewVerdict(readOutput(launched.output))`;
|
|
1788
1823
|
// `harnessReviewGate`). The agent emits a single fenced ```json block (the OUTPUT
|
|
@@ -1860,7 +1895,7 @@ export function parseIntakeVerdict(output: string): IntakeVerdict {
|
|
|
1860
1895
|
outcome !== 'bounce'
|
|
1861
1896
|
) {
|
|
1862
1897
|
// The prompt teaches the LLM to emit `spec`, so the accepted outcome set is
|
|
1863
|
-
// `ask|task|spec|bounce`. HARD CUTOVER: the legacy
|
|
1898
|
+
// `ask|task|spec|bounce`. HARD CUTOVER: the legacy ''prd'' outcome token is
|
|
1864
1899
|
// fully gone (rejected here + removed from the `IntakeOutcome` type + the
|
|
1865
1900
|
// dispatch `case`).
|
|
1866
1901
|
throw new Error(
|
|
@@ -1905,7 +1940,7 @@ export function parseIntakeVerdict(output: string): IntakeVerdict {
|
|
|
1905
1940
|
// The LONE-TASK bounded internal review (observation
|
|
1906
1941
|
// `intake-lone-task-skips-adversarial-review-the-prd-path-gets`, rulings A/B/C).
|
|
1907
1942
|
//
|
|
1908
|
-
// Give intake's lone-TASK outcome the adversarial refinement the `do
|
|
1943
|
+
// Give intake's lone-TASK outcome the adversarial refinement the `do spec:` path
|
|
1909
1944
|
// already gets — but as a small intake-NATIVE bounded review, NOT by integrating
|
|
1910
1945
|
// the tasker loop. This is a NEW prompt + a small loop + an injectable gate seam,
|
|
1911
1946
|
// MIRRORING the tasker loop's verdict/output CONVENTIONS (fenced JSON
|
|
@@ -2293,20 +2328,20 @@ export function buildLoneTaskReviewPrompt(
|
|
|
2293
2328
|
export const parseLoneTaskReviewVerdict = parseReviewVerdict;
|
|
2294
2329
|
|
|
2295
2330
|
/**
|
|
2296
|
-
* Build the intake decision
|
|
2331
|
+
* Build the intake decision SPEC (an inline prompt builder, like `buildTaskingPrd`
|
|
2297
2332
|
* in `tasking.ts` / the reviewer prompts in `review-gate.ts` — NOT a standalone
|
|
2298
2333
|
* asset/`.md` file; no such convention exists in this package). It encodes the FULL
|
|
2299
|
-
* four-outcome decision table (
|
|
2334
|
+
* four-outcome decision table (spec `issue-intake` — the source of truth) and the
|
|
2300
2335
|
* three DECISION AIDS stated once there:
|
|
2301
2336
|
*
|
|
2302
2337
|
* 1. the **"clear?" bar** = `to-task`/`needsAnswers`' "would I build the wrong
|
|
2303
2338
|
* thing if I guessed?" — if a material requirement/scope/acceptance question is
|
|
2304
2339
|
* unanswered, ASK (never guess a spec from a vague issue);
|
|
2305
2340
|
* 2. the **"one task?" bar** = `to-task`' tracer-bullet test (one thin end-to-end
|
|
2306
|
-
* path, demoable on its own) — fits → TASK, needs splitting →
|
|
2307
|
-
* 3. **
|
|
2341
|
+
* path, demoable on its own) — fits → TASK, needs splitting → SPEC;
|
|
2342
|
+
* 3. **SPEC vs BOUNCE** turns on a **SHARED VISION**: coupled (even if small) → SPEC;
|
|
2308
2343
|
* genuinely unrelated → BOUNCE. Size NEVER forces a bounce — only unrelatedness
|
|
2309
|
-
* (the over-bounce guard: a coupled-but-small pair gets a light
|
|
2344
|
+
* (the over-bounce guard: a coupled-but-small pair gets a light SPEC, never a
|
|
2310
2345
|
* bounce).
|
|
2311
2346
|
*
|
|
2312
2347
|
* The prompt anchors to `to-task`/`to-spec` for the task/spec SHAPES it drafts. Its
|
|
@@ -2328,7 +2363,7 @@ export function buildIntakeDecisionSpec(
|
|
|
2328
2363
|
`#${i + 1} ${c.author ? `@${c.author}` : '(unknown)'}: ${c.body}`,
|
|
2329
2364
|
)
|
|
2330
2365
|
.join('\n\n');
|
|
2331
|
-
// TRIAGE ENRICHMENT (
|
|
2366
|
+
// TRIAGE ENRICHMENT (spec `issue-intake`): on the raced PROCEED path the prompt is
|
|
2332
2367
|
// told which comment(s) PRE-DATE intake's last turn (context for a prior state,
|
|
2333
2368
|
// not necessarily a fresh answer) and — only then — how many previously-SEEN
|
|
2334
2369
|
// comments were DELETED (a flag + count; the bodies are gone, so do not name them).
|
|
@@ -2378,42 +2413,42 @@ export function buildIntakeDecisionSpec(
|
|
|
2378
2413
|
' (a single thin end-to-end path, demoable on its own — `to-task`’ criterion).',
|
|
2379
2414
|
' Draft that ONE task in the `to-task` shape (a `## What to build`,',
|
|
2380
2415
|
' `## Acceptance criteria`, and `## Prompt`). The runner writes',
|
|
2381
|
-
' `work/backlog/<slug>.md` (`covers: []`, NO `
|
|
2416
|
+
' `work/backlog/<slug>.md` (`covers: []`, NO `spec:`) carrying `issue: N` (the',
|
|
2382
2417
|
' lone-task closure link, NOT `Fixes #N`) and integrates it.',
|
|
2383
2418
|
'',
|
|
2384
|
-
'- **
|
|
2419
|
+
'- **SPEC** — the issue is CLEAR *and* coherent but needs MORE THAN ONE task (it',
|
|
2385
2420
|
' cannot be one tracer-bullet path — it splits for scope/architecture). >1 task',
|
|
2386
2421
|
' ⟺ a shared vision worth recording ⟺ a spec. Draft a spec in the `to-spec` shape',
|
|
2387
2422
|
' (`## Problem Statement`, `## Solution`, `## User Stories`, `## Out of Scope`).',
|
|
2388
|
-
|
|
2389
|
-
' TASKING the
|
|
2423
|
+
` The runner writes the spec file (\`${workFolderPrefix('specs-ready')}<slug>.md\`) with \`issue: N\` and integrates it;`,
|
|
2424
|
+
' TASKING the spec is a SEPARATE later step (`do spec:`) — do not task it here.',
|
|
2390
2425
|
' **INCLUDES a coupled-but-SMALL pair: if two asks share a vision they get a',
|
|
2391
|
-
' (light)
|
|
2426
|
+
' (light) spec — they are NEVER bounced.**',
|
|
2392
2427
|
'',
|
|
2393
2428
|
'- **BOUNCE** — the issue is really MULTIPLE UNRELATED concerns wearing one issue:',
|
|
2394
2429
|
' you cannot articulate a SINGLE shared vision tying them together. Draft a short',
|
|
2395
2430
|
' message asking the author to file separate issues. A bounce is TERMINAL, so the',
|
|
2396
2431
|
' runner CLOSES the issue ATOMICALLY — your message as the closing comment +',
|
|
2397
2432
|
' reason "not planned" (the honest signal that the asks must be re-filed). Intake',
|
|
2398
|
-
' closes on BOUNCE only; never on task/
|
|
2433
|
+
' closes on BOUNCE only; never on task/spec (CI’s close-job) / ask.',
|
|
2399
2434
|
'',
|
|
2400
2435
|
'## The three decision aids (apply them in order)',
|
|
2401
2436
|
'',
|
|
2402
2437
|
'1. **"clear?"** (ASK vs the rest): the `needsAnswers` bar — would acting now risk',
|
|
2403
2438
|
' building the wrong thing? If yes → ASK. Otherwise it is clear; continue.',
|
|
2404
|
-
'2. **"one task?"** (TASK vs
|
|
2405
|
-
' end-to-end path, demoable alone? Fits → TASK; needs splitting →
|
|
2406
|
-
'3. **"shared vision?"** (
|
|
2439
|
+
'2. **"one task?"** (TASK vs SPEC): the `to-task` tracer-bullet test — one thin',
|
|
2440
|
+
' end-to-end path, demoable alone? Fits → TASK; needs splitting → SPEC.',
|
|
2441
|
+
'3. **"shared vision?"** (SPEC vs BOUNCE): coupled (even if small) → SPEC; genuinely',
|
|
2407
2442
|
' unrelated → BOUNCE. SIZE NEVER forces a bounce — only UNRELATEDNESS does. Do',
|
|
2408
|
-
' not over-bounce a small coupled pair: it is a light
|
|
2443
|
+
' not over-bounce a small coupled pair: it is a light spec.',
|
|
2409
2444
|
'',
|
|
2410
2445
|
'## Boundary',
|
|
2411
2446
|
'',
|
|
2412
|
-
'You only DRAFT the verdict + its content (the task/
|
|
2447
|
+
'You only DRAFT the verdict + its content (the task/spec body, or the comment',
|
|
2413
2448
|
'text). You do NOT perform ANY git operation and you do NOT post any comment — the',
|
|
2414
|
-
'runner owns every git/seam side-effect (write, integrate, postComment). For a
|
|
2449
|
+
'runner owns every git/seam side-effect (write, integrate, postComment). For a spec',
|
|
2415
2450
|
'verdict, also judge its gate axes (humanOnly / needsAnswers) so the runner can',
|
|
2416
|
-
'surface them on the emitted
|
|
2451
|
+
'surface them on the emitted spec.',
|
|
2417
2452
|
'',
|
|
2418
2453
|
'## Output — hand the verdict back as ONE fenced JSON block',
|
|
2419
2454
|
'',
|