dorfl 0.14.2 → 0.15.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 +17 -16
- package/dist/advance-ci-template.d.ts.map +1 -1
- package/dist/advance-ci-template.js +42 -53
- package/dist/advance-ci-template.js.map +1 -1
- package/dist/advance-drivers.d.ts +8 -0
- package/dist/advance-drivers.d.ts.map +1 -1
- package/dist/advance-drivers.js +28 -4
- package/dist/advance-drivers.js.map +1 -1
- package/dist/advance-isolated.d.ts.map +1 -1
- package/dist/advance-isolated.js +3 -2
- package/dist/advance-isolated.js.map +1 -1
- package/dist/advance-lifecycle-template.d.ts +41 -40
- package/dist/advance-lifecycle-template.d.ts.map +1 -1
- package/dist/advance-lifecycle-template.js +309 -489
- package/dist/advance-lifecycle-template.js.map +1 -1
- package/dist/advance-loop-driver.d.ts.map +1 -1
- package/dist/advance-loop-driver.js +3 -2
- package/dist/advance-loop-driver.js.map +1 -1
- package/dist/advance-treeless-publish.d.ts +31 -0
- package/dist/advance-treeless-publish.d.ts.map +1 -1
- package/dist/advance-treeless-publish.js +40 -0
- package/dist/advance-treeless-publish.js.map +1 -1
- package/dist/advance.d.ts +63 -3
- package/dist/advance.d.ts.map +1 -1
- package/dist/advance.js +80 -12
- package/dist/advance.js.map +1 -1
- package/dist/advancing-lock.d.ts +9 -0
- package/dist/advancing-lock.d.ts.map +1 -1
- package/dist/advancing-lock.js +21 -1
- package/dist/advancing-lock.js.map +1 -1
- package/dist/agent-env.d.ts +61 -0
- package/dist/agent-env.d.ts.map +1 -0
- package/dist/agent-env.js +144 -0
- package/dist/agent-env.js.map +1 -0
- package/dist/agent-stop.d.ts +35 -0
- package/dist/agent-stop.d.ts.map +1 -1
- package/dist/agent-stop.js +62 -0
- package/dist/agent-stop.js.map +1 -1
- package/dist/apply-merge-action.d.ts +76 -34
- package/dist/apply-merge-action.d.ts.map +1 -1
- package/dist/apply-merge-action.js +339 -129
- package/dist/apply-merge-action.js.map +1 -1
- package/dist/apply-stuck-action.js +2 -2
- package/dist/apply-stuck-action.js.map +1 -1
- package/dist/ci-agent-result.d.ts +151 -0
- package/dist/ci-agent-result.d.ts.map +1 -0
- package/dist/ci-agent-result.js +314 -0
- package/dist/ci-agent-result.js.map +1 -0
- package/dist/ci-handoff-apply.d.ts +162 -0
- package/dist/ci-handoff-apply.d.ts.map +1 -0
- package/dist/ci-handoff-apply.js +497 -0
- package/dist/ci-handoff-apply.js.map +1 -0
- package/dist/ci-handoff-format.d.ts +369 -0
- package/dist/ci-handoff-format.d.ts.map +1 -0
- package/dist/ci-handoff-format.js +646 -0
- package/dist/ci-handoff-format.js.map +1 -0
- package/dist/ci-handoff-lfs.d.ts +146 -0
- package/dist/ci-handoff-lfs.d.ts.map +1 -0
- package/dist/ci-handoff-lfs.js +397 -0
- package/dist/ci-handoff-lfs.js.map +1 -0
- package/dist/ci-handoff.d.ts +99 -0
- package/dist/ci-handoff.d.ts.map +1 -0
- package/dist/ci-handoff.js +277 -0
- package/dist/ci-handoff.js.map +1 -0
- package/dist/ci-lock-outputs.d.ts +93 -0
- package/dist/ci-lock-outputs.d.ts.map +1 -0
- package/dist/ci-lock-outputs.js +223 -0
- package/dist/ci-lock-outputs.js.map +1 -0
- package/dist/ci-phase-build.d.ts +178 -0
- package/dist/ci-phase-build.d.ts.map +1 -0
- package/dist/ci-phase-build.js +989 -0
- package/dist/ci-phase-build.js.map +1 -0
- package/dist/ci-phase-driver.d.ts +247 -0
- package/dist/ci-phase-driver.d.ts.map +1 -0
- package/dist/ci-phase-driver.js +370 -0
- package/dist/ci-phase-driver.js.map +1 -0
- package/dist/ci-phase-intake.d.ts +172 -0
- package/dist/ci-phase-intake.d.ts.map +1 -0
- package/dist/ci-phase-intake.js +555 -0
- package/dist/ci-phase-intake.js.map +1 -0
- package/dist/ci-phase-tasking.d.ts +205 -0
- package/dist/ci-phase-tasking.d.ts.map +1 -0
- package/dist/ci-phase-tasking.js +906 -0
- package/dist/ci-phase-tasking.js.map +1 -0
- package/dist/ci-phase-treeless.d.ts +224 -0
- package/dist/ci-phase-treeless.d.ts.map +1 -0
- package/dist/ci-phase-treeless.js +1482 -0
- package/dist/ci-phase-treeless.js.map +1 -0
- package/dist/ci-read-token.d.ts +47 -0
- package/dist/ci-read-token.d.ts.map +1 -0
- package/dist/ci-read-token.js +80 -0
- package/dist/ci-read-token.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +447 -22
- package/dist/cli.js.map +1 -1
- package/dist/close-job-template.d.ts +10 -1
- package/dist/close-job-template.d.ts.map +1 -1
- package/dist/close-job-template.js +46 -14
- package/dist/close-job-template.js.map +1 -1
- package/dist/close-job.d.ts +20 -5
- package/dist/close-job.d.ts.map +1 -1
- package/dist/close-job.js +65 -12
- package/dist/close-job.js.map +1 -1
- package/dist/complete.d.ts.map +1 -1
- package/dist/complete.js +20 -1
- package/dist/complete.js.map +1 -1
- package/dist/config.d.ts +41 -44
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -4
- package/dist/config.js.map +1 -1
- package/dist/continue-branch.d.ts +63 -15
- package/dist/continue-branch.d.ts.map +1 -1
- package/dist/continue-branch.js +75 -8
- package/dist/continue-branch.js.map +1 -1
- package/dist/crashed-run-save.d.ts +73 -0
- package/dist/crashed-run-save.d.ts.map +1 -0
- package/dist/crashed-run-save.js +86 -0
- package/dist/crashed-run-save.js.map +1 -0
- package/dist/cwd-section.d.ts.map +1 -1
- package/dist/cwd-section.js +10 -2
- package/dist/cwd-section.js.map +1 -1
- package/dist/decision-engine.d.ts +10 -0
- package/dist/decision-engine.d.ts.map +1 -1
- package/dist/decision-engine.js.map +1 -1
- package/dist/do-config.d.ts +2 -24
- package/dist/do-config.d.ts.map +1 -1
- package/dist/do-config.js +1 -33
- package/dist/do-config.js.map +1 -1
- package/dist/do.d.ts +149 -1
- package/dist/do.d.ts.map +1 -1
- package/dist/do.js +115 -25
- package/dist/do.js.map +1 -1
- package/dist/dorfl-item-template.d.ts +98 -0
- package/dist/dorfl-item-template.d.ts.map +1 -0
- package/dist/dorfl-item-template.js +504 -0
- package/dist/dorfl-item-template.js.map +1 -0
- package/dist/env-config.d.ts.map +1 -1
- package/dist/env-config.js +7 -5
- package/dist/env-config.js.map +1 -1
- package/dist/frontmatter.d.ts +52 -0
- package/dist/frontmatter.d.ts.map +1 -1
- package/dist/frontmatter.js +136 -2
- package/dist/frontmatter.js.map +1 -1
- package/dist/gc.d.ts +13 -0
- package/dist/gc.d.ts.map +1 -1
- package/dist/gc.js +16 -2
- package/dist/gc.js.map +1 -1
- package/dist/git.d.ts +18 -1
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +70 -5
- package/dist/git.js.map +1 -1
- package/dist/harness.d.ts +44 -5
- package/dist/harness.d.ts.map +1 -1
- package/dist/harness.js +24 -1
- package/dist/harness.js.map +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/install-ci-action-pins.d.ts +123 -0
- package/dist/install-ci-action-pins.d.ts.map +1 -0
- package/dist/install-ci-action-pins.js +190 -0
- package/dist/install-ci-action-pins.js.map +1 -0
- package/dist/install-ci-actions-pr-creation.d.ts +70 -0
- package/dist/install-ci-actions-pr-creation.d.ts.map +1 -0
- package/dist/install-ci-actions-pr-creation.js +106 -0
- package/dist/install-ci-actions-pr-creation.js.map +1 -0
- package/dist/install-ci-capabilities/dorfl-item.d.ts +12 -0
- package/dist/install-ci-capabilities/dorfl-item.d.ts.map +1 -0
- package/dist/install-ci-capabilities/dorfl-item.js +26 -0
- package/dist/install-ci-capabilities/dorfl-item.js.map +1 -0
- package/dist/install-ci-core.d.ts +155 -37
- package/dist/install-ci-core.d.ts.map +1 -1
- package/dist/install-ci-core.js +304 -200
- package/dist/install-ci-core.js.map +1 -1
- package/dist/install-ci-github.d.ts +47 -2
- package/dist/install-ci-github.d.ts.map +1 -1
- package/dist/install-ci-github.js +113 -1
- package/dist/install-ci-github.js.map +1 -1
- package/dist/install-ci.d.ts +25 -6
- package/dist/install-ci.d.ts.map +1 -1
- package/dist/install-ci.js +72 -36
- package/dist/install-ci.js.map +1 -1
- package/dist/intake-marker.d.ts +6 -1
- package/dist/intake-marker.d.ts.map +1 -1
- package/dist/intake-marker.js.map +1 -1
- package/dist/intake-triage.d.ts.map +1 -1
- package/dist/intake-triage.js +6 -2
- package/dist/intake-triage.js.map +1 -1
- package/dist/intake-trigger-template.d.ts +31 -25
- package/dist/intake-trigger-template.d.ts.map +1 -1
- package/dist/intake-trigger-template.js +107 -292
- package/dist/intake-trigger-template.js.map +1 -1
- package/dist/intake.d.ts +186 -4
- package/dist/intake.d.ts.map +1 -1
- package/dist/intake.js +533 -416
- package/dist/intake.js.map +1 -1
- package/dist/integration-core.d.ts +154 -1
- package/dist/integration-core.d.ts.map +1 -1
- package/dist/integration-core.js +759 -486
- package/dist/integration-core.js.map +1 -1
- package/dist/integrator.d.ts +12 -0
- package/dist/integrator.d.ts.map +1 -1
- package/dist/integrator.js +21 -0
- package/dist/integrator.js.map +1 -1
- package/dist/isolation.d.ts +12 -2
- package/dist/isolation.d.ts.map +1 -1
- package/dist/isolation.js +19 -8
- package/dist/isolation.js.map +1 -1
- package/dist/item-lock.d.ts +93 -11
- package/dist/item-lock.d.ts.map +1 -1
- package/dist/item-lock.js +233 -65
- package/dist/item-lock.js.map +1 -1
- package/dist/land-question-residue.d.ts +58 -0
- package/dist/land-question-residue.d.ts.map +1 -0
- package/dist/land-question-residue.js +95 -0
- package/dist/land-question-residue.js.map +1 -0
- package/dist/lifecycle-gather.d.ts +16 -0
- package/dist/lifecycle-gather.d.ts.map +1 -1
- package/dist/lifecycle-gather.js +54 -6
- package/dist/lifecycle-gather.js.map +1 -1
- package/dist/merge-answer.d.ts +41 -0
- package/dist/merge-answer.d.ts.map +1 -0
- package/dist/merge-answer.js +60 -0
- package/dist/merge-answer.js.map +1 -0
- package/dist/merge-question-surfacer.d.ts +105 -30
- package/dist/merge-question-surfacer.d.ts.map +1 -1
- package/dist/merge-question-surfacer.js +202 -91
- package/dist/merge-question-surfacer.js.map +1 -1
- package/dist/merge-question-tick.d.ts +64 -0
- package/dist/merge-question-tick.d.ts.map +1 -0
- package/dist/merge-question-tick.js +96 -0
- package/dist/merge-question-tick.js.map +1 -0
- package/dist/mint-adr.d.ts.map +1 -1
- package/dist/mint-adr.js +20 -2
- package/dist/mint-adr.js.map +1 -1
- package/dist/needs-attention.d.ts +72 -2
- package/dist/needs-attention.d.ts.map +1 -1
- package/dist/needs-attention.js +275 -38
- package/dist/needs-attention.js.map +1 -1
- package/dist/phase-recorder.d.ts +168 -0
- package/dist/phase-recorder.d.ts.map +1 -0
- package/dist/phase-recorder.js +218 -0
- package/dist/phase-recorder.js.map +1 -0
- package/dist/phase.d.ts +94 -0
- package/dist/phase.d.ts.map +1 -0
- package/dist/phase.js +148 -0
- package/dist/phase.js.map +1 -0
- package/dist/pi-harness.d.ts.map +1 -1
- package/dist/pi-harness.js +19 -6
- package/dist/pi-harness.js.map +1 -1
- package/dist/prepare.d.ts.map +1 -1
- package/dist/prepare.js +4 -0
- package/dist/prepare.js.map +1 -1
- package/dist/prompt.d.ts +4 -0
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +48 -1
- package/dist/prompt.js.map +1 -1
- package/dist/protocol/CLAIM-PROTOCOL.md +3 -1
- package/dist/protocol/WORK-CONTRACT.md +1 -1
- package/dist/reap-branches.d.ts +48 -0
- package/dist/reap-branches.d.ts.map +1 -1
- package/dist/reap-branches.js +64 -0
- package/dist/reap-branches.js.map +1 -1
- package/dist/ref-write.d.ts +198 -0
- package/dist/ref-write.d.ts.map +1 -0
- package/dist/ref-write.js +79 -0
- package/dist/ref-write.js.map +1 -0
- package/dist/repo-config.js +8 -8
- package/dist/repo-config.js.map +1 -1
- package/dist/repo-mirror.d.ts +36 -0
- package/dist/repo-mirror.d.ts.map +1 -1
- package/dist/repo-mirror.js +91 -1
- package/dist/repo-mirror.js.map +1 -1
- package/dist/review-verdict.d.ts +1 -1
- package/dist/review-verdict.js +1 -1
- package/dist/run.d.ts +7 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +28 -4
- package/dist/run.js.map +1 -1
- package/dist/scan.d.ts +19 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +21 -8
- package/dist/scan.js.map +1 -1
- package/dist/sidecar.d.ts +14 -0
- package/dist/sidecar.d.ts.map +1 -1
- package/dist/sidecar.js +21 -0
- package/dist/sidecar.js.map +1 -1
- package/dist/single-job-warning.d.ts +63 -0
- package/dist/single-job-warning.d.ts.map +1 -0
- package/dist/single-job-warning.js +110 -0
- package/dist/single-job-warning.js.map +1 -0
- package/dist/skills/setup/protocol/CLAIM-PROTOCOL.md +3 -1
- package/dist/skills/setup/protocol/WORK-CONTRACT.md +1 -1
- package/dist/spec-complete.d.ts +13 -6
- package/dist/spec-complete.d.ts.map +1 -1
- package/dist/spec-complete.js +23 -11
- package/dist/spec-complete.js.map +1 -1
- package/dist/start.d.ts.map +1 -1
- package/dist/start.js +47 -14
- package/dist/start.js.map +1 -1
- package/dist/status.d.ts +12 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +11 -3
- package/dist/status.js.map +1 -1
- package/dist/tasking.d.ts +246 -1
- package/dist/tasking.d.ts.map +1 -1
- package/dist/tasking.js +452 -358
- package/dist/tasking.js.map +1 -1
- package/dist/triage-persist.d.ts.map +1 -1
- package/dist/triage-persist.js +21 -2
- package/dist/triage-persist.js.map +1 -1
- package/dist/verify-workflow-template.d.ts.map +1 -1
- package/dist/verify-workflow-template.js +8 -4
- package/dist/verify-workflow-template.js.map +1 -1
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +4 -0
- package/dist/verify.js.map +1 -1
- package/dist/watch-session.d.ts +42 -13
- package/dist/watch-session.d.ts.map +1 -1
- package/dist/watch-session.js +52 -23
- package/dist/watch-session.js.map +1 -1
- package/dist/work-layout.d.ts +10 -4
- package/dist/work-layout.d.ts.map +1 -1
- package/dist/work-layout.js +11 -3
- package/dist/work-layout.js.map +1 -1
- package/dist/workspace.d.ts +65 -4
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +159 -11
- package/dist/workspace.js.map +1 -1
- package/package.json +1 -1
- package/src/advance-ci-template.ts +80 -81
- package/src/advance-drivers.ts +45 -6
- package/src/advance-isolated.ts +3 -5
- package/src/advance-lifecycle-template.ts +375 -538
- package/src/advance-loop-driver.ts +3 -5
- package/src/advance-treeless-publish.ts +61 -0
- package/src/advance.ts +145 -15
- package/src/advancing-lock.ts +36 -1
- package/src/agent-env.ts +174 -0
- package/src/agent-stop.ts +81 -0
- package/src/apply-merge-action.ts +401 -154
- package/src/apply-stuck-action.ts +2 -2
- package/src/ci-agent-result.ts +421 -0
- package/src/ci-handoff-apply.ts +737 -0
- package/src/ci-handoff-format.ts +926 -0
- package/src/ci-handoff-lfs.ts +519 -0
- package/src/ci-handoff.ts +392 -0
- package/src/ci-lock-outputs.ts +273 -0
- package/src/ci-phase-build.ts +1328 -0
- package/src/ci-phase-driver.ts +548 -0
- package/src/ci-phase-intake.ts +861 -0
- package/src/ci-phase-tasking.ts +1255 -0
- package/src/ci-phase-treeless.ts +2028 -0
- package/src/ci-read-token.ts +90 -0
- package/src/cli.ts +591 -29
- package/src/close-job-template.ts +52 -15
- package/src/close-job.ts +77 -12
- package/src/complete.ts +19 -1
- package/src/config.ts +43 -48
- package/src/continue-branch.ts +121 -16
- package/src/crashed-run-save.ts +162 -0
- package/src/cwd-section.ts +10 -0
- package/src/decision-engine.ts +10 -0
- package/src/do-config.ts +2 -57
- package/src/do.ts +170 -28
- package/src/dorfl-item-template.ts +556 -0
- package/src/env-config.ts +7 -5
- package/src/frontmatter.ts +155 -2
- package/src/gc.ts +27 -2
- package/src/git.ts +83 -5
- package/src/harness.ts +58 -6
- package/src/index.ts +50 -1
- package/src/install-ci-action-pins.ts +209 -0
- package/src/install-ci-actions-pr-creation.ts +186 -0
- package/src/install-ci-capabilities/dorfl-item.ts +33 -0
- package/src/install-ci-core.ts +388 -233
- package/src/install-ci-github.ts +149 -1
- package/src/install-ci.ts +83 -37
- package/src/intake-marker.ts +6 -1
- package/src/intake-triage.ts +7 -3
- package/src/intake-trigger-template.ts +126 -327
- package/src/intake.ts +725 -544
- package/src/integration-core.ts +975 -523
- package/src/integrator.ts +28 -0
- package/src/isolation.ts +29 -10
- package/src/item-lock.ts +308 -92
- package/src/land-question-residue.ts +122 -0
- package/src/lifecycle-gather.ts +82 -10
- package/src/merge-answer.ts +82 -0
- package/src/merge-question-surfacer.ts +320 -112
- package/src/merge-question-tick.ts +182 -0
- package/src/mint-adr.ts +28 -2
- package/src/needs-attention.ts +350 -42
- package/src/phase-recorder.ts +350 -0
- package/src/phase.ts +177 -0
- package/src/pi-harness.ts +25 -5
- package/src/prepare.ts +4 -0
- package/src/prompt.ts +68 -1
- package/src/reap-branches.ts +107 -0
- package/src/ref-write.ts +324 -0
- package/src/repo-config.ts +8 -8
- package/src/repo-mirror.ts +107 -1
- package/src/review-verdict.ts +1 -1
- package/src/run.ts +47 -6
- package/src/scan.ts +37 -7
- package/src/sidecar.ts +36 -0
- package/src/single-job-warning.ts +135 -0
- package/src/spec-complete.ts +36 -14
- package/src/start.ts +55 -16
- package/src/status.ts +29 -3
- package/src/tasking.ts +593 -378
- package/src/triage-persist.ts +24 -2
- package/src/verify-workflow-template.ts +8 -4
- package/src/verify.ts +4 -0
- package/src/watch-session.ts +86 -28
- package/src/work-layout.ts +11 -3
- package/src/workspace.ts +210 -14
package/src/install-ci-github.ts
CHANGED
|
@@ -5,19 +5,27 @@
|
|
|
5
5
|
* wizard / config / `models.json` / `--export-config` / `--fake` / secret
|
|
6
6
|
* orchestration; THIS adapter only supplies the GitHub-specific I/O (repo
|
|
7
7
|
* detection, `gh secret set`, the optional `delete_branch_on_merge` repo
|
|
8
|
-
* setting
|
|
8
|
+
* setting, branch protection, and the Actions workflow permissions that let
|
|
9
|
+
* GitHub Actions open pull requests). Because the seam is the boundary, a second CI provider could be added
|
|
9
10
|
* WITHOUT touching the core (US #7/#10).
|
|
10
11
|
*
|
|
11
12
|
* `install-ci` uses the SEAMS, never `gh` directly in the core: this adapter is
|
|
12
13
|
* the ONLY place that shells out to `gh`, and it does so behind the seam so tests
|
|
13
14
|
* stub it entirely (no network, no real `gh`, no real GitHub repo detection). The
|
|
14
15
|
* adapter NEVER `--force`s and degrades gracefully when `gh` is missing.
|
|
16
|
+
*
|
|
17
|
+
* WRITE-SEAM EXEMPT (task `ci-split-route-direct-writes-through-seams`): the
|
|
18
|
+
* `gh secret set` / `gh api` writes here (secrets, rulesets, branch protection,
|
|
19
|
+
* repo settings, Actions workflow permissions) are only reached from the human-run `install-ci` wizard, never
|
|
20
|
+
* from a CI job, so they stay on this adapter's own `runGh` wrapper instead of a
|
|
21
|
+
* dorfl write seam.
|
|
15
22
|
*/
|
|
16
23
|
|
|
17
24
|
import {run, type RunResult} from './git.js';
|
|
18
25
|
import {DEFAULT_GH_BIN} from './github.js';
|
|
19
26
|
import {
|
|
20
27
|
parseRepoVisibility,
|
|
28
|
+
type ActionsWorkflowPermissions,
|
|
21
29
|
type CIProviderContext,
|
|
22
30
|
type RepoVisibility,
|
|
23
31
|
} from './install-ci-core.js';
|
|
@@ -366,6 +374,72 @@ export class GitHubCIContext implements CIProviderContext {
|
|
|
366
374
|
}
|
|
367
375
|
}
|
|
368
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Read the repo's Actions workflow permissions via
|
|
379
|
+
* `gh api repos/<repo>/actions/permissions/workflow`. Returns `undefined`
|
|
380
|
+
* when `gh` is unavailable / the repo is unknown / the call fails (it needs
|
|
381
|
+
* repo-admin read on some token kinds) / the answer is not the expected shape.
|
|
382
|
+
*/
|
|
383
|
+
async getActionsWorkflowPermissions(): Promise<
|
|
384
|
+
ActionsWorkflowPermissions | undefined
|
|
385
|
+
> {
|
|
386
|
+
if (!this.repo) {
|
|
387
|
+
return undefined;
|
|
388
|
+
}
|
|
389
|
+
const result = this.runGh([
|
|
390
|
+
'api',
|
|
391
|
+
`repos/${this.repo}/actions/permissions/workflow`,
|
|
392
|
+
]);
|
|
393
|
+
if (result === undefined || result.status !== 0) {
|
|
394
|
+
return undefined;
|
|
395
|
+
}
|
|
396
|
+
return parseActionsWorkflowPermissions(result.stdout);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Set the repo's Actions workflow permissions via
|
|
401
|
+
* `gh api -X PUT repos/<repo>/actions/permissions/workflow`, sending ONLY the
|
|
402
|
+
* fields given (an omitted field keeps its GitHub value). `-F` sends the
|
|
403
|
+
* boolean typed, `-f` the string. Throws on failure.
|
|
404
|
+
*/
|
|
405
|
+
async setActionsWorkflowPermissions(
|
|
406
|
+
permissions: Partial<ActionsWorkflowPermissions>,
|
|
407
|
+
): Promise<void> {
|
|
408
|
+
if (!this.repo) {
|
|
409
|
+
throw new Error('cannot set actions workflow permissions: repo unknown');
|
|
410
|
+
}
|
|
411
|
+
const args = [
|
|
412
|
+
'api',
|
|
413
|
+
'-X',
|
|
414
|
+
'PUT',
|
|
415
|
+
`repos/${this.repo}/actions/permissions/workflow`,
|
|
416
|
+
];
|
|
417
|
+
if (permissions.canApprovePullRequestReviews !== undefined) {
|
|
418
|
+
args.push(
|
|
419
|
+
'-F',
|
|
420
|
+
`can_approve_pull_request_reviews=${permissions.canApprovePullRequestReviews}`,
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
if (permissions.defaultWorkflowPermissions !== undefined) {
|
|
424
|
+
args.push(
|
|
425
|
+
'-f',
|
|
426
|
+
`default_workflow_permissions=${permissions.defaultWorkflowPermissions}`,
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
const result = this.runGh(args);
|
|
430
|
+
if (result === undefined) {
|
|
431
|
+
throw new Error(
|
|
432
|
+
'gh not available; cannot set actions workflow permissions',
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
if (result.status !== 0) {
|
|
436
|
+
throw new Error(
|
|
437
|
+
`gh api PUT repos/${this.repo}/actions/permissions/workflow failed: ` +
|
|
438
|
+
(result.stderr.trim() || 'unknown error'),
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
369
443
|
/**
|
|
370
444
|
* Render the GitHub project-setup payload to the steps fragment the
|
|
371
445
|
* composite setup action splices in FIRST. Free-function delegate so the
|
|
@@ -394,6 +468,37 @@ export class GitHubCIContext implements CIProviderContext {
|
|
|
394
468
|
}
|
|
395
469
|
}
|
|
396
470
|
|
|
471
|
+
/**
|
|
472
|
+
* Parse the JSON body of `GET repos/<r>/actions/permissions/workflow` into
|
|
473
|
+
* {@link ActionsWorkflowPermissions}, or `undefined` when it is not that shape
|
|
474
|
+
* (unparseable, or either field missing / mistyped). Pure, no I/O.
|
|
475
|
+
*/
|
|
476
|
+
export function parseActionsWorkflowPermissions(
|
|
477
|
+
body: string,
|
|
478
|
+
): ActionsWorkflowPermissions | undefined {
|
|
479
|
+
let parsed: unknown;
|
|
480
|
+
try {
|
|
481
|
+
parsed = JSON.parse(body);
|
|
482
|
+
} catch {
|
|
483
|
+
return undefined;
|
|
484
|
+
}
|
|
485
|
+
if (typeof parsed !== 'object' || parsed === null) {
|
|
486
|
+
return undefined;
|
|
487
|
+
}
|
|
488
|
+
const {default_workflow_permissions, can_approve_pull_request_reviews} =
|
|
489
|
+
parsed as Record<string, unknown>;
|
|
490
|
+
if (
|
|
491
|
+
typeof default_workflow_permissions !== 'string' ||
|
|
492
|
+
typeof can_approve_pull_request_reviews !== 'boolean'
|
|
493
|
+
) {
|
|
494
|
+
return undefined;
|
|
495
|
+
}
|
|
496
|
+
return {
|
|
497
|
+
defaultWorkflowPermissions: default_workflow_permissions,
|
|
498
|
+
canApprovePullRequestReviews: can_approve_pull_request_reviews,
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
|
|
397
502
|
/**
|
|
398
503
|
* An in-memory STUB provider context for tests + `--fake` mode: `setSecret`
|
|
399
504
|
* records to memory (NO real secrets store touched), `ghAvailable` is fixed
|
|
@@ -414,6 +519,16 @@ export class MemoryCIProviderContext implements CIProviderContext {
|
|
|
414
519
|
readonly branchProtections = new Map<string, unknown>();
|
|
415
520
|
/** Deadlock-guard rulesets recorded in memory (append-only). */
|
|
416
521
|
readonly rulesets: unknown[] = [];
|
|
522
|
+
/**
|
|
523
|
+
* The Actions workflow permissions: seeded from the fixture, updated by
|
|
524
|
+
* `setActionsWorkflowPermissions`. `undefined` ⇒ the read "fails".
|
|
525
|
+
*/
|
|
526
|
+
actionsWorkflowPermissions: ActionsWorkflowPermissions | undefined;
|
|
527
|
+
/** Every `setActionsWorkflowPermissions` body, in call order (append-only). */
|
|
528
|
+
readonly actionsWorkflowPermissionsSets: Partial<ActionsWorkflowPermissions>[] =
|
|
529
|
+
[];
|
|
530
|
+
/** Whether `setActionsWorkflowPermissions` should throw (tests configure). */
|
|
531
|
+
private readonly actionsWorkflowPermissionsError: string | undefined;
|
|
417
532
|
/** What `getRepoAdminScope()` should return (tests configure). */
|
|
418
533
|
private readonly adminScope: boolean | undefined;
|
|
419
534
|
/** What `getDefaultBranch()` should return (tests configure). */
|
|
@@ -442,6 +557,13 @@ export class MemoryCIProviderContext implements CIProviderContext {
|
|
|
442
557
|
branchProtectionError?: string;
|
|
443
558
|
/** When set, `setBranchRuleset` throws with this message (failure path). */
|
|
444
559
|
branchRulesetError?: string;
|
|
560
|
+
/**
|
|
561
|
+
* Fixture Actions workflow permissions; `undefined` ⇒ the read fails
|
|
562
|
+
* (models a `gh` that could not read the setting).
|
|
563
|
+
*/
|
|
564
|
+
actionsWorkflowPermissions?: ActionsWorkflowPermissions;
|
|
565
|
+
/** When set, `setActionsWorkflowPermissions` throws with this message. */
|
|
566
|
+
actionsWorkflowPermissionsError?: string;
|
|
445
567
|
/**
|
|
446
568
|
* The provider id this stub claims (default `github`). Tests of the
|
|
447
569
|
* project-setup seam may override to assert the orchestrator's
|
|
@@ -458,6 +580,9 @@ export class MemoryCIProviderContext implements CIProviderContext {
|
|
|
458
580
|
this.visibility = options.visibility;
|
|
459
581
|
this.branchProtectionError = options.branchProtectionError;
|
|
460
582
|
this.branchRulesetError = options.branchRulesetError;
|
|
583
|
+
this.actionsWorkflowPermissions = options.actionsWorkflowPermissions;
|
|
584
|
+
this.actionsWorkflowPermissionsError =
|
|
585
|
+
options.actionsWorkflowPermissionsError;
|
|
461
586
|
this.providerId = options.providerId ?? GITHUB_PROVIDER_ID;
|
|
462
587
|
}
|
|
463
588
|
|
|
@@ -498,4 +623,27 @@ export class MemoryCIProviderContext implements CIProviderContext {
|
|
|
498
623
|
}
|
|
499
624
|
this.rulesets.push(ruleset);
|
|
500
625
|
}
|
|
626
|
+
|
|
627
|
+
async getActionsWorkflowPermissions(): Promise<
|
|
628
|
+
ActionsWorkflowPermissions | undefined
|
|
629
|
+
> {
|
|
630
|
+
return this.actionsWorkflowPermissions === undefined
|
|
631
|
+
? undefined
|
|
632
|
+
: {...this.actionsWorkflowPermissions};
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
async setActionsWorkflowPermissions(
|
|
636
|
+
permissions: Partial<ActionsWorkflowPermissions>,
|
|
637
|
+
): Promise<void> {
|
|
638
|
+
if (this.actionsWorkflowPermissionsError !== undefined) {
|
|
639
|
+
throw new Error(this.actionsWorkflowPermissionsError);
|
|
640
|
+
}
|
|
641
|
+
this.actionsWorkflowPermissionsSets.push({...permissions});
|
|
642
|
+
if (this.actionsWorkflowPermissions !== undefined) {
|
|
643
|
+
this.actionsWorkflowPermissions = {
|
|
644
|
+
...this.actionsWorkflowPermissions,
|
|
645
|
+
...permissions,
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
}
|
|
501
649
|
}
|
package/src/install-ci.ts
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
type CapabilityEmitter,
|
|
30
30
|
type SecretSetResult,
|
|
31
31
|
DEFAULT_HARNESS,
|
|
32
|
+
PR_IDENTITY_SECRET_NAME,
|
|
32
33
|
loadCIConfigFile,
|
|
33
34
|
resolveCIConfig,
|
|
34
35
|
exportCIConfig,
|
|
@@ -41,6 +42,10 @@ import {
|
|
|
41
42
|
installCIBranchProtectionStep,
|
|
42
43
|
type BranchProtectionStepResult,
|
|
43
44
|
} from './install-ci-branch-protection.js';
|
|
45
|
+
import {
|
|
46
|
+
installCIActionsPrCreationStep,
|
|
47
|
+
type ActionsPrCreationStepResult,
|
|
48
|
+
} from './install-ci-actions-pr-creation.js';
|
|
44
49
|
|
|
45
50
|
/**
|
|
46
51
|
* The interactive prompt SEAM the wizard drives. Production wires readline; tests
|
|
@@ -105,6 +110,11 @@ export interface InstallCIResult {
|
|
|
105
110
|
secrets: SecretSetResult[];
|
|
106
111
|
/** The Tier-1 branch-protection outcome (undefined on `exported`). */
|
|
107
112
|
branchProtection?: BranchProtectionStepResult;
|
|
113
|
+
/**
|
|
114
|
+
* The "Allow GitHub Actions to create and approve pull requests" outcome
|
|
115
|
+
* (undefined on `exported`).
|
|
116
|
+
*/
|
|
117
|
+
actionsPrCreation?: ActionsPrCreationStepResult;
|
|
108
118
|
}
|
|
109
119
|
|
|
110
120
|
/**
|
|
@@ -311,6 +321,21 @@ export async function installCI(
|
|
|
311
321
|
fake,
|
|
312
322
|
log,
|
|
313
323
|
});
|
|
324
|
+
|
|
325
|
+
// 5c. "Allow GitHub Actions to create and approve pull requests" (task
|
|
326
|
+
// install-ci-enables-actions-pr-creation). Off on a new repo, and with it off
|
|
327
|
+
// GitHub refuses every propose-mode PR the workflows open with GITHUB_TOKEN.
|
|
328
|
+
// Same posture as branch protection: set when off and admin-scoped (keeping
|
|
329
|
+
// default_workflow_permissions), print the exact command otherwise, report
|
|
330
|
+
// only under --fake.
|
|
331
|
+
const actionsPrCreation = await installCIActionsPrCreationStep({
|
|
332
|
+
ctx: options.ctx,
|
|
333
|
+
fake,
|
|
334
|
+
log,
|
|
335
|
+
});
|
|
336
|
+
for (const line of prApprovalReminderLines(secrets)) {
|
|
337
|
+
log(line);
|
|
338
|
+
}
|
|
314
339
|
// CI-autonomy posture (task `install-ci-emits-no-gate-env-let-config-decide`):
|
|
315
340
|
// the emitted advance workflow carries NO DORFL_AUTO_BUILD /
|
|
316
341
|
// DORFL_AUTO_TASK / DORFL_OBSERVATION_TRIAGE /
|
|
@@ -361,7 +386,49 @@ export async function installCI(
|
|
|
361
386
|
log(
|
|
362
387
|
'without that hook the conflicting case is unsupported. install-ci does NOT detect likely conflicts — this is a documented boundary.',
|
|
363
388
|
);
|
|
364
|
-
return {
|
|
389
|
+
return {
|
|
390
|
+
outcome: 'generated',
|
|
391
|
+
config,
|
|
392
|
+
written,
|
|
393
|
+
secrets,
|
|
394
|
+
branchProtection,
|
|
395
|
+
actionsPrCreation,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* The closing-summary note (task `document-that-bot-opened-prs-need-approval`)
|
|
401
|
+
* about GitHub holding the `verify` run of a PR opened with `GITHUB_TOKEN` in
|
|
402
|
+
* `action_required` until someone approves it. When this run did NOT set the
|
|
403
|
+
* PR-identity token (skipped, failed, or `--fake`, where no secret is touched)
|
|
404
|
+
* the advance PRs fall back to `GITHUB_TOKEN`, so the full note is printed. When
|
|
405
|
+
* it was set, only the intake line remains true: `intake.yml` never passes
|
|
406
|
+
* {@link PR_IDENTITY_SECRET_NAME} (`ci-split-generate-workflows` Decisions), so
|
|
407
|
+
* intake PRs always need the approval. See `docs/ci/README.md`.
|
|
408
|
+
*/
|
|
409
|
+
export function prApprovalReminderLines(secrets: SecretSetResult[]): string[] {
|
|
410
|
+
const name = PR_IDENTITY_SECRET_NAME;
|
|
411
|
+
const tokenSet = secrets.some((r) => r.name === name && r.status === 'set');
|
|
412
|
+
const intakeLine = ` - intake PRs always need it: intake.yml keeps the built-in GITHUB_TOKEN and never passes ${name}.`;
|
|
413
|
+
const approveLine =
|
|
414
|
+
' To approve: open the PR, Files changed, "Awaiting approval", "Approve workflows to run" (see docs/ci/README.md).';
|
|
415
|
+
if (tokenSet) {
|
|
416
|
+
return [
|
|
417
|
+
'',
|
|
418
|
+
`PR approval: ${name} is set, so advance PRs trigger verify on their own.`,
|
|
419
|
+
intakeLine,
|
|
420
|
+
approveLine,
|
|
421
|
+
];
|
|
422
|
+
}
|
|
423
|
+
return [
|
|
424
|
+
'',
|
|
425
|
+
`PR approval: no ${name} was set in this run. Unless that secret already exists on the repository,`,
|
|
426
|
+
' the workflows open PRs with GITHUB_TOKEN, and GitHub holds their verify run in "action_required"',
|
|
427
|
+
' until someone with write access approves it:',
|
|
428
|
+
` - advance PRs (build, tasking): set ${name} (a PAT or App token) and they trigger verify on their own;`,
|
|
429
|
+
intakeLine,
|
|
430
|
+
approveLine,
|
|
431
|
+
];
|
|
365
432
|
}
|
|
366
433
|
|
|
367
434
|
/**
|
|
@@ -400,54 +467,33 @@ async function gatherSecretsForExport(
|
|
|
400
467
|
// ─── The interactive wizard ──────────────────────────────────────────────────
|
|
401
468
|
|
|
402
469
|
/**
|
|
403
|
-
* The interactive wizard: gather the
|
|
404
|
-
*
|
|
405
|
-
*
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
470
|
+
* The interactive wizard: gather the providers/models and the harness into a
|
|
471
|
+
* {@link CIConfigFile}. There is no auth-mode prompt: `models-json` is the only
|
|
472
|
+
* mode (the former `auth-json` mode was removed, see {@link AuthMode}); OAuth or
|
|
473
|
+
* other rotating credentials go behind a proxy set as a provider's `baseUrl`.
|
|
474
|
+
* Drives the {@link WizardPrompts} seam, so it runs deterministically in tests
|
|
475
|
+
* and the gathered shape exactly equals a config-file input, the equivalence the
|
|
476
|
+
* snapshot test pins. Mirrors whitesmith's prompt flow (provider type → key env
|
|
477
|
+
* var → models → defaults).
|
|
409
478
|
*/
|
|
410
479
|
export async function runWizard(prompts: WizardPrompts): Promise<CIConfigFile> {
|
|
411
|
-
const authMode = await prompts.select<AuthMode>('Auth mode:', [
|
|
412
|
-
{
|
|
413
|
-
name: 'models.json (default — one GitHub secret per provider key)',
|
|
414
|
-
value: 'models-json',
|
|
415
|
-
},
|
|
416
|
-
{
|
|
417
|
-
name: 'auth.json (single PI_AUTH_JSON + GH_PAT + OAuth refresh — the sharp edge)',
|
|
418
|
-
value: 'auth-json',
|
|
419
|
-
},
|
|
420
|
-
]);
|
|
421
|
-
|
|
422
480
|
const harness = await prompts.select<HarnessAdapter>('Agent harness:', [
|
|
423
481
|
{name: 'pi (the pi coding agent)', value: 'pi'},
|
|
424
482
|
{name: 'null (shell out to a configured agentCmd)', value: 'null'},
|
|
425
483
|
]);
|
|
426
484
|
|
|
427
|
-
if (authMode === 'auth-json') {
|
|
428
|
-
// auth.json mode: no per-provider keys, but the harness still needs a
|
|
429
|
-
// default provider/model for its invocations.
|
|
430
|
-
const defaultProvider = await prompts.input('Default AI provider:', {
|
|
431
|
-
default: 'anthropic',
|
|
432
|
-
});
|
|
433
|
-
const defaultModel = await prompts.input('Default AI model:', {
|
|
434
|
-
default: 'claude-sonnet-4-20250514',
|
|
435
|
-
});
|
|
436
|
-
return {
|
|
437
|
-
authMode,
|
|
438
|
-
providers: [],
|
|
439
|
-
defaultProvider,
|
|
440
|
-
defaultModel,
|
|
441
|
-
harness,
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
|
|
445
485
|
const providers = await promptProviders(prompts);
|
|
446
486
|
const {defaultProvider, defaultModel} = await promptDefaults(
|
|
447
487
|
prompts,
|
|
448
488
|
providers,
|
|
449
489
|
);
|
|
450
|
-
return {
|
|
490
|
+
return {
|
|
491
|
+
authMode: 'models-json',
|
|
492
|
+
providers,
|
|
493
|
+
defaultProvider,
|
|
494
|
+
defaultModel,
|
|
495
|
+
harness,
|
|
496
|
+
};
|
|
451
497
|
}
|
|
452
498
|
|
|
453
499
|
/** Prompt for one or more providers (the models-json path). */
|
package/src/intake-marker.ts
CHANGED
|
@@ -45,7 +45,12 @@ export type IntakeMarkerKind = 'ask' | 'bounced' | 'created';
|
|
|
45
45
|
export interface IntakeMarker {
|
|
46
46
|
/** What intake did (a neutral fact; the TRIAGE owns terminal-ness, not this). */
|
|
47
47
|
kind: IntakeMarkerKind;
|
|
48
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* The HUMAN comment ids intake READ this run (the per-run delta; may be
|
|
50
|
+
* empty). A CI run (task `ci-split-intake`) records EVERY comment id its lock
|
|
51
|
+
* job read (intake's own and already-seen ones included): the apply job has
|
|
52
|
+
* only the ids, and a superset of read ids is harmless to the triage.
|
|
53
|
+
*/
|
|
49
54
|
seen: string[];
|
|
50
55
|
/** The created task/spec slug \u2014 present only on `kind=created`. */
|
|
51
56
|
slug?: string;
|
package/src/intake-triage.ts
CHANGED
|
@@ -89,8 +89,12 @@ export function triageIntake(comments: IssueComment[]): IntakeTriageDecision {
|
|
|
89
89
|
const humanComments = comments.filter(
|
|
90
90
|
(c) => parseIntakeMarker(c.body) === undefined,
|
|
91
91
|
);
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
// EVERY comment id still in the thread (not only the human ones): a CI run's
|
|
93
|
+
// `seen=` lists every comment id its lock job read, intake's own included
|
|
94
|
+
// (task `ci-split-intake`), and an intake comment that is still there was
|
|
95
|
+
// not deleted.
|
|
96
|
+
const currentIds = new Set(
|
|
97
|
+
comments
|
|
94
98
|
.map((c) => c.id)
|
|
95
99
|
.filter((id): id is string => id !== undefined && id !== ''),
|
|
96
100
|
);
|
|
@@ -105,7 +109,7 @@ export function triageIntake(comments: IssueComment[]): IntakeTriageDecision {
|
|
|
105
109
|
// previously-seen human id no longer present in the thread was deleted.
|
|
106
110
|
let deletedSeenCount = 0;
|
|
107
111
|
for (const id of seenSet) {
|
|
108
|
-
if (!
|
|
112
|
+
if (!currentIds.has(id)) {
|
|
109
113
|
deletedSeenCount += 1;
|
|
110
114
|
}
|
|
111
115
|
}
|