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,217 @@
|
|
|
1
|
+
# Claim protocol (consumed by the runner — `dorfl claim`/`do`/`complete`)
|
|
2
|
+
|
|
3
|
+
This documents how a `work/tasks/ready/<slug>.md` item is **atomically claimed** by one agent (human or autonomous) when several may try at once. The tasking discipline does not perform claims — it only emits files in a shape this protocol can consume. The runner/lifecycle implements the steps here.
|
|
4
|
+
|
|
5
|
+
## The core idea: claim = acquiring the item's per-item LOCK (an atomic create-only ref push)
|
|
6
|
+
|
|
7
|
+
A claim **acquires the item's per-item lock** — a hidden `refs/dorfl/lock/<type>-<slug>` ref (`<type>` is `task`/`prd`) created by an ATOMIC create-only push (`--force-with-lease=<ref>:`, i.e. "succeed only if the ref is still absent"). Git's ref-update-on-push IS the compare-and-swap: the winner creates the ref; a concurrent acquirer for the SAME item finds it present and is rejected = **definitively lost, with NO retry budget** (a per-item ref only ever contends with another writer for that same item — a genuine conflict the loser should lose). The item's body STAYS in `work/tasks/ready/<slug>.md`; **claim writes NOTHING to `main`** (so an agent can claim even on a protected `main`).
|
|
8
|
+
|
|
9
|
+
The claimable predicate is **"the body is in the pool `tasks/ready/` on `main` AND no lock is held on its ref."**
|
|
10
|
+
|
|
11
|
+
**Separate the claim from the work.** Acquire the lock first (cheap, collision-detecting); do the work only after the lock is provably held.
|
|
12
|
+
|
|
13
|
+
## The arbiter: one serialization point for updating `main`
|
|
14
|
+
|
|
15
|
+
The atomicity comes from a **single repo that everyone treats as the integration point** (`origin`), whose ref update on push linearizes claims. It can be EITHER:
|
|
16
|
+
|
|
17
|
+
- **A remote remote** — e.g. GitHub. Bare by construction; works across machines; everyone (including the human) participates by pushing to it.
|
|
18
|
+
- **A local bare remote** — a `--bare` repo in a folder (e.g. `work.git`), reached via `file://`. Works fully offline. **Must be `--bare`** (you cannot work _in_ the arbiter: a non-bare repo with `main` checked out rejects pushes to `main`, and force-enabling that moves `main` under your working tree).
|
|
19
|
+
|
|
20
|
+
The protocol is **identical** for both — it targets a remote _by name_ (`<arbiter>`), not a hardcoded URL. Switching offline↔online is `git remote set-url <arbiter> <url>` (or adding a second remote); the claim steps do not change.
|
|
21
|
+
|
|
22
|
+
> **Consequence the human must accept:** you participate like an agent — you reach `main` via push (ff / `pull --rebase` then push), NOT via unsynchronized local commits onto a checked-out `main` that is also the arbiter. The arbiter ref and a working `main` you hand-commit to cannot be the same ref. This is mild, good hygiene, and is what keeps the claim guarantee intact for everyone.
|
|
23
|
+
>
|
|
24
|
+
> **WARNING — reconcile by REBASE, never a plain `git pull` merge.** A merge does NOT re-run `verify` on the reconciled tree, so a clean merge can hide a semantically-broken result. If your push is rejected non-fast-forward: `git pull --rebase`, then re-run `verify` on the rebased tree BEFORE pushing. (The runner path enforces this automatically as the land invariant below; on the human path it is on you — the human path is deliberately lighter, but the invariant is the same.)
|
|
25
|
+
|
|
26
|
+
### Offline setup (local bare arbiter), once
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
# create the bare arbiter next to (not inside) your working clone
|
|
30
|
+
git clone --bare /path/to/project /path/to/project-work.git # or: git init --bare
|
|
31
|
+
# in each working clone, point an `arbiter` remote at it
|
|
32
|
+
git remote add arbiter file:///path/to/project-work.git
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
When back online, repoint: `git remote set-url arbiter <github-url>` (or push the bare repo's `main` up). Same protocol throughout.
|
|
36
|
+
|
|
37
|
+
## The command: `dorfl claim` / `do`
|
|
38
|
+
|
|
39
|
+
These steps are implemented (and verified against real git, including a truly simultaneous two-agent race) by the runner — so a human or agent does not hand-run the dance:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
dorfl claim <slug> [--arbiter <remote>] [--by <who>] [--dry-run]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Exit codes: `0` claimed · `2` not claimable (not in the pool, or the lock is already held = lost) · `1` usage/env error. The acquire is self-arbitrating (no contended-retry class — a per-item lock never falsely contends). The steps it performs:
|
|
46
|
+
|
|
47
|
+
## Claim steps
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
CLAIM (acquire the per-item lock; collision-detecting, no body move):
|
|
51
|
+
1. fetch the lock refs from <arbiter> (refs/dorfl/lock/*)
|
|
52
|
+
2. confirm the body is still in the pool: work/tasks/ready/<slug>.md on <arbiter>/main
|
|
53
|
+
3. build a PARENTLESS lock-entry commit (action: implement, state: active,
|
|
54
|
+
holder/since) with plumbing — never touches the working tree/HEAD
|
|
55
|
+
4. push it create-only to refs/dorfl/lock/<type>-<slug> (<type> = task/prd)
|
|
56
|
+
with --force-with-lease=<ref>: (the EMPTY expected value = "ref must be absent")
|
|
57
|
+
├─ ACCEPTED -> the lock is atomically yours (the body stays in tasks/ready/;
|
|
58
|
+
| NOTHING was written to main).
|
|
59
|
+
└─ REJECTED -> the ref already exists: another writer holds this SAME item's
|
|
60
|
+
lock. You LOST, definitively (exit 2). No retry budget — pick a
|
|
61
|
+
DIFFERENT pool item. (holder/since are readable on the lock entry
|
|
62
|
+
via `dorfl status`.)
|
|
63
|
+
# who/when rides the lock entry, not a frontmatter field (no claimed_by/claimed_at).
|
|
64
|
+
|
|
65
|
+
WORK (only after the lock is held):
|
|
66
|
+
5. git switch -c work/<type>-<slug> <arbiter>/main # the body is still in tasks/ready/ on main
|
|
67
|
+
(use a dedicated worktree/clone for isolation when running in parallel)
|
|
68
|
+
6. do the work; tests green.
|
|
69
|
+
7a. SUCCESS path — the runner, at integration, lands the DURABLE move on main:
|
|
70
|
+
git mv work/tasks/ready/<slug>.md work/tasks/done/<slug>.md
|
|
71
|
+
committed together with the work (completed-task message, see below), then
|
|
72
|
+
RELEASES the lock (delete the ref). Order: durable main-move FIRST, lock
|
|
73
|
+
release SECOND — a crash between leaves a done-on-main item with a stale lock,
|
|
74
|
+
and recovery treats the main record as authoritative and clears it.
|
|
75
|
+
7b. STUCK path — if it could NOT complete (red gate, rebase/merge conflict, task
|
|
76
|
+
too ambiguous to build, timeout, rejected review): the runner amends the held
|
|
77
|
+
lock active -> stuck (+ reason and any surfaced questions ON THE LOCK ENTRY)
|
|
78
|
+
and SAVES the recoverable work as a wip commit on the kept work/<type>-<slug>
|
|
79
|
+
branch (pushed to the arbiter). NO main write, NO folder move. A human resumes
|
|
80
|
+
(stuck -> active) or requeues (stuck -> released; the body is already in the
|
|
81
|
+
pool). (The build agent never touches the lock — the runner owns it.)
|
|
82
|
+
8. integrate to <arbiter>/main as normal (PR on GitHub, or ff/rebase push offline).
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
> The durable `tasks/ready → tasks/done` / `prds/ready → prds/tasked` / `tasks/ready → tasks/cancelled` moves are the ONLY writes to the shared `main` ref, so THEY keep a small retrying CAS; the per-item LOCK acquire/release never does (it is self-arbitrating). The two are independent substrates that may legitimately disagree (e.g. `tasks/done` on `main` + a `stuck` lock co-exist after a rebase-conflict bounce of a just-completed item).
|
|
86
|
+
|
|
87
|
+
## The land invariant — rebase + re-verify + advance
|
|
88
|
+
|
|
89
|
+
Step 7a's durable `main` move (the LAND) is the mode-agnostic primitive: **fetch current `main` → rebase the work branch onto it → re-run `verify` (and review) on the rebased tree → advance.** A lost CAS or a moved-`main` between gate and push INVALIDATES any prior green and re-arms the gate (re-rebase, re-`verify`, retry — never a `--force`, never an auto-resolved conflict). Merge mode runs it inline at the serialised land; propose mode runs it at the human checkpoint (the propose PR is merged only after the rebased tip re-verifies green). Human review is ADDITIVE (intent/design/security), NEVER a substitute for the re-verify on the rebased tree. The durable _why_ — and the floor/ceiling gradient from bare git to a capable host — lives in ADR `land-primitive-rebase-reverify-advance`.
|
|
90
|
+
|
|
91
|
+
## The prompt handed to the work agent (the `## Prompt` wrapper)
|
|
92
|
+
|
|
93
|
+
When a human or an autonomous runner dispatches an agent to do the WORK phase, the agent is given a small, constant **wrapper** around the task's own `## Prompt` section. The wrapper is the same every time except the slug; an autonomous runner emits it deterministically. The task file is the spec; the wrapper just frames it and draws the line around git.
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
You are completing one work task in this repo. It has already been claimed for
|
|
97
|
+
you (its per-item lock is held) and lives at work/tasks/ready/<slug>.md — read that
|
|
98
|
+
file fully; it is your complete spec (What to build, Acceptance criteria, Prompt).
|
|
99
|
+
Also read its source spec (the task's `prd:` field, at work/prds/ready/<prd>.md)
|
|
100
|
+
for context.
|
|
101
|
+
|
|
102
|
+
<!-- if promptGuidance.testFirst -->
|
|
103
|
+
Implement it to satisfy every Acceptance criterion. At the agreed seam, write
|
|
104
|
+
the failing test BEFORE the production code, matching the repo's house style;
|
|
105
|
+
this is guidance, not a gate — the `verify` step still decides pass/fail.
|
|
106
|
+
<!-- else -->
|
|
107
|
+
Implement it to satisfy every Acceptance criterion. TDD where the task asks for
|
|
108
|
+
it; match the repo's house style.
|
|
109
|
+
<!-- /if -->
|
|
110
|
+
|
|
111
|
+
If you NOTICE a problem OUTSIDE this task's scope (a flaky test, a latent bug, a
|
|
112
|
+
suspicious behaviour), do NOT fix it and do NOT expand your scope. Instead drop a
|
|
113
|
+
short, dated note in work/notes/observations/<short-slug>.md (one or two sentences
|
|
114
|
+
is enough — what you saw and where) so the signal is captured, then carry on with
|
|
115
|
+
your task. (work/notes/observations/ is an append-only capture bucket; anyone, you
|
|
116
|
+
included, may add to it. Writing such a NOTE is the one exception to the "no file
|
|
117
|
+
changes outside your task" rule below — it is a note, not work.)
|
|
118
|
+
|
|
119
|
+
If the TASK ITSELF is the problem — it is ambiguous, under-specified, rests on a
|
|
120
|
+
premise that no longer matches the code/ADRs (it has DRIFTED), or hides an
|
|
121
|
+
unresolved design decision — do NOT guess and build on it. STOP and report
|
|
122
|
+
specifically what is unclear or contradicted (and where), so a human can resolve it
|
|
123
|
+
(the runner routes the item to needs-attention). Do not be shy about this: a
|
|
124
|
+
confident build on a wrong/ambiguous premise produces wrong-but-compiling work that
|
|
125
|
+
is far more expensive than a question. Building exactly what a flawed task says is
|
|
126
|
+
NOT success.
|
|
127
|
+
|
|
128
|
+
To STOP, make NO source change and end your final report with this EXACT
|
|
129
|
+
machine-readable block (the runner detects it, routes the item to
|
|
130
|
+
needs-attention with your reason VERBATIM, and SKIPS the gate + review — so put
|
|
131
|
+
the specific drift report INSIDE it):
|
|
132
|
+
|
|
133
|
+
=== TASK-STOP ===
|
|
134
|
+
<the specific reason: which premises are false, where, and a suggested re-scope>
|
|
135
|
+
=== END TASK-STOP ===
|
|
136
|
+
|
|
137
|
+
The decision bar between "resolve and proceed" and "STOP" / "record a decision":
|
|
138
|
+
A genuinely small, certain, SELF-CONTAINED factual gap you can resolve from the
|
|
139
|
+
code itself (it affects nothing outside this task), resolve and proceed silently.
|
|
140
|
+
But a choice that touches ANOTHER command/flag/task, introduces a new
|
|
141
|
+
ERROR/REFUSAL, or sets a USER-VISIBLE DEFAULT is a DESIGN decision, NOT a small
|
|
142
|
+
factual gap — do NOT bury it in code. If it is load-bearing AND hard to reverse,
|
|
143
|
+
STOP (above). Otherwise PROCEED but RECORD it DURABLY and LINK it from the done
|
|
144
|
+
record, one entry per decision — what you chose + why + the alternative(s) you
|
|
145
|
+
considered + what it touches (which other flag/command/task). Any durable home
|
|
146
|
+
is acceptable: a module JSDoc at the choice site (best when there is an obvious
|
|
147
|
+
code site the decision governs), a "## Decisions" block in the done record / PR
|
|
148
|
+
body (the recommended fallback when there is no natural code site), or a dated
|
|
149
|
+
observation note under work/notes/observations/. Whichever home you pick, LINK
|
|
150
|
+
it from the done record so it is discoverable. This does NOT stop the build; it
|
|
151
|
+
makes the choice visible so the reviewer + the human can ratify or reverse it.
|
|
152
|
+
The bar is "would another task / a user / a reviewer be surprised this was
|
|
153
|
+
decided here?" — if yes, record it. A real ambiguity or stale premise, STOP.
|
|
154
|
+
|
|
155
|
+
COHERENCE CHECK (before you introduce a new concept). Consistency and coherence
|
|
156
|
+
with the system's existing LANGUAGE is a first-class quality. Before you add a new
|
|
157
|
+
flag / config key / status / verb / named concept, check it against the project's
|
|
158
|
+
`CONTEXT.md` glossary + the ADRs + the existing code: (1) does the name already
|
|
159
|
+
MEAN something — are you silently re-meaning it or making it mean two things? (2)
|
|
160
|
+
is the concept at the RIGHT LAYER (e.g. a policy gate on the autonomous-selection
|
|
161
|
+
step vs the explicit verb a human typed)? (3) does it DUPLICATE/overlap an existing
|
|
162
|
+
concept you should reuse or rename instead of forking? If a new concept conflicts
|
|
163
|
+
with, re-means, or duplicates an existing one — or sits at the wrong layer — that is
|
|
164
|
+
NOT a "small factual gap": STOP if it is load-bearing/hard-to-reverse, else RECORD
|
|
165
|
+
it durably per the rule above (JSDoc at the choice site, a `## Decisions` entry
|
|
166
|
+
in the done record, or an observation note — linked from the done record), noting
|
|
167
|
+
what concept, what it overlaps, why your placement. This is
|
|
168
|
+
the prevention half of the review's conceptual-coherence lens — a muddled concept
|
|
169
|
+
that compiles is far more expensive than the question, because every later artifact
|
|
170
|
+
that reuses the muddled term inherits the debt.
|
|
171
|
+
|
|
172
|
+
Do NOT perform any git operations on THIS repo — do not stage, commit, push, or
|
|
173
|
+
move any files between work/ folders, and do not touch the item's lock ref or its
|
|
174
|
+
body at work/tasks/ready/<slug>.md. The runner (or human) owns every git-state
|
|
175
|
+
transition (the durable main-moves AND the per-item lock acquire/release/amend).
|
|
176
|
+
(Your TESTS may freely create and operate on their OWN throwaway git repos — that
|
|
177
|
+
is expected.)
|
|
178
|
+
|
|
179
|
+
Leave a CLEAN working tree — only the changes this task intends. The runner
|
|
180
|
+
commits everything untracked (`git add -A`), so any scratch, debug, or
|
|
181
|
+
runtime-artifact file you or your tools created would otherwise be swept into the
|
|
182
|
+
commit. Before you stop, delete such stray untracked files, or add them to
|
|
183
|
+
.gitignore if they legitimately belong ignored. This is NOT git work: deleting an
|
|
184
|
+
untracked file or editing .gitignore is producing clean WORK, like writing source
|
|
185
|
+
— the "no git" rule above (no stage/commit/push/move) still holds.
|
|
186
|
+
|
|
187
|
+
When the acceptance criteria are met and the repo's build/test/format checks are
|
|
188
|
+
green, STOP and report what you did. The runner handles the durable `git mv` of the
|
|
189
|
+
body tasks/ready/ -> work/tasks/done/, the completion commit, the lock release, and
|
|
190
|
+
integration.
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The "no git" line is **in-band** in the prompt (not delegated to a host config like a global `AGENTS.md`): a portable runner cannot assume the target machine has any such rule, so the boundary travels with the prompt. This keeps the acceptance-test gate authoritative (the agent can't commit/merge around it) and the runner the single owner of git state.
|
|
194
|
+
|
|
195
|
+
## Completed-task commit message
|
|
196
|
+
|
|
197
|
+
The commit that completes a task (the work + the `git mv` to `work/tasks/done/`) uses a consistent, greppable format so the lifecycle is visible in `git log` and an autonomous runner can author it deterministically:
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
<type>(<slug>): <task title or short summary>; done
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
- `<type>` follows conventional-commits (`feat`, `fix`, `docs`, `chore`, …); use `feat` for a task that adds behaviour.
|
|
204
|
+
- `<slug>` is the task slug (its `work/tasks/done/<slug>.md` basename).
|
|
205
|
+
- the trailing **`; done`** marks the durable `tasks/ready→tasks/done` transition landing in this commit (the claim itself has no `main` commit to mirror — it is a lock-ref acquire, not a folder move).
|
|
206
|
+
|
|
207
|
+
Example: `feat(scan): cross-repo eligible-work queue (read-only); done`
|
|
208
|
+
|
|
209
|
+
Keep it ONE commit (work + the `git mv`) so a task's completion is a single, atomic, revertable unit — just as the claim is a single commit.
|
|
210
|
+
|
|
211
|
+
## Why this prevents (not merely detects) double-claims
|
|
212
|
+
|
|
213
|
+
The rejected push is the rejection of the claim. Because the arbiter serializes ref updates, only one create-only push to `refs/dorfl/lock/<type>-<slug>` can win; all others are rejected atomically by `git receive-pack`'s ref lock. No lock server, no integrator process. `--force-with-lease` is a CAS against the expected old value (safe); `--force` would clobber and MUST NOT be used.
|
|
214
|
+
|
|
215
|
+
## Isolation for parallel agents
|
|
216
|
+
|
|
217
|
+
Run each agent's work in its **own clone or worktree** so on-disk code changes can't collide; conflicts then only surface at integration time (normal PR-style resolution), never as corrupted shared state. Clones-of-an-arbiter give fully independent object stores (best isolation); worktrees share one object store (save disk) — either is fine, but prefer separate clones when many agents run at once.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# REVIEW-PROTOCOL
|
|
2
|
+
|
|
3
|
+
The **review discipline** the autonomous runner invokes by name on a `work/`-protocol artifact before that artifact is _trusted_ — a task before it lands/is claimed, code in a work PR against the task that specified it, a spec before tasking, a set of tasks before they land, or a captured note. The runner spawns a fresh-context agent and tells it to "run the review protocol"; that agent reads THIS doc and applies its standard.
|
|
4
|
+
|
|
5
|
+
The protocol describes how work is AUTHORED (`WORK-CONTRACT.md`, the templates), CLAIMED and BUILT (`CLAIM-PROTOCOL.md`, the Gate-1 `verify` floor), and JUDGED BEFORE LANDING (this doc). It is in-band in every set-up repo, never host-specific. (The human-facing pointer is `skills/review/SKILL.md`; the standard lives here.)
|
|
6
|
+
|
|
7
|
+
> This doc is **protocol-native**: it assumes the repo uses the `work/` contract and reviews the artifact AGAINST that contract. Every bare "WORK-CONTRACT" / "ADR-FORMAT" mention below refers to `work/protocol/<doc>` in the repo under review.
|
|
8
|
+
|
|
9
|
+
You **emit a verdict; you do not act on it** — see [Your output](#your-output). Routing the verdict (to `needsAnswers`, needs-attention, a batch file, a merge) is the caller's job. This discipline is the _assessment_, not the disposition.
|
|
10
|
+
|
|
11
|
+
## When to use vs. not
|
|
12
|
+
|
|
13
|
+
- **Use** to review: a **task** (well-cut? claim-ready?); **code** in a work PR (does it deliver the task it claims?); a **spec** (taskable? gate axes honest?); a **note** (right bucket? actionable?); or a **set of tasks** — the whole-SET lens: **graph coherence / gaps / overlap / goal-composition** (does the dependency graph cohere, are there set-level gaps or overlapping/duplicated tasks, and do they compose into the spec/ADR goal?). The set-level checks live in lens 3 (cross-artifact composition) and lens 5 (the destination check).
|
|
14
|
+
- **Don't** use it to _produce_ the artifact (that's `to-spec` / `to-task` / the build agent), nor to _route_ the verdict (that's the caller — a review gate, a conductor skill, or a human). This protocol only assesses.
|
|
15
|
+
|
|
16
|
+
## The core disciplines (what makes a review thorough, not shallow)
|
|
17
|
+
|
|
18
|
+
These are _why_ this beats a single "looks fine" pass — apply them throughout:
|
|
19
|
+
|
|
20
|
+
1. **Run a SEQUENCE of distinct angles, not one pass.** Each lens below is a different framing. Re-running the _same_ angle converges on nothing fast; changing the angle keeps finding distinct _classes_ of defect. Stop when a full pass across the angles finds nothing NEW.
|
|
21
|
+
2. **A reviewer is ADVERSARIAL.** Try to _break_ the artifact ("attack these tasks: granularity? dependency order? gate correctness? drift? a missed seam?"), don't confirm it. Self-review in the producing context rubber- stamps; review as if someone else wrote it (ideally a fresh/cold read).
|
|
22
|
+
3. **Verify against what ACTUALLY LANDED, not intent or memory.** Read the real code / the committed artifact — not what you _think_ a change did. Edits silently fail; specs drift. Trust the bytes on disk.
|
|
23
|
+
4. **A SECOND instance of the same finding is a SIGNAL, not noise.** "I've seen this shape before" → generalise the fix, don't patch instances one by one (this applies to the artifact's defects _and_ to your own repeated mistakes).
|
|
24
|
+
5. **Defects concentrate in the TASK/SPEC more than in the code.** Agents build what they're told, correctly; the expensive bugs are an ambiguous premise, a wrong "reuse X", an assumed-but-absent seam, a stale central assumption. Spend the most scrutiny on the spec.
|
|
25
|
+
6. **Flag, don't guess.** When something is genuinely unresolved, that is a `block`/`needsAnswers` finding — not a guess dressed as approval. A false "looks fine" ships wrong-but-compiling work; a flagged question costs one human glance.
|
|
26
|
+
7. **Weight findings by REAL impact — do not cargo-cult the lenses.** A finding is only worth raising if acting on it changes an outcome someone would actually hit. A technically-true nit that no reader/builder/runtime will ever be bitten by is NOT a `block` (often not even worth recording). Running a lens as a checklist and reporting conformance misses ("this optional field is empty", "a list could be renumbered") as blocking is the failure mode this rule exists to stop: it buries the findings that matter under bookkeeping noise. Ask of each finding: _who hits this, and what breaks?_ No answer → drop it. The lenses find candidates; impact decides severity.
|
|
27
|
+
|
|
28
|
+
## The lenses — apply IN ORDER, ending in the destination check
|
|
29
|
+
|
|
30
|
+
For each lens: _what it catches_ + _how to apply it (against the contract)_.
|
|
31
|
+
|
|
32
|
+
### 1. Claim-vs-reality
|
|
33
|
+
|
|
34
|
+
Every concrete claim the artifact makes, checked against the real world.
|
|
35
|
+
|
|
36
|
+
- Task/spec: each referenced symbol, path, function signature, "reuse X" — does it exist and have the assumed shape? (Catches ghost paths, wrong module homes, "reuse X" where X is private / wrongly-shaped.)
|
|
37
|
+
- Code: does the diff actually do what its task/commit claims?
|
|
38
|
+
- Any doc: does it match what landed in `tasks/done/` and the relevant ADRs/findings?
|
|
39
|
+
- **Drift is a `needs-attention` / `needsAnswers` signal**, never something to paper over (WORK-CONTRACT.md). A task built on a stale premise is a `block`.
|
|
40
|
+
|
|
41
|
+
### 2. Cleanup-vs-behaviour
|
|
42
|
+
|
|
43
|
+
Anything framed as removal / dead-code / no-op, checked for **hidden live behaviour** (e.g. a flag claimed "just cleanup" that is actually still read somewhere). If a "cleanup" changes behaviour, that's a defect or an unowned scope.
|
|
44
|
+
|
|
45
|
+
This lens also owns **acceptance-criteria conformance** for code:
|
|
46
|
+
|
|
47
|
+
- Does the code meet every acceptance criterion of its task?
|
|
48
|
+
- **Shared-write isolation rule (WORK-CONTRACT.md):** if the code writes to a shared/global location (a real home/config dir, a system path, a shared service, an external tool's store), do its tests ISOLATE that location (temp/scratch via the named env/config lever) AND assert the real one is UNTOUCHED? A missing isolation test is a `block` — it silently pollutes and can crash unrelated tools.
|
|
49
|
+
|
|
50
|
+
### 3. Cross-artifact composition (contract conformance)
|
|
51
|
+
|
|
52
|
+
Do the artifacts COMPOSE, and do they obey the contract?
|
|
53
|
+
|
|
54
|
+
- **Composition:** handoffs (one task ships a stub another fills), shared helpers with no owner, two tasks editing the SAME file/command in parallel (a merge conflict waiting to happen — should carry a `blockedBy` to serialise), one task deleting another's live tooling, cross-task side-effects.
|
|
55
|
+
- **Contract conformance (assume these rules; flag violations):**
|
|
56
|
+
- **status = folder**, never a frontmatter field; **one file per item**; **no shared index/manifest**.
|
|
57
|
+
- **content-derived slug**, never a counter; **camelCase** field names (`humanOnly`, `needsAnswers`, `blockedBy`, `taskedAfter`).
|
|
58
|
+
- **gate axes set HONESTLY** — `humanOnly` (a human must drive this) and `needsAnswers` (open questions, listed in the body) reflect the artifact's real nature; a task's gate is decided from _building that task_, NOT inherited from its spec; a falsely-complete `needsAnswers:false` is a defect.
|
|
59
|
+
- **`blockedBy` / `prd` / `covers`** present and correct (`prd` required iff `covers` is set); deps reference real slugs.
|
|
60
|
+
- **bucket polarity** for notes: _observation_ = spotted/unverified (append-only); _finding_ = verified EXTERNAL/domain ground truth; _ADR_ = a decision WE made + why (in `docs/adr/`). A note in the wrong bucket is a finding.
|
|
61
|
+
- **a task's `## Prompt`** is self-contained (an agent could start from the file alone) and includes the drift-check.
|
|
62
|
+
|
|
63
|
+
### 4. Conceptual coherence (does it fit the system's LANGUAGE?)
|
|
64
|
+
|
|
65
|
+
The artifact may be internally correct yet INCOHERENT against the concepts the system already has. This lens catches the conflation that mechanical conformance (lens 3) and claim-checking (lens 1) miss — a single concept applied at the WRONG LAYER (e.g. a policy gate placed on an explicit verb when it should gate only the autonomous selection step), an inconsistency that can otherwise survive across multiple tasks and specs.
|
|
66
|
+
|
|
67
|
+
For each concept / flag / config key / verb / status the artifact introduces or touches, ask three questions:
|
|
68
|
+
|
|
69
|
+
- **(a) Consistent meaning?** Is the term used the SAME way it is already defined elsewhere (the project's `CONTEXT.md` glossary is the source of truth, plus the ADRs, other tasks, the code)? A term that silently RE-MEANS an existing word — or means two different things in two places — is incoherent.
|
|
70
|
+
- **(b) Right layer?** Is the concept placed at the conceptual layer it actually belongs to? (A policy gate on the autonomous-SELECTION step vs on the explicit VERB; a knob on the loop vs on the one-shot; a check on "who invoked" when the system cannot even distinguish the invokers.) A correct mechanism at the wrong layer is incoherent.
|
|
71
|
+
- **(c) Duplicate / overlap?** Does it FORK an existing concept under a new name instead of reusing or renaming the one that already exists? (Two flags meaning "isolate"; a new status that is really an existing one; a second lock primitive.) If it overlaps, the artifact should reuse/rename, not add.
|
|
72
|
+
|
|
73
|
+
A concept that is coherent in ISOLATION but incoherent against the system's existing language is a `block` (or, for a task/spec not yet built, a `needsAnswers` / re-scope). Coherence is a first-class quality, not a nicety: an incoherent concept is debt that compounds silently across every artifact that later reuses the muddled term. When you spot the muddle, also check whether the GLOSSARY (`CONTEXT.md`) needs the term pinned so the next author cannot re-fork it.
|
|
74
|
+
|
|
75
|
+
### 5. The destination check (the final, highest-value move)
|
|
76
|
+
|
|
77
|
+
_"If every task is built / the code is merged exactly as written, do we END UP WITH the system the spec/ADR describes?"_ — distinct from per-piece correctness, and the strongest signal a decomposition is trustworthy (especially with no human).
|
|
78
|
+
|
|
79
|
+
- Take the spec/ADR end-state as the target; **map every promised element to a delivering task** — a hole = an element no task delivers.
|
|
80
|
+
- Confirm **coverage is complete + non-duplicated** — every user story covered exactly once.
|
|
81
|
+
- Audit the **deletion sweep** — a new system means the OLD surface is GONE; every removal owned by exactly one task, none unowned or double-owned.
|
|
82
|
+
- Check for **orphans** (a task delivering something the end-state doesn't need) and that assumed-pre-existing foundations actually exist.
|
|
83
|
+
- Confirm **deliberate non-deliveries are flagged** as named follow-ups, not silently missing.
|
|
84
|
+
|
|
85
|
+
**`approve` must mean "provably reaches the spec/ADR goal," not "each piece looks fine."** If this lens finds a hole, it is the most important thing to `block`.
|
|
86
|
+
|
|
87
|
+
## Your output
|
|
88
|
+
|
|
89
|
+
Emit a verdict per reviewed item — and **write nothing** (no frontmatter edits, no `git mv`, no file changes). The caller routes it.
|
|
90
|
+
|
|
91
|
+
The verdict is a single JSON object with this shape (the **emitted-shape contract**). The runtime PARSER is the source of truth for the shape; this prose mirrors what it enforces:
|
|
92
|
+
|
|
93
|
+
- `verdict` — REQUIRED, exactly `"approve"` or `"block"`. `approve` lets the artifact proceed; `block` keeps it out (the caller routes to needs-attention / `needsAnswers` / a comment).
|
|
94
|
+
- `findings` — REQUIRED, an array (possibly empty). Each finding is:
|
|
95
|
+
- `severity` — `"blocking"` (keeps the item out of "ready") or `"non-blocking"` (a nit / future improvement). Be honest about which.
|
|
96
|
+
- `question` — the question / defect, with enough context to act WITHOUT re-deriving it.
|
|
97
|
+
- `context` — OPTIONAL, the relevant excerpt, `file:line`, or reasoning.
|
|
98
|
+
|
|
99
|
+
Several caller-specific optional channels MAY ride on the same JSON object. They are OPT-IN: each caller's prompt names which ones to fill. The shape they take when present:
|
|
100
|
+
|
|
101
|
+
- `review` — a single deliberately-authored, human-readable REVIEW string the caller posts as a comment on the PR (leads with Approved/Blocked, then the lenses + the destination-check reasoning). Plain text inside the JSON string. Advisory only — never gates the verdict.
|
|
102
|
+
- `edits` — full-content edits to apply between passes in an improver loop: an array of `{path, content}`, where `path` is a repo-relative target (typically `work/tasks/backlog/<slug>.md`) and `content` is the FULL replacement file body. The runner writes them; the agent does no disk/git.
|
|
103
|
+
- `edit` — for the lone-task review only: a single in-memory full-replacement task BODY (the markdown AFTER the frontmatter), applied before the next round. No path — the task has not been emitted yet.
|
|
104
|
+
- `questions` — an array of strings carrying open questions for a human to answer (the non-converge sink in the lone-task review).
|
|
105
|
+
- `uncertainTasks` — for the tasker improver loop: specific tasks to emit `needsAnswers: true` with the questions in their bodies. Each is `{path, questions: string[]}`.
|
|
106
|
+
- `decompositionUnclear` — for the tasker improver loop: when the WHOLE decomposition is unsound, `{questions: string[]}` to record as the spec's needs-attention reason.
|
|
107
|
+
|
|
108
|
+
Any unrecognised field is ignored by the parser; the caller routes on `verdict`/`findings` plus the channels its prompt asked for.
|
|
109
|
+
|
|
110
|
+
**Keep the JSON parseable** (a malformed verdict strands the work). Emit defensively: emit it MINIFIED on ONE single line; do NOT use a literal double-quote `"` inside any string value (paraphrase, or use single quotes — a dropped escape on an inner `"` is the most common corruption); keep every string field SHORT and SINGLE-LINE (write `\n` literally, never embed a real newline / tab / control char); and cap the longest field (`review`) at roughly 1500 characters — say less, not more.
|
|
111
|
+
|
|
112
|
+
### How callers route your verdict (not your job — for orientation only)
|
|
113
|
+
|
|
114
|
+
- a **review GATE** routes a `block` → set `needsAnswers: true` on the artifact (question in its body) or mark its per-item lock `state: stuck` (needs-attention); `approve` → let it land / auto-merge.
|
|
115
|
+
- a **conductor** (e.g. `drive-tasks`/`orchestrate`) routes a `block` → into its stuck-set / batched questions for the human; `approve` → merge / advance.
|
|
116
|
+
|
|
117
|
+
## Scope fence
|
|
118
|
+
|
|
119
|
+
This doc is the review _protocol/discipline_ only. The review **gates** — _when_ review runs (task-time / PR-time), per-repo toggles, the model override, the `--propose` PR arbiter, auto-merge-on-approve, the role/seam wiring, the trust resolver — are NOT here; they live in the runner machinery. This protocol assumes nothing about its caller beyond "you will route my verdict."
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# SURFACE-PROTOCOL
|
|
2
|
+
|
|
3
|
+
The **surface-questions discipline** the autonomous runner invokes by name on ONE `work/` item before that item can advance a lifecycle rung. The runner spawns a fresh-context agent and tells it to "run the surface protocol"; that agent reads THIS doc and applies its standard.
|
|
4
|
+
|
|
5
|
+
The protocol describes how work is AUTHORED (`WORK-CONTRACT.md`, the templates), CLAIMED and BUILT (`CLAIM-PROTOCOL.md`, the `verify` floor), JUDGED BEFORE LANDING (`REVIEW-PROTOCOL.md`) and — when judgement is genuinely open — has its OPEN QUESTIONS SURFACED for a human to answer (this doc). It is in-band in every set-up repo, never host-specific. (The human-facing pointer is `skills/surface-questions/SKILL.md`; the standard lives here.)
|
|
6
|
+
|
|
7
|
+
> This doc is **protocol-native**: it assumes the repo uses the `work/` contract and surfaces the open-judgement residue of an item AGAINST that contract. Every bare "WORK-CONTRACT" / "REVIEW-PROTOCOL" mention below refers to `work/protocol/<doc>` in the repo under work.
|
|
8
|
+
|
|
9
|
+
It is **doc-shaped, exactly like `review`**: you produce an assessment (here, a set of questions) and the **caller routes/persists it**. You never set `needsAnswers`, never write a sidecar, never `git mv`, never commit. The advance engine's surface-question rung spawns you fresh-context, takes your questions, and **ITSELF writes the sidecar (CAS-atomic)** — exactly as the review gate uses `review`. **The skill judges; the engine persists.**
|
|
10
|
+
|
|
11
|
+
## The two laws (state them; they keep the tool honest)
|
|
12
|
+
|
|
13
|
+
1. **GATHER-only.** Your job is to FORMULATE the open questions for the item — by composing the existing reviewing/triage judgement, not by re-deriving it. You add no new disposition of the item.
|
|
14
|
+
2. **PERSIST-NEVER.** You EMIT questions and **write nothing** (no `needsAnswers` edit, no sidecar, no `git mv`, no commit) — mirroring `review`. The caller (the advance engine, or a human) routes and persists. If you are tempted to write a file, STOP: that is the engine's job (or, by hand, the `advance` verb — see [the no-runner path](#the-no-runner-path)).
|
|
15
|
+
|
|
16
|
+
**The humility rule (the heart of it):** you **surface the residue, you NEVER invent an answer.** A `default:` is a _suggested_ default offered for the human's convenience — it is a humility aid, not a decision, and it never substitutes for the human answering. Automating answer creation is rejected by design; the human is the clock. When judgement is genuinely open, that is a QUESTION — never a guess dressed as a resolution.
|
|
17
|
+
|
|
18
|
+
## When to use vs. not
|
|
19
|
+
|
|
20
|
+
- **Use** to formulate the open questions for ONE item before it can advance a lifecycle rung — a task or spec that may carry open judgement, an untriaged observation, code in a work PR — whether you are the advance engine's surface rung or a human doing it by hand with no runner.
|
|
21
|
+
- **Don't** use it to PRODUCE an item (that is `to-spec` / `to-task` / the build agent), to APPLY a human's answer or advance the item (that is the engine's apply rung / the `advance` verb), or to PERSIST the questions (the engine, or the `advance` verb, owns the write). And do not use it to invent answers — there is no answer-creation here, by design.
|
|
22
|
+
|
|
23
|
+
## What you COMPOSE (single sources — do NOT duplicate)
|
|
24
|
+
|
|
25
|
+
You are a GATHERER. You stand up the existing producers/reviewers and collect what they emit; you do not reimplement their judgement. `to-task` and `review` stay the single sources, **composed and UNCHANGED**.
|
|
26
|
+
|
|
27
|
+
1. **`review` (`work/protocol/REVIEW-PROTOCOL.md`) — for a task / spec / code.** Run the `review` discipline; it EMITS a verdict `{verdict, findings:[{severity, question, context}]}` and writes nothing. ROUTE its **`block`** findings into your emitted questions (a blocking finding is an open question that must be answered before the item advances). A non-blocking finding is a nit — record it as an optional/low-priority question, never as a blocker. Do NOT re-derive review's lenses here; you call review and carry its findings over.
|
|
28
|
+
2. **The native observation-triage question — for an observation.** An observation has no gate for `review` to assess; its question is **"what becomes of this signal?"** Emit a single plain question asking the human, in their own words, what should happen to it (see [the emitted question shape](#the-emitted-question-shape-must-match-the-sidecar)). This judgement is NATIVE to this skill — investigate the observation's claim against current reality (code / tasks / specs / ADRs) so the inline context and the suggested default are honest, exactly as the triage discipline demands.
|
|
29
|
+
3. **The item's PRE-EXISTING open questions.** Collect what the item already carries: a `needsAnswers: true` item's `## Open questions` block, and any open question already written in the body. Carry each over verbatim as an emitted question (with its context). These are open judgement the author already named — they must surface, not be silently dropped.
|
|
30
|
+
|
|
31
|
+
For each gathered question, attach **inline CONTEXT** (the relevant excerpt / `file:line` / the reasoning — so the human need not open the source item) and, where you can honestly suggest one, an **optional suggested DEFAULT** (the humility aid — never a decision).
|
|
32
|
+
|
|
33
|
+
## The emitted question shape (MUST match the sidecar)
|
|
34
|
+
|
|
35
|
+
The questions you emit MUST match the **sidecar entry fields**, so the engine persists them with **zero translation**. The runtime PARSER (`parseSurfaceEmit`) is the source of truth for the shape; this prose mirrors what it enforces.
|
|
36
|
+
|
|
37
|
+
Emit a single JSON object of this exact shape (no prose OUTSIDE it):
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"item": "<type>:<slug>",
|
|
42
|
+
"questions": [
|
|
43
|
+
{
|
|
44
|
+
"question": "…",
|
|
45
|
+
"context": "…",
|
|
46
|
+
"default": "… (optional; omit if none)"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"note": "… (optional free prose; your reasoning / findings live HERE)"
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- **`item`** — OPTIONAL, the namespaced identity the surface is for (orientation only; the resolver owns identity — the parser tolerates absence).
|
|
54
|
+
- **`questions`** — REQUIRED, an ORDERED array. An EMPTY array is VALID — the honest "no open judgement" result; absence is NOT (the parser rejects it, never a silent surface). Each entry is:
|
|
55
|
+
- **`question`** — REQUIRED, the question verbatim. An all-whitespace question is dropped as a placeholder.
|
|
56
|
+
- **`context`** — OPTIONAL, inline context so the human need not open the item (the relevant excerpt / `file:line` / reasoning).
|
|
57
|
+
- **`default`** — OPTIONAL, the suggested default — the humility aid; omit when you cannot honestly suggest one (never fabricate a default just to fill the field).
|
|
58
|
+
- **`note`** — OPTIONAL free-prose channel for your reasoning / findings (the surface counterpart of the verdict's `review` field). It is the HOME for any explanation you want to give: put it HERE, INSIDE the object, never as prose around the JSON. The engine does not persist `note` (the parser ignores it); its only purpose is to give your prose somewhere to go so the emitted object can be your final, clean, single-object output. Like `review`, keep it short and single-line (write `\n` literally, never a raw newline).
|
|
59
|
+
|
|
60
|
+
There is NO `disposition` field, and no token vocabulary to learn or pick: a sidecar entry is BINARY (no-answer | answered), and the human answers in PLAIN LANGUAGE. What to DO with the answer — mint a task, a SPEC, or an ADR; delete the source; or ask a follow-up — is the agentic apply decision (read off the human's answer + the source item), not a token the surface emits. An observation's triage question is therefore just an ordinary plain question ("what becomes of this signal?"); the human writes back in their own words, and if the answer is "throw it away", the discharge is the direct-delete path (the human, the `answer-questions` skill, or the `dorfl` delete verb removes the source + sidecar in one revertible commit), not a `delete` token.
|
|
61
|
+
|
|
62
|
+
You do NOT assign ids, `answered:`, `answer:`, or `allAnswered`. Those are the SIDECAR's machine-owned fields — the engine assigns the stable monotonic id (`q1`, `q2`, …), the human fills `answer:`, and the serialiser derives `answered:`/`allAnswered`. You emit only the three authoring fields above; the engine owns the rest. (This is precisely why you must not write the sidecar: you do not own its machine fields.)
|
|
63
|
+
|
|
64
|
+
Because the shape is the sidecar's, the engine APPENDS your questions to any existing sidecar (never overwriting an already-answered entry) and writes the whole thing in one CAS-atomic commit. You need not know any of that — you just emit the four fields.
|
|
65
|
+
|
|
66
|
+
If the item carries **no open judgement** (review approves with no blocking findings, the observation has an obvious conservative outcome the repo's auto-triage bar covers, nothing pre-existing) — emit the object with an **empty `questions` array** (put WHY in `note`). Surfacing nothing is a valid, honest result; do not manufacture a question to look busy. Do NOT replace the empty-array object with a prose explanation: the JSON object is always your output, even when it carries no questions.
|
|
67
|
+
|
|
68
|
+
**The emitted object is your FINAL and ONLY output.** Do not narrate your process, and add no remark, summary, or sign-off before or after it — and take no further turn once you have emitted it (emitting it is how you finish). The caller reads only your LAST turn, so a trailing chatty turn AFTER the object discards the emit and strands the run. This is the same discipline Gate-2's verdict carries; the `note` field exists precisely so all your prose has a home inside the object.
|
|
69
|
+
|
|
70
|
+
### How the caller persists your questions (NOT your job — for orientation only)
|
|
71
|
+
|
|
72
|
+
- **The advance engine's surface-question rung** spawns you fresh-context, takes your emitted questions, and writes them to the sidecar `work/questions/<type>-<slug>.md` CAS-atomically (assigning ids, appending, setting `needsAnswers: true`). The skill judges; the engine persists.
|
|
73
|
+
- **A human (no runner)** persists via the `advance` verb (see below), or hand-writes the documented sidecar format.
|
|
74
|
+
|
|
75
|
+
## The no-runner path
|
|
76
|
+
|
|
77
|
+
You stay **human-invokable**. A human with no runner can invoke this discipline by hand, take the emitted questions, and persist them one of two ways:
|
|
78
|
+
|
|
79
|
+
- **Persist via the `advance` verb** — the apply/surface rung of the `advance` command (a **sibling top-level verb**, like `do` and `run`). It is `advance`, **NOT `do advance`** — `advance` is its own verb.
|
|
80
|
+
- **Hand-write the documented sidecar format** — write `work/questions/<type>-<slug>.md` by hand per the human-readable Markdown shape below. Because the emitted shape already matches the sidecar entry, this is a transcription, not a translation.
|
|
81
|
+
|
|
82
|
+
The hand-written sidecar shape (the SAME file is both human-readable on GitHub and machine-parseable — the machine fields hide in HTML comments that GitHub renders as nothing, the human content is real Markdown):
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
<!-- dorfl-sidecar: item=<type>:<slug> type=<type> slug=<slug> allAnswered=false -->
|
|
86
|
+
|
|
87
|
+
## Q1
|
|
88
|
+
|
|
89
|
+
**<the question, verbatim>**
|
|
90
|
+
|
|
91
|
+
> <inline context so the human need not open the item>
|
|
92
|
+
|
|
93
|
+
_Suggested default: <optional default; omit the whole line if none>_
|
|
94
|
+
|
|
95
|
+
<!-- q1 fields: id=q1 -->
|
|
96
|
+
|
|
97
|
+
**Your answer** (write below this line):
|
|
98
|
+
|
|
99
|
+
## Q2
|
|
100
|
+
|
|
101
|
+
**<next question…>**
|
|
102
|
+
|
|
103
|
+
…
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Notes for the hand-writer:
|
|
107
|
+
|
|
108
|
+
- The **identity HTML comment** at the top carries `item`/`type`/`slug` and the derived `allAnswered` mirror. Set `allAnswered=false` on first write (no answers yet); the engine recomputes it on every subsequent serialise.
|
|
109
|
+
- Each entry opens with a `## Qn` heading (`Q1`, `Q2`, …, monotonic — never reused). The heading is BOTH the entry separator and the answer-region boundary.
|
|
110
|
+
- The **question is a bold line**, the **context is a Markdown blockquote** (each line prefixed `> `), the **default is one italic line** prefixed `_Suggested default: ` and closed with `_`. Omit context/default lines entirely when absent.
|
|
111
|
+
- The **per-entry HTML comment** carries `id=qN`. There is no `disposition=` field (the token vocabulary is retired — an entry is binary). Do NOT add an `answered=` field either — the engine derives answered-ness from the answer text and only emits the override when it disagrees with that derivation.
|
|
112
|
+
- The fixed marker `**Your answer** (write below this line):` is followed by an empty region; the answer is everything from the marker up to the next `## ` heading (heading-delimited so a `---` inside an answer cannot break parsing).
|
|
113
|
+
- The human just types prose under the answer marker — no `key:`, no escaping, no fence.
|
|
114
|
+
|
|
115
|
+
**No separate write-skill is added.** Hand-writing the sidecar (or the `advance` verb) is enough. Do not invent one here.
|
|
116
|
+
|
|
117
|
+
## Boundaries (the scope fence)
|
|
118
|
+
|
|
119
|
+
- **`to-task` / `review` stay COMPOSED and UNCHANGED.** You call them; you never modify or reimplement them. They are the single sources for tasking/reviewing judgement.
|
|
120
|
+
- **You formulate the questions for ONE item; you do not batch, apply, or iterate.** Batching, applying answers, and iterating are the ENGINE's job (or `orchestrate`'s, for the human batch) — NOT yours.
|
|
121
|
+
- **You write nothing and you invent no answer.** Both laws, restated because they are the whole point: GATHER-only, PERSIST-NEVER; surface the residue, NEVER invent an answer.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# TASKING-PROTOCOL
|
|
2
|
+
|
|
3
|
+
The **tasking discipline** the autonomous runner invokes by name on a spec in `work/prds/ready/` to decompose it into independently-grabbable, file-based work tasks (tracer-bullet vertical tasks). The runner spawns a fresh-context agent and tells it to "run the tasking protocol"; that agent reads THIS doc and applies its standard.
|
|
4
|
+
|
|
5
|
+
This is one of the runner-invoked protocol disciplines (alongside `CLAIM-PROTOCOL.md`, `REVIEW-PROTOCOL.md`, and `SURFACE-PROTOCOL.md`): the protocol describes how work is AUTHORED (`WORK-CONTRACT.md`, the templates), CLAIMED and BUILT (`CLAIM-PROTOCOL.md`, the `verify` floor), JUDGED BEFORE LANDING (`REVIEW-PROTOCOL.md`), has its OPEN QUESTIONS SURFACED (`SURFACE-PROTOCOL.md`), and — between spec and buildable task — TASKED (this doc). It is in-band in every set-up repo, never host-specific. (The human-facing pointer is `skills/to-task/SKILL.md`; the standard lives here.)
|
|
6
|
+
|
|
7
|
+
> This doc is **protocol-native**: it assumes the repo uses the `work/` contract. Every bare "WORK-CONTRACT" / "CLAIM-PROTOCOL" mention below refers to `work/protocol/<doc>` in the repo under work.
|
|
8
|
+
|
|
9
|
+
You **emit task files; you do not act on them** — see [Git protocol](#git-protocol). Committing them, moving the spec, claiming any of them is the caller's job (the runner, on the agent path; a human, on the no-runner path). This discipline is the _decomposition_, not the disposition.
|
|
10
|
+
|
|
11
|
+
## When to use vs. not
|
|
12
|
+
|
|
13
|
+
- **Use** when tasking a `work/prds/ready/<slug>.md`, a design doc, or a plan into grabbable units for solo-with-agents (incl. parallel) work.
|
|
14
|
+
- **Don't** use to _write_ the spec (that's a separate step — `to-spec`) or to _claim/run_ a task (that's the runner: `dorfl claim`/`do`/`complete`, or the `drive-tasks` conductor). Don't introduce a shared index file or a status field — status is the folder (see `WORK-CONTRACT.md`).
|
|
15
|
+
|
|
16
|
+
## Process
|
|
17
|
+
|
|
18
|
+
### 1. Locate / confirm the source
|
|
19
|
+
|
|
20
|
+
Work from a `work/prds/ready/<slug>.md`, a design doc, or the conversation context. If the source is a path, read it fully. The `work/` folder lives **inside the target project repo** (versioned with its code).
|
|
21
|
+
|
|
22
|
+
### 2. Explore the codebase (if not already)
|
|
23
|
+
|
|
24
|
+
Task titles and descriptions use the project's domain glossary. Respect ADRs / findings in the area you're touching.
|
|
25
|
+
|
|
26
|
+
**Check the spec against reality first (drift = a needs-attention signal).** A spec is a launch snapshot and may have DRIFTED from what has since landed (`tasks/done/`, ADRs, sibling tasks). Before tasking, verify its assumptions still hold. If it has drifted such that tasking it as-is would emit tasks built on a false premise, do NOT task it: set `needsAnswers: true` on the spec with the discrepancy in its body (or fix a small certain factual error first). See WORK-CONTRACT.md "Drift is a needs-attention signal". Never emit tasks from a stale spec.
|
|
27
|
+
|
|
28
|
+
### 3. Draft vertical tasks
|
|
29
|
+
|
|
30
|
+
Each task is a **tracer bullet** — a thin vertical path through ALL layers end-to-end, not a horizontal cross-section of one layer.
|
|
31
|
+
|
|
32
|
+
- Each task delivers a narrow but COMPLETE path (schema → logic → API/UI → tests).
|
|
33
|
+
- A completed task is demoable/verifiable on its own.
|
|
34
|
+
- Prefer many thin tasks over few thick ones.
|
|
35
|
+
- Set the **two gate axes** ONLY where they apply (both default to OMITTED on most tasks): **`humanOnly: true`** = NEVER-for-agents BY NATURE (the NARROW DECIDED axis — secrets/release/security; survives even in the pool `work/tasks/ready/`); **`needsAnswers: true`** = unresolved questions block autonomous work (the DISCOVERED axis — list the questions in the task body). Omitted on either means "undeclared"; whether an agent may then auto-build is the _repo's_ `autoBuild` policy. Mark `blockedBy` for ordering. See `WORK-CONTRACT.md` for the two-axis semantics, the predicate, and the `autoBuild` precedence.
|
|
36
|
+
- **A task's `humanOnly` is decided from the nature of BUILDING THAT TASK — never inherited from the spec.** Evaluate each task on its own merits (does _building it_ genuinely need to be done by a human BY NATURE — secrets handling, release pipeline, hard security boundary, an AGENTS.md prohibition?), AS IF the spec's `humanOnly` field did not exist. (The two flags are disjoint — see §3b.)
|
|
37
|
+
- **Do NOT stamp `humanOnly` to mean "a human should REVIEW this before the agent builds it"** — that is the POSITION's job, not the flag's. The runner BIRTHS tasks STAGED in `work/tasks/backlog/` (not eligible); a human promotes the approved ones into the pool `work/tasks/ready/`. Review-first is encoded by the staging position; `humanOnly` is reserved for the rare never-by-nature case. (See WORK-CONTRACT.md "Task `humanOnly` is NARROW".)
|
|
38
|
+
- **Do NOT be shy about `needsAnswers` — when genuinely unsure, FLAG, don't guess.** `needsAnswers` is cheap (a human clears it in seconds) and a confidently-underspecified task is expensive (an agent builds the wrong thing, convincingly). Defects concentrate in TASKING far more than in implementation: an ambiguous premise, an unresolved design fork, a "reuse X" where X's shape is unverified, or a seam you _assume_ exists — each is a `needsAnswers` with the open question written in the body, NOT a guess dressed as a spec. The asymmetry is the whole point: a false `needsAnswers` costs one human glance; a false confidence ships wrong-but-compiling work.
|
|
39
|
+
- **Prefer file-orthogonal tasks to minimise merge conflicts.** `blockedBy` encodes logical ordering, but two independent tasks that edit the SAME files will conflict when the second integrates after the first. Parallel agents make this real. So: split along file/module boundaries where you can; and when two tasks are known to touch the same module, add a `blockedBy` to **serialize** them even if there's no strict logical dependency. The runner only rebases-or-surfaces conflicts (it never auto-resolves), so avoiding them at tasking time is the cheap win.
|
|
40
|
+
|
|
41
|
+
### 3a. Wide refactors are the EXCEPTION to vertical slicing (expand → migrate → contract)
|
|
42
|
+
|
|
43
|
+
Most work slices vertically (§3). A **wide refactor** does not, and forcing it to is the failure mode this subsection exists to stop. A wide refactor is one mechanical change — rename a shared symbol or a column, retype a pervasive identifier, cut a vocabulary over — whose **blast radius** fans across the whole codebase, so a single edit breaks thousands of call sites at once and **no vertical tracer-bullet task can land green on its own**. Sequence it as **expand → migrate → contract** instead:
|
|
44
|
+
|
|
45
|
+
- **Expand** (one task): add the NEW form BESIDE the old so nothing breaks yet. Nothing is removed; the gate stays green because every existing caller still resolves.
|
|
46
|
+
- **Migrate** (one task PER batch, each `blockedBy` the expand task): move call sites onto the new form in batches sized by blast radius — per package, per directory, per module. Each batch is its own task and stays green because the old form still exists. Split batches file-orthogonally (§3's merge-conflict rule) so parallel agents don't collide.
|
|
47
|
+
- **Contract** (one task, `blockedBy` EVERY migrate batch): delete the old form once no caller remains. It cannot start until every migrate batch is done — that is what its `blockedBy` fan-in encodes.
|
|
48
|
+
|
|
49
|
+
**When even the batches cannot stay green alone** (the change is so entangled that an individual batch can't pass the gate in isolation), keep the same expand → migrate → contract shape but let the batches share a common **integration point**: task each batch onto the work-branch discipline the runner already uses, and add a final **integrate-and-verify** task `blockedBy` all of them where green is promised — green is guaranteed only at that fan-in, not batch-by-batch. Prefer the plain green-batch-by-batch form; reach for the shared-integration form only when a batch genuinely cannot be made to pass alone.
|
|
50
|
+
|
|
51
|
+
The test for "is this a wide refactor?" is whether a single mechanical edit breaks the gate across many call sites at once such that no thin vertical path can be green. If yes, use this sequence; if a normal vertical slice CAN be green, it is not a wide refactor — slice it vertically (§3).
|
|
52
|
+
|
|
53
|
+
### 3b. Spec gate vs task gate are DISJOINT + honour cross-prd `taskedAfter`
|
|
54
|
+
|
|
55
|
+
- **`humanOnly` on a spec and `humanOnly` on a task are DISJOINT — they gate different verbs and DO NOT flow into each other.**
|
|
56
|
+
- **Spec `humanOnly`** gates _tasking_: its ONLY effect is that an agent may not **auto-task** that spec (even where the repo's `autoTask` policy is on); a human must drive the decomposition. That is its entire meaning.
|
|
57
|
+
- **Task `humanOnly`** gates _building_: it is decided per task from the nature of building that task (see §3), independently.
|
|
58
|
+
- There is **NO inheritance, NO propagation, and NOT EVEN A HINT** from the spec flag to the task flags. A `humanOnly: true` spec can produce entirely agent-buildable tasks; an un-flagged spec can produce some `humanOnly` tasks. When setting a task's gate, ignore the spec's `humanOnly` entirely.
|
|
59
|
+
- Likewise **`needsAnswers`**: on a spec it blocks auto-tasking until the questions are answered; on a task it blocks auto-building. Set a task's `needsAnswers` only when _that task_ has unresolved questions (list them in its body) — not because the spec had open questions (a spec with open questions should be resolved BEFORE tasking, not task-inherited).
|
|
60
|
+
- (A spec's body may still _describe_ which areas are judgement-heavy — use that as ordinary domain input when reasoning about a task's own build-nature, the same as any other spec prose; it is not a flag-setting shortcut.)
|
|
61
|
+
- **`taskedAfter` (cross-prd order).** If this prd has `taskedAfter: [other-prd]`, those prds must already be TASKED (their tasks exist) before you task this one — so this prd's tasks can reference the real slugs of those prds' tasks in `blockedBy`. (The auto-tasker enforces this; a human may task anyway but must then know the blocker slugs.) If a needed blocker prd is not yet tasked, task it first or record the dependency and stop.
|
|
62
|
+
|
|
63
|
+
### 4. Quiz the user — OR (no human present) do a confidence check
|
|
64
|
+
|
|
65
|
+
**If a human is present** (the normal interactive path): present the breakdown as a numbered list — Title, the two gate axes, Blocked-by, and (if the source has them) which user stories it covers. Ask: granularity right? dependencies right? merge/split any? gates correct? Iterate until approved.
|
|
66
|
+
|
|
67
|
+
**If NO human is present** (an agent auto-tasking in CI): step 4 is replaced by a **confidence check**, because there is no one to quiz. Do NOT emit guessed tasks. The source spec should already be clear (the auto-tasker only runs on a spec that is not `humanOnly` and not `needsAnswers`). If, while tasking, ANY of {granularity, dependency order, a gate, a seam} is genuinely unresolved by the spec/ADR, do not guess: either set `needsAnswers: true` (with the open questions in the body) on the specific uncertain task, or — if the whole decomposition is unclear — stop and route the spec to needs-attention with the questions, rather than emitting a wrongly-cut task. Only emit tasks you would have gotten the human to approve.
|
|
68
|
+
|
|
69
|
+
### 5. Write the task files
|
|
70
|
+
|
|
71
|
+
For each approved task, write `work/tasks/backlog/<slug>.md` using `work/protocol/task-template.md`. Create `work/` and `work/tasks/backlog/` lazily if absent. One file per task. Use a content-derived slug, never a counter. Fill `blockedBy` with the slugs of blocking tasks, and set the **required `prd`** field to the slug of the source `work/prds/ready/<slug>.md` (so `covers` story numbers are unambiguous — see `WORK-CONTRACT.md`).
|
|
72
|
+
|
|
73
|
+
### 6. Trim the spec to its durable framing (one-time)
|
|
74
|
+
|
|
75
|
+
The spec is a launch snapshot (see the `to-spec` skill). Now that the work is tasked, the spec's **technical detail is redundant** (it lives in the tasks) and is the part that would otherwise go stale. Do a ONE-TIME trim:
|
|
76
|
+
|
|
77
|
+
- The tasks now own _what to build_ (Implementation/Testing detail) — remove those sections from the spec.
|
|
78
|
+
- Any **durable rationale** worth keeping (the _why_ of a decision) is RELOCATED to an ADR (`docs/adr/<slug>.md`), not deleted.
|
|
79
|
+
- The spec settles to its durable framing: Problem / Solution / User Stories / Out of Scope (+ its launch-snapshot banner). Leave a one-line pointer that detail moved to tasks/ADRs.
|
|
80
|
+
- **Move the spec to `work/prds/tasked/`** to record that it has been tasked: `git mv work/prds/<src>/<slug>.md work/prds/tasked/<slug>.md`, where `<src>` is the spec's CURRENT non-pool resting position — `ready` on the runner/dorfl path, but `proposed` on the human-driven path (a human MAY task a spec straight from `prds/proposed/` without first promoting it to `ready/`; doing so is deliberate — staging keeps it out of the auto-tasking pool so CI cannot race the human, and a forced `proposed → ready` pre-move would re-open exactly that race). The DESTINATION is always `tasked/` regardless of source. Transforming a spec into tasks MUST move it: residence in `work/prds/tasked/` IS tasked-ness (the build-machine `tasks/done/` analogue for specs, the sole signal); a tasked spec left in `proposed/`/`ready/` both lies about its state and stays auto-taskable (CI could re-fan-out). Do NOT add a `tasked:` frontmatter marker; the folder is the source of truth. (On the dorfl path `do prd:<slug>` performs this move itself as part of its runner-owned integration commit; this manual step is for the human-driven, no-lock tasking path.)
|
|
81
|
+
|
|
82
|
+
This is a hand-off transition, not ongoing maintenance — after this single trim the spec is stable because the stale-prone part was relocated, not because it is kept in sync. (Nothing is lost: detail → tasks; rationale → ADR.)
|
|
83
|
+
|
|
84
|
+
## Git protocol
|
|
85
|
+
|
|
86
|
+
Do NOT commit/push — leave the work for the caller to inspect/integrate. The one exception is the spec `prds/<ready|proposed>/ → prds/tasked/` relocation above, which is a `git mv` (so it is staged as a rename); leave every other new/edited file unstaged. Report the exact paths written (and the trimmed + relocated spec).
|
|
87
|
+
|
|
88
|
+
When the runner spawns you on the agent tasking path, you EDIT files only — write the task files under the STAGING folder, trim the spec — and the RUNNER owns every git-state transition (it commits the produced tasks, releases the tasking lock, and moves the spec into `work/prds/tasked/`). Do not stage, commit, push, or move any files yourself. The runner integrates the tasking transition through the shared band (`--propose` PR / `--merge` main) honouring the caller's flags.
|
|
89
|
+
|
|
90
|
+
## The emitted task shape (mirrors `work/protocol/task-template.md`)
|
|
91
|
+
|
|
92
|
+
Each emitted task file is a markdown document with YAML frontmatter, BORN STAGED in `work/tasks/backlog/<slug>.md`. The shape's enforced source of truth is the frontmatter parser code (`parseFrontmatter`) and the templated body in `work/protocol/task-template.md`; this section DESCRIBES it in prose so the spawned agent emits files the parser and the runner read identically.
|
|
93
|
+
|
|
94
|
+
### Required frontmatter fields
|
|
95
|
+
|
|
96
|
+
- **`title:`** — a short, human-readable title for the task (one line).
|
|
97
|
+
- **`slug:`** — the URL-safe content-derived slug; matches the filename `<slug>.md`. Never a counter.
|
|
98
|
+
- **`prd:`** — the slug of the source `work/prds/ready/<prd>.md` this task derives from. REQUIRED when `covers:` is non-empty; OMITTED only on a self-contained chore/refactor (with `covers: []`). Disambiguates `covers:` story numbers.
|
|
99
|
+
- **`blockedBy:`** — a YAML inline list of slugs that must reach `work/tasks/done/` first; `[]` means startable now.
|
|
100
|
+
|
|
101
|
+
### Optional frontmatter axes (omit when undeclared)
|
|
102
|
+
|
|
103
|
+
- **`humanOnly: true`** — gate axis 1 (DECIDED, NARROW): NEVER-for-agents BY NATURE (secrets / release / security / an `AGENTS.md` prohibition). Survives even in the pool `work/tasks/ready/`. OMIT when the task is agent-buildable — "review this before the agent builds" is the POSITION's job (the task is BIRTHED in `work/tasks/backlog/`), NOT `humanOnly`'s.
|
|
104
|
+
- **`needsAnswers: true`** — gate axis 2 (DISCOVERED): open questions block autonomous work. List the questions under an `## Open questions` heading in the body. OMIT when the task launches fully resolved.
|
|
105
|
+
- **`covers:`** — an inline list of user-story numbers within `prd:` this task covers; `[]` (or omitted) means no specific story coverage.
|
|
106
|
+
- **`issue:`** — the GitHub issue number an `intake`-emitted task was transformed from. Carried only when the task is the direct closer for an issue (mutually exclusive with `prd:` carrying the closure via the spec).
|
|
107
|
+
|
|
108
|
+
### Body sections
|
|
109
|
+
|
|
110
|
+
- **`## What to build`** — a concise description of the vertical task — the end-to-end behaviour (a thin path through every layer: schema → logic → API/UI → tests), NOT a layer-by-layer implementation plan. Avoid specific file paths / code snippets (they go stale).
|
|
111
|
+
- **`## Acceptance criteria`** — a bullet list of verifiable / demoable criteria, ending with the test-coverage line and (where applicable) the shared-write isolation rule from `WORK-CONTRACT.md`.
|
|
112
|
+
- **`## Blocked by`** — prose mirror of the frontmatter `blockedBy:`; `None — can start immediately.` when `blockedBy: []`.
|
|
113
|
+
- **`## Prompt`** — self-contained instructions to paste into a fresh agent context: an agent must be able to start from THIS FILE ALONE. State the goal, the relevant domain vocabulary, where to look (by module/concept, not brittle paths), the seams to test at, and what "done" means. Reference any constraining ADRs / findings.
|
|
114
|
+
- **`## Open questions`** — present iff `needsAnswers: true`; lists the unresolved questions blocking autonomous build. Stripped by the apply rung on full resolution.
|
|
115
|
+
|
|
116
|
+
### Placement rule
|
|
117
|
+
|
|
118
|
+
The tasker ALWAYS writes emitted task files to `work/tasks/backlog/` (the STAGING folder). The pool `work/tasks/ready/` is the agent-eligible pool the runner owns the promotion into; a write outside the staging folder is dropped by the runner-deterministic placement resolver. The agent never self-places into the pool.
|
|
119
|
+
|
|
120
|
+
## The on-disk contract
|
|
121
|
+
|
|
122
|
+
The full `work/` layout, slug rules, and frontmatter are in `work/protocol/WORK-CONTRACT.md`. The claim/lifecycle protocol these files are designed to support (consumed by the runner — `dorfl claim`/`do`/`complete`) is in `work/protocol/CLAIM-PROTOCOL.md` — read it so the files you emit are claim-ready, but this discipline does not itself claim or run tasks.
|