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
package/src/work-on.ts
ADDED
|
@@ -0,0 +1,660 @@
|
|
|
1
|
+
import {cpSync, existsSync, mkdirSync, rmSync, statSync} from 'node:fs';
|
|
2
|
+
import {homedir} from 'node:os';
|
|
3
|
+
import {dirname, join, resolve} from 'node:path';
|
|
4
|
+
import {git, runAsync, type RunResult} from './git.js';
|
|
5
|
+
import {performClaim} from './claim-cas.js';
|
|
6
|
+
import {
|
|
7
|
+
encodeRepoKey,
|
|
8
|
+
ensureMirror,
|
|
9
|
+
fetchMirrorMain,
|
|
10
|
+
mirrorPath,
|
|
11
|
+
} from './repo-mirror.js';
|
|
12
|
+
import {
|
|
13
|
+
defaultConfigPath,
|
|
14
|
+
loadConfig,
|
|
15
|
+
saveConfig,
|
|
16
|
+
type Config,
|
|
17
|
+
} from './config.js';
|
|
18
|
+
import {brand} from './brand.js';
|
|
19
|
+
import {workBranchRef} from './slug-namespace.js';
|
|
20
|
+
import type {InteractiveLauncher} from './harness.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* `dorfl work-on` — the HUMAN command to claim a task and create an
|
|
24
|
+
* isolated **worktree in a human-friendly location**, so a person can open their
|
|
25
|
+
* editor and work several tasks in parallel without juggling branches in one
|
|
26
|
+
* checkout. It is the human counterpart to the runner's job worktrees
|
|
27
|
+
* (`workspace.ts`): it is NEVER used by agents, so it never carries the human's
|
|
28
|
+
* secrets into an agent context (see `--copy`).
|
|
29
|
+
*
|
|
30
|
+
* Two invocation forms — the ONLY intended difference between them is **where the
|
|
31
|
+
* worktree's files live**; the claim, the integration semantics, and the
|
|
32
|
+
* starting commit are IDENTICAL:
|
|
33
|
+
*
|
|
34
|
+
* work-on <slug> in-repo: the arbiter remote/URL is inferred from
|
|
35
|
+
* the current repo; the claim runs in that repo.
|
|
36
|
+
* work-on --remote <r> <slug> remote: ensure a hub mirror for <r> (creating
|
|
37
|
+
* it via repo-mirror if absent, exactly like
|
|
38
|
+
* agents do), then claim against it from a
|
|
39
|
+
* throwaway worktree. The remote target is a FLAG
|
|
40
|
+
* (consistent with `do --remote`), not positional.
|
|
41
|
+
*
|
|
42
|
+
* BOTH forms: claim the slug, then ALWAYS `git fetch` and branch the worktree off
|
|
43
|
+
* the **freshly-fetched `<arbiter>/main`** — never a possibly-stale local ref.
|
|
44
|
+
* THIS GUARANTEE is what makes the two forms equivalent: the same slug yields
|
|
45
|
+
* equivalent work either way (same starting commit).
|
|
46
|
+
*
|
|
47
|
+
* The worktree lives under the configured `humanWorktreesDir`
|
|
48
|
+
* (`<dir>/<key>/<slug>/` on branch `work/<slug>`) — prompted + saved on first use,
|
|
49
|
+
* with a sensible suggestion but no silent default, and NEVER under
|
|
50
|
+
* `~/.dorfl/` (that is the agents' area; `work-on` is human-only).
|
|
51
|
+
*
|
|
52
|
+
* A binary cannot `cd` its parent shell, so on success it prints the worktree path
|
|
53
|
+
* + a `cd` hint; `--print-dir` emits the path ONLY (stdout) so the human can
|
|
54
|
+
* install a shell function that actually cd's them:
|
|
55
|
+
*
|
|
56
|
+
* work-on() { cd "$(dorfl work-on "$@" --print-dir)"; }
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
/** The semantic outcome of a `work-on` invocation. */
|
|
60
|
+
export type WorkOnOutcome =
|
|
61
|
+
| 'created' // claimed and created the worktree
|
|
62
|
+
| 'refused' // a readiness refusal (unmet blockedBy without override)
|
|
63
|
+
| 'lost' // lost the claim race (propagated from claim) — NO worktree
|
|
64
|
+
| 'contended' // claim push kept being rejected — NO worktree
|
|
65
|
+
| 'usage-error'; // usage / environment problem
|
|
66
|
+
|
|
67
|
+
export interface WorkOnOptions {
|
|
68
|
+
/** The slug to work on (`work/backlog/<slug>.md`). Required. */
|
|
69
|
+
slug: string;
|
|
70
|
+
/**
|
|
71
|
+
* Remote mode: the remote spec/URL to mirror via `repo-mirror`. When given,
|
|
72
|
+
* `work-on --remote <r> <slug>` ensures a hub mirror (creating it if absent)
|
|
73
|
+
* and claims against it. When omitted, in-repo mode: the arbiter is inferred
|
|
74
|
+
* from `cwd`.
|
|
75
|
+
*/
|
|
76
|
+
remote?: string;
|
|
77
|
+
/** The current working directory (in-repo mode resolves the arbiter from it). */
|
|
78
|
+
cwd: string;
|
|
79
|
+
/**
|
|
80
|
+
* Name of the arbiter git remote in `cwd` (in-repo mode only). Defaults to
|
|
81
|
+
* `origin`. Ignored in remote mode (the mirror's own `origin` is used).
|
|
82
|
+
*/
|
|
83
|
+
arbiter?: string;
|
|
84
|
+
/**
|
|
85
|
+
* Override the readiness guard (`--ignore-not-ready`): claim despite
|
|
86
|
+
* an unmet `blockedBy`, and silence the `needsAnswers` warning. Forwarded to
|
|
87
|
+
* the claim CAS's human-path guard.
|
|
88
|
+
*/
|
|
89
|
+
override?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Comma-separated glob-free filenames (gitignored, untracked files like
|
|
92
|
+
* `.env.local,.env`) to COPY into the new worktree so the project is runnable.
|
|
93
|
+
* Copy, not symlink (tooling-safe). Source = the current repo in-repo mode; in
|
|
94
|
+
* remote mode there is no implicit source, so `--copy` REQUIRES `copyFrom`.
|
|
95
|
+
*/
|
|
96
|
+
copy?: string;
|
|
97
|
+
/**
|
|
98
|
+
* The explicit source dir for `--copy` in remote mode (`--copy-from <path>`).
|
|
99
|
+
* Required when `copy` is set in remote mode; ignored otherwise.
|
|
100
|
+
*/
|
|
101
|
+
copyFrom?: string;
|
|
102
|
+
/** The execution working area for hub mirrors (config `workspacesDir`). */
|
|
103
|
+
workspacesDir?: string;
|
|
104
|
+
/**
|
|
105
|
+
* The human worktree root (config `humanWorktreesDir`). When already
|
|
106
|
+
* configured this is used directly; when undefined, `promptForRoot` is invoked
|
|
107
|
+
* to obtain + SAVE it (first-use prompt). Tests pass it directly to avoid TTY.
|
|
108
|
+
*/
|
|
109
|
+
humanWorktreesDir?: string;
|
|
110
|
+
/**
|
|
111
|
+
* First-use prompt for the human worktree root. Called only when
|
|
112
|
+
* `humanWorktreesDir` is undefined (in config + options). Receives a sensible
|
|
113
|
+
* SUGGESTION; returns the chosen absolute path (or '' to abort). The CLI wires
|
|
114
|
+
* a readline prompt; tests inject a stub.
|
|
115
|
+
*/
|
|
116
|
+
promptForRoot?: (suggestion: string) => Promise<string> | string;
|
|
117
|
+
/**
|
|
118
|
+
* Persist a newly-prompted `humanWorktreesDir`. The CLI wires this to
|
|
119
|
+
* `saveConfig` at `configPath`; tests can inject a spy or a no-op.
|
|
120
|
+
*/
|
|
121
|
+
saveRoot?: (dir: string) => void;
|
|
122
|
+
/**
|
|
123
|
+
* `--agent` (task `agent-interactive-launch`): after the human worktree is
|
|
124
|
+
* created, launch the configured harness INTERACTIVELY in THAT worktree — a
|
|
125
|
+
* foreground session the human drives (no prepared prompt). Injected as a thin
|
|
126
|
+
* launcher so `work-on.ts` stays decoupled from `createHarness`: the CLI wires
|
|
127
|
+
* it to the resolved harness's `launchInteractive` (model/session resolved
|
|
128
|
+
* there). Omitted ⇒ work-on creates the worktree and prints the cd hint (its
|
|
129
|
+
* historical behaviour). It is NOT a tracked job (decision #3): no job record,
|
|
130
|
+
* no gate — after exit the human drives `complete`/`requeue`.
|
|
131
|
+
*/
|
|
132
|
+
launchInteractive?: InteractiveLauncher;
|
|
133
|
+
/** Environment for child git processes (identity etc.). */
|
|
134
|
+
env?: NodeJS.ProcessEnv;
|
|
135
|
+
/** Sink for human-readable progress + the security notice (stderr). */
|
|
136
|
+
note?: (message: string) => void;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface WorkOnResult {
|
|
140
|
+
exitCode: 0 | 1 | 2 | 3;
|
|
141
|
+
outcome: WorkOnOutcome;
|
|
142
|
+
/** Absolute path to the created worktree (only on success). */
|
|
143
|
+
dir?: string;
|
|
144
|
+
/** The work branch checked out there (`work/<slug>`). */
|
|
145
|
+
branch?: string;
|
|
146
|
+
/** The resolved arbiter URL the worktree branches from. */
|
|
147
|
+
arbiterUrl?: string;
|
|
148
|
+
/** The starting commit (freshly-fetched `<arbiter>/main`) the worktree is cut from. */
|
|
149
|
+
startCommit?: string;
|
|
150
|
+
/** Files copied in via `--copy` (basenames), in order. */
|
|
151
|
+
copied?: string[];
|
|
152
|
+
/** Human-readable summary of the terminal condition. */
|
|
153
|
+
message: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const DEFAULT_ARBITER = 'origin';
|
|
157
|
+
|
|
158
|
+
/** Raised for usage/environment errors (exit 1, outcome 'usage-error'). */
|
|
159
|
+
class WorkOnUsageError extends Error {}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Run the `work-on` ritual. Never throws for the expected lost/contended/refused
|
|
163
|
+
* cases — those are returned with the appropriate exit code and NO worktree.
|
|
164
|
+
* Usage/environment problems surface as exit 1.
|
|
165
|
+
*/
|
|
166
|
+
export async function performWorkOn(
|
|
167
|
+
options: WorkOnOptions,
|
|
168
|
+
): Promise<WorkOnResult> {
|
|
169
|
+
const note = options.note ?? (() => {});
|
|
170
|
+
try {
|
|
171
|
+
return await runWorkOn(options, note);
|
|
172
|
+
} catch (err) {
|
|
173
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
174
|
+
return {exitCode: 1, outcome: 'usage-error', message};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async function runWorkOn(
|
|
179
|
+
options: WorkOnOptions,
|
|
180
|
+
note: (m: string) => void,
|
|
181
|
+
): Promise<WorkOnResult> {
|
|
182
|
+
const slug = options.slug;
|
|
183
|
+
if (!slug) {
|
|
184
|
+
throw new WorkOnUsageError(
|
|
185
|
+
'missing <slug>. usage: dorfl work-on <slug> [--remote <r>]',
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
const env = options.env;
|
|
189
|
+
const workspacesDir =
|
|
190
|
+
options.workspacesDir ?? join(homedir(), brand.workdirName);
|
|
191
|
+
|
|
192
|
+
// The human worktree root: configured value wins; otherwise prompt + save on
|
|
193
|
+
// first use (a sensible suggestion, NEVER a silent default; never under
|
|
194
|
+
// ~/.dorfl/).
|
|
195
|
+
const root = await resolveHumanWorktreesRoot(options, note);
|
|
196
|
+
|
|
197
|
+
// Resolve the arbiter URL + a CLAIM CONTEXT (a checkout with the arbiter
|
|
198
|
+
// remote where the CAS runs). The ONLY thing that differs between the two
|
|
199
|
+
// forms is the claim context's location; both fetch + branch off the fresh
|
|
200
|
+
// arbiter main, so the starting commit is identical.
|
|
201
|
+
const ctx = await resolveClaimContext({
|
|
202
|
+
slug,
|
|
203
|
+
remote: options.remote,
|
|
204
|
+
cwd: options.cwd,
|
|
205
|
+
arbiter: options.arbiter ?? DEFAULT_ARBITER,
|
|
206
|
+
workspacesDir,
|
|
207
|
+
env,
|
|
208
|
+
note,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
// Claim FIRST. On a lost/contended/refused claim, create NO worktree
|
|
213
|
+
// (clean failure, exactly like `claim`).
|
|
214
|
+
const claim = await performClaim({
|
|
215
|
+
slug,
|
|
216
|
+
cwd: ctx.claimCwd,
|
|
217
|
+
arbiter: ctx.claimArbiter,
|
|
218
|
+
env,
|
|
219
|
+
humanPath: true,
|
|
220
|
+
override: options.override,
|
|
221
|
+
note,
|
|
222
|
+
});
|
|
223
|
+
if (claim.exitCode !== 0) {
|
|
224
|
+
const outcome: WorkOnOutcome =
|
|
225
|
+
claim.outcome === 'not-ready'
|
|
226
|
+
? 'refused'
|
|
227
|
+
: claim.exitCode === 2
|
|
228
|
+
? 'lost'
|
|
229
|
+
: claim.exitCode === 3
|
|
230
|
+
? 'contended'
|
|
231
|
+
: 'usage-error';
|
|
232
|
+
return {exitCode: claim.exitCode, outcome, message: claim.message};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// The claim landed. Create the human worktree off the FRESHLY-FETCHED
|
|
236
|
+
// arbiter main (which now includes the claim move). We branch from the hub
|
|
237
|
+
// mirror's main so both forms share one branching primitive.
|
|
238
|
+
const created = createHumanWorktree({
|
|
239
|
+
slug,
|
|
240
|
+
root,
|
|
241
|
+
arbiterUrl: ctx.arbiterUrl,
|
|
242
|
+
workspacesDir,
|
|
243
|
+
env,
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// Copy named gitignored files (copy, not symlink) so the project is
|
|
247
|
+
// runnable; print a security notice. Source resolved per mode.
|
|
248
|
+
const copied = copyGitignoredFiles({
|
|
249
|
+
copy: options.copy,
|
|
250
|
+
copyFrom: options.copyFrom,
|
|
251
|
+
remoteMode: ctx.remoteMode,
|
|
252
|
+
inRepoSource: options.cwd,
|
|
253
|
+
destDir: created.dir,
|
|
254
|
+
note,
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
const message = `Created worktree for '${slug}' at ${created.dir} (branch ${created.branch}).`;
|
|
258
|
+
note(message);
|
|
259
|
+
note(`To start working: cd ${created.dir}`);
|
|
260
|
+
|
|
261
|
+
// `--agent` (task `agent-interactive-launch`): launch the configured harness
|
|
262
|
+
// INTERACTIVELY in the freshly-created worktree so the human can immediately
|
|
263
|
+
// drive the agent there. It is NOT a tracked job (decision #3): no record, no
|
|
264
|
+
// gate — it blocks in the foreground until the human exits, then control
|
|
265
|
+
// returns and they drive `complete`/`requeue`. The model/session are bound in
|
|
266
|
+
// the CLI's launcher closure (config lives there).
|
|
267
|
+
if (options.launchInteractive) {
|
|
268
|
+
note(`Launching the configured harness interactively in ${created.dir}.`);
|
|
269
|
+
options.launchInteractive({slug, dir: created.dir, env});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
exitCode: 0,
|
|
274
|
+
outcome: 'created',
|
|
275
|
+
dir: created.dir,
|
|
276
|
+
branch: created.branch,
|
|
277
|
+
arbiterUrl: ctx.arbiterUrl,
|
|
278
|
+
startCommit: created.startCommit,
|
|
279
|
+
copied,
|
|
280
|
+
message,
|
|
281
|
+
};
|
|
282
|
+
} finally {
|
|
283
|
+
ctx.cleanup();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
interface ClaimContext {
|
|
288
|
+
/** Resolved arbiter URL (canonical; used for the hub key + worktree). */
|
|
289
|
+
arbiterUrl: string;
|
|
290
|
+
/** The checkout where the claim CAS runs. */
|
|
291
|
+
claimCwd: string;
|
|
292
|
+
/** The arbiter remote NAME valid inside `claimCwd`. */
|
|
293
|
+
claimArbiter: string;
|
|
294
|
+
/** True iff this is remote mode (no implicit `--copy` source). */
|
|
295
|
+
remoteMode: boolean;
|
|
296
|
+
/** Tear down any throwaway claim worktree. */
|
|
297
|
+
cleanup(): void;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Resolve where + how the claim CAS runs, per mode. The starting commit is
|
|
302
|
+
* guaranteed identical because the claim and the worktree both branch off the
|
|
303
|
+
* freshly-fetched arbiter main; only the claim context's LOCATION differs.
|
|
304
|
+
*/
|
|
305
|
+
async function resolveClaimContext(params: {
|
|
306
|
+
slug: string;
|
|
307
|
+
remote: string | undefined;
|
|
308
|
+
cwd: string;
|
|
309
|
+
arbiter: string;
|
|
310
|
+
workspacesDir: string;
|
|
311
|
+
env: NodeJS.ProcessEnv | undefined;
|
|
312
|
+
note: (m: string) => void;
|
|
313
|
+
}): Promise<ClaimContext> {
|
|
314
|
+
const {remote, cwd, arbiter, workspacesDir, env, note} = params;
|
|
315
|
+
|
|
316
|
+
if (remote === undefined || remote.trim() === '') {
|
|
317
|
+
// IN-REPO: infer the arbiter URL from the current repo; claim runs here.
|
|
318
|
+
if ((await gitSoft(['rev-parse', '--git-dir'], cwd, env)).status !== 0) {
|
|
319
|
+
throw new WorkOnUsageError(
|
|
320
|
+
'not inside a git repository (run inside a clone, or use the remote form: work-on --remote <r> <slug>)',
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
const url = await gitSoft(['remote', 'get-url', arbiter], cwd, env);
|
|
324
|
+
if (url.status !== 0) {
|
|
325
|
+
throw new WorkOnUsageError(
|
|
326
|
+
`no git remote named '${arbiter}' (set one, or pass --arbiter)`,
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
arbiterUrl: url.stdout.trim(),
|
|
331
|
+
claimCwd: cwd,
|
|
332
|
+
claimArbiter: arbiter,
|
|
333
|
+
remoteMode: false,
|
|
334
|
+
cleanup: () => {},
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// REMOTE: ensure a hub mirror for <remote> (create if absent, like agents do)
|
|
339
|
+
// so the worktree can later branch off it. The claim itself needs a normal
|
|
340
|
+
// (non-bare) checkout with an `origin/main` tracking ref + a work tree to
|
|
341
|
+
// commit in, which a bare mirror does not provide — so the claim runs in a
|
|
342
|
+
// THROWAWAY clone of the arbiter URL (removed in cleanup either way).
|
|
343
|
+
//
|
|
344
|
+
// When the mirror already exists we refresh ONLY `main` (non-pruning): a
|
|
345
|
+
// pruning mirror-fetch here would delete the LOCAL-ONLY `work/<slug>` branches
|
|
346
|
+
// of other live human worktrees off this hub.
|
|
347
|
+
const hubPath = mirrorPath(workspacesDir, remote);
|
|
348
|
+
let mirrorUrl: string;
|
|
349
|
+
if (existsSync(hubPath)) {
|
|
350
|
+
mirrorUrl = ensureMirrorUrl(remote);
|
|
351
|
+
fetchMirrorMain(hubPath, env);
|
|
352
|
+
note(`Reusing hub mirror for ${mirrorUrl} at ${hubPath}.`);
|
|
353
|
+
} else {
|
|
354
|
+
const created = ensureMirror({url: remote, workspacesDir, env});
|
|
355
|
+
mirrorUrl = created.url;
|
|
356
|
+
note(`Created hub mirror for ${mirrorUrl} at ${created.path}.`);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const claimDir = join(
|
|
360
|
+
workspacesDir,
|
|
361
|
+
'claim',
|
|
362
|
+
`${encodeRepoKey(mirrorUrl).split('/').join('__')}__${params.slug}`,
|
|
363
|
+
);
|
|
364
|
+
rmSync(claimDir, {recursive: true, force: true});
|
|
365
|
+
mkdirSync(dirname(claimDir), {recursive: true});
|
|
366
|
+
// A lightweight clone whose `origin` IS the arbiter URL — the claim CAS fetches
|
|
367
|
+
// `origin` + branches off `origin/main`, exactly as in the in-repo form.
|
|
368
|
+
git(['clone', '--quiet', mirrorUrl, claimDir], dirname(claimDir), {env});
|
|
369
|
+
|
|
370
|
+
return {
|
|
371
|
+
arbiterUrl: mirrorUrl,
|
|
372
|
+
claimCwd: claimDir,
|
|
373
|
+
claimArbiter: 'origin',
|
|
374
|
+
remoteMode: true,
|
|
375
|
+
cleanup: () => rmSync(claimDir, {recursive: true, force: true}),
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
interface CreatedWorktree {
|
|
380
|
+
dir: string;
|
|
381
|
+
branch: string;
|
|
382
|
+
startCommit: string;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Create the human worktree at `<root>/<key>/<slug>/` on `work/<slug>`, branched
|
|
387
|
+
* off the freshly-fetched hub-mirror `main`. The mirror is (re-)fetched here too,
|
|
388
|
+
* so even in in-repo mode the worktree is cut from the latest arbiter main — the
|
|
389
|
+
* same-starting-commit guarantee.
|
|
390
|
+
*/
|
|
391
|
+
function createHumanWorktree(params: {
|
|
392
|
+
slug: string;
|
|
393
|
+
root: string;
|
|
394
|
+
arbiterUrl: string;
|
|
395
|
+
workspacesDir: string;
|
|
396
|
+
env: NodeJS.ProcessEnv | undefined;
|
|
397
|
+
}): CreatedWorktree {
|
|
398
|
+
const {slug, root, arbiterUrl, workspacesDir, env} = params;
|
|
399
|
+
|
|
400
|
+
// Ensure the hub mirror exists, then refresh ONLY `main` to the latest arbiter
|
|
401
|
+
// tip (which, post-claim, includes the claim move). We do NOT use the pruning
|
|
402
|
+
// mirror-fetch here: this mirror also holds the LOCAL-ONLY `work/<slug>`
|
|
403
|
+
// branches of other live human worktrees, and a pruning fetch would delete
|
|
404
|
+
// (and corrupt) them. fetchMirrorMain refreshes main without touching them.
|
|
405
|
+
const hubPath = mirrorPath(workspacesDir, arbiterUrl);
|
|
406
|
+
let mirrorUrl = arbiterUrl;
|
|
407
|
+
if (existsSync(hubPath)) {
|
|
408
|
+
fetchMirrorMain(hubPath, env);
|
|
409
|
+
} else {
|
|
410
|
+
mirrorUrl = ensureMirror({url: arbiterUrl, workspacesDir, env}).url;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const key = encodeRepoKey(mirrorUrl);
|
|
414
|
+
// `work-on` builds a TASK in a worktree — the task-namespaced work branch.
|
|
415
|
+
const branch = workBranchRef('task', slug);
|
|
416
|
+
const dir = join(root, key, slug);
|
|
417
|
+
|
|
418
|
+
// Clear any stale worktree/branch for this slug (idempotent re-run).
|
|
419
|
+
clearWorktree(hubPath, dir, env);
|
|
420
|
+
pruneBranch(hubPath, branch, env);
|
|
421
|
+
|
|
422
|
+
mkdirSync(dirname(dir), {recursive: true});
|
|
423
|
+
git(['worktree', 'add', '--quiet', '-b', branch, dir, 'main'], hubPath, {
|
|
424
|
+
env,
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
const startCommit = git(['rev-parse', 'HEAD'], dir, {env}).trim();
|
|
428
|
+
return {dir, branch, startCommit};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Copy the named gitignored files into the new worktree (COPY, not symlink). A
|
|
433
|
+
* fresh worktree has NONE of your untracked files, so a project that needs e.g.
|
|
434
|
+
* `.env.local` to run won't run without this. Prints a one-line SECURITY NOTICE
|
|
435
|
+
* naming what was copied and that secrets now live in a second location.
|
|
436
|
+
*
|
|
437
|
+
* Source: the current repo in in-repo mode; in remote mode there is no implicit
|
|
438
|
+
* source, so `--copy` REQUIRES `--copy-from <path>`.
|
|
439
|
+
*/
|
|
440
|
+
function copyGitignoredFiles(params: {
|
|
441
|
+
copy: string | undefined;
|
|
442
|
+
copyFrom: string | undefined;
|
|
443
|
+
remoteMode: boolean;
|
|
444
|
+
inRepoSource: string;
|
|
445
|
+
destDir: string;
|
|
446
|
+
note: (m: string) => void;
|
|
447
|
+
}): string[] {
|
|
448
|
+
const {copy, copyFrom, remoteMode, inRepoSource, destDir, note} = params;
|
|
449
|
+
if (!copy || copy.trim() === '') {
|
|
450
|
+
return [];
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const patterns = copy
|
|
454
|
+
.split(',')
|
|
455
|
+
.map((p) => p.trim())
|
|
456
|
+
.filter((p) => p.length > 0);
|
|
457
|
+
if (patterns.length === 0) {
|
|
458
|
+
return [];
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const source = resolveCopySource({remoteMode, copyFrom, inRepoSource});
|
|
462
|
+
|
|
463
|
+
const copied: string[] = [];
|
|
464
|
+
const missing: string[] = [];
|
|
465
|
+
for (const name of patterns) {
|
|
466
|
+
const from = join(source, name);
|
|
467
|
+
if (!existsSync(from)) {
|
|
468
|
+
missing.push(name);
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
const to = join(destDir, name);
|
|
472
|
+
mkdirSync(dirname(to), {recursive: true});
|
|
473
|
+
// Copy (recursively for dirs); explicitly NOT a symlink, so the worktree is
|
|
474
|
+
// tooling-safe and self-contained.
|
|
475
|
+
cpSync(from, to, {recursive: true});
|
|
476
|
+
copied.push(name);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (missing.length > 0) {
|
|
480
|
+
note(`!! --copy: not found in ${source} (skipped): ${missing.join(', ')}.`);
|
|
481
|
+
}
|
|
482
|
+
if (copied.length > 0) {
|
|
483
|
+
note(
|
|
484
|
+
`!! SECURITY NOTICE: copied ${copied.length} gitignored file(s) into the ` +
|
|
485
|
+
`new worktree: ${copied.join(', ')}. These are real copies (not ` +
|
|
486
|
+
`symlinks) — secrets now live in a SECOND location (${destDir}). ` +
|
|
487
|
+
'Treat that worktree like the source for credential hygiene.',
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
return copied;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/** Resolve the source dir for `--copy`, enforcing `--copy-from` in remote mode. */
|
|
494
|
+
function resolveCopySource(params: {
|
|
495
|
+
remoteMode: boolean;
|
|
496
|
+
copyFrom: string | undefined;
|
|
497
|
+
inRepoSource: string;
|
|
498
|
+
}): string {
|
|
499
|
+
const {remoteMode, copyFrom, inRepoSource} = params;
|
|
500
|
+
if (remoteMode) {
|
|
501
|
+
if (!copyFrom || copyFrom.trim() === '') {
|
|
502
|
+
throw new WorkOnUsageError(
|
|
503
|
+
'--copy needs an explicit source in remote mode: pass --copy-from <path> ' +
|
|
504
|
+
'(there is no current repo to copy gitignored files from).',
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
const src = resolve(copyFrom);
|
|
508
|
+
if (!existsSync(src) || !statSync(src).isDirectory()) {
|
|
509
|
+
throw new WorkOnUsageError(
|
|
510
|
+
`--copy-from path does not exist or is not a directory: ${src}`,
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
return src;
|
|
514
|
+
}
|
|
515
|
+
return inRepoSource;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Resolve the human worktree root: a configured `humanWorktreesDir` wins; else
|
|
520
|
+
* prompt for it (a sensible SUGGESTION, no silent default) and SAVE it, so the
|
|
521
|
+
* human is asked exactly once. NEVER allow a root under `~/.dorfl/` (that
|
|
522
|
+
* is the agents' execution area — work-on is human-only).
|
|
523
|
+
*/
|
|
524
|
+
async function resolveHumanWorktreesRoot(
|
|
525
|
+
options: WorkOnOptions,
|
|
526
|
+
note: (m: string) => void,
|
|
527
|
+
): Promise<string> {
|
|
528
|
+
const configured = options.humanWorktreesDir;
|
|
529
|
+
if (configured && configured.trim() !== '') {
|
|
530
|
+
return assertHumanRoot(resolve(configured));
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (!options.promptForRoot) {
|
|
534
|
+
throw new WorkOnUsageError(
|
|
535
|
+
'humanWorktreesDir is not configured and no prompt is available; set ' +
|
|
536
|
+
'`humanWorktreesDir` in config (a human-only worktree root, NOT under ' +
|
|
537
|
+
'~/.dorfl/).',
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
const suggestion = suggestHumanWorktreesDir();
|
|
542
|
+
const answeredRaw = await options.promptForRoot(suggestion);
|
|
543
|
+
const answered = (answeredRaw ?? '').trim();
|
|
544
|
+
if (answered === '') {
|
|
545
|
+
throw new WorkOnUsageError(
|
|
546
|
+
'no humanWorktreesDir provided — aborting (work-on needs a worktree root).',
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
const chosen = assertHumanRoot(resolve(answered));
|
|
550
|
+
if (options.saveRoot) {
|
|
551
|
+
options.saveRoot(chosen);
|
|
552
|
+
note(`Saved humanWorktreesDir = ${chosen} to config.`);
|
|
553
|
+
}
|
|
554
|
+
return chosen;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Reject a human worktree root under `~/.dorfl/` (the agents' area, ADR
|
|
559
|
+
* §3): work-on is human-only and must never share that space.
|
|
560
|
+
*/
|
|
561
|
+
function assertHumanRoot(dir: string): string {
|
|
562
|
+
const agentArea = join(homedir(), brand.workdirName);
|
|
563
|
+
const normalized = dir.endsWith('/') ? dir.slice(0, -1) : dir;
|
|
564
|
+
if (normalized === agentArea || normalized.startsWith(agentArea + '/')) {
|
|
565
|
+
throw new WorkOnUsageError(
|
|
566
|
+
`humanWorktreesDir must NOT be under ${agentArea} (that is the agents' ` +
|
|
567
|
+
'execution area; work-on is human-only). Choose a separate human dir.',
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
return dir;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* A sensible SUGGESTION for the human worktree root. Deliberately uses a name
|
|
575
|
+
* (`~/worktrees`) that does NOT share a prefix with the usual code dir
|
|
576
|
+
* (`~/dev/...`), so shell tab-completion on the code dir never collides with it.
|
|
577
|
+
* This is only a suggestion — there is no silent default; the human confirms.
|
|
578
|
+
*/
|
|
579
|
+
export function suggestHumanWorktreesDir(): string {
|
|
580
|
+
return join(homedir(), 'worktrees');
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/** Remove a worktree registration from the hub (git's own removal, never rm -rf). */
|
|
584
|
+
function clearWorktree(
|
|
585
|
+
mirrorPath: string,
|
|
586
|
+
dir: string,
|
|
587
|
+
env: NodeJS.ProcessEnv | undefined,
|
|
588
|
+
): void {
|
|
589
|
+
if (existsSync(dir)) {
|
|
590
|
+
try {
|
|
591
|
+
git(['worktree', 'remove', '--force', dir], mirrorPath, {env});
|
|
592
|
+
} catch {
|
|
593
|
+
// not a registered worktree — fall through to a plain rm + prune
|
|
594
|
+
rmSync(dir, {recursive: true, force: true});
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
try {
|
|
598
|
+
git(['worktree', 'prune'], mirrorPath, {env});
|
|
599
|
+
} catch {
|
|
600
|
+
// best-effort
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/** Drop a branch from the hub if it exists (idempotent re-run safety). */
|
|
605
|
+
function pruneBranch(
|
|
606
|
+
mirrorPath: string,
|
|
607
|
+
branch: string,
|
|
608
|
+
env: NodeJS.ProcessEnv | undefined,
|
|
609
|
+
): void {
|
|
610
|
+
try {
|
|
611
|
+
git(['branch', '-D', branch], mirrorPath, {env});
|
|
612
|
+
} catch {
|
|
613
|
+
// branch may not exist
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* The canonical arbiter URL a mirror tracks for a given `remote` spec. The
|
|
619
|
+
* mirror is cloned from `remote`, so the tracked URL is just the trimmed spec
|
|
620
|
+
* (the same value {@link ensureMirror} would resolve from `url`).
|
|
621
|
+
*/
|
|
622
|
+
function ensureMirrorUrl(remote: string): string {
|
|
623
|
+
return remote.trim();
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/** Run git, returning the raw result (no throw) — for soft checks. */
|
|
627
|
+
function gitSoft(
|
|
628
|
+
args: string[],
|
|
629
|
+
cwd: string,
|
|
630
|
+
env: NodeJS.ProcessEnv | undefined,
|
|
631
|
+
): Promise<RunResult> {
|
|
632
|
+
return runAsync('git', args, cwd, {env});
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Resolve `humanWorktreesDir` + `configPath` for the CLI: read config from
|
|
637
|
+
* `configPath` and surface its `humanWorktreesDir` (undefined ⇒ first use). The
|
|
638
|
+
* CLI wires the prompt/save around this; kept here so the wiring is testable.
|
|
639
|
+
*/
|
|
640
|
+
export function loadHumanWorktreesDir(
|
|
641
|
+
configPath: string = defaultConfigPath(),
|
|
642
|
+
): {
|
|
643
|
+
dir: string | undefined;
|
|
644
|
+
config: Config;
|
|
645
|
+
} {
|
|
646
|
+
const config = loadConfig(configPath);
|
|
647
|
+
return {dir: config.humanWorktreesDir, config};
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/** Save a chosen `humanWorktreesDir` back to `configPath`, preserving the rest. */
|
|
651
|
+
export function persistHumanWorktreesDir(
|
|
652
|
+
dir: string,
|
|
653
|
+
configPath: string = defaultConfigPath(),
|
|
654
|
+
): void {
|
|
655
|
+
const config = loadConfig(configPath);
|
|
656
|
+
saveConfig({...config, humanWorktreesDir: dir}, configPath);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Re-export for callers that want the encoding without importing repo-mirror.
|
|
660
|
+
export {encodeRepoKey};
|