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/orphan-sidecar.ts
CHANGED
|
@@ -3,17 +3,53 @@ import {join} from 'node:path';
|
|
|
3
3
|
import {run} from './git.js';
|
|
4
4
|
import {resolveSidecarIdentity} from './sidecar.js';
|
|
5
5
|
import {resolveItemPathByIdentity} from './item-path.js';
|
|
6
|
+
import {terminalMainPaths} from './item-lock.js';
|
|
6
7
|
import {workFolderPath, workFolderRel} from './work-layout.js';
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the source item's CURRENT on-disk path INCLUDING its TERMINAL resting
|
|
11
|
+
* records — the orphan-sweep existence predicate.
|
|
12
|
+
*
|
|
13
|
+
* This deliberately WIDENS {@link resolveItemPathByIdentity} (which scans the
|
|
14
|
+
* ACTIVE lifecycle folders + staging, and EXCLUDES terminals on purpose: for the
|
|
15
|
+
* apply rung a terminal-reached item is `vanished`). The orphan sweep asks a
|
|
16
|
+
* DIFFERENT question — "does a source item for this sidecar exist AT ALL?" — and a
|
|
17
|
+
* task/spec that reached its terminal (`tasks/cancelled/`, `specs/dropped/`) is a
|
|
18
|
+
* durable RESTING record that still EXISTS, so its sidecar is NOT an orphan.
|
|
19
|
+
* Treating "reached a terminal" as "gone" would let a routine `gc` delete a live
|
|
20
|
+
* sidecar (and any human answer it carries) — the 2026-07-12 false-positive.
|
|
21
|
+
*
|
|
22
|
+
* Reuses the shared {@link terminalMainPaths} (`item-lock.ts`, the SAME per-type
|
|
23
|
+
* terminal set the lock/branch reapers key off) so the "where do terminals live?"
|
|
24
|
+
* knowledge stays single-sourced. Returns the ACTIVE path when present, else the
|
|
25
|
+
* first existing TERMINAL path, else `undefined` (a genuine orphan).
|
|
26
|
+
*/
|
|
27
|
+
function resolveSourceForOrphanSweep(
|
|
28
|
+
cwd: string,
|
|
29
|
+
item: string,
|
|
30
|
+
): string | undefined {
|
|
31
|
+
const active = resolveItemPathByIdentity(cwd, item);
|
|
32
|
+
if (active !== undefined) {
|
|
33
|
+
return active;
|
|
34
|
+
}
|
|
35
|
+
const {type, slug} = resolveSidecarIdentity(item);
|
|
36
|
+
for (const rel of terminalMainPaths(type, slug)) {
|
|
37
|
+
if (existsSync(join(cwd, rel))) {
|
|
38
|
+
return rel;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
|
|
8
44
|
/**
|
|
9
45
|
* The **orphan-sidecar reaper** — the WORKING-TREE counterpart of the job-worktree
|
|
10
46
|
* and remote-branch reapers (`gc.ts` / `reap-branches.ts`), folded into `dorfl gc`
|
|
11
|
-
* (
|
|
47
|
+
* (spec `agentic-question-resolution-retire-disposition-vocabulary`, US #10).
|
|
12
48
|
*
|
|
13
49
|
* A question sidecar is a tooling-owned file `work/questions/<type>-<slug>.md`
|
|
14
50
|
* keyed on its source item's `(type, slug)` identity (`sidecarPathFor`). The
|
|
15
51
|
* contract is that notes/sidecars leave by DELETION (git history is the archive),
|
|
16
|
-
* so when a human deletes the source observation (or task/
|
|
52
|
+
* so when a human deletes the source observation (or task/spec) out-of-band, its
|
|
17
53
|
* sidecar is ORPHANED.
|
|
18
54
|
*
|
|
19
55
|
* WHY THIS IS A SWEEP, NOT AN APPLY STEP. An orphan's source item is GONE, so it
|
|
@@ -26,10 +62,14 @@ import {workFolderPath, workFolderRel} from './work-layout.js';
|
|
|
26
62
|
*
|
|
27
63
|
* The existence check REUSES the keystone's extracted `resolveItemPathByIdentity`
|
|
28
64
|
* (`item-path.ts`, the neutral re-exported seam) — the same working-tree,
|
|
29
|
-
* by-identity "does the source item exist?" resolver the apply rung uses —
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
65
|
+
* by-identity "does the source item exist?" resolver the apply rung uses — WIDENED
|
|
66
|
+
* to also count a source that has reached a TERMINAL folder (`tasks/cancelled/`,
|
|
67
|
+
* `specs/dropped/`, via the shared `terminalMainPaths`) as EXISTING: a terminal is
|
|
68
|
+
* a durable resting record, not "gone", so its sidecar is NOT an orphan (see
|
|
69
|
+
* `resolveSourceForOrphanSweep`). A sidecar whose source EXISTS anywhere is left
|
|
70
|
+
* untouched; a sidecar whose source is ABSENT from every active AND terminal
|
|
71
|
+
* folder is `git rm`'d (deletion, not a `git mv`: the sidecar leaves by deletion,
|
|
72
|
+
* recoverable from git history).
|
|
33
73
|
*/
|
|
34
74
|
|
|
35
75
|
/** A sidecar the orphan sweep reaped (its source item was absent). */
|
|
@@ -111,9 +151,10 @@ export function sweepOrphanSidecars(
|
|
|
111
151
|
const {item} = resolveSidecarIdentity(stem.replace('-', ':'));
|
|
112
152
|
const path = `${workFolderRel('questions')}/${entry}`;
|
|
113
153
|
|
|
114
|
-
const sourcePath =
|
|
154
|
+
const sourcePath = resolveSourceForOrphanSweep(input.cwd, item);
|
|
115
155
|
if (sourcePath !== undefined) {
|
|
116
|
-
// The source item still exists
|
|
156
|
+
// The source item still exists (active lifecycle OR a terminal resting
|
|
157
|
+
// record) ⇒ a LIVE sidecar ⇒ leave it untouched.
|
|
117
158
|
retained.push({path, item, sourcePath});
|
|
118
159
|
note(`Retained ${path}: source ${item} still exists (${sourcePath}).`);
|
|
119
160
|
continue;
|
package/src/pi-harness.ts
CHANGED
|
@@ -65,6 +65,15 @@ import type {HarnessAdapter} from './config.js';
|
|
|
65
65
|
/** The default pi CLI binary name (resolved on `PATH`). */
|
|
66
66
|
export const DEFAULT_PI_BIN = 'pi';
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* The grace period between a deadline SIGTERM and the follow-up SIGKILL in
|
|
70
|
+
* {@link PiHarness.launchAsync} (spec `graceful-pre-timeout-wip-checkpoint`).
|
|
71
|
+
* Ten seconds gives pi enough time to flush its session `.jsonl` and exit
|
|
72
|
+
* cleanly; a wedged/frozen child that ignores SIGTERM still gets reaped in a
|
|
73
|
+
* bounded time so the promise settles and the caller's checkpoint routing runs.
|
|
74
|
+
*/
|
|
75
|
+
export const DEADLINE_SIGKILL_GRACE_MS = 10_000;
|
|
76
|
+
|
|
68
77
|
export interface PiHarnessOptions {
|
|
69
78
|
/**
|
|
70
79
|
* The pi CLI binary (default `pi` on `PATH`). Tests inject a stub script here
|
|
@@ -239,11 +248,60 @@ export class PiHarness implements Harness {
|
|
|
239
248
|
child.stdout?.on('data', () => {});
|
|
240
249
|
// Guard so `exit` and a late `error` never double-settle the promise.
|
|
241
250
|
let settled = false;
|
|
251
|
+
let timedOut = false;
|
|
252
|
+
// DEADLINE RACE (spec `graceful-pre-timeout-wip-checkpoint`): when the
|
|
253
|
+
// caller threads a `deadlineMs` (absolute wall-clock epoch-ms), arm a
|
|
254
|
+
// SOFT SIGTERM at that time, then a HARD SIGKILL after a ~10s grace. The
|
|
255
|
+
// child's own `exit` handler below still resolves the promise (with
|
|
256
|
+
// `timedOut: true`), so we preserve the settle-once + FD-release
|
|
257
|
+
// discipline and never double-settle. A run that finishes BEFORE the
|
|
258
|
+
// deadline clears both timers (see the `exit` handler) — byte-for-byte
|
|
259
|
+
// unchanged from the pre-task behaviour.
|
|
260
|
+
let softTimer: NodeJS.Timeout | undefined;
|
|
261
|
+
let hardTimer: NodeJS.Timeout | undefined;
|
|
262
|
+
const clearDeadlineTimers = (): void => {
|
|
263
|
+
if (softTimer !== undefined) {
|
|
264
|
+
clearTimeout(softTimer);
|
|
265
|
+
softTimer = undefined;
|
|
266
|
+
}
|
|
267
|
+
if (hardTimer !== undefined) {
|
|
268
|
+
clearTimeout(hardTimer);
|
|
269
|
+
hardTimer = undefined;
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
if (input.deadlineMs !== undefined) {
|
|
273
|
+
const softMs = Math.max(0, input.deadlineMs - Date.now());
|
|
274
|
+
softTimer = setTimeout(() => {
|
|
275
|
+
if (settled) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
timedOut = true;
|
|
279
|
+
try {
|
|
280
|
+
child.kill('SIGTERM');
|
|
281
|
+
} catch {
|
|
282
|
+
// Best-effort: a already-exited child throws ESRCH; the `exit`
|
|
283
|
+
// handler will still settle the promise.
|
|
284
|
+
}
|
|
285
|
+
hardTimer = setTimeout(() => {
|
|
286
|
+
if (settled) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
try {
|
|
290
|
+
child.kill('SIGKILL');
|
|
291
|
+
} catch {
|
|
292
|
+
// Best-effort: see above.
|
|
293
|
+
}
|
|
294
|
+
}, DEADLINE_SIGKILL_GRACE_MS);
|
|
295
|
+
hardTimer.unref?.();
|
|
296
|
+
}, softMs);
|
|
297
|
+
softTimer.unref?.();
|
|
298
|
+
}
|
|
242
299
|
child.on('error', (err) => {
|
|
243
300
|
if (settled) {
|
|
244
301
|
return;
|
|
245
302
|
}
|
|
246
303
|
settled = true;
|
|
304
|
+
clearDeadlineTimers();
|
|
247
305
|
reject(new Error(`failed to spawn pi (${this.piBin}): ${err.message}`));
|
|
248
306
|
});
|
|
249
307
|
// Resolve on `exit` (pi itself terminated), NOT `close`: `close` waits for
|
|
@@ -255,6 +313,7 @@ export class PiHarness implements Harness {
|
|
|
255
313
|
return;
|
|
256
314
|
}
|
|
257
315
|
settled = true;
|
|
316
|
+
clearDeadlineTimers();
|
|
258
317
|
// Release our end of the stdio pipes so a leaked grandchild's inherited
|
|
259
318
|
// FDs stop keeping our streams referenced; `unref` the child handle too.
|
|
260
319
|
child.stdout?.destroy();
|
|
@@ -263,9 +322,11 @@ export class PiHarness implements Harness {
|
|
|
263
322
|
child.unref?.();
|
|
264
323
|
const status = code ?? -1;
|
|
265
324
|
resolve({
|
|
266
|
-
ok: status === 0,
|
|
325
|
+
ok: status === 0 && !timedOut,
|
|
267
326
|
record,
|
|
268
|
-
detail:
|
|
327
|
+
detail:
|
|
328
|
+
status === 0 && !timedOut ? undefined : stderr.trim() || undefined,
|
|
329
|
+
timedOut: timedOut ? true : undefined,
|
|
269
330
|
// Read the agent's ANSWER from the `.jsonl` at `exit` — the same
|
|
270
331
|
// last-assistant-text read `launch` does at return (task
|
|
271
332
|
// `harness-agent-output`); the process has exited so the log is final.
|
|
@@ -354,6 +415,14 @@ export class PiHarness implements Harness {
|
|
|
354
415
|
* pointer with an `existsSync` check. This is the pi-native "is there an audit
|
|
355
416
|
* trail to look at?" signal — distinct from PID liveness, and STILL not mtime
|
|
356
417
|
* (we check existence, never modification time).
|
|
418
|
+
*
|
|
419
|
+
* Studied (task `pi-harness-polish`, finding
|
|
420
|
+
* `work/notes/findings/pi-harness-channels.md`): the recorded `--session <path>`
|
|
421
|
+
* file remains the right audit pointer even against pi's other output surfaces
|
|
422
|
+
* (`--mode json` stdout stream, `--mode rpc`, in-process SDK) — those are
|
|
423
|
+
* transient stdio channels that do not survive the process, whereas the session
|
|
424
|
+
* file is the versioned, dashboard-visible activity trail pi itself treats as
|
|
425
|
+
* the audit artefact. PID stays the liveness anchor alongside it.
|
|
357
426
|
*/
|
|
358
427
|
export function piSessionExists(record: HarnessRecord): boolean {
|
|
359
428
|
return record.session !== undefined && existsSync(record.session);
|
|
@@ -368,6 +437,17 @@ export function piSessionExists(record: HarnessRecord): boolean {
|
|
|
368
437
|
* It REUSES `watch-session.ts`'s {@link lastAssistantText} (one `.jsonl` parser,
|
|
369
438
|
* not two). An absent file (pi never wrote it) yields `undefined`, as does a log
|
|
370
439
|
* with no assistant text — a read error is never thrown back into the launch.
|
|
440
|
+
*
|
|
441
|
+
* Studied (task `pi-harness-polish`, finding
|
|
442
|
+
* `work/notes/findings/pi-harness-channels.md`, pinned against pi 0.73.1 +
|
|
443
|
+
* session format v3): the session `.jsonl` is the right channel for output
|
|
444
|
+
* because it is the only one that is BOTH post-mortem readable AND explicitly
|
|
445
|
+
* versioned + migrated (`docs/session-format.md`). The `--mode json` STDOUT
|
|
446
|
+
* event stream is not versioned and is transient; `--mode rpc` and the
|
|
447
|
+
* in-process SDK cost more without solving anything the file does not. The
|
|
448
|
+
* cross-harness `LaunchResult.output` seam (Option C) is a bare `string | undefined`,
|
|
449
|
+
* so a future stream/HTTP-shaped harness (opencode-style) still fits: the file
|
|
450
|
+
* shape lives BEHIND this reader and is not observable through the seam.
|
|
371
451
|
*/
|
|
372
452
|
function readLastAssistantText(sessionFile: string): string | undefined {
|
|
373
453
|
let jsonl: string;
|
package/src/placement.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* **The shared STAGING/POOL placement resolver** (
|
|
2
|
+
* **The shared STAGING/POOL placement resolver** (spec
|
|
3
3
|
* `staging-pool-position-gate-and-trust-model`, task
|
|
4
4
|
* `runner-deterministic-slice-placement-policy-and-precedence`, governing ADR
|
|
5
5
|
* `placement-is-runner-deterministic-humanonly-is-agent-judgement`).
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
* LIFECYCLE-GENERIC. The folder names + the configured-default value are
|
|
21
21
|
* PARAMETERS (`slots`, `configuredDefault`), so the same resolver serves the
|
|
22
|
-
* TASK lifecycle (`tasksLandIn`: `
|
|
22
|
+
* TASK lifecycle (`tasksLandIn`: `backlog`/`ready` — the POOL value was
|
|
23
23
|
* renamed `'backlog'` → `'todo'` → `'ready'`, ADR
|
|
24
24
|
* `rename-task-pool-folder-todo-to-ready`) AND the SPEC-
|
|
25
25
|
* placement lifecycle (`specsLandIn`: `pre-proposed`/`ready`) without forking. A future
|
|
@@ -31,19 +31,19 @@
|
|
|
31
31
|
* Which side of the staging/pool split the runner chose. The CALLER maps this
|
|
32
32
|
* onto the lifecycle's concrete folder name via {@link PlacementSlots}.
|
|
33
33
|
*
|
|
34
|
-
* - `'staging'` — land in the staging area (tasks: `
|
|
35
|
-
* `
|
|
34
|
+
* - `'staging'` — land in the staging area (tasks: `tasks/backlog/`; prds:
|
|
35
|
+
* `specs/proposed/`). Not in the agent pool; a human/runner promotion is needed to make
|
|
36
36
|
* the item eligible. Review-without-PR review surface.
|
|
37
37
|
* - `'pool'` — land directly in the agent-eligible pool (tasks: `tasks/ready/`;
|
|
38
|
-
* prds: `
|
|
38
|
+
* prds: `specs/ready/`). The trusted-fast-path landing.
|
|
39
39
|
*/
|
|
40
40
|
export type PlacementSide = 'staging' | 'pool';
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
43
|
* The two folder names a lifecycle uses for its staging/pool split. Supplied by
|
|
44
44
|
* the caller so this resolver stays lifecycle-generic (the TASK caller passes
|
|
45
|
-
* `{staging: '
|
|
46
|
-
* `{staging: '
|
|
45
|
+
* `{staging: 'tasks/backlog', pool: 'tasks/ready'}`; the SPEC-placement caller passes
|
|
46
|
+
* `{staging: 'specs/proposed', pool: 'specs/ready'}`).
|
|
47
47
|
*/
|
|
48
48
|
export interface PlacementSlots {
|
|
49
49
|
staging: string;
|
|
@@ -100,7 +100,7 @@ const BUILT_IN_FLOOR: PlacementSide = 'staging';
|
|
|
100
100
|
* explicit > untrusted-origin ⇒ staging > configured default > built-in
|
|
101
101
|
*
|
|
102
102
|
* Pure: no I/O, no env reads — the caller resolves config + reads the
|
|
103
|
-
* frontmatter and passes both in. Reused by every lifecycle (task +
|
|
103
|
+
* frontmatter and passes both in. Reused by every lifecycle (task + spec
|
|
104
104
|
* placement + future intake variants) so a precedence change touches ONE place.
|
|
105
105
|
*/
|
|
106
106
|
export function resolvePlacement(
|
package/src/prd-to-spec.ts
CHANGED
|
@@ -8,10 +8,11 @@ import {
|
|
|
8
8
|
mkdirSync,
|
|
9
9
|
rmdirSync,
|
|
10
10
|
} from 'node:fs';
|
|
11
|
-
import {join, relative, dirname} from 'node:path';
|
|
11
|
+
import {join, relative, dirname, basename} from 'node:path';
|
|
12
12
|
import {run, git, gitMv} from './git.js';
|
|
13
13
|
import {resolveProtocolDoc} from './prompt.js';
|
|
14
14
|
import {WORK_ROOT} from './work-layout.js';
|
|
15
|
+
import {repoConfigPath} from './repo-config.js';
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* The **`dorfl prd-to-spec` migration ENGINE** (spec
|
|
@@ -675,7 +676,9 @@ export function migrateConfig(
|
|
|
675
676
|
migration: VocabularyMigration = MIGRATION,
|
|
676
677
|
options: {dryRun?: boolean} = {},
|
|
677
678
|
): ConfigRewrite[] {
|
|
678
|
-
|
|
679
|
+
// Resolve the repo's actual config file (prefers `dorfl.json`, falls back to
|
|
680
|
+
// the legacy `.dorfl.json`), so the key rewrite finds it under either name.
|
|
681
|
+
const configAbs = repoConfigPath(repoPath);
|
|
679
682
|
if (!existsSync(configAbs)) {
|
|
680
683
|
return [];
|
|
681
684
|
}
|
|
@@ -922,10 +925,15 @@ export function scanForLeaks(
|
|
|
922
925
|
scanText(rel, readFileSync(join(repoPath, rel), 'utf8'), []);
|
|
923
926
|
}
|
|
924
927
|
}
|
|
925
|
-
// The config file (the key layer).
|
|
926
|
-
|
|
928
|
+
// The config file (the key layer) — under either the preferred `dorfl.json`
|
|
929
|
+
// or the legacy `.dorfl.json`.
|
|
930
|
+
const configAbs = repoConfigPath(repoPath);
|
|
927
931
|
if (existsSync(configAbs)) {
|
|
928
|
-
scanText(
|
|
932
|
+
scanText(
|
|
933
|
+
basename(configAbs),
|
|
934
|
+
readFileSync(configAbs, 'utf8'),
|
|
935
|
+
configKeyPatterns,
|
|
936
|
+
);
|
|
929
937
|
}
|
|
930
938
|
// The FOLDER TREE itself: a surviving `work/prds/` directory (empty ⇒ no
|
|
931
939
|
// file, but the folder still leaks). Report it structurally.
|
package/src/prompt.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Builds the prompt the runner hands to `agentCmd`: a small CONSTANT wrapper
|
|
3
|
-
* (only the `<slug>` / source-
|
|
3
|
+
* (only the `<slug>` / source-spec path vary) around the claimed task's own
|
|
4
4
|
* `## Prompt` section. This is dual-use — the SAME assembly the autonomous
|
|
5
5
|
* runner feeds `agentCmd` and the human `dorfl prompt [<slug>]` command.
|
|
6
6
|
*
|
|
@@ -416,7 +416,7 @@ export function buildContinueBlock(slug: string, ctx: ContinueContext): string {
|
|
|
416
416
|
}
|
|
417
417
|
|
|
418
418
|
/**
|
|
419
|
-
* Build the full prompt: the canonical wrapper for `slug` (with its source
|
|
419
|
+
* Build the full prompt: the canonical wrapper for `slug` (with its source spec
|
|
420
420
|
* substituted) followed by the task's own `## Prompt` body, appended verbatim.
|
|
421
421
|
*
|
|
422
422
|
* In CONTINUE-mode (a {@link ContinueContext} is supplied), a CONTINUE block is
|
|
@@ -459,10 +459,7 @@ export interface ResolvedTask {
|
|
|
459
459
|
path: string;
|
|
460
460
|
/** The folder the task was resolved from (in-progress wins over tasks-ready). */
|
|
461
461
|
folder: TaskFolder;
|
|
462
|
-
/**
|
|
463
|
-
* The task's source SPEC slug (frontmatter `spec:`, or the legacy `prd:` key
|
|
464
|
-
* as read-only back-compat), if any.
|
|
465
|
-
*/
|
|
462
|
+
/** The task's source SPEC slug (frontmatter `spec:`), if any. */
|
|
466
463
|
spec: string | undefined;
|
|
467
464
|
/** The extracted `## Prompt` body. */
|
|
468
465
|
taskPrompt: string;
|
|
@@ -493,7 +490,7 @@ export class PromptError extends Error {}
|
|
|
493
490
|
/**
|
|
494
491
|
* The CONTINUE-only gate that lets {@link resolveTask} reach a task that has
|
|
495
492
|
* already been done-moved into `work/done/` — story 5 of the `ledger-integrity`
|
|
496
|
-
*
|
|
493
|
+
* spec (defect 3). A continue/re-claim can legitimately land on a branch whose
|
|
497
494
|
* task was ALREADY moved to `done/` (the green-but-unpushed STRAND state), and
|
|
498
495
|
* onboard must find it; but a `done/` task is folder-indistinguishable between
|
|
499
496
|
* two states and re-onboarding a genuinely-finished one would RE-RUN it. So
|
|
@@ -533,7 +530,7 @@ export interface ContinueResolutionGate {
|
|
|
533
530
|
|
|
534
531
|
/**
|
|
535
532
|
* Extra knobs for {@link resolveTask} beyond the continue gate. Today the only
|
|
536
|
-
* member is `allowBacklog` (
|
|
533
|
+
* member is `allowBacklog` (spec
|
|
537
534
|
* `do-allow-backlog-drive-staged-tasks-without-promotion`): the operator's
|
|
538
535
|
* EXPLICIT `do … --allow-backlog`, which widens resolution to also search
|
|
539
536
|
* `tasks-backlog` (staging) at LOWEST priority. Default off (omitted) \u21d2 the
|
|
@@ -574,7 +571,7 @@ function isStrandedDoneTip(gate: ContinueResolutionGate): boolean {
|
|
|
574
571
|
|
|
575
572
|
/**
|
|
576
573
|
* Resolve a task's file: prefer `work/in-progress/<slug>.md`, fall back to
|
|
577
|
-
* `work/tasks/ready/<slug>.md` (the pool). Returns the parsed
|
|
574
|
+
* `work/tasks/ready/<slug>.md` (the pool). Returns the parsed spec + extracted
|
|
578
575
|
* `## Prompt` body. Throws {@link PromptError} when neither file exists or it has
|
|
579
576
|
* no prompt body.
|
|
580
577
|
*
|
|
@@ -588,11 +585,11 @@ function isStrandedDoneTip(gate: ContinueResolutionGate): boolean {
|
|
|
588
585
|
* the only addition, and it is gated. With no gate (a fresh claim) the behaviour
|
|
589
586
|
* is byte-identical to the original `['in-progress','tasks-ready']`-only resolution.
|
|
590
587
|
*
|
|
591
|
-
* `--allow-backlog` (
|
|
588
|
+
* `--allow-backlog` (spec `do-allow-backlog-drive-staged-tasks-without-promotion`):
|
|
592
589
|
* when {@link ResolveTaskOptions.allowBacklog} is set, `tasks-backlog` (the staging
|
|
593
590
|
* folder) is appended at the LOWEST priority — after `tasks-ready`, so a slug
|
|
594
591
|
* present in BOTH the pool and staging resolves to the READY copy (the same-slug
|
|
595
|
-
* precedence the
|
|
592
|
+
* precedence the spec's decision 5 fixes). Default off ⇒ byte-identical to today
|
|
596
593
|
* (no autonomous path sets it; staging stays unreachable to `run`/auto-pick).
|
|
597
594
|
*/
|
|
598
595
|
export function resolveTask(
|
|
@@ -627,9 +624,8 @@ export function resolveTask(
|
|
|
627
624
|
);
|
|
628
625
|
}
|
|
629
626
|
const fm = parseFrontmatter(content);
|
|
630
|
-
// Read the parent-spec pointer off `fm.spec` (populated from
|
|
631
|
-
//
|
|
632
|
-
// `spec`-only `ResolvedTask` (spec
|
|
627
|
+
// Read the parent-spec pointer off `fm.spec` (populated from the canonical
|
|
628
|
+
// `spec:` key) into the `spec`-only `ResolvedTask` (spec
|
|
633
629
|
// `prd-to-spec-vocabulary-cutover-and-migration-command`).
|
|
634
630
|
return {slug, path, folder, spec: fm.spec, taskPrompt};
|
|
635
631
|
}
|
|
@@ -665,13 +661,13 @@ export function inferSlugFromBranch(
|
|
|
665
661
|
*/
|
|
666
662
|
/**
|
|
667
663
|
* Resolve the EFFECTIVE `promptGuidance` for an item by walking the precedence
|
|
668
|
-
* chain (highest → lowest): the per-task frontmatter override, the per-
|
|
669
|
-
* frontmatter override (only when the task carries a `
|
|
664
|
+
* chain (highest → lowest): the per-task frontmatter override, the per-spec
|
|
665
|
+
* frontmatter override (only when the task carries a `spec:`), then the
|
|
670
666
|
* already-resolved repo policy. Each nudge member resolves independently — a
|
|
671
667
|
* task's `promptGuidance.testFirst` override never bleeds into a sibling
|
|
672
668
|
* member — mirroring the `humanOnly`/`autoBuild` per-item override shape.
|
|
673
669
|
*
|
|
674
|
-
* A task may carry the override even when it has NO `
|
|
670
|
+
* A task may carry the override even when it has NO `spec:` (a self-contained
|
|
675
671
|
* chore), by symmetry with `humanOnly` at the item level; `specFrontmatter`
|
|
676
672
|
* is then simply absent and the chain reads task ⇒ repo.
|
|
677
673
|
*/
|
|
@@ -688,11 +684,11 @@ export function resolveItemPromptGuidance(
|
|
|
688
684
|
}
|
|
689
685
|
|
|
690
686
|
/**
|
|
691
|
-
* Locate a
|
|
692
|
-
* auto-slice pool), then fall back to `work/
|
|
687
|
+
* Locate a spec's file on disk: prefer `work/specs/ready/<slug>.md` (the
|
|
688
|
+
* auto-slice pool), then fall back to `work/specs/tasked/<slug>.md` (tasked,
|
|
693
689
|
* resting). Returns `undefined` when neither exists — the caller treats that
|
|
694
|
-
* as "no
|
|
695
|
-
* through to the repo policy (a missing
|
|
690
|
+
* as "no spec-level override available" and the precedence chain falls
|
|
691
|
+
* through to the repo policy (a missing spec is NOT an error at this seam;
|
|
696
692
|
* the per-item override is OPTIONAL by design).
|
|
697
693
|
*/
|
|
698
694
|
export function findSpecPath(
|
|
@@ -714,7 +710,7 @@ export function findSpecPath(
|
|
|
714
710
|
/**
|
|
715
711
|
* The convenience seam every caller of {@link buildAgentPrompt} reuses to
|
|
716
712
|
* resolve the per-item override: load the task frontmatter from its file +
|
|
717
|
-
* (when the task carries `
|
|
713
|
+
* (when the task carries `spec:`) the spec frontmatter, then walk
|
|
718
714
|
* {@link resolveItemPromptGuidance}. Pure-ish (reads at most two files);
|
|
719
715
|
* returns the repo policy verbatim when neither item layer overrides anything.
|
|
720
716
|
*/
|
|
@@ -725,8 +721,7 @@ export function resolvePromptGuidanceForItem(options: {
|
|
|
725
721
|
}): PromptGuidance {
|
|
726
722
|
const taskFm = parseFrontmatter(options.taskContent);
|
|
727
723
|
let specFm: Frontmatter | undefined;
|
|
728
|
-
// Read the parent-spec pointer off `fm.spec` (populated from the `spec:` key
|
|
729
|
-
// the legacy `prd:` back-compat alias).
|
|
724
|
+
// Read the parent-spec pointer off `fm.spec` (populated from the `spec:` key).
|
|
730
725
|
if (taskFm.spec !== undefined) {
|
|
731
726
|
const specPath = findSpecPath(options.cwd, taskFm.spec);
|
|
732
727
|
if (specPath !== undefined) {
|
|
@@ -745,7 +740,7 @@ export function renderPrompt(options: PromptOptions): string {
|
|
|
745
740
|
);
|
|
746
741
|
}
|
|
747
742
|
const task = resolveTask(options.cwd, slug);
|
|
748
|
-
// Per-item override layer: a task or
|
|
743
|
+
// Per-item override layer: a task or spec may pin `promptGuidance.testFirst`
|
|
749
744
|
// in its frontmatter, superseding the resolved repo policy for THIS item.
|
|
750
745
|
// We ALWAYS walk the resolver (even when no repo policy was threaded), so a
|
|
751
746
|
// task can opt IN to the strengthened nudge even on a repo whose default is
|
package/src/readiness.ts
CHANGED
|
@@ -16,7 +16,7 @@ import {ledgerRead} from './ledger-read.js';
|
|
|
16
16
|
* the shared {@link resolveBlockedBy} (no reimplemented dep resolution).
|
|
17
17
|
*
|
|
18
18
|
* The two axes are deliberately treated differently (see WORK-CONTRACT and the
|
|
19
|
-
* task
|
|
19
|
+
* task spec):
|
|
20
20
|
*
|
|
21
21
|
* - `blockedBy` unmet is a FACTUAL prerequisite (the dep work does not exist
|
|
22
22
|
* yet) → REFUSE by default. An override flag is the human escape hatch.
|
package/src/reap-branches.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {run} from './git.js';
|
|
2
|
-
import {
|
|
2
|
+
import {isProvablyMergedForReap} from './gc.js';
|
|
3
3
|
import {parseWorkBranchRef} from './slug-namespace.js';
|
|
4
|
+
import type {SidecarType} from './sidecar.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* The **remote merged-work-branch reaper** — the cross-machine COUNTERPART of the
|
|
@@ -9,13 +10,15 @@ import {parseWorkBranchRef} from './slug-namespace.js';
|
|
|
9
10
|
* the arbiter after their propose-mode PR has MERGED.
|
|
10
11
|
*
|
|
11
12
|
* The safety lynchpin is the SAME provably-merged predicate the worktree reaper
|
|
12
|
-
* uses (`gc.ts` `
|
|
13
|
-
* `work/<slug>` branch is reapable **iff**
|
|
14
|
-
* `git merge-base --is-ancestor <tip> <arbiter>/main`
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
13
|
+
* uses (`gc.ts` `isProvablyMergedForReap`, REUSED here, never a second one): a
|
|
14
|
+
* remote `work/<slug>` branch is reapable **iff** it is provably on
|
|
15
|
+
* `<arbiter>/main` — EITHER `git merge-base --is-ancestor <tip> <arbiter>/main`
|
|
16
|
+
* (fast path) OR the squash-aware fallback (durable done/dropped record on main
|
|
17
|
+
* AND branch carries nothing main lacks). A merely-pushed-but-unmerged branch
|
|
18
|
+
* (an in-flight, kept-for-continue recovery point) has no terminal record on
|
|
19
|
+
* main AND is not an ancestor, so the predicate AUTOMATICALLY excludes it — the
|
|
20
|
+
* never-delete-the-in-flight-branch invariant (ADR §4 deletion-safety) stays
|
|
21
|
+
* absolute. Deletion of a fully-merged ref needs NO force, so this NEVER
|
|
19
22
|
* `--force`s.
|
|
20
23
|
*
|
|
21
24
|
* It is provider-AGNOSTIC plain git (`git ls-remote` to enumerate, `git push
|
|
@@ -101,8 +104,9 @@ export interface SweepRemoteBranchesResult {
|
|
|
101
104
|
* 2. Fetch `<arbiter>/main` into a local tracking ref so the ancestor check
|
|
102
105
|
* resolves the descendant LOCALLY; fetch each candidate tip object too (so
|
|
103
106
|
* `merge-base` can read it) — best-effort, into a scratch ref.
|
|
104
|
-
* 3. For each branch
|
|
105
|
-
*
|
|
107
|
+
* 3. For each branch that is provably merged for reap (fast-path ancestor
|
|
108
|
+
* OR squash-aware fallback — {@link isProvablyMergedForReap}) ⇒ delete
|
|
109
|
+
* via `git push <arbiter> --delete <branch>`; else retain with a reason.
|
|
106
110
|
*/
|
|
107
111
|
export function sweepRemoteMergedBranches(
|
|
108
112
|
input: SweepRemoteBranchesInput,
|
|
@@ -126,12 +130,32 @@ export function sweepRemoteMergedBranches(
|
|
|
126
130
|
retain(retained, note, branch, tip, 'main-unresolved');
|
|
127
131
|
continue;
|
|
128
132
|
}
|
|
129
|
-
// Make the candidate tip OBJECT readable locally so `merge-base`
|
|
130
|
-
// (ls-remote gave us the sha, but the
|
|
133
|
+
// Make the candidate tip OBJECT readable locally so `merge-base` /
|
|
134
|
+
// `diff` / `cherry` can read it (ls-remote gave us the sha, but the
|
|
135
|
+
// object may not be in the local repo).
|
|
131
136
|
fetchScratch(input.cwd, input.arbiter, branch, env);
|
|
132
137
|
|
|
133
|
-
|
|
134
|
-
|
|
138
|
+
const parsed = parseWorkBranchRef(branch);
|
|
139
|
+
if (parsed === undefined) {
|
|
140
|
+
// Guarded above by `listRemoteWorkBranches` (which only enumerates
|
|
141
|
+
// parseable heads), but keep a defensive belt: without a slug the
|
|
142
|
+
// squash-aware fallback has no anchor ⇒ retain.
|
|
143
|
+
retain(retained, note, branch, tip, 'not-merged');
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (
|
|
148
|
+
!isProvablyMergedForReap({
|
|
149
|
+
cwd: input.cwd,
|
|
150
|
+
tip,
|
|
151
|
+
arbiterMain: mainRef,
|
|
152
|
+
namespace: parsed.namespace as SidecarType,
|
|
153
|
+
slug: parsed.slug,
|
|
154
|
+
env,
|
|
155
|
+
})
|
|
156
|
+
) {
|
|
157
|
+
// NOT provably merged (neither ancestor nor squash-aware equivalent)
|
|
158
|
+
// ⇒ still in-flight ⇒ NEVER delete (the invariant).
|
|
135
159
|
retain(retained, note, branch, tip, 'not-merged');
|
|
136
160
|
continue;
|
|
137
161
|
}
|
package/src/recover-isolated.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type {ReviewProvider} from './integrator.js';
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* **`complete --isolated <slug>` — FINISH an already-committed, already-done-moved
|
|
14
|
-
* STRANDED isolated worktree** (
|
|
14
|
+
* STRANDED isolated worktree** (spec `ledger-integrity` story 6, the
|
|
15
15
|
* `finish-already-committed-branch` task). The LOCATE-EXISTING inverse of
|
|
16
16
|
* `do --isolated` (which CREATES a worktree): it resolves the slug's RETAINED job
|
|
17
17
|
* worktree via the existing arbiter-URL-keyed naming
|
|
@@ -57,6 +57,18 @@ export interface RecoverIsolatedOptions {
|
|
|
57
57
|
integration?: IntegrationMode;
|
|
58
58
|
/** Suppress the PR on the propose path (push the branch, open no review request). */
|
|
59
59
|
noPR?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* **The cross-job merge-serialiser CAS-retry cap** (config `mergeRetries`, spec
|
|
62
|
+
* `land-time-reverify-and-parallel-merge-ceiling` Story 5 / Applied Answer q1
|
|
63
|
+
* (a)). Threaded VERBATIM into {@link performIntegration} so a wide-matrix CI's
|
|
64
|
+
* raised cap actually reaches the cross-job land queue on the isolated-recovery
|
|
65
|
+
* path too (task `thread-merge-retries-cross-task-and-ratify-default`). Resolved
|
|
66
|
+
* ONCE at the CLI (the `complete --isolated` command) through the SAME
|
|
67
|
+
* gate-family precedence chain the plain `complete` path uses (flag > env >
|
|
68
|
+
* per-repo > global > default). Unset ⇒ the engine's `DEFAULT_MERGE_RETRIES =
|
|
69
|
+
* 1000` (byte-for-byte unchanged).
|
|
70
|
+
*/
|
|
71
|
+
mergeRetries?: number;
|
|
60
72
|
/** Optional fully-formed provider used verbatim (test/embedding seam). */
|
|
61
73
|
providerInstance?: ReviewProvider;
|
|
62
74
|
/** Optional injectable PR opener (legacy bridge); used in `propose` mode. */
|
|
@@ -177,6 +189,11 @@ export async function performRecoverIsolated(
|
|
|
177
189
|
recovering: false,
|
|
178
190
|
committedRecovery: true,
|
|
179
191
|
mode: options.integration ?? 'propose',
|
|
192
|
+
// The cross-job merge-serialiser CAS-retry cap (config `mergeRetries`) — the
|
|
193
|
+
// git-alone floor of the cross-job land queue, resolved through the gate-
|
|
194
|
+
// family precedence chain in the CLI and threaded here so the isolated-
|
|
195
|
+
// recovery land tail respects the per-repo cap.
|
|
196
|
+
mergeRetries: options.mergeRetries,
|
|
180
197
|
noPR: options.noPR,
|
|
181
198
|
providerInstance: options.providerInstance,
|
|
182
199
|
openPr: options.openPr,
|