dorfl 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advance-ci-template.d.ts +73 -0
- package/dist/advance-ci-template.d.ts.map +1 -0
- package/dist/advance-ci-template.js +104 -0
- package/dist/advance-ci-template.js.map +1 -0
- package/dist/advance-classify.d.ts +132 -0
- package/dist/advance-classify.d.ts.map +1 -0
- package/dist/advance-classify.js +120 -0
- package/dist/advance-classify.js.map +1 -0
- package/dist/advance-drivers.d.ts +182 -0
- package/dist/advance-drivers.d.ts.map +1 -0
- package/dist/advance-drivers.js +231 -0
- package/dist/advance-drivers.js.map +1 -0
- package/dist/advance-isolated.d.ts +156 -0
- package/dist/advance-isolated.d.ts.map +1 -0
- package/dist/advance-isolated.js +256 -0
- package/dist/advance-isolated.js.map +1 -0
- package/dist/advance-lifecycle-template.d.ts +107 -0
- package/dist/advance-lifecycle-template.d.ts.map +1 -0
- package/dist/advance-lifecycle-template.js +668 -0
- package/dist/advance-lifecycle-template.js.map +1 -0
- package/dist/advance-loop-driver.d.ts +325 -0
- package/dist/advance-loop-driver.d.ts.map +1 -0
- package/dist/advance-loop-driver.js +437 -0
- package/dist/advance-loop-driver.js.map +1 -0
- package/dist/advance-treeless-publish.d.ts +108 -0
- package/dist/advance-treeless-publish.d.ts.map +1 -0
- package/dist/advance-treeless-publish.js +71 -0
- package/dist/advance-treeless-publish.js.map +1 -0
- package/dist/advance.d.ts +340 -0
- package/dist/advance.d.ts.map +1 -0
- package/dist/advance.js +1122 -0
- package/dist/advance.js.map +1 -0
- package/dist/advancing-lock.d.ts +294 -0
- package/dist/advancing-lock.d.ts.map +1 -0
- package/dist/advancing-lock.js +594 -0
- package/dist/advancing-lock.js.map +1 -0
- package/dist/agent-launch.d.ts +79 -0
- package/dist/agent-launch.d.ts.map +1 -0
- package/dist/agent-launch.js +61 -0
- package/dist/agent-launch.js.map +1 -0
- package/dist/agent-stop.d.ts +149 -0
- package/dist/agent-stop.d.ts.map +1 -0
- package/dist/agent-stop.js +307 -0
- package/dist/agent-stop.js.map +1 -0
- package/dist/apply-decide.d.ts +127 -0
- package/dist/apply-decide.d.ts.map +1 -0
- package/dist/apply-decide.js +176 -0
- package/dist/apply-decide.js.map +1 -0
- package/dist/apply-merge-action.d.ts +206 -0
- package/dist/apply-merge-action.d.ts.map +1 -0
- package/dist/apply-merge-action.js +307 -0
- package/dist/apply-merge-action.js.map +1 -0
- package/dist/apply-persist.d.ts +174 -0
- package/dist/apply-persist.d.ts.map +1 -0
- package/dist/apply-persist.js +359 -0
- package/dist/apply-persist.js.map +1 -0
- package/dist/arbiter.d.ts +120 -0
- package/dist/arbiter.d.ts.map +1 -0
- package/dist/arbiter.js +255 -0
- package/dist/arbiter.js.map +1 -0
- package/dist/brand.d.ts +70 -0
- package/dist/brand.d.ts.map +1 -0
- package/dist/brand.js +84 -0
- package/dist/brand.js.map +1 -0
- package/dist/buildable-body.d.ts +132 -0
- package/dist/buildable-body.d.ts.map +1 -0
- package/dist/buildable-body.js +131 -0
- package/dist/buildable-body.js.map +1 -0
- package/dist/categorise.d.ts +66 -0
- package/dist/categorise.d.ts.map +1 -0
- package/dist/categorise.js +106 -0
- package/dist/categorise.js.map +1 -0
- package/dist/claim-cas.d.ts +117 -0
- package/dist/claim-cas.d.ts.map +1 -0
- package/dist/claim-cas.js +312 -0
- package/dist/claim-cas.js.map +1 -0
- package/dist/cli-spinner.d.ts +112 -0
- package/dist/cli-spinner.d.ts.map +1 -0
- package/dist/cli-spinner.js +157 -0
- package/dist/cli-spinner.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +3094 -0
- package/dist/cli.js.map +1 -0
- package/dist/close-job-template.d.ts +70 -0
- package/dist/close-job-template.d.ts.map +1 -0
- package/dist/close-job-template.js +180 -0
- package/dist/close-job-template.js.map +1 -0
- package/dist/close-job.d.ts +95 -0
- package/dist/close-job.d.ts.map +1 -0
- package/dist/close-job.js +226 -0
- package/dist/close-job.js.map +1 -0
- package/dist/complete.d.ts +361 -0
- package/dist/complete.d.ts.map +1 -0
- package/dist/complete.js +885 -0
- package/dist/complete.js.map +1 -0
- package/dist/concurrency.d.ts +68 -0
- package/dist/concurrency.d.ts.map +1 -0
- package/dist/concurrency.js +112 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/config-override.d.ts +76 -0
- package/dist/config-override.d.ts.map +1 -0
- package/dist/config-override.js +50 -0
- package/dist/config-override.js.map +1 -0
- package/dist/config.d.ts +668 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +241 -0
- package/dist/config.js.map +1 -0
- package/dist/continue-branch.d.ts +249 -0
- package/dist/continue-branch.d.ts.map +1 -0
- package/dist/continue-branch.js +389 -0
- package/dist/continue-branch.js.map +1 -0
- package/dist/cwd-section.d.ts +186 -0
- package/dist/cwd-section.d.ts.map +1 -0
- package/dist/cwd-section.js +209 -0
- package/dist/cwd-section.js.map +1 -0
- package/dist/decision-engine.d.ts +170 -0
- package/dist/decision-engine.d.ts.map +1 -0
- package/dist/decision-engine.js +136 -0
- package/dist/decision-engine.js.map +1 -0
- package/dist/detect.d.ts +17 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +118 -0
- package/dist/detect.js.map +1 -0
- package/dist/do-autopick.d.ts +85 -0
- package/dist/do-autopick.d.ts.map +1 -0
- package/dist/do-autopick.js +112 -0
- package/dist/do-autopick.js.map +1 -0
- package/dist/do-config.d.ts +312 -0
- package/dist/do-config.d.ts.map +1 -0
- package/dist/do-config.js +358 -0
- package/dist/do-config.js.map +1 -0
- package/dist/do-remote-auto.d.ts +75 -0
- package/dist/do-remote-auto.d.ts.map +1 -0
- package/dist/do-remote-auto.js +111 -0
- package/dist/do-remote-auto.js.map +1 -0
- package/dist/do.d.ts +621 -0
- package/dist/do.d.ts.map +1 -0
- package/dist/do.js +1882 -0
- package/dist/do.js.map +1 -0
- package/dist/drop-source.d.ts +96 -0
- package/dist/drop-source.d.ts.map +1 -0
- package/dist/drop-source.js +91 -0
- package/dist/drop-source.js.map +1 -0
- package/dist/eligibility.d.ts +46 -0
- package/dist/eligibility.d.ts.map +1 -0
- package/dist/eligibility.js +34 -0
- package/dist/eligibility.js.map +1 -0
- package/dist/env-config.d.ts +51 -0
- package/dist/env-config.d.ts.map +1 -0
- package/dist/env-config.js +272 -0
- package/dist/env-config.js.map +1 -0
- package/dist/failure-cause.d.ts +70 -0
- package/dist/failure-cause.d.ts.map +1 -0
- package/dist/failure-cause.js +126 -0
- package/dist/failure-cause.js.map +1 -0
- package/dist/format.d.ts +43 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +256 -0
- package/dist/format.js.map +1 -0
- package/dist/frontmatter.d.ts +215 -0
- package/dist/frontmatter.d.ts.map +1 -0
- package/dist/frontmatter.js +345 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/gate-readiness.d.ts +84 -0
- package/dist/gate-readiness.d.ts.map +1 -0
- package/dist/gate-readiness.js +103 -0
- package/dist/gate-readiness.js.map +1 -0
- package/dist/gc.d.ts +165 -0
- package/dist/gc.d.ts.map +1 -0
- package/dist/gc.js +313 -0
- package/dist/gc.js.map +1 -0
- package/dist/gh-failure.d.ts +42 -0
- package/dist/gh-failure.d.ts.map +1 -0
- package/dist/gh-failure.js +49 -0
- package/dist/gh-failure.js.map +1 -0
- package/dist/git.d.ts +75 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +130 -0
- package/dist/git.js.map +1 -0
- package/dist/github.d.ts +187 -0
- package/dist/github.d.ts.map +1 -0
- package/dist/github.js +343 -0
- package/dist/github.js.map +1 -0
- package/dist/harness.d.ts +242 -0
- package/dist/harness.d.ts.map +1 -0
- package/dist/harness.js +157 -0
- package/dist/harness.js.map +1 -0
- package/dist/identity.d.ts +167 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +231 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +147 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/install-ci-branch-protection.d.ts +147 -0
- package/dist/install-ci-branch-protection.d.ts.map +1 -0
- package/dist/install-ci-branch-protection.js +166 -0
- package/dist/install-ci-branch-protection.js.map +1 -0
- package/dist/install-ci-capabilities/advance-lifecycle.d.ts +15 -0
- package/dist/install-ci-capabilities/advance-lifecycle.d.ts.map +1 -0
- package/dist/install-ci-capabilities/advance-lifecycle.js +28 -0
- package/dist/install-ci-capabilities/advance-lifecycle.js.map +1 -0
- package/dist/install-ci-capabilities/close-job.d.ts +13 -0
- package/dist/install-ci-capabilities/close-job.d.ts.map +1 -0
- package/dist/install-ci-capabilities/close-job.js +26 -0
- package/dist/install-ci-capabilities/close-job.js.map +1 -0
- package/dist/install-ci-capabilities/example-noop.d.ts +16 -0
- package/dist/install-ci-capabilities/example-noop.d.ts.map +1 -0
- package/dist/install-ci-capabilities/example-noop.js +23 -0
- package/dist/install-ci-capabilities/example-noop.js.map +1 -0
- package/dist/install-ci-capabilities/intake.d.ts +15 -0
- package/dist/install-ci-capabilities/intake.d.ts.map +1 -0
- package/dist/install-ci-capabilities/intake.js +28 -0
- package/dist/install-ci-capabilities/intake.js.map +1 -0
- package/dist/install-ci-capabilities/verify.d.ts +14 -0
- package/dist/install-ci-capabilities/verify.d.ts.map +1 -0
- package/dist/install-ci-capabilities/verify.js +27 -0
- package/dist/install-ci-capabilities/verify.js.map +1 -0
- package/dist/install-ci-core.d.ts +446 -0
- package/dist/install-ci-core.d.ts.map +1 -0
- package/dist/install-ci-core.js +760 -0
- package/dist/install-ci-core.js.map +1 -0
- package/dist/install-ci-github.d.ts +167 -0
- package/dist/install-ci-github.d.ts.map +1 -0
- package/dist/install-ci-github.js +315 -0
- package/dist/install-ci-github.js.map +1 -0
- package/dist/install-ci.d.ts +105 -0
- package/dist/install-ci.d.ts.map +1 -0
- package/dist/install-ci.js +363 -0
- package/dist/install-ci.js.map +1 -0
- package/dist/intake-event.d.ts +88 -0
- package/dist/intake-event.d.ts.map +1 -0
- package/dist/intake-event.js +66 -0
- package/dist/intake-event.js.map +1 -0
- package/dist/intake-marker.d.ts +95 -0
- package/dist/intake-marker.d.ts.map +1 -0
- package/dist/intake-marker.js +127 -0
- package/dist/intake-marker.js.map +1 -0
- package/dist/intake-triage.d.ts +48 -0
- package/dist/intake-triage.d.ts.map +1 -0
- package/dist/intake-triage.js +95 -0
- package/dist/intake-triage.js.map +1 -0
- package/dist/intake-trigger-template.d.ts +185 -0
- package/dist/intake-trigger-template.d.ts.map +1 -0
- package/dist/intake-trigger-template.js +449 -0
- package/dist/intake-trigger-template.js.map +1 -0
- package/dist/intake.d.ts +569 -0
- package/dist/intake.d.ts.map +1 -0
- package/dist/intake.js +1628 -0
- package/dist/intake.js.map +1 -0
- package/dist/integration-core.d.ts +539 -0
- package/dist/integration-core.d.ts.map +1 -0
- package/dist/integration-core.js +2195 -0
- package/dist/integration-core.js.map +1 -0
- package/dist/integrator.d.ts +343 -0
- package/dist/integrator.d.ts.map +1 -0
- package/dist/integrator.js +400 -0
- package/dist/integrator.js.map +1 -0
- package/dist/isolation.d.ts +219 -0
- package/dist/isolation.d.ts.map +1 -0
- package/dist/isolation.js +261 -0
- package/dist/isolation.js.map +1 -0
- package/dist/issue-provider.d.ts +349 -0
- package/dist/issue-provider.d.ts.map +1 -0
- package/dist/issue-provider.js +360 -0
- package/dist/issue-provider.js.map +1 -0
- package/dist/item-lock.d.ts +626 -0
- package/dist/item-lock.d.ts.map +1 -0
- package/dist/item-lock.js +1381 -0
- package/dist/item-lock.js.map +1 -0
- package/dist/item-path.d.ts +49 -0
- package/dist/item-path.d.ts.map +1 -0
- package/dist/item-path.js +66 -0
- package/dist/item-path.js.map +1 -0
- package/dist/ledger-lint.d.ts +129 -0
- package/dist/ledger-lint.d.ts.map +1 -0
- package/dist/ledger-lint.js +249 -0
- package/dist/ledger-lint.js.map +1 -0
- package/dist/ledger-read.d.ts +357 -0
- package/dist/ledger-read.d.ts.map +1 -0
- package/dist/ledger-read.js +442 -0
- package/dist/ledger-read.js.map +1 -0
- package/dist/ledger-write.d.ts +330 -0
- package/dist/ledger-write.d.ts.map +1 -0
- package/dist/ledger-write.js +411 -0
- package/dist/ledger-write.js.map +1 -0
- package/dist/lifecycle-gather.d.ts +30 -0
- package/dist/lifecycle-gather.d.ts.map +1 -0
- package/dist/lifecycle-gather.js +205 -0
- package/dist/lifecycle-gather.js.map +1 -0
- package/dist/lifecycle-pools.d.ts +180 -0
- package/dist/lifecycle-pools.d.ts.map +1 -0
- package/dist/lifecycle-pools.js +78 -0
- package/dist/lifecycle-pools.js.map +1 -0
- package/dist/merge-question-surfacer.d.ts +166 -0
- package/dist/merge-question-surfacer.d.ts.map +1 -0
- package/dist/merge-question-surfacer.js +297 -0
- package/dist/merge-question-surfacer.js.map +1 -0
- package/dist/mint-adr.d.ts +126 -0
- package/dist/mint-adr.d.ts.map +1 -0
- package/dist/mint-adr.js +257 -0
- package/dist/mint-adr.js.map +1 -0
- package/dist/mirror-pool-scan.d.ts +125 -0
- package/dist/mirror-pool-scan.d.ts.map +1 -0
- package/dist/mirror-pool-scan.js +104 -0
- package/dist/mirror-pool-scan.js.map +1 -0
- package/dist/needs-attention.d.ts +341 -0
- package/dist/needs-attention.d.ts.map +1 -0
- package/dist/needs-attention.js +900 -0
- package/dist/needs-attention.js.map +1 -0
- package/dist/orphan-sidecar.d.ts +79 -0
- package/dist/orphan-sidecar.d.ts.map +1 -0
- package/dist/orphan-sidecar.js +71 -0
- package/dist/orphan-sidecar.js.map +1 -0
- package/dist/output.d.ts +48 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +66 -0
- package/dist/output.js.map +1 -0
- package/dist/pi-harness.d.ts +179 -0
- package/dist/pi-harness.d.ts.map +1 -0
- package/dist/pi-harness.js +342 -0
- package/dist/pi-harness.js.map +1 -0
- package/dist/placement.d.ts +99 -0
- package/dist/placement.d.ts.map +1 -0
- package/dist/placement.js +67 -0
- package/dist/placement.js.map +1 -0
- package/dist/prd-to-spec.d.ts +315 -0
- package/dist/prd-to-spec.d.ts.map +1 -0
- package/dist/prd-to-spec.js +684 -0
- package/dist/prd-to-spec.js.map +1 -0
- package/dist/prepare.d.ts +121 -0
- package/dist/prepare.d.ts.map +1 -0
- package/dist/prepare.js +140 -0
- package/dist/prepare.js.map +1 -0
- package/dist/prompt.d.ts +360 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +499 -0
- package/dist/prompt.js.map +1 -0
- package/dist/protocol/ADR-FORMAT.md +47 -0
- package/dist/protocol/CLAIM-PROTOCOL.md +217 -0
- package/dist/protocol/REVIEW-PROTOCOL.md +119 -0
- package/dist/protocol/SURFACE-PROTOCOL.md +121 -0
- package/dist/protocol/TASKING-PROTOCOL.md +122 -0
- package/dist/protocol/WORK-CONTRACT.md +276 -0
- package/dist/protocol/spec-template.md +71 -0
- package/dist/protocol/task-template.md +65 -0
- package/dist/readiness.d.ts +66 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +36 -0
- package/dist/readiness.js.map +1 -0
- package/dist/reap-branches.d.ts +102 -0
- package/dist/reap-branches.d.ts.map +1 -0
- package/dist/reap-branches.js +149 -0
- package/dist/reap-branches.js.map +1 -0
- package/dist/recover-isolated.d.ts +72 -0
- package/dist/recover-isolated.d.ts.map +1 -0
- package/dist/recover-isolated.js +188 -0
- package/dist/recover-isolated.js.map +1 -0
- package/dist/registry.d.ts +172 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +296 -0
- package/dist/registry.js.map +1 -0
- package/dist/repo-config.d.ts +201 -0
- package/dist/repo-config.d.ts.map +1 -0
- package/dist/repo-config.js +414 -0
- package/dist/repo-config.js.map +1 -0
- package/dist/repo-key.d.ts +20 -0
- package/dist/repo-key.d.ts.map +1 -0
- package/dist/repo-key.js +68 -0
- package/dist/repo-key.js.map +1 -0
- package/dist/repo-mirror.d.ts +177 -0
- package/dist/repo-mirror.d.ts.map +1 -0
- package/dist/repo-mirror.js +271 -0
- package/dist/repo-mirror.js.map +1 -0
- package/dist/retry-backoff.d.ts +90 -0
- package/dist/retry-backoff.d.ts.map +1 -0
- package/dist/retry-backoff.js +98 -0
- package/dist/retry-backoff.js.map +1 -0
- package/dist/review-gate.d.ts +173 -0
- package/dist/review-gate.d.ts.map +1 -0
- package/dist/review-gate.js +261 -0
- package/dist/review-gate.js.map +1 -0
- package/dist/review-verdict.d.ts +149 -0
- package/dist/review-verdict.d.ts.map +1 -0
- package/dist/review-verdict.js +332 -0
- package/dist/review-verdict.js.map +1 -0
- package/dist/run.d.ts +221 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +963 -0
- package/dist/run.js.map +1 -0
- package/dist/scan.d.ts +308 -0
- package/dist/scan.d.ts.map +1 -0
- package/dist/scan.js +374 -0
- package/dist/scan.js.map +1 -0
- package/dist/select-order.d.ts +75 -0
- package/dist/select-order.d.ts.map +1 -0
- package/dist/select-order.js +108 -0
- package/dist/select-order.js.map +1 -0
- package/dist/select-priority.d.ts +188 -0
- package/dist/select-priority.d.ts.map +1 -0
- package/dist/select-priority.js +80 -0
- package/dist/select-priority.js.map +1 -0
- package/dist/select.d.ts +25 -0
- package/dist/select.d.ts.map +1 -0
- package/dist/select.js +43 -0
- package/dist/select.js.map +1 -0
- package/dist/session-path.d.ts +36 -0
- package/dist/session-path.d.ts.map +1 -0
- package/dist/session-path.js +129 -0
- package/dist/session-path.js.map +1 -0
- package/dist/sidecar-apply.d.ts +83 -0
- package/dist/sidecar-apply.d.ts.map +1 -0
- package/dist/sidecar-apply.js +111 -0
- package/dist/sidecar-apply.js.map +1 -0
- package/dist/sidecar.d.ts +245 -0
- package/dist/sidecar.d.ts.map +1 -0
- package/dist/sidecar.js +481 -0
- package/dist/sidecar.js.map +1 -0
- package/dist/slug-namespace.d.ts +204 -0
- package/dist/slug-namespace.d.ts.map +1 -0
- package/dist/slug-namespace.js +229 -0
- package/dist/slug-namespace.js.map +1 -0
- package/dist/spec-complete.d.ts +44 -0
- package/dist/spec-complete.d.ts.map +1 -0
- package/dist/spec-complete.js +69 -0
- package/dist/spec-complete.js.map +1 -0
- package/dist/start.d.ts +97 -0
- package/dist/start.d.ts.map +1 -0
- package/dist/start.js +633 -0
- package/dist/start.js.map +1 -0
- package/dist/status.d.ts +199 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +228 -0
- package/dist/status.js.map +1 -0
- package/dist/surface-gate.d.ts +162 -0
- package/dist/surface-gate.d.ts.map +1 -0
- package/dist/surface-gate.js +206 -0
- package/dist/surface-gate.js.map +1 -0
- package/dist/surface-persist.d.ts +86 -0
- package/dist/surface-persist.d.ts.map +1 -0
- package/dist/surface-persist.js +129 -0
- package/dist/surface-persist.js.map +1 -0
- package/dist/tasker-review-loop.d.ts +249 -0
- package/dist/tasker-review-loop.d.ts.map +1 -0
- package/dist/tasker-review-loop.js +369 -0
- package/dist/tasker-review-loop.js.map +1 -0
- package/dist/tasking-eligibility.d.ts +74 -0
- package/dist/tasking-eligibility.d.ts.map +1 -0
- package/dist/tasking-eligibility.js +52 -0
- package/dist/tasking-eligibility.js.map +1 -0
- package/dist/tasking-lock.d.ts +111 -0
- package/dist/tasking-lock.d.ts.map +1 -0
- package/dist/tasking-lock.js +256 -0
- package/dist/tasking-lock.js.map +1 -0
- package/dist/tasking.d.ts +275 -0
- package/dist/tasking.d.ts.map +1 -0
- package/dist/tasking.js +952 -0
- package/dist/tasking.js.map +1 -0
- package/dist/triage-gate.d.ts +127 -0
- package/dist/triage-gate.d.ts.map +1 -0
- package/dist/triage-gate.js +139 -0
- package/dist/triage-gate.js.map +1 -0
- package/dist/triage-persist.d.ts +163 -0
- package/dist/triage-persist.d.ts.map +1 -0
- package/dist/triage-persist.js +387 -0
- package/dist/triage-persist.js.map +1 -0
- package/dist/verdict-json.d.ts +32 -0
- package/dist/verdict-json.d.ts.map +1 -0
- package/dist/verdict-json.js +74 -0
- package/dist/verdict-json.js.map +1 -0
- package/dist/verify-workflow-template.d.ts +60 -0
- package/dist/verify-workflow-template.d.ts.map +1 -0
- package/dist/verify-workflow-template.js +126 -0
- package/dist/verify-workflow-template.js.map +1 -0
- package/dist/verify.d.ts +60 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +62 -0
- package/dist/verify.js.map +1 -0
- package/dist/watch-session.d.ts +112 -0
- package/dist/watch-session.d.ts.map +1 -0
- package/dist/watch-session.js +347 -0
- package/dist/watch-session.js.map +1 -0
- package/dist/work-layout.d.ts +198 -0
- package/dist/work-layout.d.ts.map +1 -0
- package/dist/work-layout.js +217 -0
- package/dist/work-layout.js.map +1 -0
- package/dist/work-on.d.ts +154 -0
- package/dist/work-on.d.ts.map +1 -0
- package/dist/work-on.js +387 -0
- package/dist/work-on.js.map +1 -0
- package/dist/workspace.d.ts +224 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +325 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +46 -2
- package/src/advance-ci-template.ts +203 -0
- package/src/advance-classify.ts +197 -0
- package/src/advance-drivers.ts +414 -0
- package/src/advance-isolated.ts +432 -0
- package/src/advance-lifecycle-template.ts +791 -0
- package/src/advance-loop-driver.ts +745 -0
- package/src/advance-treeless-publish.ts +177 -0
- package/src/advance.ts +1564 -0
- package/src/advancing-lock.ts +988 -0
- package/src/agent-launch.ts +137 -0
- package/src/agent-stop.ts +361 -0
- package/src/apply-decide.ts +242 -0
- package/src/apply-merge-action.ts +502 -0
- package/src/apply-persist.ts +518 -0
- package/src/arbiter.ts +372 -0
- package/src/brand.ts +111 -0
- package/src/buildable-body.ts +196 -0
- package/src/categorise.ts +158 -0
- package/src/claim-cas.ts +513 -0
- package/src/cli-spinner.ts +225 -0
- package/src/cli.ts +4369 -0
- package/src/close-job-template.ts +236 -0
- package/src/close-job.ts +319 -0
- package/src/complete.ts +1379 -0
- package/src/concurrency.ts +151 -0
- package/src/config-override.ts +116 -0
- package/src/config.ts +883 -0
- package/src/continue-branch.ts +542 -0
- package/src/cwd-section.ts +392 -0
- package/src/decision-engine.ts +272 -0
- package/src/detect.ts +124 -0
- package/src/do-autopick.ts +223 -0
- package/src/do-config.ts +589 -0
- package/src/do-remote-auto.ts +197 -0
- package/src/do.ts +2623 -0
- package/src/drop-source.ts +194 -0
- package/src/eligibility.ts +79 -0
- package/src/env-config.ts +305 -0
- package/src/failure-cause.ts +142 -0
- package/src/format.ts +313 -0
- package/src/frontmatter.ts +485 -0
- package/src/gate-readiness.ts +147 -0
- package/src/gc.ts +510 -0
- package/src/gh-failure.ts +53 -0
- package/src/git.ts +186 -0
- package/src/github.ts +468 -0
- package/src/harness.ts +355 -0
- package/src/identity.ts +322 -0
- package/src/index.ts +785 -0
- package/src/install-ci-branch-protection.ts +255 -0
- package/src/install-ci-capabilities/advance-lifecycle.ts +34 -0
- package/src/install-ci-capabilities/close-job.ts +32 -0
- package/src/install-ci-capabilities/example-noop.ts +24 -0
- package/src/install-ci-capabilities/intake.ts +34 -0
- package/src/install-ci-capabilities/verify.ts +33 -0
- package/src/install-ci-core.ts +1088 -0
- package/src/install-ci-github.ts +376 -0
- package/src/install-ci.ts +552 -0
- package/src/intake-event.ts +102 -0
- package/src/intake-marker.ts +195 -0
- package/src/intake-triage.ts +138 -0
- package/src/intake-trigger-template.ts +591 -0
- package/src/intake.ts +2445 -0
- package/src/integration-core.ts +3065 -0
- package/src/integrator.ts +771 -0
- package/src/isolation.ts +484 -0
- package/src/issue-provider.ts +733 -0
- package/src/item-lock.ts +1858 -0
- package/src/item-path.ts +75 -0
- package/src/ledger-lint.ts +332 -0
- package/src/ledger-read.ts +924 -0
- package/src/ledger-write.ts +865 -0
- package/src/lifecycle-gather.ts +298 -0
- package/src/lifecycle-pools.ts +250 -0
- package/src/merge-question-surfacer.ts +496 -0
- package/src/mint-adr.ts +362 -0
- package/src/mirror-pool-scan.ts +240 -0
- package/src/needs-attention.ts +1506 -0
- package/src/orphan-sidecar.ts +150 -0
- package/src/output.ts +89 -0
- package/src/pi-harness.ts +403 -0
- package/src/placement.ts +131 -0
- package/src/prd-to-spec.ts +1023 -0
- package/src/prepare.ts +230 -0
- package/src/prompt.ts +760 -0
- package/src/readiness.ts +98 -0
- package/src/reap-branches.ts +278 -0
- package/src/recover-isolated.ts +276 -0
- package/src/registry.ts +475 -0
- package/src/repo-config.ts +550 -0
- package/src/repo-key.ts +74 -0
- package/src/repo-mirror.ts +367 -0
- package/src/retry-backoff.ts +130 -0
- package/src/review-gate.ts +389 -0
- package/src/review-verdict.ts +422 -0
- package/src/run.ts +1430 -0
- package/src/scan.ts +611 -0
- package/src/select-order.ts +143 -0
- package/src/select-priority.ts +266 -0
- package/src/select.ts +62 -0
- package/src/session-path.ts +153 -0
- package/src/sidecar-apply.ts +216 -0
- package/src/sidecar.ts +700 -0
- package/src/slug-namespace.ts +367 -0
- package/src/spec-complete.ts +118 -0
- package/src/start.ts +974 -0
- package/src/status.ts +441 -0
- package/src/surface-gate.ts +337 -0
- package/src/surface-persist.ts +241 -0
- package/src/tasker-review-loop.ts +671 -0
- package/src/tasking-eligibility.ts +114 -0
- package/src/tasking-lock.ts +416 -0
- package/src/tasking.ts +1438 -0
- package/src/triage-gate.ts +248 -0
- package/src/triage-persist.ts +570 -0
- package/src/verdict-json.ts +73 -0
- package/src/verify-workflow-template.ts +159 -0
- package/src/verify.ts +123 -0
- package/src/watch-session.ts +397 -0
- package/src/work-layout.ts +262 -0
- package/src/work-on.ts +660 -0
- package/src/workspace.ts +502 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import {type Harness, type LaunchResult} from './harness.js';
|
|
2
|
+
import {PiHarness} from './pi-harness.js';
|
|
3
|
+
import {SessionTailer} from './watch-session.js';
|
|
4
|
+
import {generateSessionPath} from './session-path.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The SHARED launch-with-optional-watch helper (task `watch-review-session`).
|
|
8
|
+
*
|
|
9
|
+
* This is the ONE codepath both the BUILD launch (`do.ts`'s `runDoAgent`) and the
|
|
10
|
+
* REVIEW launch (`review-gate.ts`'s `harnessReviewGate`) use to run an agent
|
|
11
|
+
* through the harness seam, optionally tailing its pi session `.jsonl` live. It
|
|
12
|
+
* was EXTRACTED from `do.ts` (where the watch wiring — `generateSessionPath` →
|
|
13
|
+
* `SessionTailer` → `start()` → `launchAsync` → `finally stop()`, else sync
|
|
14
|
+
* `launch` — used to live INLINE) so the review path can tail its OWN session
|
|
15
|
+
* without COPYING that block (the run/do duplication anti-pattern; copying would
|
|
16
|
+
* fork the watch wiring into a second implementation, and `run.ts` would become a
|
|
17
|
+
* third). One implementation, two callers.
|
|
18
|
+
*
|
|
19
|
+
* What it owns (the parts that were inline in `do.ts`):
|
|
20
|
+
*
|
|
21
|
+
* - **A known session path per launch**, generated up-front via
|
|
22
|
+
* {@link generateSessionPath} from `sessionId` (+ `sessionsDir`/`dir`), so the
|
|
23
|
+
* tailer follows the EXACT file (no newest-by-mtime guessing). Distinct callers
|
|
24
|
+
* pass distinct `sessionId`s (the build uses the slug; the review uses
|
|
25
|
+
* `<slug>-review`) so their sessions never collide.
|
|
26
|
+
* - **Tail when `watch` is on** (and the harness is a {@link PiHarness}): start a
|
|
27
|
+
* {@link SessionTailer} on that known path, launch NON-BLOCKING via
|
|
28
|
+
* `launchAsync`, and `finally stop()` the tailer (one final drain + the
|
|
29
|
+
* `\u2713 agent finished` line), EXACTLY as the build path did before. A non-pi
|
|
30
|
+
* harness with `watch` on falls through to the sync `launch` (the caller is
|
|
31
|
+
* responsible for rejecting `--watch` on a non-pi harness up-front, as `do`
|
|
32
|
+
* does); this helper degrades safely rather than tailing a log that does not
|
|
33
|
+
* exist.
|
|
34
|
+
* - **OFF the watch path** (or a non-pi harness): a plain synchronous
|
|
35
|
+
* `harness.launch(...)` — BYTE-IDENTICAL to the pre-extraction behaviour, so no
|
|
36
|
+
* tailer is created and the {@link LaunchResult} is unchanged.
|
|
37
|
+
*
|
|
38
|
+
* It is OBSERVABILITY ONLY: the returned {@link LaunchResult} is identical whether
|
|
39
|
+
* or not `watch` is on (the tailer is a pure reader), so it never changes a run's
|
|
40
|
+
* outcome, gate, routing, git, or exit code.
|
|
41
|
+
*/
|
|
42
|
+
export interface LaunchWithOptionalWatchInput {
|
|
43
|
+
/** The harness seam to launch through (pi enables the live tail). */
|
|
44
|
+
harness: Harness;
|
|
45
|
+
/** The working directory the agent runs in (the worktree/checkout). */
|
|
46
|
+
dir: string;
|
|
47
|
+
/** The slug being processed (for adapters that name/log per slug). */
|
|
48
|
+
slug: string;
|
|
49
|
+
/** The command the null/shell adapter shells out to (ignored by pi). */
|
|
50
|
+
command: string;
|
|
51
|
+
/** The prompt fed to the agent on stdin. */
|
|
52
|
+
prompt: string;
|
|
53
|
+
/** The model routing intent forwarded to the harness (ADR \u00a713). */
|
|
54
|
+
model?: string;
|
|
55
|
+
/**
|
|
56
|
+
* The human-readable id for the session-FILE stem (made unique per launch
|
|
57
|
+
* inside {@link generateSessionPath}). DISTINCT per caller so two launches in
|
|
58
|
+
* one run never collide: the build passes the slug; the review passes
|
|
59
|
+
* `<slug>-review`.
|
|
60
|
+
*/
|
|
61
|
+
sessionId: string;
|
|
62
|
+
/**
|
|
63
|
+
* The HOST-ONLY sessions root (resolved `config.sessionsDir`). `undefined` \u21d2
|
|
64
|
+
* pi's default per-cwd folder for {@link dir} (see {@link generateSessionPath}).
|
|
65
|
+
*/
|
|
66
|
+
sessionsDir?: string;
|
|
67
|
+
/** Tail the session `.jsonl` live (pi harness only). */
|
|
68
|
+
watch?: boolean;
|
|
69
|
+
/** Where the tailed high-signal lines are written (defaults to stderr). */
|
|
70
|
+
watchSink?: (line: string) => void;
|
|
71
|
+
/** Emit ANSI colour in the tailed lines (the caller's TTY/`NO_COLOR` decision). */
|
|
72
|
+
color?: boolean;
|
|
73
|
+
/** Environment for the child agent process. */
|
|
74
|
+
env?: NodeJS.ProcessEnv;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Launch the agent through the harness, optionally tailing its pi session log
|
|
79
|
+
* live. Returns the {@link LaunchResult} unchanged on either path (the tailer is
|
|
80
|
+
* a pure observer). See {@link LaunchWithOptionalWatchInput} for the watch-on vs
|
|
81
|
+
* watch-off behaviour (the latter is byte-identical to a plain `harness.launch`).
|
|
82
|
+
*/
|
|
83
|
+
export async function launchWithOptionalWatch(
|
|
84
|
+
input: LaunchWithOptionalWatchInput,
|
|
85
|
+
): Promise<LaunchResult> {
|
|
86
|
+
const {harness} = input;
|
|
87
|
+
|
|
88
|
+
// Generate the full pi session-FILE path ONCE here (caller-generates) so the
|
|
89
|
+
// adapter and the `--watch` tailer cannot disagree, and so the tailer knows it
|
|
90
|
+
// BEFORE pi starts (task `session-path-pi-default`). `sessionsDir` unset \u21d2
|
|
91
|
+
// pi's per-cwd default folder. The non-pi null adapter ignores `session`, but
|
|
92
|
+
// generating it unconditionally keeps ONE path for BOTH the watch and
|
|
93
|
+
// non-watch branches.
|
|
94
|
+
const session = generateSessionPath({
|
|
95
|
+
sessionsDir: input.sessionsDir,
|
|
96
|
+
cwd: input.dir,
|
|
97
|
+
id: input.sessionId,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// `--watch` (pi only): launch async + tail the KNOWN session .jsonl path
|
|
101
|
+
// concurrently. The caller is responsible for rejecting `--watch` on a non-pi
|
|
102
|
+
// harness up-front (as `do` does); a non-pi harness here falls through to the
|
|
103
|
+
// sync launch below rather than tailing a log that will never exist.
|
|
104
|
+
if (input.watch === true && harness instanceof PiHarness) {
|
|
105
|
+
const tailer = new SessionTailer({
|
|
106
|
+
sessionFile: session,
|
|
107
|
+
color: input.color ?? false,
|
|
108
|
+
sink: input.watchSink,
|
|
109
|
+
});
|
|
110
|
+
tailer.start();
|
|
111
|
+
try {
|
|
112
|
+
return await harness.launchAsync({
|
|
113
|
+
dir: input.dir,
|
|
114
|
+
slug: input.slug,
|
|
115
|
+
command: input.command,
|
|
116
|
+
prompt: input.prompt,
|
|
117
|
+
model: input.model,
|
|
118
|
+
session,
|
|
119
|
+
env: input.env,
|
|
120
|
+
});
|
|
121
|
+
} finally {
|
|
122
|
+
// Always release the tailer (one final drain) — even on a launch error —
|
|
123
|
+
// so the observer never outlives the run or leaks a handle.
|
|
124
|
+
await tailer.stop();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return harness.launch({
|
|
129
|
+
dir: input.dir,
|
|
130
|
+
slug: input.slug,
|
|
131
|
+
command: input.command,
|
|
132
|
+
prompt: input.prompt,
|
|
133
|
+
model: input.model,
|
|
134
|
+
session,
|
|
135
|
+
env: input.env,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import {runAsync} from './git.js';
|
|
2
|
+
import {JOB_RECORD_FILENAME} from './workspace.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* **The build-agent → runner REPORTING CHANNEL** (task `agent-stop-signal`).
|
|
6
|
+
*
|
|
7
|
+
* A build agent reports back to the runner on ONE channel: its FINAL OUTPUT
|
|
8
|
+
* (`LaunchResult.output`, captured as `agent.output`). This module defines the
|
|
9
|
+
* two machine-recognisable verdicts an agent can raise on that channel and the
|
|
10
|
+
* deterministic backstop the runner uses when the agent stopped without one:
|
|
11
|
+
*
|
|
12
|
+
* 1. A HARD **STOP** sentinel ({@link STOP_SENTINEL_OPEN} … {@link
|
|
13
|
+
* STOP_SENTINEL_CLOSE}): the task DRIFTED / is ambiguous / rests on a stale
|
|
14
|
+
* premise, so the agent could not build it. The runner routes the item to
|
|
15
|
+
* `work/needs-attention/` (the agent's reason VERBATIM) and SKIPS the
|
|
16
|
+
* acceptance gate + the Gate-2 review (a clean STOP is not a build that
|
|
17
|
+
* changed nothing). See {@link parseStopSentinel}.
|
|
18
|
+
* 2. A SOFT **`## Decisions`** block ({@link extractDecisionsBlock}): the agent
|
|
19
|
+
* PROCEEDED but made a non-obvious in-scope decision the task did not
|
|
20
|
+
* specify (a cross-task interaction / a new error/refusal / a user-visible
|
|
21
|
+
* default). This does NOT stop the build — it just makes the choice visible
|
|
22
|
+
* for Gate-2 + the human to ratify (it rides the same `agent.output` → PR-body
|
|
23
|
+
* path the propose-mode summary uses).
|
|
24
|
+
*
|
|
25
|
+
* The sentinel form is documented IN-BAND next to the existing "STOP and report"
|
|
26
|
+
* instruction in the CLAIM-PROTOCOL wrapper (`skills/setup/protocol/CLAIM-PROTOCOL.md`)
|
|
27
|
+
* so the agent emits the EXACT shape this module parses — the same "agent edits,
|
|
28
|
+
* runner does git" in-band discipline the rest of the protocol uses.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/** The exact opening marker line of the STOP sentinel block. */
|
|
32
|
+
export const STOP_SENTINEL_OPEN = '=== TASK-STOP ===';
|
|
33
|
+
/** The exact closing marker line of the STOP sentinel block. */
|
|
34
|
+
export const STOP_SENTINEL_CLOSE = '=== END TASK-STOP ===';
|
|
35
|
+
|
|
36
|
+
/** A parsed STOP verdict raised by the build agent on its output channel. */
|
|
37
|
+
export interface StopSentinel {
|
|
38
|
+
/**
|
|
39
|
+
* The human-readable STOP reason from INSIDE the block (the specific drift
|
|
40
|
+
* report). Recorded VERBATIM as the needs-attention reason. Trimmed; never
|
|
41
|
+
* empty (a sentinel with an empty body still yields a default reason — see
|
|
42
|
+
* {@link parseStopSentinel}).
|
|
43
|
+
*/
|
|
44
|
+
reason: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Detect the STOP sentinel in an agent's final output and extract its reason.
|
|
49
|
+
*
|
|
50
|
+
* The sentinel is a line `{@link STOP_SENTINEL_OPEN}` followed by the reason prose
|
|
51
|
+
* and a closing `{@link STOP_SENTINEL_CLOSE}` line. The markers must each be on
|
|
52
|
+
* their OWN line (leading/trailing whitespace tolerated) so a passing mention of
|
|
53
|
+
* the marker inside ordinary prose does not trip it. The agent may surround the
|
|
54
|
+
* block with other prose; we read the FIRST complete block.
|
|
55
|
+
*
|
|
56
|
+
* Returns `undefined` when no complete sentinel block is present (the common
|
|
57
|
+
* case: a normal build, a `## Decisions`-only report, or an empty result). When a
|
|
58
|
+
* block is present but its body is empty, the reason degrades to a stable default
|
|
59
|
+
* so the runner still routes honestly.
|
|
60
|
+
*/
|
|
61
|
+
export function parseStopSentinel(
|
|
62
|
+
output: string | undefined,
|
|
63
|
+
): StopSentinel | undefined {
|
|
64
|
+
if (output === undefined || output === '') {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
const lines = output.replace(/\r\n/g, '\n').split('\n');
|
|
68
|
+
let open = -1;
|
|
69
|
+
for (let i = 0; i < lines.length; i++) {
|
|
70
|
+
if (lines[i].trim() === STOP_SENTINEL_OPEN) {
|
|
71
|
+
open = i;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (open === -1) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
let close = -1;
|
|
79
|
+
for (let i = open + 1; i < lines.length; i++) {
|
|
80
|
+
if (lines[i].trim() === STOP_SENTINEL_CLOSE) {
|
|
81
|
+
close = i;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (close === -1) {
|
|
86
|
+
return undefined; // an unterminated marker is not a complete sentinel.
|
|
87
|
+
}
|
|
88
|
+
const reason = lines
|
|
89
|
+
.slice(open + 1, close)
|
|
90
|
+
.join('\n')
|
|
91
|
+
.trim();
|
|
92
|
+
return {
|
|
93
|
+
reason:
|
|
94
|
+
reason === ''
|
|
95
|
+
? 'the agent raised a TASK-STOP with no reason (the task could not be ' +
|
|
96
|
+
'built as written — re-scope or re-claim).'
|
|
97
|
+
: reason,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** The heading that opens the soft `## Decisions` block in an agent's output. */
|
|
102
|
+
const DECISIONS_HEADING = '## Decisions';
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Extract the body of the soft `## Decisions` block from an agent's final output:
|
|
106
|
+
* the prose under a `## Decisions` heading, up to the next `## ` heading or EOF,
|
|
107
|
+
* trimmed. Returns `undefined` when the agent reported no such block (the common
|
|
108
|
+
* case). This is purely informational — it NEVER blocks the build; it is surfaced
|
|
109
|
+
* for review (it already rides the `agent.output` → PR-body path; the caller may
|
|
110
|
+
* also fold it into the review-nits observation).
|
|
111
|
+
*/
|
|
112
|
+
export function extractDecisionsBlock(
|
|
113
|
+
output: string | undefined,
|
|
114
|
+
): string | undefined {
|
|
115
|
+
if (output === undefined || output === '') {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
const lines = output.replace(/\r\n/g, '\n').split('\n');
|
|
119
|
+
let start = -1;
|
|
120
|
+
for (let i = 0; i < lines.length; i++) {
|
|
121
|
+
if (lines[i].trim() === DECISIONS_HEADING) {
|
|
122
|
+
start = i + 1;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (start === -1) {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
const body: string[] = [];
|
|
130
|
+
for (let i = start; i < lines.length; i++) {
|
|
131
|
+
if (/^##\s/.test(lines[i])) {
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
body.push(lines[i]);
|
|
135
|
+
}
|
|
136
|
+
const text = body.join('\n').trim();
|
|
137
|
+
return text === '' ? undefined : text;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* The DETERMINISTIC backstop for the STOP sentinel: did the agent leave NO source
|
|
142
|
+
* change at all? An `agent.ok` run that changed NOTHING is NEVER a successful
|
|
143
|
+
* build — treat it as an implicit STOP/no-op and route to needs-attention WITHOUT
|
|
144
|
+
* paying for the gate + Gate-2, even when the agent stopped without (or with a
|
|
145
|
+
* malformed) sentinel.
|
|
146
|
+
*
|
|
147
|
+
* The check has TWO independent signals; the build is empty IFF BOTH say "no
|
|
148
|
+
* source change":
|
|
149
|
+
*
|
|
150
|
+
* 1. **The WORKING TREE** (the primary signal, the common FRESH-build path). At
|
|
151
|
+
* this point in the pipeline (after the agent returns, BEFORE the gate /
|
|
152
|
+
* done-move) the runner has committed nothing of the agent's work — for a
|
|
153
|
+
* FRESH build the work branch HEAD is still the CLAIM commit, so the agent's
|
|
154
|
+
* output sits ENTIRELY in the WORKING TREE (tracked modifications OR
|
|
155
|
+
* brand-new untracked files; the agent does no git):
|
|
156
|
+
* - tracked modifications: `git status --porcelain` reports any modified/
|
|
157
|
+
* added/deleted TRACKED path;
|
|
158
|
+
* - untracked files: `--porcelain` also lists `??` untracked paths (a new
|
|
159
|
+
* source file the agent created), which a `git diff` would MISS.
|
|
160
|
+
*
|
|
161
|
+
* 2. **SOURCE COMMITS on the branch ahead of `<arbiter>/main`** (the additional
|
|
162
|
+
* condition that honours a `requeue` CONTINUE-FROM-TIP). The working-tree-only
|
|
163
|
+
* assumption — "HEAD is still the claim commit" — is FALSE for a `requeue`
|
|
164
|
+
* keep+continue: the kept `work/<slug>` branch's prior work is a chain of
|
|
165
|
+
* COMMITTED commits ahead of main, with a legitimately CLEAN working tree.
|
|
166
|
+
* Such a continue is NOT a no-op, so we ALSO ask: does any commit in
|
|
167
|
+
* `git rev-list <arbiter>/main..HEAD` touch a NON-`work/` path? If so the
|
|
168
|
+
* branch carries real source work and the build is NOT empty, even though the
|
|
169
|
+
* current session's working tree is clean.
|
|
170
|
+
*
|
|
171
|
+
* TWO things are filtered out of BOTH signals so they do not read as a build: the
|
|
172
|
+
* `work/` ledger (the runner's own claim move, the ONLY thing in the tree — and
|
|
173
|
+
* the ONLY thing the claim commit touches — on a clean STOP) and the runner's own
|
|
174
|
+
* `.dorfl-job.json` record (a job-worktree leaves one — the SAME line
|
|
175
|
+
* `gc`'s `isWorktreeClean` filters). The build is empty IFF nothing else remains
|
|
176
|
+
* in EITHER signal. Best-effort: a plumbing failure in EITHER check is treated as
|
|
177
|
+
* NON-empty (the safe direction — never short-circuit a genuine build by mistake).
|
|
178
|
+
*
|
|
179
|
+
* `arbiter` (already threaded for call-site symmetry) is used by signal 2 to
|
|
180
|
+
* resolve `<arbiter>/main`; we fetch it first (mirroring the integration band) so
|
|
181
|
+
* the remote-tracking ref exists / is current even in a bare-mirror job worktree.
|
|
182
|
+
*/
|
|
183
|
+
export async function isWorkBranchDiffEmpty(params: {
|
|
184
|
+
cwd: string;
|
|
185
|
+
arbiter: string;
|
|
186
|
+
env?: NodeJS.ProcessEnv;
|
|
187
|
+
}): Promise<boolean> {
|
|
188
|
+
const {cwd, arbiter, env} = params;
|
|
189
|
+
if (await hasUncommittedSourceChanges({cwd, env})) {
|
|
190
|
+
return false; // the working tree carries source change ⇒ a real build.
|
|
191
|
+
}
|
|
192
|
+
// Working tree is clean. It is STILL a real build if the branch carries source
|
|
193
|
+
// COMMITS ahead of `<arbiter>/main` (a `requeue` continue-from-tip). Only when
|
|
194
|
+
// there are none is this a genuine no-op.
|
|
195
|
+
return !(await hasSourceCommitsAhead({cwd, arbiter, env}));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* The WORKING-TREE-DIRTY predicate (the first half of {@link
|
|
200
|
+
* isWorkBranchDiffEmpty}): does the working tree carry any uncommitted source
|
|
201
|
+
* change — tracked modifications, deletions, OR brand-new untracked files —
|
|
202
|
+
* outside `work/` and outside the runner's `.dorfl-job.json` record?
|
|
203
|
+
*
|
|
204
|
+
* This is a **best-effort** check in the SAFE direction (a git plumbing failure
|
|
205
|
+
* reads as TRUE: "dirty" / "has source") so an unknown can never short-circuit a
|
|
206
|
+
* genuine build by mistake.
|
|
207
|
+
*
|
|
208
|
+
* Two consumers share this seam, so they NEVER drift on what "the agent left
|
|
209
|
+
* uncommitted source work in the tree" means:
|
|
210
|
+
*
|
|
211
|
+
* - {@link isWorkBranchDiffEmpty} (the STOP backstop): empty IFF this is FALSE
|
|
212
|
+
* AND `<arbiter>/main..HEAD` has no source commits.
|
|
213
|
+
*
|
|
214
|
+
* - `complete.ts`'s stranded-done auto-recover gate (task
|
|
215
|
+
* `recover-autodetect-gated-on-nothing-to-commit`): on the autonomous path,
|
|
216
|
+
* `committedRecovery` (the folder-shape stranded-done auto-detect) fires only
|
|
217
|
+
* when this is FALSE. A dirty tree on a done-stranded branch means the agent
|
|
218
|
+
* produced new uncommitted work THIS run (a CONTINUE, not a finished strand),
|
|
219
|
+
* so the recover must NOT mis-fire and silently discard it.
|
|
220
|
+
*
|
|
221
|
+
* DELIBERATELY NOT used at the complete.ts gate point: (1) the core's
|
|
222
|
+
* `nothingStaged` (`git diff --cached --quiet`) — that is INDEX-only and reads
|
|
223
|
+
* empty BEFORE the core's later `git add -A`, so it would miss the agent's
|
|
224
|
+
* unstaged edits; (2) the FULL `isWorkBranchDiffEmpty` — its commits-ahead half
|
|
225
|
+
* is true for a GENUINE FINISHED STRAND too (the kept tip carries source commits
|
|
226
|
+
* ahead of main), which would wrongly block the legitimate recover.
|
|
227
|
+
*/
|
|
228
|
+
export async function hasUncommittedSourceChanges(params: {
|
|
229
|
+
cwd: string;
|
|
230
|
+
env?: NodeJS.ProcessEnv;
|
|
231
|
+
}): Promise<boolean> {
|
|
232
|
+
const {cwd, env} = params;
|
|
233
|
+
// Count ANY uncommitted tracked change (mods, deletions, untracked), dropping
|
|
234
|
+
// ONLY the runner's own `.dorfl-job.json` record (a job worktree leaves it).
|
|
235
|
+
//
|
|
236
|
+
// It does NOT exclude `work/`: a `work/` change is frequently the GENUINE
|
|
237
|
+
// DELIVERABLE of a task (extend an idea, transcribe a `## Decisions` block into a
|
|
238
|
+
// done-record, ratify in a protocol doc, author an ADR-note). Excluding `work/`
|
|
239
|
+
// wholesale mis-classified every DOCS-ONLY task as an empty-diff no-op and
|
|
240
|
+
// FALSE-bounced completed, correct work (observation
|
|
241
|
+
// `runner-empty-diff-false-positive-bounces-completed-work-2026-07-09`). The
|
|
242
|
+
// old exclusion existed for a claim BOOKKEEPING commit that touched `work/`
|
|
243
|
+
// only — but the per-item-lock claim writes NOTHING (`claim-cas.ts`: "there is
|
|
244
|
+
// NO claim commit"), so the exclusion now only over-drops real deliverables.
|
|
245
|
+
// Genuine bookkeeping is excluded by TRAILER at the commits-ahead check, not by
|
|
246
|
+
// path here (the working tree carries no bookkeeping — the agent's edits are
|
|
247
|
+
// its deliverable).
|
|
248
|
+
const status = await runAsync('git', ['status', '--porcelain'], cwd, {env});
|
|
249
|
+
if (status.status !== 0) {
|
|
250
|
+
return true; // plumbing error ⇒ treat as DIRTY (the safe direction).
|
|
251
|
+
}
|
|
252
|
+
// Each porcelain line is `XY <path>` (path from column 3).
|
|
253
|
+
const remaining = status.stdout
|
|
254
|
+
.split('\n')
|
|
255
|
+
.map((line) => line.trimEnd())
|
|
256
|
+
.filter((line) => line !== '')
|
|
257
|
+
.filter((line) => line.slice(3).trim() !== JOB_RECORD_FILENAME);
|
|
258
|
+
return remaining.length > 0;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Does the work branch have at least one GENUINE-WORK commit in
|
|
263
|
+
* `<arbiter>/main..HEAD` (a commit that is NOT a runner bookkeeping commit,
|
|
264
|
+
* identified by its `Dorfl-Bookkeeping` trailer)? Fetches `<arbiter>/main` first
|
|
265
|
+
* (mirroring the integration band) so the ref resolves even in a bare-mirror job
|
|
266
|
+
* worktree. Best-effort / SAFE direction: any plumbing failure (the fetch, the
|
|
267
|
+
* rev-list, an unresolvable ref) reads as TRUE ("has source") — the same
|
|
268
|
+
* never-short-circuit-a-genuine-build stance the working-tree check takes, so an
|
|
269
|
+
* unknown can never collapse a real continue-from-tip into a no-op.
|
|
270
|
+
*/
|
|
271
|
+
async function hasSourceCommitsAhead(params: {
|
|
272
|
+
cwd: string;
|
|
273
|
+
arbiter: string;
|
|
274
|
+
env?: NodeJS.ProcessEnv;
|
|
275
|
+
}): Promise<boolean> {
|
|
276
|
+
const {cwd, arbiter, env} = params;
|
|
277
|
+
// Refresh `<arbiter>/main` so the range resolves (a bare-mirror job worktree
|
|
278
|
+
// has no fetch refspec; a regular clone gets the same harmless explicit ref).
|
|
279
|
+
const fetched = await runAsync(
|
|
280
|
+
'git',
|
|
281
|
+
[
|
|
282
|
+
'fetch',
|
|
283
|
+
'--quiet',
|
|
284
|
+
arbiter,
|
|
285
|
+
`+refs/heads/main:refs/remotes/${arbiter}/main`,
|
|
286
|
+
],
|
|
287
|
+
cwd,
|
|
288
|
+
{env},
|
|
289
|
+
);
|
|
290
|
+
if (fetched.status !== 0) {
|
|
291
|
+
return true; // could not refresh the ref ⇒ NON-empty (safe direction).
|
|
292
|
+
}
|
|
293
|
+
// Enumerate the commits in `<arbiter>/main..HEAD` and count those that carry
|
|
294
|
+
// GENUINE work — i.e. NOT a runner BOOKKEEPING commit. A bookkeeping commit is
|
|
295
|
+
// identified by its recorded `Dorfl-Bookkeeping` trailer (task
|
|
296
|
+
// `identify-bookkeeping-commits-by-trailer-not-rendered-todo-text`), NOT by a
|
|
297
|
+
// `work/` path: a `work/` change is frequently the real deliverable of a
|
|
298
|
+
// docs/protocol/observation task, so a path-based `:(exclude)work` here
|
|
299
|
+
// FALSE-bounced completed docs-only work (observation
|
|
300
|
+
// `runner-empty-diff-false-positive-bounces-completed-work-2026-07-09`). Read
|
|
301
|
+
// each commit's sha + bookkeeping trailer via plumbing (NUL-delimited, one
|
|
302
|
+
// record per commit); a commit with a non-empty `Dorfl-Bookkeeping` trailer is
|
|
303
|
+
// bookkeeping and does not count; any other commit is genuine work.
|
|
304
|
+
// Per commit: its sha + its `Dorfl-Bookkeeping` trailer value, NUL-delimited
|
|
305
|
+
// then a record separator, so we can inspect each commit's files too.
|
|
306
|
+
const log = await runAsync(
|
|
307
|
+
'git',
|
|
308
|
+
[
|
|
309
|
+
'log',
|
|
310
|
+
'--format=%H%x00%(trailers:key=Dorfl-Bookkeeping,valueonly)%x1e',
|
|
311
|
+
`${arbiter}/main..HEAD`,
|
|
312
|
+
],
|
|
313
|
+
cwd,
|
|
314
|
+
{env},
|
|
315
|
+
);
|
|
316
|
+
if (log.status !== 0) {
|
|
317
|
+
return true; // could not compute the range ⇒ NON-empty (safe direction).
|
|
318
|
+
}
|
|
319
|
+
const records = log.stdout
|
|
320
|
+
.split('\x1e')
|
|
321
|
+
.map((r) => r.trim())
|
|
322
|
+
.filter((r) => r !== '');
|
|
323
|
+
for (const record of records) {
|
|
324
|
+
const [sha, bookkeepingTrailer = ''] = record.split('\0');
|
|
325
|
+
// A bookkeeping-trailered commit is not genuine work.
|
|
326
|
+
if (bookkeepingTrailer.trim() !== '') {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
// A commit whose ONLY touched path is the runner's own job-record is
|
|
330
|
+
// bookkeeping too (no trailer, but not the agent's deliverable).
|
|
331
|
+
const files = await runAsync(
|
|
332
|
+
'git',
|
|
333
|
+
['show', '--name-only', '--format=', sha],
|
|
334
|
+
cwd,
|
|
335
|
+
{env},
|
|
336
|
+
);
|
|
337
|
+
const touched =
|
|
338
|
+
files.status === 0
|
|
339
|
+
? files.stdout
|
|
340
|
+
.split('\n')
|
|
341
|
+
.map((p) => p.trim())
|
|
342
|
+
.filter((p) => p !== '')
|
|
343
|
+
: [];
|
|
344
|
+
const jobRecordOnly =
|
|
345
|
+
touched.length > 0 && touched.every((p) => p === JOB_RECORD_FILENAME);
|
|
346
|
+
if (jobRecordOnly) {
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
// A non-bookkeeping commit that touches real files ⇒ genuine work.
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** The needs-attention reason for the deterministic empty-diff backstop. */
|
|
356
|
+
export function emptyDiffStopReason(slug: string): string {
|
|
357
|
+
return (
|
|
358
|
+
`the agent produced no source change building '${slug}' (empty diff vs the ` +
|
|
359
|
+
'arbiter main); treating as a no-op/stop — re-scope or re-claim.'
|
|
360
|
+
);
|
|
361
|
+
}
|