dorfl 0.14.2 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advance-ci-template.d.ts +17 -16
- package/dist/advance-ci-template.d.ts.map +1 -1
- package/dist/advance-ci-template.js +42 -53
- package/dist/advance-ci-template.js.map +1 -1
- package/dist/advance-drivers.d.ts +8 -0
- package/dist/advance-drivers.d.ts.map +1 -1
- package/dist/advance-drivers.js +28 -4
- package/dist/advance-drivers.js.map +1 -1
- package/dist/advance-isolated.d.ts.map +1 -1
- package/dist/advance-isolated.js +3 -2
- package/dist/advance-isolated.js.map +1 -1
- package/dist/advance-lifecycle-template.d.ts +41 -40
- package/dist/advance-lifecycle-template.d.ts.map +1 -1
- package/dist/advance-lifecycle-template.js +309 -489
- package/dist/advance-lifecycle-template.js.map +1 -1
- package/dist/advance-loop-driver.d.ts.map +1 -1
- package/dist/advance-loop-driver.js +3 -2
- package/dist/advance-loop-driver.js.map +1 -1
- package/dist/advance-treeless-publish.d.ts +31 -0
- package/dist/advance-treeless-publish.d.ts.map +1 -1
- package/dist/advance-treeless-publish.js +40 -0
- package/dist/advance-treeless-publish.js.map +1 -1
- package/dist/advance.d.ts +63 -3
- package/dist/advance.d.ts.map +1 -1
- package/dist/advance.js +80 -12
- package/dist/advance.js.map +1 -1
- package/dist/advancing-lock.d.ts +9 -0
- package/dist/advancing-lock.d.ts.map +1 -1
- package/dist/advancing-lock.js +21 -1
- package/dist/advancing-lock.js.map +1 -1
- package/dist/agent-env.d.ts +61 -0
- package/dist/agent-env.d.ts.map +1 -0
- package/dist/agent-env.js +144 -0
- package/dist/agent-env.js.map +1 -0
- package/dist/agent-stop.d.ts +35 -0
- package/dist/agent-stop.d.ts.map +1 -1
- package/dist/agent-stop.js +62 -0
- package/dist/agent-stop.js.map +1 -1
- package/dist/apply-merge-action.d.ts +76 -34
- package/dist/apply-merge-action.d.ts.map +1 -1
- package/dist/apply-merge-action.js +339 -129
- package/dist/apply-merge-action.js.map +1 -1
- package/dist/apply-stuck-action.js +2 -2
- package/dist/apply-stuck-action.js.map +1 -1
- package/dist/ci-agent-result.d.ts +151 -0
- package/dist/ci-agent-result.d.ts.map +1 -0
- package/dist/ci-agent-result.js +314 -0
- package/dist/ci-agent-result.js.map +1 -0
- package/dist/ci-handoff-apply.d.ts +162 -0
- package/dist/ci-handoff-apply.d.ts.map +1 -0
- package/dist/ci-handoff-apply.js +497 -0
- package/dist/ci-handoff-apply.js.map +1 -0
- package/dist/ci-handoff-format.d.ts +369 -0
- package/dist/ci-handoff-format.d.ts.map +1 -0
- package/dist/ci-handoff-format.js +646 -0
- package/dist/ci-handoff-format.js.map +1 -0
- package/dist/ci-handoff-lfs.d.ts +146 -0
- package/dist/ci-handoff-lfs.d.ts.map +1 -0
- package/dist/ci-handoff-lfs.js +397 -0
- package/dist/ci-handoff-lfs.js.map +1 -0
- package/dist/ci-handoff.d.ts +99 -0
- package/dist/ci-handoff.d.ts.map +1 -0
- package/dist/ci-handoff.js +277 -0
- package/dist/ci-handoff.js.map +1 -0
- package/dist/ci-lock-outputs.d.ts +93 -0
- package/dist/ci-lock-outputs.d.ts.map +1 -0
- package/dist/ci-lock-outputs.js +223 -0
- package/dist/ci-lock-outputs.js.map +1 -0
- package/dist/ci-phase-build.d.ts +178 -0
- package/dist/ci-phase-build.d.ts.map +1 -0
- package/dist/ci-phase-build.js +989 -0
- package/dist/ci-phase-build.js.map +1 -0
- package/dist/ci-phase-driver.d.ts +247 -0
- package/dist/ci-phase-driver.d.ts.map +1 -0
- package/dist/ci-phase-driver.js +370 -0
- package/dist/ci-phase-driver.js.map +1 -0
- package/dist/ci-phase-intake.d.ts +172 -0
- package/dist/ci-phase-intake.d.ts.map +1 -0
- package/dist/ci-phase-intake.js +555 -0
- package/dist/ci-phase-intake.js.map +1 -0
- package/dist/ci-phase-tasking.d.ts +205 -0
- package/dist/ci-phase-tasking.d.ts.map +1 -0
- package/dist/ci-phase-tasking.js +906 -0
- package/dist/ci-phase-tasking.js.map +1 -0
- package/dist/ci-phase-treeless.d.ts +224 -0
- package/dist/ci-phase-treeless.d.ts.map +1 -0
- package/dist/ci-phase-treeless.js +1482 -0
- package/dist/ci-phase-treeless.js.map +1 -0
- package/dist/ci-read-token.d.ts +47 -0
- package/dist/ci-read-token.d.ts.map +1 -0
- package/dist/ci-read-token.js +80 -0
- package/dist/ci-read-token.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +447 -22
- package/dist/cli.js.map +1 -1
- package/dist/close-job-template.d.ts +10 -1
- package/dist/close-job-template.d.ts.map +1 -1
- package/dist/close-job-template.js +46 -14
- package/dist/close-job-template.js.map +1 -1
- package/dist/close-job.d.ts +20 -5
- package/dist/close-job.d.ts.map +1 -1
- package/dist/close-job.js +65 -12
- package/dist/close-job.js.map +1 -1
- package/dist/complete.d.ts.map +1 -1
- package/dist/complete.js +20 -1
- package/dist/complete.js.map +1 -1
- package/dist/config.d.ts +41 -44
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -4
- package/dist/config.js.map +1 -1
- package/dist/continue-branch.d.ts +63 -15
- package/dist/continue-branch.d.ts.map +1 -1
- package/dist/continue-branch.js +75 -8
- package/dist/continue-branch.js.map +1 -1
- package/dist/crashed-run-save.d.ts +73 -0
- package/dist/crashed-run-save.d.ts.map +1 -0
- package/dist/crashed-run-save.js +86 -0
- package/dist/crashed-run-save.js.map +1 -0
- package/dist/cwd-section.d.ts.map +1 -1
- package/dist/cwd-section.js +10 -2
- package/dist/cwd-section.js.map +1 -1
- package/dist/decision-engine.d.ts +10 -0
- package/dist/decision-engine.d.ts.map +1 -1
- package/dist/decision-engine.js.map +1 -1
- package/dist/do-config.d.ts +2 -24
- package/dist/do-config.d.ts.map +1 -1
- package/dist/do-config.js +1 -33
- package/dist/do-config.js.map +1 -1
- package/dist/do.d.ts +149 -1
- package/dist/do.d.ts.map +1 -1
- package/dist/do.js +115 -25
- package/dist/do.js.map +1 -1
- package/dist/dorfl-item-template.d.ts +98 -0
- package/dist/dorfl-item-template.d.ts.map +1 -0
- package/dist/dorfl-item-template.js +504 -0
- package/dist/dorfl-item-template.js.map +1 -0
- package/dist/env-config.d.ts.map +1 -1
- package/dist/env-config.js +7 -5
- package/dist/env-config.js.map +1 -1
- package/dist/frontmatter.d.ts +52 -0
- package/dist/frontmatter.d.ts.map +1 -1
- package/dist/frontmatter.js +136 -2
- package/dist/frontmatter.js.map +1 -1
- package/dist/gc.d.ts +13 -0
- package/dist/gc.d.ts.map +1 -1
- package/dist/gc.js +16 -2
- package/dist/gc.js.map +1 -1
- package/dist/git.d.ts +18 -1
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +70 -5
- package/dist/git.js.map +1 -1
- package/dist/harness.d.ts +44 -5
- package/dist/harness.d.ts.map +1 -1
- package/dist/harness.js +24 -1
- package/dist/harness.js.map +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/install-ci-action-pins.d.ts +123 -0
- package/dist/install-ci-action-pins.d.ts.map +1 -0
- package/dist/install-ci-action-pins.js +190 -0
- package/dist/install-ci-action-pins.js.map +1 -0
- package/dist/install-ci-actions-pr-creation.d.ts +70 -0
- package/dist/install-ci-actions-pr-creation.d.ts.map +1 -0
- package/dist/install-ci-actions-pr-creation.js +106 -0
- package/dist/install-ci-actions-pr-creation.js.map +1 -0
- package/dist/install-ci-capabilities/dorfl-item.d.ts +12 -0
- package/dist/install-ci-capabilities/dorfl-item.d.ts.map +1 -0
- package/dist/install-ci-capabilities/dorfl-item.js +26 -0
- package/dist/install-ci-capabilities/dorfl-item.js.map +1 -0
- package/dist/install-ci-core.d.ts +155 -37
- package/dist/install-ci-core.d.ts.map +1 -1
- package/dist/install-ci-core.js +304 -200
- package/dist/install-ci-core.js.map +1 -1
- package/dist/install-ci-github.d.ts +47 -2
- package/dist/install-ci-github.d.ts.map +1 -1
- package/dist/install-ci-github.js +113 -1
- package/dist/install-ci-github.js.map +1 -1
- package/dist/install-ci.d.ts +25 -6
- package/dist/install-ci.d.ts.map +1 -1
- package/dist/install-ci.js +72 -36
- package/dist/install-ci.js.map +1 -1
- package/dist/intake-marker.d.ts +6 -1
- package/dist/intake-marker.d.ts.map +1 -1
- package/dist/intake-marker.js.map +1 -1
- package/dist/intake-triage.d.ts.map +1 -1
- package/dist/intake-triage.js +6 -2
- package/dist/intake-triage.js.map +1 -1
- package/dist/intake-trigger-template.d.ts +31 -25
- package/dist/intake-trigger-template.d.ts.map +1 -1
- package/dist/intake-trigger-template.js +107 -292
- package/dist/intake-trigger-template.js.map +1 -1
- package/dist/intake.d.ts +186 -4
- package/dist/intake.d.ts.map +1 -1
- package/dist/intake.js +533 -416
- package/dist/intake.js.map +1 -1
- package/dist/integration-core.d.ts +154 -1
- package/dist/integration-core.d.ts.map +1 -1
- package/dist/integration-core.js +759 -486
- package/dist/integration-core.js.map +1 -1
- package/dist/integrator.d.ts +12 -0
- package/dist/integrator.d.ts.map +1 -1
- package/dist/integrator.js +21 -0
- package/dist/integrator.js.map +1 -1
- package/dist/isolation.d.ts +12 -2
- package/dist/isolation.d.ts.map +1 -1
- package/dist/isolation.js +19 -8
- package/dist/isolation.js.map +1 -1
- package/dist/item-lock.d.ts +93 -11
- package/dist/item-lock.d.ts.map +1 -1
- package/dist/item-lock.js +233 -65
- package/dist/item-lock.js.map +1 -1
- package/dist/land-question-residue.d.ts +58 -0
- package/dist/land-question-residue.d.ts.map +1 -0
- package/dist/land-question-residue.js +95 -0
- package/dist/land-question-residue.js.map +1 -0
- package/dist/lifecycle-gather.d.ts +16 -0
- package/dist/lifecycle-gather.d.ts.map +1 -1
- package/dist/lifecycle-gather.js +54 -6
- package/dist/lifecycle-gather.js.map +1 -1
- package/dist/merge-answer.d.ts +41 -0
- package/dist/merge-answer.d.ts.map +1 -0
- package/dist/merge-answer.js +60 -0
- package/dist/merge-answer.js.map +1 -0
- package/dist/merge-question-surfacer.d.ts +105 -30
- package/dist/merge-question-surfacer.d.ts.map +1 -1
- package/dist/merge-question-surfacer.js +202 -91
- package/dist/merge-question-surfacer.js.map +1 -1
- package/dist/merge-question-tick.d.ts +64 -0
- package/dist/merge-question-tick.d.ts.map +1 -0
- package/dist/merge-question-tick.js +96 -0
- package/dist/merge-question-tick.js.map +1 -0
- package/dist/mint-adr.d.ts.map +1 -1
- package/dist/mint-adr.js +20 -2
- package/dist/mint-adr.js.map +1 -1
- package/dist/needs-attention.d.ts +72 -2
- package/dist/needs-attention.d.ts.map +1 -1
- package/dist/needs-attention.js +275 -38
- package/dist/needs-attention.js.map +1 -1
- package/dist/phase-recorder.d.ts +168 -0
- package/dist/phase-recorder.d.ts.map +1 -0
- package/dist/phase-recorder.js +218 -0
- package/dist/phase-recorder.js.map +1 -0
- package/dist/phase.d.ts +94 -0
- package/dist/phase.d.ts.map +1 -0
- package/dist/phase.js +148 -0
- package/dist/phase.js.map +1 -0
- package/dist/pi-harness.d.ts.map +1 -1
- package/dist/pi-harness.js +19 -6
- package/dist/pi-harness.js.map +1 -1
- package/dist/prepare.d.ts.map +1 -1
- package/dist/prepare.js +4 -0
- package/dist/prepare.js.map +1 -1
- package/dist/prompt.d.ts +4 -0
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +48 -1
- package/dist/prompt.js.map +1 -1
- package/dist/protocol/CLAIM-PROTOCOL.md +3 -1
- package/dist/protocol/WORK-CONTRACT.md +1 -1
- package/dist/reap-branches.d.ts +48 -0
- package/dist/reap-branches.d.ts.map +1 -1
- package/dist/reap-branches.js +64 -0
- package/dist/reap-branches.js.map +1 -1
- package/dist/ref-write.d.ts +198 -0
- package/dist/ref-write.d.ts.map +1 -0
- package/dist/ref-write.js +79 -0
- package/dist/ref-write.js.map +1 -0
- package/dist/repo-config.js +8 -8
- package/dist/repo-config.js.map +1 -1
- package/dist/repo-mirror.d.ts +36 -0
- package/dist/repo-mirror.d.ts.map +1 -1
- package/dist/repo-mirror.js +91 -1
- package/dist/repo-mirror.js.map +1 -1
- package/dist/review-verdict.d.ts +1 -1
- package/dist/review-verdict.js +1 -1
- package/dist/run.d.ts +7 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +28 -4
- package/dist/run.js.map +1 -1
- package/dist/scan.d.ts +19 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +21 -8
- package/dist/scan.js.map +1 -1
- package/dist/sidecar.d.ts +14 -0
- package/dist/sidecar.d.ts.map +1 -1
- package/dist/sidecar.js +21 -0
- package/dist/sidecar.js.map +1 -1
- package/dist/single-job-warning.d.ts +63 -0
- package/dist/single-job-warning.d.ts.map +1 -0
- package/dist/single-job-warning.js +110 -0
- package/dist/single-job-warning.js.map +1 -0
- package/dist/skills/setup/protocol/CLAIM-PROTOCOL.md +3 -1
- package/dist/skills/setup/protocol/WORK-CONTRACT.md +1 -1
- package/dist/spec-complete.d.ts +13 -6
- package/dist/spec-complete.d.ts.map +1 -1
- package/dist/spec-complete.js +23 -11
- package/dist/spec-complete.js.map +1 -1
- package/dist/start.d.ts.map +1 -1
- package/dist/start.js +47 -14
- package/dist/start.js.map +1 -1
- package/dist/status.d.ts +12 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +11 -3
- package/dist/status.js.map +1 -1
- package/dist/tasking.d.ts +246 -1
- package/dist/tasking.d.ts.map +1 -1
- package/dist/tasking.js +452 -358
- package/dist/tasking.js.map +1 -1
- package/dist/triage-persist.d.ts.map +1 -1
- package/dist/triage-persist.js +21 -2
- package/dist/triage-persist.js.map +1 -1
- package/dist/verify-workflow-template.d.ts.map +1 -1
- package/dist/verify-workflow-template.js +8 -4
- package/dist/verify-workflow-template.js.map +1 -1
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +4 -0
- package/dist/verify.js.map +1 -1
- package/dist/watch-session.d.ts +42 -13
- package/dist/watch-session.d.ts.map +1 -1
- package/dist/watch-session.js +52 -23
- package/dist/watch-session.js.map +1 -1
- package/dist/work-layout.d.ts +10 -4
- package/dist/work-layout.d.ts.map +1 -1
- package/dist/work-layout.js +11 -3
- package/dist/work-layout.js.map +1 -1
- package/dist/workspace.d.ts +65 -4
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +159 -11
- package/dist/workspace.js.map +1 -1
- package/package.json +1 -1
- package/src/advance-ci-template.ts +80 -81
- package/src/advance-drivers.ts +45 -6
- package/src/advance-isolated.ts +3 -5
- package/src/advance-lifecycle-template.ts +375 -538
- package/src/advance-loop-driver.ts +3 -5
- package/src/advance-treeless-publish.ts +61 -0
- package/src/advance.ts +145 -15
- package/src/advancing-lock.ts +36 -1
- package/src/agent-env.ts +174 -0
- package/src/agent-stop.ts +81 -0
- package/src/apply-merge-action.ts +401 -154
- package/src/apply-stuck-action.ts +2 -2
- package/src/ci-agent-result.ts +421 -0
- package/src/ci-handoff-apply.ts +737 -0
- package/src/ci-handoff-format.ts +926 -0
- package/src/ci-handoff-lfs.ts +519 -0
- package/src/ci-handoff.ts +392 -0
- package/src/ci-lock-outputs.ts +273 -0
- package/src/ci-phase-build.ts +1328 -0
- package/src/ci-phase-driver.ts +548 -0
- package/src/ci-phase-intake.ts +861 -0
- package/src/ci-phase-tasking.ts +1255 -0
- package/src/ci-phase-treeless.ts +2028 -0
- package/src/ci-read-token.ts +90 -0
- package/src/cli.ts +591 -29
- package/src/close-job-template.ts +52 -15
- package/src/close-job.ts +77 -12
- package/src/complete.ts +19 -1
- package/src/config.ts +43 -48
- package/src/continue-branch.ts +121 -16
- package/src/crashed-run-save.ts +162 -0
- package/src/cwd-section.ts +10 -0
- package/src/decision-engine.ts +10 -0
- package/src/do-config.ts +2 -57
- package/src/do.ts +170 -28
- package/src/dorfl-item-template.ts +556 -0
- package/src/env-config.ts +7 -5
- package/src/frontmatter.ts +155 -2
- package/src/gc.ts +27 -2
- package/src/git.ts +83 -5
- package/src/harness.ts +58 -6
- package/src/index.ts +50 -1
- package/src/install-ci-action-pins.ts +209 -0
- package/src/install-ci-actions-pr-creation.ts +186 -0
- package/src/install-ci-capabilities/dorfl-item.ts +33 -0
- package/src/install-ci-core.ts +388 -233
- package/src/install-ci-github.ts +149 -1
- package/src/install-ci.ts +83 -37
- package/src/intake-marker.ts +6 -1
- package/src/intake-triage.ts +7 -3
- package/src/intake-trigger-template.ts +126 -327
- package/src/intake.ts +725 -544
- package/src/integration-core.ts +975 -523
- package/src/integrator.ts +28 -0
- package/src/isolation.ts +29 -10
- package/src/item-lock.ts +308 -92
- package/src/land-question-residue.ts +122 -0
- package/src/lifecycle-gather.ts +82 -10
- package/src/merge-answer.ts +82 -0
- package/src/merge-question-surfacer.ts +320 -112
- package/src/merge-question-tick.ts +182 -0
- package/src/mint-adr.ts +28 -2
- package/src/needs-attention.ts +350 -42
- package/src/phase-recorder.ts +350 -0
- package/src/phase.ts +177 -0
- package/src/pi-harness.ts +25 -5
- package/src/prepare.ts +4 -0
- package/src/prompt.ts +68 -1
- package/src/reap-branches.ts +107 -0
- package/src/ref-write.ts +324 -0
- package/src/repo-config.ts +8 -8
- package/src/repo-mirror.ts +107 -1
- package/src/review-verdict.ts +1 -1
- package/src/run.ts +47 -6
- package/src/scan.ts +37 -7
- package/src/sidecar.ts +36 -0
- package/src/single-job-warning.ts +135 -0
- package/src/spec-complete.ts +36 -14
- package/src/start.ts +55 -16
- package/src/status.ts +29 -3
- package/src/tasking.ts +593 -378
- package/src/triage-persist.ts +24 -2
- package/src/verify-workflow-template.ts +8 -4
- package/src/verify.ts +4 -0
- package/src/watch-session.ts +86 -28
- package/src/work-layout.ts +11 -3
- package/src/workspace.ts +210 -14
package/src/frontmatter.ts
CHANGED
|
@@ -157,19 +157,172 @@ function extractBlock(content: string): string | undefined {
|
|
|
157
157
|
return lines.slice(1, closing).join('\n');
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* Strip surrounding single or double quotes from a scalar token. A
|
|
162
|
+
* SINGLE-quoted scalar also has its one YAML escape decoded (`''` is a literal
|
|
163
|
+
* `'`), so a value written by {@link quoteYamlScalar} reads back verbatim.
|
|
164
|
+
* Double-quoted scalars keep their inner text as-is (no backslash decoding).
|
|
165
|
+
*/
|
|
161
166
|
function unquote(value: string): string {
|
|
162
167
|
const trimmed = value.trim();
|
|
163
168
|
if (trimmed.length >= 2) {
|
|
164
169
|
const first = trimmed[0];
|
|
165
170
|
const last = trimmed[trimmed.length - 1];
|
|
166
171
|
if ((first === '"' || first === "'") && last === first) {
|
|
167
|
-
|
|
172
|
+
const inner = trimmed.slice(1, -1);
|
|
173
|
+
return first === "'" ? inner.replace(/''/g, "'") : inner;
|
|
168
174
|
}
|
|
169
175
|
}
|
|
170
176
|
return trimmed;
|
|
171
177
|
}
|
|
172
178
|
|
|
179
|
+
/**
|
|
180
|
+
* The read half of {@link quoteYamlScalar}, for the frontmatter readers that
|
|
181
|
+
* live outside this module (the `title:` readers in `tasking.ts` and
|
|
182
|
+
* `integration-core.ts`), so a quoted title reads back the same everywhere.
|
|
183
|
+
*/
|
|
184
|
+
export function unquoteYamlScalar(value: string): string {
|
|
185
|
+
return unquote(value);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Raised when a runner-side renderer is handed a value it cannot write safely
|
|
190
|
+
* into frontmatter, or when the rendered document does not read back the keys
|
|
191
|
+
* the runner meant to write (task
|
|
192
|
+
* `intake-frontmatter-title-injection-strips-origin-stamp`).
|
|
193
|
+
*/
|
|
194
|
+
export class FrontmatterRenderError extends Error {
|
|
195
|
+
constructor(message: string) {
|
|
196
|
+
super(message);
|
|
197
|
+
this.name = 'FrontmatterRenderError';
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Any character that can end or fold a YAML line, or any other control
|
|
203
|
+
* character: C0 controls (incl. tab, LF, CR), DEL, the C1 range (incl. NEL
|
|
204
|
+
* U+0085, a YAML 1.1 line break), and the Unicode line/paragraph separators.
|
|
205
|
+
*/
|
|
206
|
+
// eslint-disable-next-line no-control-regex
|
|
207
|
+
const SCALAR_CONTROL_RE = /[\u0000-\u001f\u007f-\u009f\u2028\u2029]/;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Why `value` cannot be a one-line frontmatter scalar, or `undefined` when it
|
|
211
|
+
* can. The verdict boundaries (intake, ADR mint) use it to refuse an
|
|
212
|
+
* agent-drafted title before anything is rendered.
|
|
213
|
+
*/
|
|
214
|
+
export function singleLineScalarProblem(value: string): string | undefined {
|
|
215
|
+
return SCALAR_CONTROL_RE.test(value)
|
|
216
|
+
? 'must be a single line with no control characters'
|
|
217
|
+
: undefined;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* THE shared quoter for agent-supplied text a runner writes into frontmatter
|
|
222
|
+
* (task `intake-frontmatter-title-injection-strips-origin-stamp`). Returns a
|
|
223
|
+
* YAML single-quoted scalar (`'...'`, an embedded `'` doubled), which is valid
|
|
224
|
+
* YAML for every one-line string and reads back verbatim through
|
|
225
|
+
* {@link unquote} (and so {@link readFrontmatterField}). A single-quoted scalar
|
|
226
|
+
* has no escape for a line break, so a value that is not one line, or holds any
|
|
227
|
+
* control character, THROWS {@link FrontmatterRenderError}: callers must reject
|
|
228
|
+
* such a value at their verdict boundary, and this throw is the backstop.
|
|
229
|
+
*/
|
|
230
|
+
export function quoteYamlScalar(value: string): string {
|
|
231
|
+
const problem = singleLineScalarProblem(value);
|
|
232
|
+
if (problem !== undefined) {
|
|
233
|
+
throw new FrontmatterRenderError(
|
|
234
|
+
`frontmatter value ${JSON.stringify(value)} ${problem}`,
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** A top-level `key: value` frontmatter line (the key grammar {@link parseFrontmatter} uses). */
|
|
241
|
+
const TOP_LEVEL_KEY_RE = /^([A-Za-z0-9_.]+)\s*:\s*(.*)$/;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* The post-render RE-PARSE assertion (task
|
|
245
|
+
* `intake-frontmatter-title-injection-strips-origin-stamp`). A runner renders a
|
|
246
|
+
* document, then calls this with the frontmatter values it MEANT to write;
|
|
247
|
+
* any disagreement THROWS {@link FrontmatterRenderError}, so a document whose
|
|
248
|
+
* runner-owned keys were displaced (a closed-early fence demoting the
|
|
249
|
+
* `originTrust` stamp into the body, a smuggled duplicate `slug:`) is never
|
|
250
|
+
* emitted.
|
|
251
|
+
*
|
|
252
|
+
* For each `expected` entry: a string value means the key must appear EXACTLY
|
|
253
|
+
* ONCE as a top-level key and read back (via {@link unquote}) equal to it;
|
|
254
|
+
* `undefined` means the key must be ABSENT. The typed keys that
|
|
255
|
+
* {@link parseFrontmatter} models (`slug`, `issue`, `origin`, `originTrust`,
|
|
256
|
+
* `humanOnly`, `needsAnswers`) are ALSO cross-checked through that parser, the
|
|
257
|
+
* same reader the rest of dorfl uses. With `exact`, the frontmatter may hold no
|
|
258
|
+
* top-level key outside `expected` (for a document the runner renders whole).
|
|
259
|
+
*/
|
|
260
|
+
export function assertFrontmatterFields(
|
|
261
|
+
content: string,
|
|
262
|
+
expected: Readonly<Record<string, string | undefined>>,
|
|
263
|
+
options: {exact?: boolean} = {},
|
|
264
|
+
): void {
|
|
265
|
+
const block = extractBlock(content);
|
|
266
|
+
if (block === undefined) {
|
|
267
|
+
throw new FrontmatterRenderError(
|
|
268
|
+
'rendered document has no frontmatter block',
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
const seen = new Map<string, string[]>();
|
|
272
|
+
for (const line of block.split('\n')) {
|
|
273
|
+
const match = TOP_LEVEL_KEY_RE.exec(line);
|
|
274
|
+
if (!match) continue;
|
|
275
|
+
const values = seen.get(match[1]) ?? [];
|
|
276
|
+
values.push(unquote(match[2]));
|
|
277
|
+
seen.set(match[1], values);
|
|
278
|
+
}
|
|
279
|
+
const fail = (detail: string): never => {
|
|
280
|
+
throw new FrontmatterRenderError(
|
|
281
|
+
`rendered frontmatter does not read back as written: ${detail}`,
|
|
282
|
+
);
|
|
283
|
+
};
|
|
284
|
+
for (const [key, want] of Object.entries(expected)) {
|
|
285
|
+
const got = seen.get(key) ?? [];
|
|
286
|
+
if (want === undefined) {
|
|
287
|
+
if (got.length > 0) fail(`'${key}' must be absent`);
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
if (got.length !== 1) {
|
|
291
|
+
fail(`'${key}' appears ${got.length} time(s), expected once`);
|
|
292
|
+
}
|
|
293
|
+
if (got[0] !== want) {
|
|
294
|
+
fail(
|
|
295
|
+
`'${key}' reads ${JSON.stringify(got[0])}, expected ${JSON.stringify(want)}`,
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (options.exact === true) {
|
|
300
|
+
for (const key of seen.keys()) {
|
|
301
|
+
if (!(key in expected)) fail(`unexpected key '${key}'`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// Cross-check through the typed parser (last-wins, value-normalising), so a
|
|
305
|
+
// document that passes the line check but that dorfl would READ differently
|
|
306
|
+
// still fails.
|
|
307
|
+
const fm = parseFrontmatter(content);
|
|
308
|
+
const typed: Record<string, string | undefined> = {
|
|
309
|
+
slug: fm.slug,
|
|
310
|
+
issue: fm.issue === undefined ? undefined : String(fm.issue),
|
|
311
|
+
origin: fm.origin,
|
|
312
|
+
originTrust: fm.originTrust,
|
|
313
|
+
humanOnly: fm.humanOnly === undefined ? undefined : String(fm.humanOnly),
|
|
314
|
+
needsAnswers:
|
|
315
|
+
fm.needsAnswers === undefined ? undefined : String(fm.needsAnswers),
|
|
316
|
+
};
|
|
317
|
+
for (const [key, parsed] of Object.entries(typed)) {
|
|
318
|
+
if (key in expected && parsed !== expected[key]) {
|
|
319
|
+
fail(
|
|
320
|
+
`parsed '${key}' is ${JSON.stringify(parsed)}, expected ${JSON.stringify(expected[key])}`,
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
173
326
|
/**
|
|
174
327
|
* Extract the `[...]` body of a YAML flow-style inline list, IGNORING anything
|
|
175
328
|
* after the matching closing `]` (notably a trailing `# comment`, the documented
|
package/src/gc.ts
CHANGED
|
@@ -247,6 +247,30 @@ export interface RetainedJob extends GcJob {
|
|
|
247
247
|
reason: RetainReason;
|
|
248
248
|
/** Human-readable reason text (`RETAIN_REASON_TEXT[reason]`). */
|
|
249
249
|
reasonText: string;
|
|
250
|
+
/**
|
|
251
|
+
* How to SAVE the retained work, for a task job (every retain reason means the
|
|
252
|
+
* worktree holds work the arbiter lacks): `requeue <slug>` pushes it to the
|
|
253
|
+
* work branch before releasing a crashed run's lock (task
|
|
254
|
+
* `a-crashed-runs-local-work-is-saved-before-its-lock-is-released`). Absent
|
|
255
|
+
* for a non-task branch.
|
|
256
|
+
*/
|
|
257
|
+
hint?: string;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* The save hint {@link gc} attaches to a retained TASK job (see
|
|
262
|
+
* {@link RetainedJob.hint}), or `undefined` for any other branch.
|
|
263
|
+
*/
|
|
264
|
+
export function retainedWorkHint(job: GcJob): string | undefined {
|
|
265
|
+
const parsed = parseWorkBranchRef(job.branch);
|
|
266
|
+
if (parsed === undefined || parsed.namespace !== 'task') {
|
|
267
|
+
return undefined;
|
|
268
|
+
}
|
|
269
|
+
return (
|
|
270
|
+
`it holds work the arbiter lacks; if its run is dead and its lock still ` +
|
|
271
|
+
`held, \`dorfl requeue ${parsed.slug}\` saves it to ${job.branch} before ` +
|
|
272
|
+
`releasing the lock (else push ${job.branch} from ${job.dir})`
|
|
273
|
+
);
|
|
250
274
|
}
|
|
251
275
|
|
|
252
276
|
export interface GcOptions {
|
|
@@ -363,8 +387,9 @@ export function gc(options: GcOptions): GcResult {
|
|
|
363
387
|
|
|
364
388
|
const reason = result.verdict.reason ?? 'unmerged-commits';
|
|
365
389
|
const reasonText = RETAIN_REASON_TEXT[reason];
|
|
366
|
-
|
|
367
|
-
|
|
390
|
+
const hint = retainedWorkHint(job);
|
|
391
|
+
retained.push({...job, reason, reasonText, ...(hint ? {hint} : {})});
|
|
392
|
+
note(`Retained ${job.slug}: ${reasonText}${hint ? ` (${hint})` : ''}.`);
|
|
368
393
|
}
|
|
369
394
|
|
|
370
395
|
return {reaped, retained, sweptOrphans};
|
package/src/git.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {spawnSync, spawn} from 'node:child_process';
|
|
2
2
|
import {existsSync, mkdirSync, statSync} from 'node:fs';
|
|
3
3
|
import {delimiter, dirname, isAbsolute, join} from 'node:path';
|
|
4
|
+
import {gitChildEnv} from './ci-read-token.js';
|
|
4
5
|
|
|
5
6
|
/** Result of running a git (or any) command. */
|
|
6
7
|
export interface RunResult {
|
|
@@ -28,7 +29,49 @@ const SYSTEM_PATH_DIRS = [
|
|
|
28
29
|
];
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
|
-
*
|
|
32
|
+
* The NixOS system profiles. NixOS has no FHS `/usr/bin/git`: a system-wide git
|
|
33
|
+
* lives under `/run/current-system/sw/bin` (the NixOS system profile) or
|
|
34
|
+
* `/nix/var/nix/profiles/default/bin` (the multi-user Nix default profile), both
|
|
35
|
+
* symlinks into the Nix store. Without these, a spawn whose env has no usable
|
|
36
|
+
* `PATH` (a caller or test passing `env: {}`) cannot find git on NixOS at all.
|
|
37
|
+
* APPENDED after {@link SYSTEM_PATH_DIRS}, so the caller's own `PATH` and the FHS
|
|
38
|
+
* dirs still win; on a non-NixOS host these dirs simply do not exist and are
|
|
39
|
+
* skipped by the probe (and harmless on the spawn `PATH`).
|
|
40
|
+
*/
|
|
41
|
+
const NIXOS_PROFILE_DIRS = [
|
|
42
|
+
'/run/current-system/sw/bin',
|
|
43
|
+
'/nix/var/nix/profiles/default/bin',
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
/** The default fallback probe list: FHS dirs first, then the NixOS profiles. */
|
|
47
|
+
const DEFAULT_FALLBACK_PATH_DIRS: readonly string[] = [
|
|
48
|
+
...SYSTEM_PATH_DIRS,
|
|
49
|
+
...NIXOS_PROFILE_DIRS,
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The fallback dirs actually in use. Defaults to
|
|
54
|
+
* {@link DEFAULT_FALLBACK_PATH_DIRS}; replaceable ONLY via
|
|
55
|
+
* {@link setFallbackPathDirsForTest}, the probe-list seam a test uses to point
|
|
56
|
+
* the fallback at a fake bin dir.
|
|
57
|
+
*/
|
|
58
|
+
let fallbackPathDirs: readonly string[] = DEFAULT_FALLBACK_PATH_DIRS;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Replace the fallback probe list (tests only); pass `undefined` to restore the
|
|
62
|
+
* default. Clears the {@link resolveGitBinary} cache so no stale resolution from
|
|
63
|
+
* the previous list survives.
|
|
64
|
+
*/
|
|
65
|
+
export function setFallbackPathDirsForTest(
|
|
66
|
+
dirs: readonly string[] | undefined,
|
|
67
|
+
): void {
|
|
68
|
+
fallbackPathDirs = dirs ?? DEFAULT_FALLBACK_PATH_DIRS;
|
|
69
|
+
gitBinaryCache.clear();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* `PATH` with the fallback dirs ({@link SYSTEM_PATH_DIRS}, then
|
|
74
|
+
* {@link NIXOS_PROFILE_DIRS}) APPENDED (caller entries kept FIRST, so a
|
|
32
75
|
* pinned tool earlier on `PATH` still wins; missing system dirs are added, not
|
|
33
76
|
* substituted). Deduplicated, preserving first-seen order.
|
|
34
77
|
*/
|
|
@@ -37,7 +80,7 @@ function pathWithSystemDirs(path: string | undefined): string {
|
|
|
37
80
|
const out: string[] = [];
|
|
38
81
|
for (const dir of [
|
|
39
82
|
...(path ? path.split(delimiter) : []),
|
|
40
|
-
...
|
|
83
|
+
...fallbackPathDirs,
|
|
41
84
|
]) {
|
|
42
85
|
if (dir !== '' && !seen.has(dir)) {
|
|
43
86
|
seen.add(dir);
|
|
@@ -85,7 +128,9 @@ export function resetResolvedGitBinaryForTest(): void {
|
|
|
85
128
|
* 2. a probe of the env's OWN `PATH` FIRST (so a shim / pinned git earlier on
|
|
86
129
|
* `PATH` wins), then the standard system dirs APPENDED — so `/usr/bin/git`
|
|
87
130
|
* is still found when the caller dropped `/usr/bin`, but never AHEAD of the
|
|
88
|
-
* caller's own entries.
|
|
131
|
+
* caller's own entries. LAST come the NixOS system profiles
|
|
132
|
+
* ({@link NIXOS_PROFILE_DIRS}), so git resolves on NixOS even when the env
|
|
133
|
+
* carries no `PATH` at all.
|
|
89
134
|
*
|
|
90
135
|
* Falls back to the bare name `'git'` when nothing resolves (git genuinely
|
|
91
136
|
* absent) so the spawn still runs and produces the diagnostic path. Cached PER
|
|
@@ -145,8 +190,13 @@ function resolveSpawn(
|
|
|
145
190
|
env: NodeJS.ProcessEnv,
|
|
146
191
|
): {command: string; env: NodeJS.ProcessEnv} {
|
|
147
192
|
const hardenedEnv = envWithSystemPath(env);
|
|
148
|
-
|
|
149
|
-
|
|
193
|
+
if (command !== 'git') {
|
|
194
|
+
return {command, env: hardenedEnv};
|
|
195
|
+
}
|
|
196
|
+
// In the CI `agent` phase, the job's read token rides on this ONE git child
|
|
197
|
+
// process (never `.git/config`); a no-op otherwise. See `ci-read-token.ts`.
|
|
198
|
+
const gitEnv = gitChildEnv(hardenedEnv);
|
|
199
|
+
return {command: resolveGitBinary(gitEnv), env: gitEnv};
|
|
150
200
|
}
|
|
151
201
|
|
|
152
202
|
/**
|
|
@@ -261,6 +311,34 @@ export function git(
|
|
|
261
311
|
return result.stdout;
|
|
262
312
|
}
|
|
263
313
|
|
|
314
|
+
/**
|
|
315
|
+
* Run `git <args>` in `cwd` and return its stdout as raw BYTES (no text
|
|
316
|
+
* decoding), for output that mixes headers with object contents (`cat-file
|
|
317
|
+
* --batch`). Throws on a non-zero exit, like {@link git}.
|
|
318
|
+
*/
|
|
319
|
+
export function gitBytes(
|
|
320
|
+
args: string[],
|
|
321
|
+
cwd: string,
|
|
322
|
+
options: {input?: string; env?: NodeJS.ProcessEnv} = {},
|
|
323
|
+
): Buffer {
|
|
324
|
+
const {command: exe, env} = resolveSpawn('git', options.env ?? process.env);
|
|
325
|
+
const result = spawnSync(exe, args, {
|
|
326
|
+
cwd,
|
|
327
|
+
input: options.input,
|
|
328
|
+
env,
|
|
329
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
330
|
+
});
|
|
331
|
+
if (result.error) {
|
|
332
|
+
throw new Error(spawnErrorMessage('git', exe, env, result.error));
|
|
333
|
+
}
|
|
334
|
+
if (result.status !== 0) {
|
|
335
|
+
throw new Error(
|
|
336
|
+
`git ${args.join(' ')} failed (exit ${result.status}): ${String(result.stderr).trim()}`,
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
return result.stdout;
|
|
340
|
+
}
|
|
341
|
+
|
|
264
342
|
/**
|
|
265
343
|
* Move a tracked file with `git mv`, creating the destination directory first
|
|
266
344
|
* (`mkdir -p`). The `work/` contract requires this: git does not track empty
|
package/src/harness.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {spawnSync} from 'node:child_process';
|
|
2
|
+
import {agentEnvFor} from './agent-env.js';
|
|
3
|
+
import {assertAgentOrRepoCodeAllowed} from './phase.js';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* The **harness seam** (ADR §5): how a job's command is launched and how its
|
|
@@ -214,17 +216,32 @@ export interface LaunchResult {
|
|
|
214
216
|
* **The model OUTPUT-CAP signal** (observation
|
|
215
217
|
* `tasker-review-edits-payload-caps-the-verdict-response`): present iff the
|
|
216
218
|
* adapter detected the agent's final assistant turn was TRUNCATED at the
|
|
217
|
-
* model's output-token cap before it finished — i.e. its
|
|
218
|
-
*
|
|
219
|
-
* `usage.output` token count.
|
|
219
|
+
* model's output-token cap before it finished — i.e. its stop reason is the
|
|
220
|
+
* cap signal (pi's `stopReason: 'length'`, or a raw `max_tokens`) AND it
|
|
221
|
+
* produced a positive `usage.output` token count. A normal end, an error, or no
|
|
222
|
+
* recorded stop reason is NOT a cap. The value is that token count (the observed cap).
|
|
220
223
|
* A gate that fails to parse a verdict AND sees this signal names the failure
|
|
221
224
|
* a cap-truncation (NOT a generic parse error) so an operator does not mis-read
|
|
222
225
|
* it as a model flake and retry blindly. `undefined` when the adapter has no
|
|
223
|
-
* usage/
|
|
224
|
-
*
|
|
226
|
+
* usage/stop-reason telemetry (the null/shell adapter) or the turn did not
|
|
227
|
+
* hit the cap — in which case a parse failure stays the generic `ReviewParseError`
|
|
225
228
|
* (still needs-attention, NEVER a silent approve).
|
|
226
229
|
*/
|
|
227
230
|
outputCapped?: number;
|
|
231
|
+
/**
|
|
232
|
+
* **The agent's FINAL model turn was CUT OFF** (task
|
|
233
|
+
* `a-truncated-agent-turn-routes-as-agent-failed`, observation
|
|
234
|
+
* `a-truncated-model-turn-is-read-as-nothing-to-do-and-defaults-to-cancel`):
|
|
235
|
+
* present iff the LAST assistant message of the run (whatever it carried: text,
|
|
236
|
+
* a tool call, or only a thinking block) ended with a `length` (the per-turn
|
|
237
|
+
* output-token cap) or `error` (a provider error) stop rather than a normal end
|
|
238
|
+
* of turn. The run ending there is a HARNESS failure, not the agent's judgement
|
|
239
|
+
* that there was nothing to build, so the build pipelines route an empty diff
|
|
240
|
+
* with this signal as `agent-failed` instead of the empty-diff STOP backstop.
|
|
241
|
+
* `undefined` when the final turn ended normally or the adapter has no
|
|
242
|
+
* stop-reason telemetry (the null/shell adapter).
|
|
243
|
+
*/
|
|
244
|
+
cutOffTurn?: CutOffTurn;
|
|
228
245
|
/**
|
|
229
246
|
* **The verified outcome of reaping the agent's process TREE** after a deadline
|
|
230
247
|
* stop (observation
|
|
@@ -242,6 +259,17 @@ export interface LaunchResult {
|
|
|
242
259
|
reap?: AgentTreeReap;
|
|
243
260
|
}
|
|
244
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Why the agent's final model turn ended abnormally (see
|
|
264
|
+
* {@link LaunchResult.cutOffTurn}): `length` = the turn hit the model's per-turn
|
|
265
|
+
* output-token cap; `error` = the provider ended the turn with an error.
|
|
266
|
+
* `errorMessage` is the provider's error text when the session recorded one.
|
|
267
|
+
*/
|
|
268
|
+
export interface CutOffTurn {
|
|
269
|
+
cause: 'length' | 'error';
|
|
270
|
+
errorMessage?: string;
|
|
271
|
+
}
|
|
272
|
+
|
|
245
273
|
/**
|
|
246
274
|
* The harness-reported result of reaping a stopped agent's process tree — the
|
|
247
275
|
* adapter-agnostic projection of `reap-agent-tree.ts`'s `ReapResult`.
|
|
@@ -296,6 +324,26 @@ export function isBenignPromptWriteError(error: Error): boolean {
|
|
|
296
324
|
return (error as NodeJS.ErrnoException).code === 'EPIPE';
|
|
297
325
|
}
|
|
298
326
|
|
|
327
|
+
/**
|
|
328
|
+
* The environment an autonomous AGENT is launched with. In GitHub Actions every
|
|
329
|
+
* GitHub credential is removed (`GH_TOKEN`, `GITHUB_TOKEN`, `DORFL_GH_TOKEN`,
|
|
330
|
+
* any value containing a GitHub token, the Actions OIDC/runtime tokens, the
|
|
331
|
+
* runner command files, and git env config carrying a credential; see
|
|
332
|
+
* `agent-env.ts`). Applied INSIDE every adapter's autonomous launch, so no
|
|
333
|
+
* caller and no workflow can hand a CI agent the token by accident. On a laptop
|
|
334
|
+
* the caller's env passes through unchanged.
|
|
335
|
+
*
|
|
336
|
+
* PHASE GUARD: throws a `PhaseGuardError` in the CI `lock` and `apply` phases
|
|
337
|
+
* (their jobs hold the write token, so no agent may launch there; see
|
|
338
|
+
* `phase.ts`).
|
|
339
|
+
*/
|
|
340
|
+
export function agentLaunchEnv(
|
|
341
|
+
env: NodeJS.ProcessEnv | undefined,
|
|
342
|
+
): NodeJS.ProcessEnv {
|
|
343
|
+
assertAgentOrRepoCodeAllowed('agent-launch-env');
|
|
344
|
+
return agentEnvFor(env ?? process.env);
|
|
345
|
+
}
|
|
346
|
+
|
|
299
347
|
/**
|
|
300
348
|
* The **null adapter**: runs the configured command synchronously to completion
|
|
301
349
|
* in the job dir, recording the PID. Liveness is `process.kill(pid, 0)` against
|
|
@@ -307,6 +355,8 @@ export class NullHarness implements Harness {
|
|
|
307
355
|
readonly adapter = 'null';
|
|
308
356
|
|
|
309
357
|
launch(input: LaunchInput): LaunchResult {
|
|
358
|
+
// PHASE GUARD first: no launch at all in the CI lock/apply phases.
|
|
359
|
+
assertAgentOrRepoCodeAllowed('harness-launch');
|
|
310
360
|
// BACKSTOP (config error, NOT a spawn failure): an empty/whitespace command
|
|
311
361
|
// resolves the null adapter to `bash -c ''`, which exits 0 with no output — a
|
|
312
362
|
// "successful" build that ran NOTHING. The `do`/`run`/`--remote` CLI sites
|
|
@@ -328,7 +378,8 @@ export class NullHarness implements Harness {
|
|
|
328
378
|
cwd: input.dir,
|
|
329
379
|
encoding: 'utf8',
|
|
330
380
|
input: input.prompt,
|
|
331
|
-
|
|
381
|
+
// No GitHub token reaches a CI agent (see agentLaunchEnv).
|
|
382
|
+
env: agentLaunchEnv(input.env),
|
|
332
383
|
maxBuffer: 64 * 1024 * 1024,
|
|
333
384
|
});
|
|
334
385
|
if (result.error && !isBenignPromptWriteError(result.error)) {
|
|
@@ -366,6 +417,7 @@ export class NullHarness implements Harness {
|
|
|
366
417
|
* shelling out the wrong way.
|
|
367
418
|
*/
|
|
368
419
|
launchInteractive(_input: InteractiveLaunchInput): InteractiveLaunchResult {
|
|
420
|
+
assertAgentOrRepoCodeAllowed('harness-launch');
|
|
369
421
|
throw new Error(
|
|
370
422
|
'interactive launch requires the pi harness; configure `harness: pi` ' +
|
|
371
423
|
'(the null/shell adapter only supports the captured autonomous launch).',
|
package/src/index.ts
CHANGED
|
@@ -200,6 +200,50 @@ export type {
|
|
|
200
200
|
LedgerWriteStrategy,
|
|
201
201
|
} from './ledger-write.js';
|
|
202
202
|
export {currentLedgerWrite, ledgerWrite} from './ledger-write.js';
|
|
203
|
+
export type {
|
|
204
|
+
RefWriteStrategy,
|
|
205
|
+
LockRefCreateInput,
|
|
206
|
+
LockRefDeleteInput,
|
|
207
|
+
ContinuedBranchPushInput,
|
|
208
|
+
TaskingCandidatesPushInput,
|
|
209
|
+
} from './ref-write.js';
|
|
210
|
+
export {currentRefWrite, refWrite} from './ref-write.js';
|
|
211
|
+
|
|
212
|
+
export type {Phase, GuardedOperation} from './phase.js';
|
|
213
|
+
export {
|
|
214
|
+
PHASES,
|
|
215
|
+
AGENT_SPAWNING_VERBS,
|
|
216
|
+
NON_AGENT_VERBS,
|
|
217
|
+
PhaseGuardError,
|
|
218
|
+
PhaseUsageError,
|
|
219
|
+
parsePhase,
|
|
220
|
+
activePhase,
|
|
221
|
+
enterPhase,
|
|
222
|
+
assertAgentOrRepoCodeAllowed,
|
|
223
|
+
} from './phase.js';
|
|
224
|
+
export type {
|
|
225
|
+
WriteSeamName,
|
|
226
|
+
WriteSeamCall,
|
|
227
|
+
RecordedWriteIntent,
|
|
228
|
+
PhaseRecorder,
|
|
229
|
+
AgentPhaseOutcome,
|
|
230
|
+
} from './phase-recorder.js';
|
|
231
|
+
export {
|
|
232
|
+
PhaseHaltSentinel,
|
|
233
|
+
UnrecordedWriteError,
|
|
234
|
+
createPhaseRecorder,
|
|
235
|
+
installRecordingSeams,
|
|
236
|
+
recordingReviewProvider,
|
|
237
|
+
recordingIssueProvider,
|
|
238
|
+
runAgentPhase,
|
|
239
|
+
activateProcessPhase,
|
|
240
|
+
} from './phase-recorder.js';
|
|
241
|
+
export {
|
|
242
|
+
resolveReadToken,
|
|
243
|
+
readTokenHeaderKey,
|
|
244
|
+
withReadTokenGitConfig,
|
|
245
|
+
gitChildEnv,
|
|
246
|
+
} from './ci-read-token.js';
|
|
203
247
|
|
|
204
248
|
export type {ReadyItem, ScannedItem, RepoReport, ScanReport} from './scan.js';
|
|
205
249
|
export {scan, scanRepoPaths, readReadyItems, readDoneSlugs} from './scan.js';
|
|
@@ -331,6 +375,7 @@ export type {
|
|
|
331
375
|
ReleaseHeldResult,
|
|
332
376
|
LockReportEntry,
|
|
333
377
|
ItemLockReport,
|
|
378
|
+
LockKeptFor,
|
|
334
379
|
} from './item-lock.js';
|
|
335
380
|
export {
|
|
336
381
|
LOCK_REF_PREFIX,
|
|
@@ -352,6 +397,9 @@ export {
|
|
|
352
397
|
listItemLocks,
|
|
353
398
|
listItemLockEntries,
|
|
354
399
|
heldTaskSlugs,
|
|
400
|
+
proposeKeptTaskSlugs,
|
|
401
|
+
markLockKeptForProposePr,
|
|
402
|
+
takeOverProposeKeptLock,
|
|
355
403
|
resolveLockHolder,
|
|
356
404
|
serialiseLockEntry,
|
|
357
405
|
parseLockEntry,
|
|
@@ -501,6 +549,7 @@ export {
|
|
|
501
549
|
encodeWorkId,
|
|
502
550
|
jobWorktreePath,
|
|
503
551
|
createJob,
|
|
552
|
+
RetainedWorktreeUnsavedWorkError,
|
|
504
553
|
writeJobRecord,
|
|
505
554
|
readJobRecord,
|
|
506
555
|
updateJobRecord,
|
|
@@ -797,7 +846,7 @@ export {
|
|
|
797
846
|
resolveCIConfig,
|
|
798
847
|
exportCIConfig,
|
|
799
848
|
generateSetupAction,
|
|
800
|
-
|
|
849
|
+
AUTH_JSON_REMOVED_MESSAGE,
|
|
801
850
|
buildSetupArtifacts,
|
|
802
851
|
outputBaseName,
|
|
803
852
|
writeArtifacts,
|