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,760 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The provider-agnostic CORE of the `install-ci` scaffolder (prd `runner-in-ci`,
|
|
3
|
+
* task `install-ci-core-and-github-adapter`; US #7/#10). `install-ci` is a
|
|
4
|
+
* human-run, one-time SCAFFOLDER (mirrors whitesmith's `src/providers/github-ci.ts`):
|
|
5
|
+
* it writes `.github/**` + a composite setup action + secrets so autonomous work
|
|
6
|
+
* can run headless in CI. The running CI job NEVER edits `.github/workflows/**`
|
|
7
|
+
* (US #9 — that boundary is enforced by the per-capability workflow tasks; the
|
|
8
|
+
* core stays agnostic to it).
|
|
9
|
+
*
|
|
10
|
+
* This module is the PROVIDER-AGNOSTIC half: the config model (`ProviderEntry` /
|
|
11
|
+
* `AuthMode` / `CIConfigFile`), the `models.json` builder, the secret-orchestration
|
|
12
|
+
* LOGIC (which secrets, dedup, prompt-or-take-from-config), the `--export-config`
|
|
13
|
+
* (+ `--include-secrets`) round-trip, the composite-setup-action + OAuth-refresh-
|
|
14
|
+
* script generators, the `--fake` snapshot mechanism (write to `.fake/` instead of
|
|
15
|
+
* `.github/`), and the capability-emitter REGISTRY seam. It imports NOTHING
|
|
16
|
+
* GitHub-specific: the thin GitHub adapter (`github-ci.ts`) plugs into the
|
|
17
|
+
* {@link CIProviderContext} seam, so a second provider could slot in WITHOUT
|
|
18
|
+
* touching this core.
|
|
19
|
+
*
|
|
20
|
+
* Reuses whitesmith's PATTERNS (the wizard prompts, the `models.json` shape, the
|
|
21
|
+
* config load/export, the `--fake` mechanism, the secret dedup) but NOT its label
|
|
22
|
+
* state-machine or issue lifecycle (out of scope). The auth/config shape carries
|
|
23
|
+
* NO CI-specific policy field: per ADR `ci-config-policy-and-gate-family`, CI
|
|
24
|
+
* policy is the SAME engine gate family resolved via the generated workflow's
|
|
25
|
+
* `DORFL_*` env block, NOT a new config knob minted here.
|
|
26
|
+
*/
|
|
27
|
+
import { readFileSync, writeFileSync, mkdirSync, readdirSync } from 'node:fs';
|
|
28
|
+
import { dirname, join, relative } from 'node:path';
|
|
29
|
+
import { fileURLToPath } from 'node:url';
|
|
30
|
+
/** The default harness the composite setup action installs. */
|
|
31
|
+
export const DEFAULT_HARNESS = 'pi';
|
|
32
|
+
/**
|
|
33
|
+
* The default {@link CIConfigFile.maxParallel}: cap the advance-lifecycle fan-out
|
|
34
|
+
* at 4 concurrent legs. A full agent session per leg, so this keeps the loop
|
|
35
|
+
* draining steadily rather than stampeding the model-provider rate limit + the
|
|
36
|
+
* arbiter CAS. Tunable via `install-ci --max-parallel <n>` / the config file.
|
|
37
|
+
*/
|
|
38
|
+
export const DEFAULT_MAX_PARALLEL = 4;
|
|
39
|
+
/** The default install source: the published CLI via `npm install -g`. */
|
|
40
|
+
export const DEFAULT_INSTALL_SOURCE = 'registry';
|
|
41
|
+
/**
|
|
42
|
+
* The in-memory capability REGISTRY. Capability modules self-register by calling
|
|
43
|
+
* {@link registerCapability} at import time; {@link loadCapabilityRegistry}
|
|
44
|
+
* discovers + imports every module under `install-ci-capabilities/` (a DIRECTORY
|
|
45
|
+
* of emitters, NOT a hand-edited central list), so adding a capability is a NEW
|
|
46
|
+
* file, never an edit to this one.
|
|
47
|
+
*/
|
|
48
|
+
const REGISTRY = new Map();
|
|
49
|
+
/**
|
|
50
|
+
* Register a capability emitter. Idempotent per id (re-registering the same id
|
|
51
|
+
* replaces it — module import is idempotent). Called at import time by each
|
|
52
|
+
* capability module under `install-ci-capabilities/`.
|
|
53
|
+
*/
|
|
54
|
+
export function registerCapability(emitter) {
|
|
55
|
+
REGISTRY.set(emitter.id, emitter);
|
|
56
|
+
}
|
|
57
|
+
/** The currently-registered capabilities (in registration order). */
|
|
58
|
+
export function registeredCapabilities() {
|
|
59
|
+
return [...REGISTRY.values()];
|
|
60
|
+
}
|
|
61
|
+
/** Reset the registry (tests; never used in production). */
|
|
62
|
+
export function clearCapabilityRegistry() {
|
|
63
|
+
REGISTRY.clear();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Locate the `install-ci-capabilities/` directory next to this module — the
|
|
67
|
+
* DIRECTORY of self-registering capability emitters. Resolved relative to this
|
|
68
|
+
* source file so it works from both `src/` (tsx) and `dist/` (the built CLI).
|
|
69
|
+
* `override` short-circuits for tests / unusual layouts.
|
|
70
|
+
*/
|
|
71
|
+
export function resolveCapabilitiesDir(override) {
|
|
72
|
+
if (override) {
|
|
73
|
+
return override;
|
|
74
|
+
}
|
|
75
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
76
|
+
return join(here, 'install-ci-capabilities');
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Discover + import every capability module under `install-ci-capabilities/`,
|
|
80
|
+
* each of which self-registers via {@link registerCapability} at import time.
|
|
81
|
+
* This is the file-orthogonality mechanism: a new capability is a NEW file in
|
|
82
|
+
* that directory, picked up here WITHOUT editing any shared list/switch. Returns
|
|
83
|
+
* the registry after loading. `dir` overrides the directory (tests).
|
|
84
|
+
*/
|
|
85
|
+
export async function loadCapabilityRegistry(dir) {
|
|
86
|
+
const capDir = resolveCapabilitiesDir(dir);
|
|
87
|
+
let entries;
|
|
88
|
+
try {
|
|
89
|
+
entries = readdirSync(capDir);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return registeredCapabilities(); // no directory yet → nothing to load
|
|
93
|
+
}
|
|
94
|
+
// Import each emitter module. Built output is `.js`; source (tsx) is `.ts`.
|
|
95
|
+
const modules = entries
|
|
96
|
+
.filter((f) => /\.(js|ts)$/.test(f) && !/\.d\.ts$/.test(f))
|
|
97
|
+
.sort();
|
|
98
|
+
for (const file of modules) {
|
|
99
|
+
// A path-based dynamic import works under both tsx (src) and node (dist).
|
|
100
|
+
await import(pathToFileUrl(join(capDir, file)));
|
|
101
|
+
}
|
|
102
|
+
return registeredCapabilities();
|
|
103
|
+
}
|
|
104
|
+
/** Convert an absolute path to a `file://` URL for a portable dynamic import. */
|
|
105
|
+
function pathToFileUrl(absPath) {
|
|
106
|
+
return new URL(`file://${absPath}`).href;
|
|
107
|
+
}
|
|
108
|
+
// ─── models.json generation ──────────────────────────────────────────────────
|
|
109
|
+
/**
|
|
110
|
+
* Build the harness `models.json` object from the providers. Built-in providers
|
|
111
|
+
* (`anthropic`/`openai`) get `{apiKey: <ENV_VAR>}` (the harness resolves the env
|
|
112
|
+
* var at runtime); a custom provider carries its `baseUrl`/`api`/`models`/`compat`.
|
|
113
|
+
* Mirrors whitesmith's `buildModelsJson`.
|
|
114
|
+
*/
|
|
115
|
+
export function buildModelsJson(providers) {
|
|
116
|
+
const providersObj = {};
|
|
117
|
+
for (const p of providers) {
|
|
118
|
+
if (p.builtin) {
|
|
119
|
+
const entry = { apiKey: p.apiKeyEnvVar };
|
|
120
|
+
if (p.baseUrl)
|
|
121
|
+
entry.baseUrl = p.baseUrl;
|
|
122
|
+
providersObj[p.name] = entry;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
const entry = {
|
|
126
|
+
baseUrl: p.baseUrl,
|
|
127
|
+
api: p.api,
|
|
128
|
+
apiKey: p.apiKeyEnvVar,
|
|
129
|
+
models: p.models,
|
|
130
|
+
};
|
|
131
|
+
if (p.compat)
|
|
132
|
+
entry.compat = p.compat;
|
|
133
|
+
providersObj[p.name] = entry;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { providers: providersObj };
|
|
137
|
+
}
|
|
138
|
+
// ─── secret-orchestration LOGIC (which secrets, dedup) ───────────────────────
|
|
139
|
+
/**
|
|
140
|
+
* The DEDUPLICATED set of secret env-var names the config requires, in first-seen
|
|
141
|
+
* order. For `models-json` mode it is one per distinct provider `apiKeyEnvVar`;
|
|
142
|
+
* for `auth-json` mode it is the fixed `PI_AUTH_JSON` + `GH_PAT` pair (the sharp
|
|
143
|
+
* edge). This is the pure secret-orchestration LOGIC the adapter's setter
|
|
144
|
+
* consumes — which secrets, deduped — separated from any provider I/O.
|
|
145
|
+
*/
|
|
146
|
+
export function requiredSecretNames(config) {
|
|
147
|
+
if (config.authMode === 'auth-json') {
|
|
148
|
+
return ['PI_AUTH_JSON', 'GH_PAT'];
|
|
149
|
+
}
|
|
150
|
+
const seen = new Set();
|
|
151
|
+
const names = [];
|
|
152
|
+
for (const p of config.providers) {
|
|
153
|
+
if (seen.has(p.apiKeyEnvVar))
|
|
154
|
+
continue;
|
|
155
|
+
seen.add(p.apiKeyEnvVar);
|
|
156
|
+
names.push(p.apiKeyEnvVar);
|
|
157
|
+
}
|
|
158
|
+
return names;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* The GitHub secret the propose/merge CI legs read as `GH_TOKEN` to open PRs
|
|
162
|
+
* under a CHOSEN identity (a PAT / App token). It is the PR-IDENTITY token, a
|
|
163
|
+
* distinct purpose from `auth-json` mode's `GH_PAT` (which exists only to rotate
|
|
164
|
+
* the OAuth `PI_AUTH_JSON` secret). The generated workflows reference it as
|
|
165
|
+
* `${{ secrets.DORFL_GH_TOKEN || secrets.GITHUB_TOKEN }}` so it is
|
|
166
|
+
* OPTIONAL: unset ⇒ the legs fall back to the built-in `GITHUB_TOKEN` (PRs are
|
|
167
|
+
* `github-actions[bot]` and do not trigger downstream `on: pull_request`
|
|
168
|
+
* workflows); set ⇒ PRs carry the token's identity and DO trigger them.
|
|
169
|
+
*/
|
|
170
|
+
export const PR_IDENTITY_SECRET_NAME = 'DORFL_GH_TOKEN';
|
|
171
|
+
/**
|
|
172
|
+
* The DEDUPLICATED set of OPTIONAL secret env-var names install-ci offers but
|
|
173
|
+
* never requires. Today that is the single PR-identity token
|
|
174
|
+
* ({@link PR_IDENTITY_SECRET_NAME}). Kept separate from {@link requiredSecretNames}
|
|
175
|
+
* so "required" stays honestly required (an empty required key still SKIPS, but
|
|
176
|
+
* these are offered as explicitly optional and are never part of the required
|
|
177
|
+
* set the export/validation paths reason about). De-duped against the required
|
|
178
|
+
* names so a token already required (it never is today) is not offered twice.
|
|
179
|
+
*/
|
|
180
|
+
export function optionalSecretNames(config) {
|
|
181
|
+
const required = new Set(requiredSecretNames(config));
|
|
182
|
+
return [PR_IDENTITY_SECRET_NAME].filter((name) => !required.has(name));
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The `with:` block (YAML fragment, leading newline included) the AGENT-RUNNING CI
|
|
186
|
+
* jobs append to their `uses: ./.github/actions/dorfl-setup` line to pass
|
|
187
|
+
* the configured provider API key secret(s) to the setup action ONCE — the action
|
|
188
|
+
* forwards them to `$GITHUB_ENV` so `pi` can authenticate. Indented to attach
|
|
189
|
+
* under a ` - uses: ...` step line (8 spaces for `with:`, 10 for each
|
|
190
|
+
* entry). Each entry maps the action input (named identically to the secret) to
|
|
191
|
+
* `${{ secrets.<NAME> }}`.
|
|
192
|
+
*
|
|
193
|
+
* Empty string when there are no provider keys (auth-json mode, or no providers),
|
|
194
|
+
* so the `uses:` line is emitted bare and unchanged. This is the SINGLE place the
|
|
195
|
+
* provider→`with:` shape lives, shared by every capability workflow generator, so
|
|
196
|
+
* no template re-derives it.
|
|
197
|
+
*/
|
|
198
|
+
export function providerSecretsWithBlock(config) {
|
|
199
|
+
const names = config.authMode === 'models-json' ? requiredSecretNames(config) : [];
|
|
200
|
+
if (names.length === 0) {
|
|
201
|
+
return '';
|
|
202
|
+
}
|
|
203
|
+
const entries = names
|
|
204
|
+
.map((name) => ` ${name}: \${{ secrets.${name} }}`)
|
|
205
|
+
.join('\n');
|
|
206
|
+
return `\n with:\n${entries}`;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Orchestrate the required secrets through the provider seam: for each
|
|
210
|
+
* DEDUPLICATED required name, take its value from `knownSecrets` (the
|
|
211
|
+
* config-file/`--include-secrets` path) when present, else from `prompt` (the
|
|
212
|
+
* interactive path), then record it via `ctx.setSecret`. An empty value is
|
|
213
|
+
* SKIPPED (never set blank); a `setSecret` rejection is reported as `failed`
|
|
214
|
+
* without aborting the rest. Mirrors whitesmith's `setOrPromptSecrets` dedup +
|
|
215
|
+
* prompt-or-take logic, but provider-agnostic (the seam is `ctx.setSecret`).
|
|
216
|
+
*
|
|
217
|
+
* NO real secret is touched in `--fake` mode / tests: the caller passes a STUB
|
|
218
|
+
* `ctx` whose `setSecret` records to memory. This function never reads/writes a
|
|
219
|
+
* real secrets store, `~`, or git config.
|
|
220
|
+
*/
|
|
221
|
+
export async function orchestrateSecrets(options) {
|
|
222
|
+
const { ctx, config, knownSecrets, prompt, optionalPrompt } = options;
|
|
223
|
+
const results = [];
|
|
224
|
+
const processOne = async (name, asker) => {
|
|
225
|
+
let value = knownSecrets?.[name];
|
|
226
|
+
if (value === undefined && asker) {
|
|
227
|
+
value = await asker(name);
|
|
228
|
+
}
|
|
229
|
+
if (!value) {
|
|
230
|
+
results.push({ name, status: 'skipped' });
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
await ctx.setSecret(name, value);
|
|
235
|
+
results.push({ name, status: 'set' });
|
|
236
|
+
}
|
|
237
|
+
catch (err) {
|
|
238
|
+
results.push({
|
|
239
|
+
name,
|
|
240
|
+
status: 'failed',
|
|
241
|
+
error: err instanceof Error ? err.message : String(err),
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
for (const name of requiredSecretNames(config)) {
|
|
246
|
+
await processOne(name, prompt);
|
|
247
|
+
}
|
|
248
|
+
// OPTIONAL secrets (the PR-identity token) come AFTER the required set, are
|
|
249
|
+
// prompted only via `optionalPrompt`, and otherwise behave identically
|
|
250
|
+
// (empty ⇒ skipped, the zero-config fallback).
|
|
251
|
+
for (const name of optionalSecretNames(config)) {
|
|
252
|
+
await processOne(name, optionalPrompt);
|
|
253
|
+
}
|
|
254
|
+
return results;
|
|
255
|
+
}
|
|
256
|
+
// ─── config load + export ────────────────────────────────────────────────────
|
|
257
|
+
/** Raised for a malformed `--config <file>`. */
|
|
258
|
+
export class CIConfigError extends Error {
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Load + validate a `--config <file>`: the non-interactive path that skips all
|
|
262
|
+
* prompts. The loaded config reproduces the wizard's output byte-for-byte. A
|
|
263
|
+
* missing/empty required field is a loud {@link CIConfigError} (never a silent
|
|
264
|
+
* default), because a config file is a deliberate reproduction artifact.
|
|
265
|
+
*/
|
|
266
|
+
export function loadCIConfigFile(filePath) {
|
|
267
|
+
let data;
|
|
268
|
+
try {
|
|
269
|
+
data = JSON.parse(readFileSync(filePath, 'utf8'));
|
|
270
|
+
}
|
|
271
|
+
catch (err) {
|
|
272
|
+
throw new CIConfigError(`could not read/parse config file ${filePath}: ` +
|
|
273
|
+
(err instanceof Error ? err.message : String(err)));
|
|
274
|
+
}
|
|
275
|
+
const authMode = data.authMode ?? 'models-json';
|
|
276
|
+
if (authMode !== 'models-json' && authMode !== 'auth-json') {
|
|
277
|
+
throw new CIConfigError(`config file "authMode" must be "models-json" or "auth-json"`);
|
|
278
|
+
}
|
|
279
|
+
if (!data.defaultProvider) {
|
|
280
|
+
throw new CIConfigError('config file must contain "defaultProvider"');
|
|
281
|
+
}
|
|
282
|
+
if (!data.defaultModel) {
|
|
283
|
+
throw new CIConfigError('config file must contain "defaultModel"');
|
|
284
|
+
}
|
|
285
|
+
if (data.installSource !== undefined &&
|
|
286
|
+
data.installSource !== 'registry' &&
|
|
287
|
+
data.installSource !== 'workspace') {
|
|
288
|
+
throw new CIConfigError(`config file "installSource" must be "registry" or "workspace"`);
|
|
289
|
+
}
|
|
290
|
+
if (data.projectSetup !== undefined) {
|
|
291
|
+
if (data.projectSetup === null ||
|
|
292
|
+
typeof data.projectSetup !== 'object' ||
|
|
293
|
+
Array.isArray(data.projectSetup)) {
|
|
294
|
+
throw new CIConfigError('config file "projectSetup" must be a provider-namespaced object ' +
|
|
295
|
+
'(e.g. {"github": "<native step YAML>"}); ' +
|
|
296
|
+
'the per-provider payload is OPAQUE to the core');
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (authMode === 'models-json') {
|
|
300
|
+
if (!data.providers ||
|
|
301
|
+
!Array.isArray(data.providers) ||
|
|
302
|
+
data.providers.length === 0) {
|
|
303
|
+
throw new CIConfigError('config file (models-json) must contain a non-empty "providers" array');
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
authMode,
|
|
308
|
+
providers: data.providers ?? [],
|
|
309
|
+
defaultProvider: data.defaultProvider,
|
|
310
|
+
defaultModel: data.defaultModel,
|
|
311
|
+
harness: data.harness,
|
|
312
|
+
installSource: data.installSource,
|
|
313
|
+
secrets: data.secrets,
|
|
314
|
+
projectSetup: data.projectSetup,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
/** Resolve a loaded/gathered {@link CIConfigFile} into a {@link ResolvedCIConfig}. */
|
|
318
|
+
export function resolveCIConfig(file) {
|
|
319
|
+
return {
|
|
320
|
+
authMode: file.authMode,
|
|
321
|
+
providers: file.providers,
|
|
322
|
+
defaultProvider: file.defaultProvider,
|
|
323
|
+
defaultModel: file.defaultModel,
|
|
324
|
+
harness: file.harness ?? DEFAULT_HARNESS,
|
|
325
|
+
installSource: file.installSource ?? DEFAULT_INSTALL_SOURCE,
|
|
326
|
+
projectSetup: file.projectSetup,
|
|
327
|
+
maxParallel: file.maxParallel ?? DEFAULT_MAX_PARALLEL,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Serialise a config to the `--export-config` JSON text (stable 2-space indent +
|
|
332
|
+
* trailing newline, exactly the shape {@link loadCIConfigFile} reads back). When
|
|
333
|
+
* `secrets` is supplied (the `--include-secrets` path) it is included; otherwise
|
|
334
|
+
* the `secrets` field is omitted entirely (never an empty object).
|
|
335
|
+
*/
|
|
336
|
+
export function exportCIConfig(config, secrets) {
|
|
337
|
+
const file = {
|
|
338
|
+
authMode: config.authMode,
|
|
339
|
+
providers: config.providers,
|
|
340
|
+
defaultProvider: config.defaultProvider,
|
|
341
|
+
defaultModel: config.defaultModel,
|
|
342
|
+
harness: config.harness,
|
|
343
|
+
installSource: config.installSource,
|
|
344
|
+
};
|
|
345
|
+
// Emit `maxParallel` only when it deviates from the default, so an unchanged
|
|
346
|
+
// config stays minimal (mirrors how projectSetup is omitted when empty).
|
|
347
|
+
if (config.maxParallel !== DEFAULT_MAX_PARALLEL) {
|
|
348
|
+
file.maxParallel = config.maxParallel;
|
|
349
|
+
}
|
|
350
|
+
if (config.projectSetup && Object.keys(config.projectSetup).length > 0) {
|
|
351
|
+
file.projectSetup = config.projectSetup;
|
|
352
|
+
}
|
|
353
|
+
if (secrets && Object.keys(secrets).length > 0) {
|
|
354
|
+
file.secrets = secrets;
|
|
355
|
+
}
|
|
356
|
+
return JSON.stringify(file, null, 2) + '\n';
|
|
357
|
+
}
|
|
358
|
+
// ─── composite setup action + OAuth-refresh script generation ────────────────
|
|
359
|
+
/** Indent every non-blank line of `text` by `spaces` spaces. */
|
|
360
|
+
function indent(text, spaces) {
|
|
361
|
+
const pad = ' '.repeat(spaces);
|
|
362
|
+
return text
|
|
363
|
+
.split('\n')
|
|
364
|
+
.map((line) => (line.trim() === '' ? '' : pad + line))
|
|
365
|
+
.join('\n');
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* The install step for the configured harness (the `pi` CLI; `''` ⇒ none).
|
|
369
|
+
* `registry` mode installs via `npm install -g`; `workspace` mode installs via
|
|
370
|
+
* `pnpm add -g` so the harness lands on the pnpm global bin already on
|
|
371
|
+
* `$GITHUB_PATH` (mirroring whitesmith's dev mode).
|
|
372
|
+
*/
|
|
373
|
+
function harnessInstallStep(harness, installSource) {
|
|
374
|
+
if (harness === 'pi') {
|
|
375
|
+
const run = installSource === 'workspace'
|
|
376
|
+
? 'pnpm add -g @mariozechner/pi-coding-agent'
|
|
377
|
+
: 'npm install -g @mariozechner/pi-coding-agent';
|
|
378
|
+
return `
|
|
379
|
+
- name: Install agent harness (pi)
|
|
380
|
+
shell: bash
|
|
381
|
+
run: ${run}`;
|
|
382
|
+
}
|
|
383
|
+
return '';
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Generate the shared COMPOSITE SETUP ACTION (`dorfl-setup`): installs
|
|
387
|
+
* Node + `dorfl` + the configured harness, configures git identity, and
|
|
388
|
+
* configures AI-provider auth. Written to
|
|
389
|
+
* `<base>/actions/dorfl-setup/action.yml` so a workflow can
|
|
390
|
+
* `uses: ./.github/actions/dorfl-setup`. The advance-loop seed template
|
|
391
|
+
* already references this exact action name + path (`docs/ci/README.md`).
|
|
392
|
+
*
|
|
393
|
+
* The auth step branches on the mode: `models-json` writes a generated
|
|
394
|
+
* `~/.pi/agent/models.json` inline (the conservative default) AND exports each
|
|
395
|
+
* configured provider's API key from a same-named ACTION INPUT to `$GITHUB_ENV`,
|
|
396
|
+
* so the agent step (`pi`) can resolve the env var `models.json` references; the
|
|
397
|
+
* workflow passes the secrets ONCE via `with:` on the `uses:` line (no
|
|
398
|
+
* per-step / per-capability provider enumeration). `auth-json` writes
|
|
399
|
+
* `~/.pi/agent/auth.json` from `$PI_AUTH_JSON` + runs the OAuth-refresh script
|
|
400
|
+
* (the sharp edge). Deterministic: the same config produces byte-identical output.
|
|
401
|
+
*/
|
|
402
|
+
export function generateSetupAction(config,
|
|
403
|
+
/**
|
|
404
|
+
* OPTIONAL provider-rendered project-setup steps fragment, already indented
|
|
405
|
+
* to splice into the composite action's `steps:` body (4-space indent on
|
|
406
|
+
* the `- ` list-item lines). The CORE treats this as OPAQUE: bytes-in ==
|
|
407
|
+
* bytes-out (modulo the indentation the adapter already applied). When
|
|
408
|
+
* absent/empty, the generated action is BYTE-IDENTICAL to the no-hook
|
|
409
|
+
* baseline (the load-bearing absent-⇒-identical contract).
|
|
410
|
+
*/
|
|
411
|
+
projectSetupSteps) {
|
|
412
|
+
let authStep;
|
|
413
|
+
// models-json mode declares one ACTION INPUT per distinct provider key (named
|
|
414
|
+
// identically to the secret / env var) and exports it to `$GITHUB_ENV`, so every
|
|
415
|
+
// later step inherits it. auth-json mode has no provider keys (it uses auth.json).
|
|
416
|
+
const providerKeyNames = config.authMode === 'models-json' ? requiredSecretNames(config) : [];
|
|
417
|
+
if (config.authMode === 'auth-json') {
|
|
418
|
+
authStep = `\
|
|
419
|
+
- name: Configure agent auth (auth.json)
|
|
420
|
+
shell: bash
|
|
421
|
+
run: |
|
|
422
|
+
if [ -z "$PI_AUTH_JSON" ]; then
|
|
423
|
+
echo "ERROR: PI_AUTH_JSON secret is not set" >&2; exit 1
|
|
424
|
+
fi
|
|
425
|
+
mkdir -p ~/.pi/agent
|
|
426
|
+
echo "$PI_AUTH_JSON" > ~/.pi/agent/auth.json
|
|
427
|
+
chmod 600 ~/.pi/agent/auth.json
|
|
428
|
+
|
|
429
|
+
# Workaround for https://github.com/badlogic/pi-mono/issues/2743 — the SINGLE
|
|
430
|
+
# CI→repo mutation in the design; needs GH_PAT to rotate PI_AUTH_JSON.
|
|
431
|
+
- name: Refresh OAuth token
|
|
432
|
+
shell: bash
|
|
433
|
+
run: node .github/scripts/refresh-oauth-token.mjs`;
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
const modelsJsonStr = JSON.stringify(buildModelsJson(config.providers), null, 2);
|
|
437
|
+
// Map each provider-key INPUT into the step env, then append the non-empty
|
|
438
|
+
// ones to `$GITHUB_ENV` so the agent step inherits them. Values flow via env
|
|
439
|
+
// (never interpolated into the script body), and Actions masks the secret in
|
|
440
|
+
// logs. `models.json`'s `apiKey` is the env-var NAME; this puts the value there.
|
|
441
|
+
const exportEnvLines = providerKeyNames
|
|
442
|
+
.map((name) => ` ${name}: \${{ inputs.${name} }}`)
|
|
443
|
+
.join('\n');
|
|
444
|
+
const exportRunLines = providerKeyNames
|
|
445
|
+
.map((name) => ` if [ -n "\${${name}}" ]; then echo "${name}=\${${name}}" >> "$GITHUB_ENV"; fi`)
|
|
446
|
+
.join('\n');
|
|
447
|
+
const exportStep = providerKeyNames.length > 0
|
|
448
|
+
? `\n
|
|
449
|
+
# Surface the configured provider API key(s) to the environment so the agent
|
|
450
|
+
# step (\`pi\`) can resolve the env var \`models.json\` references. The workflow
|
|
451
|
+
# passes the secret(s) via \`with:\` on the \`uses:\` line; we forward the
|
|
452
|
+
# non-empty one(s) to \`$GITHUB_ENV\` (Actions masks the value in logs).
|
|
453
|
+
- name: Export provider API key(s) to the environment
|
|
454
|
+
shell: bash
|
|
455
|
+
env:
|
|
456
|
+
${exportEnvLines}
|
|
457
|
+
run: |
|
|
458
|
+
${exportRunLines}`
|
|
459
|
+
: '';
|
|
460
|
+
authStep = `\
|
|
461
|
+
- name: Configure agent models (models.json)
|
|
462
|
+
shell: bash
|
|
463
|
+
run: |
|
|
464
|
+
mkdir -p ~/.pi/agent
|
|
465
|
+
cat > ~/.pi/agent/models.json << 'MODELS_EOF'
|
|
466
|
+
${indent(modelsJsonStr, 8)}
|
|
467
|
+
MODELS_EOF${exportStep}`;
|
|
468
|
+
}
|
|
469
|
+
const installHarness = harnessInstallStep(config.harness, config.installSource);
|
|
470
|
+
// The CLI-install block branches on installSource. `registry` installs the
|
|
471
|
+
// published CLI via `npm install -g dorfl` (the default for every
|
|
472
|
+
// consumer repo). `workspace` builds the CLI from the checked-out source and
|
|
473
|
+
// links it onto PATH — for the self-hosting dorfl monorepo, which is
|
|
474
|
+
// not published under that npm name. We add pnpm's global bin to $GITHUB_PATH
|
|
475
|
+
// so the linked `dorfl` (and the pnpm-installed harness) are on PATH in
|
|
476
|
+
// all subsequent steps; we always rebuild because source changes per commit.
|
|
477
|
+
let installSteps;
|
|
478
|
+
if (config.installSource === 'workspace') {
|
|
479
|
+
installSteps = `\
|
|
480
|
+
- name: Setup pnpm
|
|
481
|
+
uses: pnpm/action-setup@v4
|
|
482
|
+
|
|
483
|
+
- name: Add pnpm global bin to PATH
|
|
484
|
+
shell: bash
|
|
485
|
+
run: |
|
|
486
|
+
pnpm setup
|
|
487
|
+
echo "$HOME/.local/share/pnpm" >> "$GITHUB_PATH"
|
|
488
|
+
|
|
489
|
+
- name: Install dependencies and build dorfl
|
|
490
|
+
shell: bash
|
|
491
|
+
run: |
|
|
492
|
+
pnpm install
|
|
493
|
+
pnpm -r build
|
|
494
|
+
cd packages/dorfl && pnpm link --global${installHarness}`;
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
installSteps = `\
|
|
498
|
+
- name: Install dorfl
|
|
499
|
+
shell: bash
|
|
500
|
+
run: npm install -g dorfl${installHarness}`;
|
|
501
|
+
}
|
|
502
|
+
// PREFER-LOCAL RESOLVER (task install-ci-prefer-project-local-dorfl,
|
|
503
|
+
// PRD install-ci-project-provisioning axis C1+C3): emit a `dorfl` SHIM
|
|
504
|
+
// that resolves a project-local `node_modules/.bin/dorfl` FIRST (the repo's
|
|
505
|
+
// devDep pin, populated by the project-setup hook's `pnpm install` — C3),
|
|
506
|
+
// and falls back to the global bootstrap dorfl this composite action just
|
|
507
|
+
// installed (C1). Prepended to `$GITHUB_PATH` so EVERY downstream
|
|
508
|
+
// `dorfl <verb>` step in EVERY capability workflow inherits the resolver
|
|
509
|
+
// without each template editing its literal `dorfl` invocation (single
|
|
510
|
+
// shared prefix, no per-capability drift). The captured global path is
|
|
511
|
+
// written to a sibling file so the shim's `command -v` never recurses into
|
|
512
|
+
// itself once the shim dir is on PATH. Applied uniformly in both registry
|
|
513
|
+
// and workspace modes; the workspace-mode install path itself is untouched
|
|
514
|
+
// (the shim runs AFTER the install).
|
|
515
|
+
const resolverStep = `\
|
|
516
|
+
|
|
517
|
+
# Generated by install-ci (task install-ci-prefer-project-local-dorfl):
|
|
518
|
+
# a single shared shim that prefers a project-local node_modules/.bin/dorfl
|
|
519
|
+
# (the repo's devDep pin, C3) over the global bootstrap dorfl just installed
|
|
520
|
+
# (C1), so CI runs the dorfl the repo DECLARES, not a skewed global.
|
|
521
|
+
- name: Install dorfl resolver (prefer project-local over global)
|
|
522
|
+
shell: bash
|
|
523
|
+
run: |
|
|
524
|
+
global_dorfl="$(command -v dorfl || true)"
|
|
525
|
+
if [ -z "$global_dorfl" ]; then
|
|
526
|
+
echo "ERROR: dorfl bootstrap not found on PATH after install" >&2
|
|
527
|
+
exit 1
|
|
528
|
+
fi
|
|
529
|
+
shim_dir="\${RUNNER_TEMP:-/tmp}/dorfl-resolver"
|
|
530
|
+
mkdir -p "$shim_dir"
|
|
531
|
+
printf '%s\\n' "$global_dorfl" > "$shim_dir/global-path"
|
|
532
|
+
# Write the shim via printf (not a heredoc) so the shebang lands at
|
|
533
|
+
# column 0 — a YAML \`run: |\` block's common-indent would otherwise
|
|
534
|
+
# prefix every heredoc line and break the shebang.
|
|
535
|
+
printf '%s\\n' \\
|
|
536
|
+
'#!/usr/bin/env bash' \\
|
|
537
|
+
'# Prefer the project-pinned dorfl (devDep, populated by the' \\
|
|
538
|
+
"# project's dependency install) over the global bootstrap." \\
|
|
539
|
+
'# Generated by install-ci.' \\
|
|
540
|
+
'local_bin="\${GITHUB_WORKSPACE:-$PWD}/node_modules/.bin/dorfl"' \\
|
|
541
|
+
'if [ -x "$local_bin" ]; then' \\
|
|
542
|
+
' exec "$local_bin" "$@"' \\
|
|
543
|
+
'fi' \\
|
|
544
|
+
'global_path_file="$(dirname "$0")/global-path"' \\
|
|
545
|
+
'exec "$(cat "$global_path_file")" "$@"' \\
|
|
546
|
+
> "$shim_dir/dorfl"
|
|
547
|
+
chmod +x "$shim_dir/dorfl"
|
|
548
|
+
echo "$shim_dir" >> "$GITHUB_PATH"`;
|
|
549
|
+
installSteps = installSteps + resolverStep;
|
|
550
|
+
// One optional ACTION INPUT per provider key (models-json mode), named
|
|
551
|
+
// identically to the secret/env var. Optional + default '' so a workflow that
|
|
552
|
+
// does not pass it (or auth-json mode, which declares none) is valid; the export
|
|
553
|
+
// step skips an empty value. auth-json mode declares no inputs.
|
|
554
|
+
const inputsBlock = providerKeyNames.length > 0
|
|
555
|
+
? `inputs:
|
|
556
|
+
${providerKeyNames
|
|
557
|
+
.map((name) => ` ${name}:
|
|
558
|
+
description: 'Provider API key, forwarded to the agent environment as ${name}.'
|
|
559
|
+
required: false
|
|
560
|
+
default: ''`)
|
|
561
|
+
.join('\n')}
|
|
562
|
+
|
|
563
|
+
`
|
|
564
|
+
: '';
|
|
565
|
+
// The project-setup fragment splices in FIRST, before setup-node, dorfl-install,
|
|
566
|
+
// and AI-auth (US #10 of `install-ci-project-provisioning`). Absent/empty ⇒ the
|
|
567
|
+
// emitted text below is byte-identical to the no-hook baseline.
|
|
568
|
+
const projectSetupBlock = projectSetupSteps && projectSetupSteps.length > 0
|
|
569
|
+
? `${projectSetupSteps.replace(/\s+$/, '')}\n\n`
|
|
570
|
+
: '';
|
|
571
|
+
return `\
|
|
572
|
+
name: Setup dorfl
|
|
573
|
+
description: Install Node.js, dorfl, the agent harness, and configure AI provider auth
|
|
574
|
+
|
|
575
|
+
${inputsBlock}# Project-toolchain boundary (task install-ci-document-toolchain-boundary):
|
|
576
|
+
# This composite action provisions ONLY what dorfl + the agent harness need.
|
|
577
|
+
# dorfl declares engines.node '>=18' and only PINS Node 22 below for its own
|
|
578
|
+
# runtime — it does NOT provision the project's own toolchain (a project-
|
|
579
|
+
# pinned package manager, a project Node version, rust, system packages,
|
|
580
|
+
# project-dep install steps, ...).
|
|
581
|
+
# A custom or conflicting project toolchain is supported ONLY via the
|
|
582
|
+
# project-setup hook (sibling task install-ci-project-setup-hook); without
|
|
583
|
+
# that hook the conflicting case is unsupported. install-ci does NOT detect
|
|
584
|
+
# a likely conflict — the boundary is documentation, not detection.
|
|
585
|
+
runs:
|
|
586
|
+
using: composite
|
|
587
|
+
steps:
|
|
588
|
+
${projectSetupBlock} - name: Setup Node.js
|
|
589
|
+
uses: actions/setup-node@v4
|
|
590
|
+
with:
|
|
591
|
+
node-version: '22'
|
|
592
|
+
|
|
593
|
+
- name: Configure git identity
|
|
594
|
+
shell: bash
|
|
595
|
+
run: |
|
|
596
|
+
git config user.name "dorfl[bot]"
|
|
597
|
+
git config user.email "dorfl[bot]@users.noreply.github.com"
|
|
598
|
+
|
|
599
|
+
${installSteps}
|
|
600
|
+
|
|
601
|
+
${authStep}
|
|
602
|
+
`;
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* The OAuth-refresh script emitted ONLY in `auth-json` mode (whitesmith's
|
|
606
|
+
* `pi-mono#2743` workaround): refreshes the Anthropic OAuth token in
|
|
607
|
+
* `~/.pi/agent/auth.json` before the agent runs, then writes the rotated token
|
|
608
|
+
* BACK via `gh secret set PI_AUTH_JSON` (the single CI→repo mutation, needing a
|
|
609
|
+
* `GH_PAT`). This is the documented SHARP EDGE; `models-json` mode avoids it.
|
|
610
|
+
*/
|
|
611
|
+
export const REFRESH_OAUTH_SCRIPT = `\
|
|
612
|
+
#!/usr/bin/env node
|
|
613
|
+
/**
|
|
614
|
+
* Refresh OAuth tokens in the agent's auth.json before it runs.
|
|
615
|
+
*
|
|
616
|
+
* Workaround for https://github.com/badlogic/pi-mono/issues/2743.
|
|
617
|
+
* After refreshing, updates the PI_AUTH_JSON GitHub secret so the next run has
|
|
618
|
+
* the latest rotated refresh token (requires GH_PAT with repo scope). This is the
|
|
619
|
+
* known SHARP EDGE of auth-json mode; models-json mode avoids it entirely.
|
|
620
|
+
*
|
|
621
|
+
* Remove this script once the upstream fix is released.
|
|
622
|
+
*/
|
|
623
|
+
import { readFileSync, writeFileSync, chmodSync } from "fs";
|
|
624
|
+
import { join } from "path";
|
|
625
|
+
import { execSync } from "child_process";
|
|
626
|
+
|
|
627
|
+
const ANTHROPIC_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
628
|
+
const ANTHROPIC_TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
|
|
629
|
+
|
|
630
|
+
const authPath = join(process.env.HOME, ".pi", "agent", "auth.json");
|
|
631
|
+
const auth = JSON.parse(readFileSync(authPath, "utf-8"));
|
|
632
|
+
const cred = auth.anthropic;
|
|
633
|
+
|
|
634
|
+
if (!cred || cred.type !== "oauth") {
|
|
635
|
+
console.log("No OAuth credentials for anthropic, skipping refresh");
|
|
636
|
+
process.exit(0);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
if (Date.now() < cred.expires) {
|
|
640
|
+
console.log("Token still valid until", new Date(cred.expires).toISOString());
|
|
641
|
+
process.exit(0);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
console.log(
|
|
645
|
+
"Token expired at",
|
|
646
|
+
new Date(cred.expires).toISOString(),
|
|
647
|
+
"- refreshing..."
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
const response = await fetch(ANTHROPIC_TOKEN_URL, {
|
|
651
|
+
method: "POST",
|
|
652
|
+
headers: {
|
|
653
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
654
|
+
Accept: "application/json",
|
|
655
|
+
},
|
|
656
|
+
body: new URLSearchParams({
|
|
657
|
+
grant_type: "refresh_token",
|
|
658
|
+
client_id: ANTHROPIC_CLIENT_ID,
|
|
659
|
+
refresh_token: cred.refresh,
|
|
660
|
+
}).toString(),
|
|
661
|
+
signal: AbortSignal.timeout(30_000),
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
const data = await response.json();
|
|
665
|
+
|
|
666
|
+
if (!response.ok) {
|
|
667
|
+
console.error("Refresh failed:", response.status, JSON.stringify(data));
|
|
668
|
+
process.exit(1);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
auth.anthropic = {
|
|
672
|
+
type: "oauth",
|
|
673
|
+
refresh: data.refresh_token,
|
|
674
|
+
access: data.access_token,
|
|
675
|
+
expires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000,
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
writeFileSync(authPath, JSON.stringify(auth, null, 2));
|
|
679
|
+
chmodSync(authPath, 0o600);
|
|
680
|
+
console.log(
|
|
681
|
+
"Token refreshed, new expiry:",
|
|
682
|
+
new Date(auth.anthropic.expires).toISOString()
|
|
683
|
+
);
|
|
684
|
+
|
|
685
|
+
// Update the GitHub secret so the next run has the latest refresh token.
|
|
686
|
+
const repo = process.env.GITHUB_REPOSITORY;
|
|
687
|
+
const token = process.env.GH_PAT;
|
|
688
|
+
if (repo && token) {
|
|
689
|
+
try {
|
|
690
|
+
execSync(\`gh secret set PI_AUTH_JSON --repo "\${repo}"\`, {
|
|
691
|
+
input: JSON.stringify(auth),
|
|
692
|
+
env: { ...process.env, GH_TOKEN: token },
|
|
693
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
694
|
+
});
|
|
695
|
+
console.log("PI_AUTH_JSON secret updated");
|
|
696
|
+
} catch (err) {
|
|
697
|
+
console.warn("Failed to update secret (non-fatal):", err.stderr?.toString() || err.message);
|
|
698
|
+
}
|
|
699
|
+
} else {
|
|
700
|
+
console.log("Skipping secret update (no GH_PAT or GITHUB_REPOSITORY)");
|
|
701
|
+
}
|
|
702
|
+
`;
|
|
703
|
+
// ─── the --fake snapshot mechanism + artifact assembly ───────────────────────
|
|
704
|
+
/**
|
|
705
|
+
* The setup ARTIFACTS this task generates: the composite setup action + (in
|
|
706
|
+
* `auth-json` mode) the OAuth-refresh script, plus any selected capabilities'
|
|
707
|
+
* workflow files. This task emits NO capability workflow itself (those are the
|
|
708
|
+
* sibling tasks); `capabilities` defaults to none.
|
|
709
|
+
*/
|
|
710
|
+
export function buildSetupArtifacts(config, capabilities = [],
|
|
711
|
+
/**
|
|
712
|
+
* OPTIONAL bag of provider-rendered fragments to splice into the generated
|
|
713
|
+
* artifacts. `projectSetupSteps`: see {@link generateSetupAction}. Threaded
|
|
714
|
+
* here so the orchestrator (`installCI`) can pre-render via the active
|
|
715
|
+
* provider seam and keep this core function provider-agnostic.
|
|
716
|
+
*/
|
|
717
|
+
options) {
|
|
718
|
+
const files = [
|
|
719
|
+
{
|
|
720
|
+
path: join('actions', 'dorfl-setup', 'action.yml'),
|
|
721
|
+
content: generateSetupAction(config, options?.projectSetupSteps),
|
|
722
|
+
},
|
|
723
|
+
];
|
|
724
|
+
if (config.authMode === 'auth-json') {
|
|
725
|
+
files.push({
|
|
726
|
+
path: join('scripts', 'refresh-oauth-token.mjs'),
|
|
727
|
+
content: REFRESH_OAUTH_SCRIPT,
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
for (const cap of capabilities) {
|
|
731
|
+
files.push(...cap.emit(config));
|
|
732
|
+
}
|
|
733
|
+
return files;
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* The output base directory name: `.fake` in `--fake` snapshot mode (a scratch
|
|
737
|
+
* dir, NEVER `.github/`), else `.github`. The `--fake` mechanism: write to a
|
|
738
|
+
* `.fake/` scratch dir, never the real `.github/`, and set NO real secret — so
|
|
739
|
+
* the produced files are snapshot-asserted with no side effects on the repo.
|
|
740
|
+
*/
|
|
741
|
+
export function outputBaseName(fake) {
|
|
742
|
+
return fake ? '.fake' : '.github';
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Write the artifacts under `<workDir>/<base>/` (base = `.fake` when `fake`, else
|
|
746
|
+
* `.github`). Returns the repo-relative paths actually written. Pure filesystem
|
|
747
|
+
* I/O — no secrets, no git. Creates parent dirs as needed.
|
|
748
|
+
*/
|
|
749
|
+
export function writeArtifacts(options) {
|
|
750
|
+
const base = outputBaseName(options.fake);
|
|
751
|
+
const written = [];
|
|
752
|
+
for (const file of options.files) {
|
|
753
|
+
const abs = join(options.workDir, base, file.path);
|
|
754
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
755
|
+
writeFileSync(abs, file.content, 'utf8');
|
|
756
|
+
written.push(relative(options.workDir, abs));
|
|
757
|
+
}
|
|
758
|
+
return written;
|
|
759
|
+
}
|
|
760
|
+
//# sourceMappingURL=install-ci-core.js.map
|