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