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
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
* `advance-lifecycle-template.ts` / `advance-ci-template.ts` (the package depends on
|
|
8
8
|
* NO YAML lib, so the checks are presence/shape assertions over the raw text). It
|
|
9
9
|
* ALSO carries the PURE intake-flags DERIVATION ({@link deriveIntakeFlags}) —
|
|
10
|
-
* CI's merge-vs-propose POLICY
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* CI's merge-vs-propose POLICY. Since the CI split (task
|
|
11
|
+
* `ci-split-generate-workflows`) the workflow no longer derives it in a shell
|
|
12
|
+
* step: the called `dorfl-item.yml` lock job derives the same rule from trusted
|
|
13
|
+
* inputs (`ci-phase-intake.ts`: the event's author association, `dorfl.json`
|
|
14
|
+
* at the base). The DOCUMENT mode is the resolved `intakeIntegration`
|
|
15
|
+
* (operator/config); author-trust drives ONLY the origin-trust stamp +
|
|
13
16
|
* placement, never the mode.
|
|
14
17
|
*
|
|
15
18
|
* SCOPE FENCE (spec Out-of-Scope): the issue→artifact TRANSFORM engine is
|
|
@@ -22,8 +25,10 @@
|
|
|
22
25
|
* RESOLVED design decisions in the task):
|
|
23
26
|
*
|
|
24
27
|
* - TRIGGERS: `issues` opened, `issue_comment` created, and a label
|
|
25
|
-
* (`dorfl:intake`).
|
|
26
|
-
*
|
|
28
|
+
* (`dorfl:intake`). Its one job calls `dorfl-item.yml` with
|
|
29
|
+
* `item: issue:<N>` (lock, agent, apply; decision 10 of ADR
|
|
30
|
+
* `ci-agent-job-holds-no-write-token`), which runs `intake <N>` (EXPLICIT,
|
|
31
|
+
* four-outcome dispatch) — never a bare slug.
|
|
27
32
|
* - EVENT→`IntakeEventKind` MAPPING (Decision 2: no edit-detection): only a
|
|
28
33
|
* CREATED `issue_comment` (and an opened issue / the label) drives
|
|
29
34
|
* (re-)evaluation; an EDITED comment is NOT a trigger (the ID-based
|
|
@@ -58,9 +63,11 @@
|
|
|
58
63
|
* overlapping ticks on the SAME issue; the `processing` lock / claim CAS is the
|
|
59
64
|
* real cross-run serialiser.
|
|
60
65
|
* - The running CI job NEVER edits `.github/workflows/**` (US #9): it requests NO
|
|
61
|
-
* `workflows` permission and cannot rewrite its own triggers. It
|
|
66
|
+
* `workflows` permission and cannot rewrite its own triggers. It grants
|
|
62
67
|
* `contents: write` + `pull-requests: write` (emit/propose the artifact) +
|
|
63
|
-
* `issues: write` (post the clarifying/review comment back)
|
|
68
|
+
* `issues: write` (post the clarifying/review comment back) + `actions` and
|
|
69
|
+
* `checks: read` (the apply job tells a timed-out agent job from a
|
|
70
|
+
* cancelled one), which the called workflow's jobs narrow per job.
|
|
64
71
|
*
|
|
65
72
|
* The structural validator is the dependency-free counterpart of "the workflow
|
|
66
73
|
* parses + carries the right discipline" the task's acceptance criteria require;
|
|
@@ -69,7 +76,10 @@
|
|
|
69
76
|
|
|
70
77
|
import {brand} from './brand.js';
|
|
71
78
|
import type {ResolvedCIConfig} from './install-ci-core.js';
|
|
72
|
-
import {
|
|
79
|
+
import {
|
|
80
|
+
ITEM_WORKFLOW_CALLER_PERMISSIONS,
|
|
81
|
+
itemCallSecrets,
|
|
82
|
+
} from './dorfl-item-template.js';
|
|
73
83
|
|
|
74
84
|
/** The capability id (the registry key + the emitted workflow file stem). */
|
|
75
85
|
export const INTAKE_TRIGGER_CAPABILITY_ID = 'intake';
|
|
@@ -161,9 +171,10 @@ export interface IntakeIntegrationFlags {
|
|
|
161
171
|
* DERIVE the per-outcome file-emit modes + the origin-trust stamp — CI's intake
|
|
162
172
|
* POLICY (ADR `untrusted-origin-carries-via-stamp-not-forced-staging`; spec
|
|
163
173
|
* `intake-integration-knob-and-specs-land-in-proposed-rename` US #1/#2). This is
|
|
164
|
-
* the load-bearing pure
|
|
165
|
-
* resolved `intakeIntegration ?? integration`
|
|
166
|
-
* MODE, and `author_association` off the event payload for the STAMP
|
|
174
|
+
* the load-bearing pure rule the intake lock job applies at runtime (it reads
|
|
175
|
+
* the resolved `intakeIntegration ?? integration` from `dorfl.json` at the base
|
|
176
|
+
* for the MODE, and `author_association` off the event payload for the STAMP;
|
|
177
|
+
* `ci-phase-intake.ts`):
|
|
167
178
|
*
|
|
168
179
|
* - **DOCUMENT mode (spec = task)** — the resolved `intakeIntegration` value, a
|
|
169
180
|
* SINGLE mode applied to BOTH the spec and task document: `merge` ⇒
|
|
@@ -232,27 +243,22 @@ export function isAuthorTrusted(
|
|
|
232
243
|
|
|
233
244
|
/**
|
|
234
245
|
* Generate the intake-trigger workflow YAML. Deterministic: the same config
|
|
235
|
-
* produces byte-identical output.
|
|
236
|
-
* policy is env/config, so the artifact carries no config-derived policy beyond
|
|
237
|
-
* the env-block scaffolding) — `config` is accepted for parity with the
|
|
238
|
-
* `CapabilityEmitter` seam and future per-config wiring, but the intake-trigger
|
|
239
|
-
* shape itself is config-independent.
|
|
246
|
+
* produces byte-identical output.
|
|
240
247
|
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
248
|
+
* THE SPLIT (spec `ci-agent-job-without-write-token`, decision 10 of ADR
|
|
249
|
+
* `ci-agent-job-holds-no-write-token`; task `ci-split-generate-workflows`): the
|
|
250
|
+
* one job CALLS the per-item workflow `dorfl-item.yml` with
|
|
251
|
+
* `item: issue:<N>`, under this workflow's per-issue concurrency group. Its lock
|
|
252
|
+
* job (write token, no agent) takes the `processing` label and DERIVES the
|
|
253
|
+
* intake policy itself: the origin-trust stamp from this run's event
|
|
254
|
+
* (`comment.author_association`, else `issue.author_association`; a called
|
|
255
|
+
* workflow sees its caller's event) and the document mode from
|
|
256
|
+
* `intakeIntegration ?? integration` in `dorfl.json` at the base, the same rule
|
|
257
|
+
* {@link deriveIntakeFlags} states. The decision agent runs in the agent job
|
|
258
|
+
* (read-only token), and the apply job (write token, no agent) posts the
|
|
259
|
+
* comment or integrates the document.
|
|
251
260
|
*/
|
|
252
261
|
export function generateIntakeWorkflow(config: ResolvedCIConfig): string {
|
|
253
|
-
// `intake <N>` runs the prompt→verdict decision (the agent), so it needs the
|
|
254
|
-
// provider secret(s) forwarded to `$GITHUB_ENV` by the setup action.
|
|
255
|
-
const setupWith = providerSecretsWithBlock(config);
|
|
256
262
|
return `\
|
|
257
263
|
# dorfl — the ISSUE INTAKE trigger in CI (capability D: consider incoming
|
|
258
264
|
# issues → task/spec, PLUS insertion point E: surface the review verdict into the
|
|
@@ -267,6 +273,14 @@ export function generateIntakeWorkflow(config: ResolvedCIConfig): string {
|
|
|
267
273
|
# findings as questions back into THIS issue thread via the issue-comment seam (insertion
|
|
268
274
|
# point E) — REUSED, not a new review mechanism.
|
|
269
275
|
#
|
|
276
|
+
# THE SPLIT (ADR ci-agent-job-holds-no-write-token): ANY GitHub user can write
|
|
277
|
+
# the issue text the decision agent reads, so the agent never shares a job with
|
|
278
|
+
# a write token. The one job below calls dorfl-item.yml with
|
|
279
|
+
# \`item: issue:<N>\`: a LOCK job (write token, no agent: takes the \`processing\`
|
|
280
|
+
# label), an AGENT job (read-only token, no persisted credential: runs the
|
|
281
|
+
# decision) and an APPLY job (write token, no agent: validates the agent's
|
|
282
|
+
# handoff as hostile, then comments or integrates the document).
|
|
283
|
+
#
|
|
270
284
|
# TRIGGERS (capability D): an OPENED issue, a CREATED issue comment, and the
|
|
271
285
|
# \`${INTAKE_TRIGGER_LABEL}\` label. A CREATED comment is the (re-)evaluation
|
|
272
286
|
# trigger; an EDITED comment is deliberately NOT a trigger (the ID-based
|
|
@@ -276,31 +290,29 @@ export function generateIntakeWorkflow(config: ResolvedCIConfig): string {
|
|
|
276
290
|
# re-evaluation (a fresh id the watermark catches). There is NO edit-detection /
|
|
277
291
|
# \`updated_at\` / body-hash tracking.
|
|
278
292
|
#
|
|
279
|
-
# THE DOCUMENT MODE is \`intakeIntegration\`; AUTHOR-TRUST → PLACEMENT + the STAMP
|
|
280
|
-
# the
|
|
281
|
-
#
|
|
282
|
-
#
|
|
283
|
-
#
|
|
284
|
-
#
|
|
285
|
-
#
|
|
286
|
-
#
|
|
287
|
-
#
|
|
288
|
-
#
|
|
289
|
-
#
|
|
290
|
-
# \`
|
|
291
|
-
#
|
|
292
|
-
#
|
|
293
|
-
#
|
|
294
|
-
# AND of who filed the issue — so a repo can have autonomy AND merged documents.
|
|
293
|
+
# THE DOCUMENT MODE is \`intakeIntegration\`; AUTHOR-TRUST → PLACEMENT + the STAMP.
|
|
294
|
+
# Both are derived by the item's LOCK job from trusted inputs, never from the
|
|
295
|
+
# agent: the document merge-vs-propose mode is the resolved
|
|
296
|
+
# \`intakeIntegration ?? integration\` in dorfl.json at the base (an
|
|
297
|
+
# operator/config choice, a SINGLE value applied to BOTH the task and spec
|
|
298
|
+
# document, DECOUPLED from the autonomy gates; spec
|
|
299
|
+
# intake-integration-knob-and-specs-land-in-proposed-rename), and the
|
|
300
|
+
# origin-trust stamp comes from THIS run's event: an author outside
|
|
301
|
+
# OWNER/MEMBER/COLLABORATOR (\`comment.author_association\`, else
|
|
302
|
+
# \`issue.author_association\`) is untrusted (ADR
|
|
303
|
+
# untrusted-origin-carries-via-stamp-not-forced-staging). Author-trust drives
|
|
304
|
+
# only (1) the \`originTrust\` STAMP on the emitted document and (2), via that
|
|
305
|
+
# stamp, which PLACEMENT default the document lands in; the untrusted safety is
|
|
306
|
+
# the CARRIED stamp (it forces the later BUILD to a code PR) plus the placement
|
|
307
|
+
# default, not a forced document PR.
|
|
295
308
|
#
|
|
296
309
|
# CI runs IN-PLACE (the CI container IS the isolation): NO --isolated/--remote/
|
|
297
310
|
# registry (laptop-only affordances). The PER-ISSUE concurrency group below
|
|
298
311
|
# serialises overlapping ticks on the SAME issue; the \`processing\` lock / claim
|
|
299
312
|
# CAS is the real cross-run serialiser.
|
|
300
313
|
#
|
|
301
|
-
# SAFETY (US #9):
|
|
302
|
-
#
|
|
303
|
-
# its own triggers.
|
|
314
|
+
# SAFETY (US #9): no job requests a \`workflows\` permission, so none can
|
|
315
|
+
# rewrite its own triggers.
|
|
304
316
|
|
|
305
317
|
name: intake
|
|
306
318
|
|
|
@@ -323,39 +335,14 @@ on:
|
|
|
323
335
|
# triggers landing close together must not run intake on one issue twice at once).
|
|
324
336
|
# The \`processing\` lock / claim CAS is the real cross-run serialiser; this just
|
|
325
337
|
# avoids redundant concurrent ticks. Keyed by the issue number so DIFFERENT issues
|
|
326
|
-
# still run in parallel.
|
|
338
|
+
# still run in parallel. One intake run carries exactly one issue, so no
|
|
339
|
+
# parallelism slot applies here.
|
|
327
340
|
concurrency:
|
|
328
341
|
group: intake-\${{ github.event.issue.number }}
|
|
329
342
|
cancel-in-progress: false
|
|
330
343
|
|
|
331
|
-
#
|
|
332
|
-
|
|
333
|
-
# the artifact; \`issues: write\` posts the clarifying/review comment back into the
|
|
334
|
-
# thread (insertion point E). It never rewrites its triggers.
|
|
335
|
-
permissions:
|
|
336
|
-
contents: write
|
|
337
|
-
pull-requests: write
|
|
338
|
-
issues: write
|
|
339
|
-
|
|
340
|
-
# ── The intake DOCUMENT mode is resolved FROM CONFIG, not carried here ───────
|
|
341
|
-
# CI is NOT a special policy surface (ADR ci-config-policy-and-gate-family §5):
|
|
342
|
-
# it runs the SAME engine config, resolved through flag > env > per-repo > global
|
|
343
|
-
# > default. The SAME dorfl.json the laptop uses applies here. This workflow emits
|
|
344
|
-
# NO DORFL_AUTO_BUILD / DORFL_AUTO_TASK line (ADR
|
|
345
|
-
# untrusted-origin-carries-via-stamp-not-forced-staging: hardcoding them here made
|
|
346
|
-
# the env layer OUTRANK the committed dorfl.json — the shadowing bug). So the env
|
|
347
|
-
# layer carries NO config default; the policy step below READS the resolved intake
|
|
348
|
-
# DOCUMENT mode \`intakeIntegration ?? integration\` via \`dorfl config --json\` (the
|
|
349
|
-
# mechanism \`advance\` already uses), so your committed dorfl.json wins (then the
|
|
350
|
-
# global config, then the built-in default \`propose\`). To land intake documents on
|
|
351
|
-
# main, set \`intakeIntegration: merge\` (or \`integration: merge\`) in dorfl.json
|
|
352
|
-
# (applies everywhere) — NOT by re-running install-ci (ADR §6: install-ci is
|
|
353
|
-
# one-time). The autonomy gates \`autoBuild\`/\`autoTask\` are DECOUPLED from the
|
|
354
|
-
# document mode (spec intake-integration-knob-and-specs-land-in-proposed-rename):
|
|
355
|
-
# they gate autonomy only and are NOT read here. \`intake\` itself is GATE-FREE (the
|
|
356
|
-
# explicit invocation is its own authorization); CI READS only the resolved
|
|
357
|
-
# \`intakeIntegration\`/\`integration\` to DERIVE the merge-vs-propose document flags
|
|
358
|
-
# below (the merge-vs-propose POLICY).
|
|
344
|
+
# Nothing at workflow level: the calling job grants what dorfl-item.yml needs.
|
|
345
|
+
permissions: {}
|
|
359
346
|
|
|
360
347
|
jobs:
|
|
361
348
|
intake:
|
|
@@ -363,124 +350,15 @@ jobs:
|
|
|
363
350
|
# comment on a PR also fires \`issue_comment\`; skip those — there is no issue to
|
|
364
351
|
# intake). \`pull_request\` is absent on a real issue comment.
|
|
365
352
|
if: \${{ github.event.issue.number && !github.event.issue.pull_request }}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
# The intake POLICY, executed at runtime — the SAME rule
|
|
376
|
-
# \`deriveIntakeFlags\` unit-tests (they cannot desync; the test asserts this
|
|
377
|
-
# shell matches the function). The DOCUMENT mode is the resolved
|
|
378
|
-
# \`intakeIntegration ?? integration\` (operator/config), DECOUPLED from the
|
|
379
|
-
# autonomy gates; author-trust drives ONLY the stamp + placement (ADR
|
|
380
|
-
# untrusted-origin-carries-via-stamp-not-forced-staging; spec
|
|
381
|
-
# intake-integration-knob-and-specs-land-in-proposed-rename):
|
|
382
|
-
# * DOCUMENT mode (spec = task) — config-derived: --merge-* iff the
|
|
383
|
-
# resolved intakeIntegration is merge, else --propose-*. A SINGLE
|
|
384
|
-
# value applied to BOTH the spec and task document. autoBuild/
|
|
385
|
-
# autoTask are NOT read (they gate autonomy only).
|
|
386
|
-
# * ORIGIN-TRUST stamp — the ONLY thing author-trust drives: --origin-trust
|
|
387
|
-
# untrusted iff the author is not OWNER/MEMBER/COLLABORATOR, which
|
|
388
|
-
# \`intake\`'s dispatch reads to select the untrusted PLACEMENT
|
|
389
|
-
# default and to force the later BUILD to a code PR.
|
|
390
|
-
# author_association comes from the COMMENT on an \`issue_comment\` event,
|
|
391
|
-
# else the ISSUE on an \`issues\` event — read straight off the payload, no
|
|
392
|
-
# extra API call.
|
|
393
|
-
env:
|
|
394
|
-
AUTHOR_ASSOCIATION: \${{ github.event.comment.author_association || github.event.issue.author_association }}
|
|
395
|
-
run: |
|
|
396
|
-
set -euo pipefail
|
|
397
|
-
|
|
398
|
-
# Read the RESOLVED intake DOCUMENT mode from the committed config via
|
|
399
|
-
# \`dorfl config --json\` (the mechanism \`advance\` already uses), NOT a
|
|
400
|
-
# hardcoded DORFL_* env (ADR
|
|
401
|
-
# untrusted-origin-carries-via-stamp-not-forced-staging: an env default
|
|
402
|
-
# would OUTRANK dorfl.json — the shadowing bug). In-place, so the
|
|
403
|
-
# resolution chain reads THIS repo's dorfl.json exactly like the laptop.
|
|
404
|
-
# \`intakeIntegration\` is OPTIONAL (unset ⇒ falls back to \`integration\`),
|
|
405
|
-
# so read \`.intakeIntegration // .integration\` in ONE jq expression — the
|
|
406
|
-
# shell twin of the \`intakeIntegration ?? integration\` the CLI applies.
|
|
407
|
-
# The autonomy gates (autoBuild/autoTask) are DECOUPLED from the document
|
|
408
|
-
# mode (spec intake-integration-knob-and-specs-land-in-proposed-rename):
|
|
409
|
-
# they gate autonomy only and are NOT read here.
|
|
410
|
-
config_json="$(dorfl config --json)"
|
|
411
|
-
intake_integration="$(echo "\${config_json}" | jq -r '.intakeIntegration // .integration')"
|
|
412
|
-
|
|
413
|
-
# DOCUMENT mode: config-derived from the single \`intakeIntegration ??
|
|
414
|
-
# integration\` value, applied to BOTH the spec and task document (US #1
|
|
415
|
-
# chose one intake knob, not a per-type split). merge ⇒ --merge-*,
|
|
416
|
-
# else --propose-*. Author-trust does NOT bite the mode (ADR
|
|
417
|
-
# untrusted-origin-carries-via-stamp-not-forced-staging): an untrusted
|
|
418
|
-
# author's DOCUMENT merges just like a trusted one; the untrusted safety
|
|
419
|
-
# is the stamp + placement below, not a document PR.
|
|
420
|
-
if [ "\${intake_integration}" = "merge" ]; then
|
|
421
|
-
spec_flag="--merge-spec"
|
|
422
|
-
task_flag="--merge-task"
|
|
423
|
-
else
|
|
424
|
-
spec_flag="--propose-spec"
|
|
425
|
-
task_flag="--propose-task"
|
|
426
|
-
fi
|
|
427
|
-
|
|
428
|
-
# Author-trust: TRUSTED iff OWNER/MEMBER/COLLABORATOR (admin / write-
|
|
429
|
-
# collaborator — the whole signal). Anything else (incl. empty) is
|
|
430
|
-
# UNTRUSTED. It drives ONLY the origin-trust stamp below (NOT the modes).
|
|
431
|
-
trusted="false"
|
|
432
|
-
case "\${AUTHOR_ASSOCIATION:-}" in
|
|
433
|
-
OWNER|MEMBER|COLLABORATOR) trusted="true" ;;
|
|
434
|
-
esac
|
|
435
|
-
|
|
436
|
-
# ORIGIN-TRUST stamp — the SOLE thing author-trust drives on the wire
|
|
437
|
-
# (task untrusted-origin-forces-build-propose). \`intake\` STAMPS this
|
|
438
|
-
# onto the emitted spec/task frontmatter (origin: issue + originTrust:
|
|
439
|
-
# <value>); its dispatch reads the stamp to (1) select the untrusted-side
|
|
440
|
-
# PLACEMENT default (\`untrusted*LandIn\`) and (2) force the later BUILD of
|
|
441
|
-
# an untrusted task to a code PR. It does NOT re-resolve trust (that is
|
|
442
|
-
# CI's policy, passed IN). The stamp SURVIVES the merge boundary so a
|
|
443
|
-
# later auto-task/auto-build of an untrusted-origin artifact still forces
|
|
444
|
-
# a human becomes-code checkpoint (the laundering gap is closed).
|
|
445
|
-
if [ "\${trusted}" = "true" ]; then
|
|
446
|
-
origin_trust_flag="--origin-trust=trusted"
|
|
447
|
-
else
|
|
448
|
-
origin_trust_flag="--origin-trust=untrusted"
|
|
449
|
-
fi
|
|
450
|
-
|
|
451
|
-
echo "spec_flag=\${spec_flag}" >> "\$GITHUB_OUTPUT"
|
|
452
|
-
echo "task_flag=\${task_flag}" >> "\$GITHUB_OUTPUT"
|
|
453
|
-
echo "origin_trust_flag=\${origin_trust_flag}" >> "\$GITHUB_OUTPUT"
|
|
454
|
-
echo "intake policy: intakeIntegration='\${intake_integration}' author_association='\${AUTHOR_ASSOCIATION:-}' trusted=\${trusted} → \${spec_flag} \${task_flag} \${origin_trust_flag}"
|
|
455
|
-
|
|
456
|
-
- name: intake the issue (four-outcome dispatch; surfaces the review verdict into the thread)
|
|
457
|
-
# In-place in this checkout (no --isolated/--remote): the CI container IS
|
|
458
|
-
# the isolation. EXPLICIT \`intake <N>\`, never a bare slug. The per-outcome
|
|
459
|
-
# flags carry the (intakeIntegration-derived) document modes + the
|
|
460
|
-
# origin-trust stamp derived above (author-trust drives only the stamp +
|
|
461
|
-
# placement, not the document merge-vs-propose; the autonomy gates drive
|
|
462
|
-
# neither). \`intake\` runs the
|
|
463
|
-
# lone-task review/edit loop and posts its findings as questions back into
|
|
464
|
-
# THIS issue thread (insertion point E) through the issue-comment seam —
|
|
465
|
-
# CI surfaces E by invoking intake; it adds no new review mechanism.
|
|
466
|
-
#
|
|
467
|
-
# Every value reaches the shell through \`env:\` as DATA and is read back as a
|
|
468
|
-
# quoted variable, never as \`\${{ }}\` text spliced into the script
|
|
469
|
-
# (GitHub's script-injection guidance). The issue number is an integer and
|
|
470
|
-
# the policy outputs are fixed flags today; routing them through env anyway
|
|
471
|
-
# keeps "no \`\${{ }}\` inside \`run:\`" a rule with no exceptions.
|
|
472
|
-
env:
|
|
473
|
-
GH_TOKEN: \${{ secrets.GITHUB_TOKEN }}
|
|
474
|
-
ISSUE_NUMBER: \${{ github.event.issue.number }}
|
|
475
|
-
SPEC_FLAG: \${{ steps.policy.outputs.spec_flag }}
|
|
476
|
-
TASK_FLAG: \${{ steps.policy.outputs.task_flag }}
|
|
477
|
-
ORIGIN_TRUST_FLAG: \${{ steps.policy.outputs.origin_trust_flag }}
|
|
478
|
-
run: |
|
|
479
|
-
dorfl intake "\${ISSUE_NUMBER}" \\
|
|
480
|
-
"\${SPEC_FLAG}" \\
|
|
481
|
-
"\${TASK_FLAG}" \\
|
|
482
|
-
"\${ORIGIN_TRUST_FLAG}" \\
|
|
483
|
-
--arbiter origin
|
|
353
|
+
# The union of what dorfl-item.yml's jobs request (a called workflow can
|
|
354
|
+
# only narrow this): the lock and apply jobs write (the \`processing\` label,
|
|
355
|
+
# the comment back into the thread = insertion point E, the document PR or
|
|
356
|
+
# merge); apply reads the agent job's check runs (a timeout vs a cancel).
|
|
357
|
+
permissions:
|
|
358
|
+
${ITEM_WORKFLOW_CALLER_PERMISSIONS}
|
|
359
|
+
uses: ./.github/workflows/dorfl-item.yml
|
|
360
|
+
with:
|
|
361
|
+
item: issue:\${{ github.event.issue.number }}${itemCallSecrets(config, false)}
|
|
484
362
|
`;
|
|
485
363
|
}
|
|
486
364
|
|
|
@@ -524,33 +402,38 @@ export function validateIntakeWorkflow(text: string): IntakeTriggerValidation {
|
|
|
524
402
|
.filter((line) => !/^\s*#/.test(line))
|
|
525
403
|
.join('\n');
|
|
526
404
|
|
|
527
|
-
// ---
|
|
528
|
-
require('
|
|
405
|
+
// --- CALLS the per-item workflow with `item: issue:<N>` (decision 10) -------
|
|
406
|
+
require('calls-item-workflow', /\n {4}uses: \.\/\.github\/workflows\/dorfl-item\.yml\n/.test(
|
|
529
407
|
operative,
|
|
530
|
-
), '
|
|
531
|
-
'
|
|
532
|
-
// The issue number rides the explicit
|
|
533
|
-
//
|
|
534
|
-
require('intake-explicit-issue-number',
|
|
408
|
+
), 'the intake job must call the per-item workflow ' +
|
|
409
|
+
'(`uses: ./.github/workflows/dorfl-item.yml`: lock, agent, apply).');
|
|
410
|
+
// The issue number rides the explicit `issue:<N>` item id from the event
|
|
411
|
+
// payload (the issue under intake) — never a bare slug.
|
|
412
|
+
require('intake-explicit-issue-number', /\n {6}item: issue:\$\{\{ github\.event\.issue\.number \}\}\n/.test(
|
|
535
413
|
operative,
|
|
536
|
-
), 'the
|
|
537
|
-
'(`github.event.issue.number
|
|
538
|
-
// No
|
|
539
|
-
//
|
|
540
|
-
require('
|
|
414
|
+
), 'the item must be the explicit `issue:<N>` id ' +
|
|
415
|
+
'(`item: issue:${{ github.event.issue.number }}`).');
|
|
416
|
+
// No agent verb runs in THIS workflow: the decision agent runs in the called
|
|
417
|
+
// workflow's agent job (read-only token).
|
|
418
|
+
require('no-agent-verbs', !/dorfl (?:do|advance|intake|run)\b/.test(
|
|
541
419
|
operative,
|
|
542
|
-
)
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
420
|
+
), 'the intake workflow must run no dorfl verb itself: `intake` runs in the ' +
|
|
421
|
+
"called workflow's lock, agent and apply jobs.");
|
|
422
|
+
// The caller grants the union of what the called jobs request.
|
|
423
|
+
require('caller-grants-item-scopes', /\n {4}permissions:\n {6}contents: write\n {6}issues: write\n {6}pull-requests: write\n {6}actions: read\n {6}checks: read\n/.test(
|
|
424
|
+
operative,
|
|
425
|
+
), 'the calling job must grant every scope a job of dorfl-item.yml requests ' +
|
|
426
|
+
'(`contents`, `issues`, `pull-requests: write`; `actions`, `checks: read`).');
|
|
427
|
+
require('workflow-permissions-empty', /^permissions: \{\}$/m.test(
|
|
428
|
+
text,
|
|
429
|
+
), 'the workflow must grant nothing at workflow level (`permissions: {}`).');
|
|
430
|
+
require('secrets-explicit', !/secrets:\s*inherit\b/.test(
|
|
551
431
|
operative,
|
|
552
|
-
), 'the
|
|
553
|
-
|
|
432
|
+
), 'secrets reach the called workflow explicitly, never `secrets: inherit`.');
|
|
433
|
+
require('no-pr-identity-token', !/DORFL_GH_TOKEN/.test(
|
|
434
|
+
operative,
|
|
435
|
+
), 'intake keeps the built-in token for its writes (no DORFL_GH_TOKEN is ' +
|
|
436
|
+
'passed to the called workflow).');
|
|
554
437
|
|
|
555
438
|
// --- TRIGGERS: issues opened + issue_comment created + the label ------------
|
|
556
439
|
require('trigger-issues-opened', /\bissues:\s*[\s\S]*?types:\s*[\s\S]*?-\s*opened\b/.test(
|
|
@@ -563,10 +446,12 @@ export function validateIntakeWorkflow(text: string): IntakeTriggerValidation {
|
|
|
563
446
|
require('trigger-label', /\bissues:\s*[\s\S]*?types:\s*[\s\S]*?-\s*labeled\b/.test(
|
|
564
447
|
text,
|
|
565
448
|
), 'must trigger on a label (`on.issues.types: [labeled]`).');
|
|
449
|
+
// A comment on a PR also fires `issue_comment`: there is no issue to intake.
|
|
450
|
+
require('skips-pull-request-comments', /if: \$\{\{ github\.event\.issue\.number && !github\.event\.issue\.pull_request \}\}/.test(
|
|
451
|
+
operative,
|
|
452
|
+
), 'the intake job must skip a comment on a pull request (no issue to intake).');
|
|
566
453
|
|
|
567
454
|
// --- Decision 2: a CREATED comment triggers; an EDITED comment does NOT ------
|
|
568
|
-
// The `issue_comment` trigger must NOT list `edited` (no edit-detection); and
|
|
569
|
-
// there must be no `updated_at`/body-hash edit-tracking wiring.
|
|
570
455
|
require('no-comment-edited-trigger', !/issue_comment:\s*[\s\S]*?types:\s*[\s\S]*?-\s*edited\b/.test(
|
|
571
456
|
text,
|
|
572
457
|
), 'the `issue_comment` trigger must NOT include `edited` (Decision 2: no ' +
|
|
@@ -574,122 +459,37 @@ export function validateIntakeWorkflow(text: string): IntakeTriggerValidation {
|
|
|
574
459
|
require('no-edit-tracking', !/updated_at|body-hash|bodyHash/.test(
|
|
575
460
|
operative,
|
|
576
461
|
), 'must NOT implement `updated_at` / body-hash edit-tracking (Decision 2).');
|
|
577
|
-
// The "post a NEW comment to signal an edit" CONVENTION must be documented in
|
|
578
|
-
// the workflow so a human knows how to re-trigger after editing a comment.
|
|
579
462
|
require('documents-new-comment-convention', /post a NEW comment/i.test(
|
|
580
463
|
text,
|
|
581
464
|
), 'must DOCUMENT the "post a new comment to signal an edit" convention ' +
|
|
582
465
|
'(Decision 2) so a human knows how to drive re-evaluation.');
|
|
583
466
|
|
|
584
|
-
// ---
|
|
585
|
-
// The
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
), 'must read `author_association` off the event payload to compose author-' +
|
|
589
|
-
'trust into the merge-vs-propose policy (Decision 1; no extra API call).');
|
|
590
|
-
// Trust = OWNER/MEMBER/COLLABORATOR (the whole signal).
|
|
591
|
-
require('trust-owner-member-collaborator', /OWNER\|MEMBER\|COLLABORATOR|OWNER[\s\S]{0,40}MEMBER[\s\S]{0,40}COLLABORATOR/.test(
|
|
592
|
-
text,
|
|
593
|
-
), 'author-trust must be OWNER/MEMBER/COLLABORATOR (admin / write-collaborator ' +
|
|
594
|
-
'— the whole signal; Decision 1).');
|
|
595
|
-
// The DOCUMENT mode is intakeIntegration-DERIVED (spec
|
|
596
|
-
// intake-integration-knob-and-specs-land-in-proposed-rename; the autonomy gates
|
|
597
|
-
// no longer bite it): the derivation must be able to emit both task modes
|
|
598
|
-
// (merge iff the resolved intakeIntegration is merge, else propose).
|
|
599
|
-
require('derives-propose-task', /--propose-task\b/.test(
|
|
600
|
-
operative,
|
|
601
|
-
), 'the policy derivation must be able to emit `--propose-task` (the ' +
|
|
602
|
-
'intakeIntegration-propose path).');
|
|
603
|
-
require('derives-merge-task', /--merge-task\b/.test(
|
|
604
|
-
operative,
|
|
605
|
-
), 'the policy derivation must be able to emit `--merge-task` (the ' +
|
|
606
|
-
'intakeIntegration-merge path; a task DOCUMENT merges regardless of the ' +
|
|
607
|
-
'autonomy gates or author-trust).');
|
|
608
|
-
// --merge-spec is emitted when the resolved intakeIntegration is merge (the
|
|
609
|
-
// SAME single value as the task; the gates do not bite it).
|
|
610
|
-
require('derives-merge-spec', /--merge-spec\b/.test(
|
|
611
|
-
operative,
|
|
612
|
-
), 'the policy derivation must be able to emit `--merge-spec` (the ' +
|
|
613
|
-
'intakeIntegration-merge path).');
|
|
614
|
-
require('derives-propose-spec', /--propose-spec\b/.test(
|
|
615
|
-
operative,
|
|
616
|
-
), 'the policy derivation must be able to emit `--propose-spec` (the ' +
|
|
617
|
-
'intakeIntegration-propose path).');
|
|
618
|
-
// ORIGIN-TRUST stamp (task untrusted-origin-forces-build-propose): the shell
|
|
619
|
-
// must derive `--origin-trust <trusted|untrusted>` from the author-trust case
|
|
620
|
-
// (independent of the document mode) and pass it to `intake` so the emitted
|
|
621
|
-
// artifact is stamped (the stamp is the SOLE thing author-trust drives).
|
|
622
|
-
require('derives-origin-trust-untrusted', /--origin-trust=untrusted\b/.test(
|
|
623
|
-
operative,
|
|
624
|
-
), 'the policy derivation must emit `--origin-trust=untrusted` for a non-trusted ' +
|
|
625
|
-
'author (so the emitted artifact is stamped untrusted; task ' +
|
|
626
|
-
'untrusted-origin-forces-build-propose).');
|
|
627
|
-
require('derives-origin-trust-trusted', /--origin-trust=trusted\b/.test(
|
|
628
|
-
operative,
|
|
629
|
-
), 'the policy derivation must emit `--origin-trust=trusted` for a trusted author.');
|
|
630
|
-
require('passes-origin-trust-to-intake', /steps\.policy\.outputs\.origin_trust_flag/.test(
|
|
631
|
-
operative,
|
|
632
|
-
), 'the intake invocation must pass the derived `--origin-trust` flag (the ' +
|
|
633
|
-
'stamp must reach `dorfl intake`).');
|
|
634
|
-
// The derivation must read the RESOLVED intake DOCUMENT mode via `dorfl config
|
|
635
|
-
// --json` (the mechanism `advance` uses), NOT a hardcoded DORFL_* env (ADR
|
|
636
|
-
// untrusted-origin-carries-via-stamp-not-forced-staging — the shadowing bug).
|
|
637
|
-
require('reads-config-json', /dorfl config --json/.test(
|
|
638
|
-
operative,
|
|
639
|
-
), 'the policy derivation must read the resolved config via ' +
|
|
640
|
-
'`dorfl config --json` (as `advance` does), so a committed `dorfl.json` ' +
|
|
641
|
-
'mode is honored in CI (not shadowed by a hardcoded env).');
|
|
642
|
-
// The DOCUMENT mode is the resolved `intakeIntegration ?? integration` (spec
|
|
643
|
-
// intake-integration-knob-and-specs-land-in-proposed-rename): the derivation
|
|
644
|
-
// must read `.intakeIntegration` with a `.integration` FALLBACK (the shell twin
|
|
645
|
-
// of `intakeIntegration ?? integration`), NOT the autonomy gates. Pin BOTH the
|
|
646
|
-
// key and the fallback so a regression to a gate-derived mode is caught.
|
|
647
|
-
require('reads-intake-integration', /\.intakeIntegration\b/.test(
|
|
648
|
-
operative,
|
|
649
|
-
), 'the policy derivation must read the resolved `intakeIntegration` mode (jq ' +
|
|
650
|
-
'`.intakeIntegration` off `dorfl config --json`) for the document mode.');
|
|
651
|
-
require('intake-integration-falls-back-to-integration', /\.intakeIntegration\s*\/\/\s*\.integration/.test(
|
|
652
|
-
operative,
|
|
653
|
-
), 'the policy derivation must fall back to `.integration` when ' +
|
|
654
|
-
'`intakeIntegration` is unset (jq `.intakeIntegration // .integration`, the ' +
|
|
655
|
-
'shell twin of `intakeIntegration ?? integration`).');
|
|
656
|
-
// The DOCUMENT mode must NOT be derived from the autonomy gates (spec
|
|
657
|
-
// intake-integration-knob-and-specs-land-in-proposed-rename: autoBuild/autoTask
|
|
658
|
-
// gate autonomy ONLY, never the document PR-mode). The mode branch must not read
|
|
659
|
-
// `.autoBuild` / `.autoTask` off the config json.
|
|
660
|
-
require('mode-not-gate-derived', !/\.auto(?:Build|Task)\b/.test(
|
|
661
|
-
operative,
|
|
662
|
-
), 'the intake DOCUMENT mode must be derived from `intakeIntegration ?? ' +
|
|
663
|
-
'integration`, NOT the autonomy gates — the derivation must not read ' +
|
|
664
|
-
'`.autoBuild` / `.autoTask` (they gate autonomy only; spec ' +
|
|
665
|
-
'intake-integration-knob-and-specs-land-in-proposed-rename).');
|
|
666
|
-
// ANTI-REGRESSION (ADR untrusted-origin-carries-via-stamp-not-forced-staging;
|
|
667
|
-
// spec US #12): the workflow must NOT emit a `DORFL_AUTO_BUILD:` /
|
|
668
|
-
// `DORFL_AUTO_TASK:` env ASSIGNMENT. The env layer OUTRANKS per-repo config, so
|
|
669
|
-
// a hardcoded default here SHADOWS the committed `dorfl.json` gates (the bug this
|
|
670
|
-
// task fixes). Mirrors `advance-lifecycle-template.ts`'s `no-gate-env-auto-build`
|
|
671
|
-
// / `no-gate-env-auto-task`. Checked over the OPERATIVE (non-comment) lines so
|
|
672
|
-
// the header comment that NAMES these keys is not a false positive.
|
|
467
|
+
// --- The policy is derived in the lock job, from trusted inputs --------------
|
|
468
|
+
// The document mode and the origin-trust stamp are derived by the called
|
|
469
|
+
// workflow's LOCK job (`ci-phase-intake.ts`), never by the agent: this
|
|
470
|
+
// workflow must not derive them itself any more, nor carry a gate env.
|
|
673
471
|
require('no-gate-env-auto-build', !/DORFL_AUTO_BUILD\s*:/.test(
|
|
674
472
|
operative,
|
|
675
473
|
), 'the workflow must NOT emit a `DORFL_AUTO_BUILD:` env assignment (env ' +
|
|
676
|
-
'carries no defaults
|
|
677
|
-
'default — else the env SHADOWS the committed dorfl.json).');
|
|
474
|
+
'carries no defaults — else the env SHADOWS the committed dorfl.json).');
|
|
678
475
|
require('no-gate-env-auto-task', !/DORFL_AUTO_TASK\s*:/.test(
|
|
679
476
|
operative,
|
|
680
477
|
), 'the workflow must NOT emit a `DORFL_AUTO_TASK:` env assignment (env ' +
|
|
681
|
-
'carries no defaults
|
|
682
|
-
|
|
478
|
+
'carries no defaults — else the env SHADOWS the committed dorfl.json).');
|
|
479
|
+
require('documents-policy-derivation', /OWNER\/MEMBER\/COLLABORATOR/.test(
|
|
480
|
+
text,
|
|
481
|
+
) &&
|
|
482
|
+
/intakeIntegration \?\? integration/.test(
|
|
483
|
+
text,
|
|
484
|
+
), "must DOCUMENT where the policy comes from: the lock job's origin trust " +
|
|
485
|
+
'(OWNER/MEMBER/COLLABORATOR, from the event) and document mode ' +
|
|
486
|
+
'(`intakeIntegration ?? integration`, from dorfl.json at the base).');
|
|
683
487
|
|
|
684
488
|
// --- Insertion point E: the issue-thread review surface ---------------------
|
|
685
|
-
// E is REUSED via `intake` (which runs the lone-task review and posts to the
|
|
686
|
-
// thread). The workflow must request `issues: write` so that comment can land.
|
|
687
489
|
require('issues-write-permission', /\bissues:\s*write\b/.test(
|
|
688
490
|
operative,
|
|
689
|
-
), 'must
|
|
491
|
+
), 'must grant `issues: write` so the review verdict / clarifying question ' +
|
|
690
492
|
'can be posted back into the issue thread (insertion point E).');
|
|
691
|
-
// It must NOT route the review verdict through the PR-comment seam — E posts to
|
|
692
|
-
// the ISSUE (postIssueComment by number), NOT the PR (postPRComment by url).
|
|
693
493
|
require('no-pr-comment-seam', !/postPRComment\b/.test(
|
|
694
494
|
operative,
|
|
695
495
|
), 'insertion point E posts to the ISSUE thread (postIssueComment by number), ' +
|
|
@@ -717,15 +517,14 @@ export function validateIntakeWorkflow(text: string): IntakeTriggerValidation {
|
|
|
717
517
|
text,
|
|
718
518
|
), 'the running job must request NO `workflows` permission (US #9: it can ' +
|
|
719
519
|
'never edit `.github/workflows/**` / rewrite its own triggers).');
|
|
520
|
+
// Calling a reusable workflow (`uses: ./.github/workflows/...`) is not a
|
|
521
|
+
// step touching the tree; anything else naming it is.
|
|
720
522
|
require('never-edits-dot-github-workflows', !/\.github\/workflows\//.test(
|
|
721
|
-
operative
|
|
523
|
+
operative
|
|
524
|
+
.split('\n')
|
|
525
|
+
.filter((line) => !/^\s*uses: \.\/\.github\/workflows\//.test(line))
|
|
526
|
+
.join('\n'),
|
|
722
527
|
), 'no emitted job step may touch `.github/workflows/**` (US #9).');
|
|
723
528
|
|
|
724
|
-
// --- Wires the SHARED composite setup action -------------------------------
|
|
725
|
-
require('uses-shared-setup-action', /uses:\s*\.\/\.github\/actions\/dorfl-setup\b/.test(
|
|
726
|
-
text,
|
|
727
|
-
), 'the job must wire the shared composite setup action ' +
|
|
728
|
-
'(`./.github/actions/dorfl-setup`, emitted by the core task).');
|
|
729
|
-
|
|
730
529
|
return {ok: problems.length === 0, problems};
|
|
731
530
|
}
|