@coreplane/switchboard 1.260.3 → 1.260.5
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/assets/deploy/cloudflare/package.json +2 -2
- package/dist/assets/deploy/cloudflare-docs/package.json +1 -1
- package/dist/assets/deploy/cloudflare-memory/package.json +2 -2
- package/dist/assets/deploy/cloudflare-memory/worker.ts +205 -8
- package/dist/assets/deploy/cloudflare-resident/Dockerfile +11 -2
- package/dist/assets/deploy/cloudflare-resident/package.json +2 -2
- package/dist/assets/deploy/cloudflare-resident/worker.ts +124 -40
- package/dist/assets/deploy/cloudflare-sandbox/package.json +2 -2
- package/dist/assets/package-lock.json +712 -97
- package/dist/assets/package.json +7 -6
- package/dist/assets/project.json +4 -0
- package/dist/assets/source.json +3 -3
- package/dist/assets/src/core/budgets.ts +5 -0
- package/dist/assets/src/core/coordinator/contract.ts +5 -0
- package/dist/assets/src/core/coordinator/driver.ts +118 -29
- package/dist/assets/src/core/pipelineStanding.ts +2 -0
- package/dist/assets/src/core/plane/decide.ts +19 -2
- package/dist/assets/src/core/provider.ts +380 -0
- package/dist/assets/src/core/refusal.ts +1 -0
- package/dist/assets/src/core/runEvents.ts +8 -0
- package/dist/assets/src/core/runFriction.ts +1 -1
- package/dist/assets/src/core/runLedger/types.ts +10 -1
- package/dist/assets/src/core/runRecord.ts +31 -0
- package/dist/assets/src/core/ship/contract.ts +3 -1
- package/dist/assets/src/core/ship/coordinator.ts +518 -56
- package/dist/assets/src/core/ship/renewal.ts +3 -1
- package/dist/assets/src/core/types.ts +6 -0
- package/dist/assets/src/execution/bashTimeout.ts +1 -1
- package/dist/assets/src/execution/residentRebind.ts +15 -0
- package/dist/assets/src/execution/residentReuse.ts +23 -2
- package/dist/assets/src/execution/sandboxErrors.ts +6 -6
- package/dist/assets/web/dist/.vite/manifest.json +505 -505
- package/dist/assets/web/dist/assets/{AppShell-CSXDCV4x.js → AppShell-DPJVhUGP.js} +1 -1
- package/dist/assets/web/dist/assets/{CostChart-DsuPS2g7.js → CostChart-4TeDdbvJ.js} +1 -1
- package/dist/assets/web/dist/assets/CostsPage-8HDgvuWB.js +1 -0
- package/dist/assets/web/dist/assets/{DeliveryPage-62qCSLvk.js → DeliveryPage-Cf1joUyA.js} +1 -1
- package/dist/assets/web/dist/assets/{HomePage-Dk3HRBc3.js → HomePage-DZEAnCCv.js} +1 -1
- package/dist/assets/web/dist/assets/{InputMenu-BdZXnibG.js → InputMenu-BRV35UWP.js} +1 -1
- package/dist/assets/web/dist/assets/{MetricsPage-o5fSaCTe.js → MetricsPage-BQBuIuYU.js} +1 -1
- package/dist/assets/web/dist/assets/{NotFoundPage-DHuWyjlq.js → NotFoundPage-CDjMfCcj.js} +1 -1
- package/dist/assets/web/dist/assets/{PendingTurnRow-CeTGOXUy.js → PendingTurnRow-4B8JwETU.js} +1 -1
- package/dist/assets/web/dist/assets/{PlanePage-RD0M6O6W.js → PlanePage-CHU2szQs.js} +1 -1
- package/dist/assets/web/dist/assets/{ResidentDetailPage-Dl2KId95.js → ResidentDetailPage-L5SRcN_O.js} +1 -1
- package/dist/assets/web/dist/assets/{ResidentsIndexPage-DBy43I1R.js → ResidentsIndexPage-BIFf8qyE.js} +1 -1
- package/dist/assets/web/dist/assets/RunFoldRow-DzPIshJx.js +1 -0
- package/dist/assets/web/dist/assets/{RunRoutePage-Du1HqLZs.js → RunRoutePage-Cru5IVux.js} +3 -3
- package/dist/assets/web/dist/assets/{RunsIndexPage-BZphy3Hr.js → RunsIndexPage-CBkdPAdj.js} +1 -1
- package/dist/assets/web/dist/assets/{RunsTabs-kHbbxVHx.js → RunsTabs-C7Ua3XX5.js} +1 -1
- package/dist/assets/web/dist/assets/{ScheduledPage-B7jh898t.js → ScheduledPage-D_R55BDk.js} +1 -1
- package/dist/assets/web/dist/assets/{SettingSelect-BfID5nF4.js → SettingSelect-CEeA4iuC.js} +1 -1
- package/dist/assets/web/dist/assets/{SettingsPage-3uLEsiiE.js → SettingsPage-DlmZvAvf.js} +1 -1
- package/dist/assets/web/dist/assets/{SilentTurn-CKxSxnQC.js → SilentTurn-PWMDMbMG.js} +1 -1
- package/dist/assets/web/dist/assets/{SlackMark-CtiHrNjr.js → SlackMark-DB0MGiF5.js} +1 -1
- package/dist/assets/web/dist/assets/{StatusDot-x7vcK0iE.js → StatusDot-Bq0mYMFo.js} +1 -1
- package/dist/assets/web/dist/assets/{Tooltip-wVXCWhMp.js → Tooltip-Bs6zd7yE.js} +1 -1
- package/dist/assets/web/dist/assets/{UnitRoutePage-V5BXK7FH.js → UnitRoutePage-BMGEZCvn.js} +1 -1
- package/dist/assets/web/dist/assets/{angular-html-C8b5YTHf.js → angular-html-BRRhsdQE.js} +1 -1
- package/dist/assets/web/dist/assets/{angular-ts-C3f4WYNe.js → angular-ts-BFj-mqCm.js} +1 -1
- package/dist/assets/web/dist/assets/{apl-DSHxUJc3.js → apl-CsBuy1IL.js} +1 -1
- package/dist/assets/web/dist/assets/{astro-BSGCCBP6.js → astro-cVaqxBZq.js} +1 -1
- package/dist/assets/web/dist/assets/{blade-DFeYrMKk.js → blade-MEP5mWha.js} +1 -1
- package/dist/assets/web/dist/assets/{browser-B6T5hjfR.js → browser-CCImen5O.js} +1 -1
- package/dist/assets/web/dist/assets/budgets-0szUBIMv.js +1 -0
- package/dist/assets/web/dist/assets/{c-L_QOnFVv.js → c-D4NGQ_Pd.js} +1 -1
- package/dist/assets/web/dist/assets/{chapel-DLQWUwhu.js → chapel-BkWImsIy.js} +1 -1
- package/dist/assets/web/dist/assets/{cobol-1DlMmrEO.js → cobol-RPDSPSET.js} +1 -1
- package/dist/assets/web/dist/assets/{coffee-BTB6os6N.js → coffee-DZ5z7oVX.js} +1 -1
- package/dist/assets/web/dist/assets/{cpp-BvJI2z3u.js → cpp-CrBtIaRZ.js} +1 -1
- package/dist/assets/web/dist/assets/{crystal-B11wGW_h.js → crystal-DJesYi6f.js} +1 -1
- package/dist/assets/web/dist/assets/{css-BiIWx5Pw.js → css-DO9mjau-.js} +1 -1
- package/dist/assets/web/dist/assets/{dist-C-XGnvM4.js → dist-EkKVbIM-.js} +12 -12
- package/dist/assets/web/dist/assets/{edge-nSglEXaD.js → edge-C3VzbSW0.js} +1 -1
- package/dist/assets/web/dist/assets/{elixir-x7o8qMl8.js → elixir-BkD_Vhfe.js} +1 -1
- package/dist/assets/web/dist/assets/{elm-DGrRyqTQ.js → elm-KIM0mFPk.js} +1 -1
- package/dist/assets/web/dist/assets/{erb--_dh58Nw.js → erb-D2ruCqb2.js} +1 -1
- package/dist/assets/web/dist/assets/{eventSource-Bj_dZf6M.js → eventSource-Cv0AFlMi.js} +1 -1
- package/dist/assets/web/dist/assets/{git-rebase-DbpUXwyg.js → git-rebase-CnfbQTxA.js} +1 -1
- package/dist/assets/web/dist/assets/{glimmer-js-BG0CuZG5.js → glimmer-js-CbiwFXWH.js} +1 -1
- package/dist/assets/web/dist/assets/{glimmer-ts-CQIl5qyR.js → glimmer-ts-DV8ii0Pv.js} +1 -1
- package/dist/assets/web/dist/assets/{glsl-9PJNQTcw.js → glsl-CgmznWkA.js} +1 -1
- package/dist/assets/web/dist/assets/{graphql-CzVTzjEI.js → graphql-BK-bBYfH.js} +1 -1
- package/dist/assets/web/dist/assets/{hack-BhCmAz3Q.js → hack-DnwTTP5n.js} +1 -1
- package/dist/assets/web/dist/assets/{haml-BmI12COR.js → haml-DAVJsWwT.js} +1 -1
- package/dist/assets/web/dist/assets/{handlebars-Cib-ISTS.js → handlebars-voOVfxFL.js} +1 -1
- package/dist/assets/web/dist/assets/{html-D3lDapvI.js → html-3FTqwaPk.js} +1 -1
- package/dist/assets/web/dist/assets/{html-derivative-DRPY8vOK.js → html-derivative-CSlhLDQn.js} +1 -1
- package/dist/assets/web/dist/assets/{http-B9VttK6m.js → http-Vx4ilPfS.js} +1 -1
- package/dist/assets/web/dist/assets/{hurl-C0saNJYj.js → hurl-DxyZDE3R.js} +1 -1
- package/dist/assets/web/dist/assets/{indexRow-Dxg7C8s9.js → indexRow-5s3hNzZ9.js} +1 -1
- package/dist/assets/web/dist/assets/{java-BCFbtYAj.js → java-nWqdjNJG.js} +1 -1
- package/dist/assets/web/dist/assets/{javascript-nwBjnrhh.js → javascript-Dr82HOwp.js} +1 -1
- package/dist/assets/web/dist/assets/{jinja-CMYO9byN.js → jinja-BhjLrPOt.js} +1 -1
- package/dist/assets/web/dist/assets/{jison-Cko8HnE_.js → jison-DilGIUa8.js} +1 -1
- package/dist/assets/web/dist/assets/{json-Dzv__YsX.js → json-CrOcvmhJ.js} +1 -1
- package/dist/assets/web/dist/assets/{jsx-CTFxagih.js → jsx-BW_RX-fo.js} +1 -1
- package/dist/assets/web/dist/assets/{julia-_Xvten1-.js → julia-CWH071DB.js} +1 -1
- package/dist/assets/web/dist/assets/{just-bLps4qOu.js → just-DkhhoWBy.js} +1 -1
- package/dist/assets/web/dist/assets/{latex-D6UaYsUP.js → latex-cuHJ4TUT.js} +1 -1
- package/dist/assets/web/dist/assets/{liquid-CoDIeULa.js → liquid-DG6afYQN.js} +1 -1
- package/dist/assets/web/dist/assets/{lua-D1KFRnVf.js → lua-C5CMnCPS.js} +1 -1
- package/dist/assets/web/dist/assets/{main-DAL--hyj.js → main-Disot0n_.js} +3 -3
- package/dist/assets/web/dist/assets/{marko-B5N5XcOw.js → marko-Dy2_DuC4.js} +1 -1
- package/dist/assets/web/dist/assets/{mdc-uxzjQO3q.js → mdc-BMKb_EeA.js} +1 -1
- package/dist/assets/web/dist/assets/{nginx-BMJxs2TK.js → nginx-og0RgMKf.js} +1 -1
- package/dist/assets/web/dist/assets/{nim-DqQ3-8p1.js → nim-CQxTQQP0.js} +1 -1
- package/dist/assets/web/dist/assets/{org-DsY6LK59.js → org-b5lkq_Pl.js} +1 -1
- package/dist/assets/web/dist/assets/{perl--pq9iJFp.js → perl-D9X5_i_J.js} +1 -1
- package/dist/assets/web/dist/assets/{php-RHCMbsM2.js → php-CwUxvLX0.js} +1 -1
- package/dist/assets/web/dist/assets/{pug-CFNq_FCp.js → pug-uOIOExr0.js} +1 -1
- package/dist/assets/web/dist/assets/{qml-C9Acx9E8.js → qml-g5RoADf-.js} +1 -1
- package/dist/assets/web/dist/assets/{r-DxlU8FBd.js → r-5LdAopD3.js} +1 -1
- package/dist/assets/web/dist/assets/{razor-CLJ2kKih.js → razor-DwrvFLYQ.js} +1 -1
- package/dist/assets/web/dist/assets/{regexp-CzmdGoEp.js → regexp-dGtAaxC-.js} +1 -1
- package/dist/assets/web/dist/assets/{rst-D9yuxBET.js → rst-wFdW0brr.js} +1 -1
- package/dist/assets/web/dist/assets/{ruby-CIRcEvnD.js → ruby-DPglN6I9.js} +1 -1
- package/dist/assets/web/dist/assets/{sas-LOl-uUPh.js → sas-CUbCs40d.js} +1 -1
- package/dist/assets/web/dist/assets/{scss-BX2_sZHY.js → scss-B-DUiI1c.js} +1 -1
- package/dist/assets/web/dist/assets/{shellscript-4d-QvKkY.js → shellscript-lGOV7Ram.js} +1 -1
- package/dist/assets/web/dist/assets/{shellsession-DhB16UGy.js → shellsession-BDWtAAjr.js} +1 -1
- package/dist/assets/web/dist/assets/{soy-Cm1xTUBr.js → soy-zod_dcOy.js} +1 -1
- package/dist/assets/web/dist/assets/{sql-BsfcBJdu.js → sql-BG0HSSoM.js} +1 -1
- package/dist/assets/web/dist/assets/{sseReplay-BqgOggyQ.js → sseReplay-9gcMpylx.js} +1 -1
- package/dist/assets/web/dist/assets/{stata-Dwat3BSw.js → stata-BVUMLp1W.js} +1 -1
- package/dist/assets/web/dist/assets/{surrealql-P4rtxzAW.js → surrealql-DiSUbHKF.js} +1 -1
- package/dist/assets/web/dist/assets/{svelte-DTcsi8S8.js → svelte-DZenT45Y.js} +1 -1
- package/dist/assets/web/dist/assets/{templ-D-kP0Tg5.js → templ-BWKRNM0-.js} +1 -1
- package/dist/assets/web/dist/assets/{tex-D-4vuedK.js → tex-CbMzBlkK.js} +1 -1
- package/dist/assets/web/dist/assets/{ts-tags-jEEWYxsu.js → ts-tags-CZsVorDN.js} +1 -1
- package/dist/assets/web/dist/assets/{tsx-CFnlrVzT.js → tsx-R1r3mH4W.js} +1 -1
- package/dist/assets/web/dist/assets/{twig-D5rGrPjs.js → twig-BjPMyjKH.js} +1 -1
- package/dist/assets/web/dist/assets/{typescript-nYIQ35or.js → typescript-Bx-66VN_.js} +1 -1
- package/dist/assets/web/dist/assets/{typst-3-UX8dna.js → typst-fW037Eo6.js} +1 -1
- package/dist/assets/web/dist/assets/{vue-CLIPIX03.js → vue-D1V_GNxW.js} +1 -1
- package/dist/assets/web/dist/assets/{vue-html-Ci9CpkHU.js → vue-html-C-4pTZ-s.js} +1 -1
- package/dist/assets/web/dist/assets/{vue-vine-DL5pEYYk.js → vue-vine-C-QsX3hR.js} +1 -1
- package/dist/assets/web/dist/assets/{wallClock-DmaC1sKA.js → wallClock-x0hjr0J_.js} +1 -1
- package/dist/assets/web/dist/assets/{xml-bO80qikC.js → xml-BJTJXPgC.js} +1 -1
- package/dist/assets/web/dist/assets/{xsl-BPze60Ej.js → xsl-Xc9lukqe.js} +1 -1
- package/dist/assets/web/dist/assets/{yaml-BQUSon_o.js → yaml-Dw-FMsQa.js} +1 -1
- package/dist/cli.js +1988 -546
- package/package.json +4 -4
- package/dist/assets/web/dist/assets/CostsPage-BaeWnm-o.js +0 -1
- package/dist/assets/web/dist/assets/RunFoldRow-CwHDL-Mo.js +0 -1
- package/dist/assets/web/dist/assets/budgets-KNNkT4PZ.js +0 -1
package/dist/assets/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchboard",
|
|
3
|
-
"version": "1.260.
|
|
3
|
+
"version": "1.260.5",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Mention it in Slack and an agent reviews the PR, ships the fix, or answers the question — on the model you choose, with its tools running where you decide.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"cli": "tsx src/cli.ts",
|
|
40
40
|
"verify": "npm run verify:root && npm run verify --workspaces --if-present && npm run check:site",
|
|
41
41
|
"verify:root": "npm run check:consistency && npm run typecheck && npm run lint && npm run format:check && npm test && npm run check:dist",
|
|
42
|
-
"check:consistency": "npm run check:lockfile && npm run check:sandbox-pair && npm run skills:check && npm run check:deps-drift && npm run licenses:check && npm run docs:check && npm run pr-title:check && npm run specs:check && npm run decisions:check && npm run hygiene:check && npm run vocabulary:check && npm run check:project-facts && npm run check:registry-drift && npm run agents:check && npm run clock:check && npm run screenshots:check",
|
|
42
|
+
"check:consistency": "npm run check:lockfile && npm run check:sandbox-pair && npm run skills:check && npm run check:deps-drift && npm run licenses:check && npm run docs:check && npm run pr-title:check && npm run specs:check && npm run decisions:check && npm run hygiene:check && npm run vocabulary:check && npm run user-message:check && npm run check:project-facts && npm run check:registry-drift && npm run agents:check && npm run clock:check && npm run screenshots:check",
|
|
43
43
|
"ci:gate": "node scripts/ci-gate.mjs",
|
|
44
|
-
"fix": "npm run docs:gen && npm run pr-title:gen && npm run agents:gen && npm run clock:gen && npm run hygiene:gen && npm run vocabulary:gen && npm run deploy:gen && npm run skills:sync && npm run lint:fix && npm run format",
|
|
44
|
+
"fix": "npm run docs:gen && npm run pr-title:gen && npm run agents:gen && npm run clock:gen && npm run hygiene:gen && npm run vocabulary:gen && npm run user-message:check -- --write && npm run deploy:gen && npm run skills:sync && npm run lint:fix && npm run format",
|
|
45
45
|
"deploy:gen": "npm run --silent cli -- deploy init",
|
|
46
46
|
"deploy:check": "npm run --silent cli -- deploy init --check",
|
|
47
47
|
"check:lockfile": "node scripts/check-lockfile.mjs",
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
"hygiene:gen": "node scripts/public-hygiene.mjs --write",
|
|
76
76
|
"vocabulary:check": "node scripts/vocabulary-check.mjs",
|
|
77
77
|
"vocabulary:gen": "node scripts/vocabulary-check.mjs --write",
|
|
78
|
+
"user-message:check": "node scripts/user-message-check.mjs",
|
|
78
79
|
"docs:changed": "node scripts/docs-changed.mjs",
|
|
79
80
|
"deploy:targets": "node scripts/deploy-targets.mjs",
|
|
80
81
|
"docs:dev": "npm run dev -w docs --",
|
|
@@ -88,11 +89,11 @@
|
|
|
88
89
|
"@earendil-works/pi-ai": "0.85.1",
|
|
89
90
|
"@slack/bolt": "^5.1.0",
|
|
90
91
|
"aws4fetch": "^1.0.20",
|
|
91
|
-
"e2b": "^2.
|
|
92
|
+
"e2b": "^2.49.1",
|
|
92
93
|
"mdast-util-from-markdown": "^2.0.3",
|
|
93
94
|
"undici": "^8.10.2",
|
|
94
|
-
"yaml": "^2.
|
|
95
|
-
"zod": "^4.5
|
|
95
|
+
"yaml": "^2.9.1",
|
|
96
|
+
"zod": "^4.6.5"
|
|
96
97
|
},
|
|
97
98
|
"devDependencies": {
|
|
98
99
|
"@earendil-works/pi-coding-agent": "0.85.1",
|
package/dist/assets/project.json
CHANGED
|
@@ -183,6 +183,10 @@
|
|
|
183
183
|
"does": "Records the remaining internal words; refuses growth unless `-- --force`.",
|
|
184
184
|
"when": "Part of `fix`."
|
|
185
185
|
},
|
|
186
|
+
"user-message:check": {
|
|
187
|
+
"does": "No user-facing statement delegates recovery.",
|
|
188
|
+
"when": "Part of `check:consistency`; the baseline only shrinks."
|
|
189
|
+
},
|
|
186
190
|
"agents:gen": {
|
|
187
191
|
"does": "Writes the Commands table in AGENTS.md from `package.json` and this file.",
|
|
188
192
|
"when": "After adding or changing a script; part of `fix`."
|
package/dist/assets/source.json
CHANGED
|
@@ -150,6 +150,11 @@ export function intakeReceiptRetentionMs(catchUpWindowMs: number): number {
|
|
|
150
150
|
* prompt one bounds the ratio the gate is judged by. */
|
|
151
151
|
export const INTAKE_RECOVERY_WINDOW_MS = 10 * MINUTE_MS;
|
|
152
152
|
|
|
153
|
+
/** How long one process owns the right to post a stored intake-failure
|
|
154
|
+
* sentence. A rejected post releases immediately; this bound only recovers a
|
|
155
|
+
* process that died after the atomic claim and before it could finish it. */
|
|
156
|
+
export const INTAKE_DELIVERY_CLAIM_MS = 5 * MINUTE_MS;
|
|
157
|
+
|
|
153
158
|
/** The presets that run the tool loop, and the one pipeline preset. */
|
|
154
159
|
export const LOOP_PRESETS = [
|
|
155
160
|
"general",
|
|
@@ -489,6 +489,10 @@ export interface CoordinatorUnit {
|
|
|
489
489
|
* — no pre-check, no branch, no round 0. A task string's row only; written by
|
|
490
490
|
* the hand-off, read by the driver into the machine's input. */
|
|
491
491
|
resume?: { pr: number; headSha?: string; url?: string };
|
|
492
|
+
/** The decision-record number reserved at admission for this unit. A unit
|
|
493
|
+
* that writes a record carries it through every attempt and briefs its child
|
|
494
|
+
* as `record: NNNN`; the child never scans the directory for a number. */
|
|
495
|
+
record?: string;
|
|
492
496
|
/** The head the unit's own coding child last pushed, recorded when the unit
|
|
493
497
|
* ended `review_pending` (the wall clock capped after the pull request was
|
|
494
498
|
* opened or updated): the next attempt's pre-check starts at the review
|
|
@@ -659,6 +663,7 @@ export function isCoordinatorUnit(v: unknown): v is CoordinatorUnit {
|
|
|
659
663
|
if (r.issue !== undefined && !isFinite(r.issue)) return false;
|
|
660
664
|
if (r.pr !== undefined && !isPr(r.pr)) return false;
|
|
661
665
|
if (r.resume !== undefined && !isResume(r.resume)) return false;
|
|
666
|
+
if (r.record !== undefined && (typeof r.record !== "string" || !/^\d{4}$/.test(r.record))) return false;
|
|
662
667
|
if (r.lastPush !== undefined && !isText(r.lastPush)) return false;
|
|
663
668
|
if (r.segments !== undefined && (!Array.isArray(r.segments) || !r.segments.every(isSegment))) return false;
|
|
664
669
|
if (r.idle !== undefined && !isUnitIdle(r.idle)) return false;
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
type UnitStatus,
|
|
54
54
|
renderUnitReport,
|
|
55
55
|
reenterApprovedRebase,
|
|
56
|
+
reconcileTerminalPr,
|
|
56
57
|
settleUnit,
|
|
57
58
|
startUnit,
|
|
58
59
|
type ChildFacts,
|
|
@@ -110,6 +111,7 @@ export type CoordinatorStepRoute =
|
|
|
110
111
|
| "branch"
|
|
111
112
|
| "spawn"
|
|
112
113
|
| "read-record"
|
|
114
|
+
| "steer"
|
|
113
115
|
| "pr-check"
|
|
114
116
|
| "round"
|
|
115
117
|
| "unit-end"
|
|
@@ -334,11 +336,25 @@ function readRecordReturn(step: string, a: BotAnswer): StepReturn {
|
|
|
334
336
|
// The hard stop's mark, as the bot's answer carries it (record 0060; issue
|
|
335
337
|
// 1924): a finished child's unit ends stopped on it.
|
|
336
338
|
const stopped = a.body.stopped === true ? { stopped: true as const } : {};
|
|
339
|
+
const pullRequest = isRecord(a.body.pullRequest)
|
|
340
|
+
? prCheckReturn(step, {
|
|
341
|
+
status: a.status,
|
|
342
|
+
body: { ok: true, ...a.body.pullRequest, at: a.body.at },
|
|
343
|
+
}).pr
|
|
344
|
+
: undefined;
|
|
337
345
|
// The interrupted child restarted from its request (issue 1903): the bot
|
|
338
346
|
// answers the live successor's id, and the machine keeps the wait on it.
|
|
339
347
|
const restarted = typeof a.body.restartedAs === "string" ? { restartedAs: a.body.restartedAs } : {};
|
|
340
348
|
if (!run.finished)
|
|
341
|
-
return {
|
|
349
|
+
return {
|
|
350
|
+
type: "read-record",
|
|
351
|
+
step,
|
|
352
|
+
run: { finished: false },
|
|
353
|
+
...(pullRequest !== undefined ? { pullRequest } : {}),
|
|
354
|
+
...stopped,
|
|
355
|
+
...restarted,
|
|
356
|
+
at: a.body.at,
|
|
357
|
+
};
|
|
342
358
|
if (typeof run.status !== "string") throw new UnreadableAnswer("read-record", a, "status");
|
|
343
359
|
// The typed artifacts as the bot's record carries them — shape-checked where
|
|
344
360
|
// they were written (the run record's validator), read here as they are.
|
|
@@ -367,6 +383,7 @@ function readRecordReturn(step: string, a: BotAnswer): StepReturn {
|
|
|
367
383
|
type: "read-record",
|
|
368
384
|
step,
|
|
369
385
|
...stopped,
|
|
386
|
+
...(pullRequest !== undefined ? { pullRequest } : {}),
|
|
370
387
|
run: {
|
|
371
388
|
finished: true,
|
|
372
389
|
status: run.status as Extract<ChildFacts, { finished: true }>["status"],
|
|
@@ -435,8 +452,8 @@ function entryHumanGate(v: unknown):
|
|
|
435
452
|
};
|
|
436
453
|
}
|
|
437
454
|
|
|
438
|
-
function prCheckReturn(step: string, a: BotAnswer): StepReturn {
|
|
439
|
-
const { ok, state, prNumber, url, headSha, sha, mergedAt, at } = a.body;
|
|
455
|
+
function prCheckReturn(step: string, a: BotAnswer): Extract<StepReturn, { type: "pr-check" }> {
|
|
456
|
+
const { ok, state, prNumber, url, headSha, sha, mergedAt, mergedBy, closedBy, at } = a.body;
|
|
440
457
|
if (ok === true && state === "none") {
|
|
441
458
|
const { unrecovered, aheadOfBase, prClosed } = a.body;
|
|
442
459
|
return {
|
|
@@ -464,6 +481,7 @@ function prCheckReturn(step: string, a: BotAnswer): StepReturn {
|
|
|
464
481
|
prNumber,
|
|
465
482
|
url,
|
|
466
483
|
...(typeof headSha === "string" ? { headSha } : {}),
|
|
484
|
+
...(typeof a.body.headBranchExists === "boolean" ? { headBranchExists: a.body.headBranchExists } : {}),
|
|
467
485
|
// The entry facts (issue 1689): the branch's own tip and whether the
|
|
468
486
|
// bot's approval stands at the head, read at the unit-start's pre-check
|
|
469
487
|
// so a re-issued plan resumes at review or at the merge decision.
|
|
@@ -494,10 +512,36 @@ function prCheckReturn(step: string, a: BotAnswer): StepReturn {
|
|
|
494
512
|
typeof sha === "string" &&
|
|
495
513
|
typeof mergedAt === "string"
|
|
496
514
|
)
|
|
497
|
-
return {
|
|
515
|
+
return {
|
|
516
|
+
type: "pr-check",
|
|
517
|
+
step,
|
|
518
|
+
pr: {
|
|
519
|
+
state: "merged",
|
|
520
|
+
prNumber,
|
|
521
|
+
url,
|
|
522
|
+
sha,
|
|
523
|
+
mergedAt,
|
|
524
|
+
...(typeof mergedBy === "string" ? { mergedBy } : {}),
|
|
525
|
+
},
|
|
526
|
+
at,
|
|
527
|
+
};
|
|
528
|
+
if (
|
|
529
|
+
ok === true &&
|
|
530
|
+
state === "closed" &&
|
|
531
|
+
typeof prNumber === "number" &&
|
|
532
|
+
typeof url === "string" &&
|
|
533
|
+
typeof closedBy === "string"
|
|
534
|
+
)
|
|
535
|
+
return { type: "pr-check", step, pr: { state: "closed", prNumber, url, closedBy }, at };
|
|
498
536
|
throw new UnreadableAnswer("pr-check", a, "state");
|
|
499
537
|
}
|
|
500
538
|
|
|
539
|
+
function steerReturn(step: string, a: BotAnswer): Extract<StepReturn, { type: "steer" }> {
|
|
540
|
+
if (a.body.ok === true && (a.body.outcome === "steered" || a.body.outcome === "not_live"))
|
|
541
|
+
return { type: "steer", step, outcome: a.body.outcome, at: a.body.at };
|
|
542
|
+
throw new UnreadableAnswer("steer", a, "outcome");
|
|
543
|
+
}
|
|
544
|
+
|
|
501
545
|
/** The round's checks read as the bot answered it (record 0055): the runs at
|
|
502
546
|
* the reviewed head, or none when GitHub could not be read — the machine
|
|
503
547
|
* treats an absent read as pending and asks again at the chunk's end. A retry
|
|
@@ -510,6 +554,14 @@ function checksReturn(step: string, a: BotAnswer): StepReturn {
|
|
|
510
554
|
type: "checks",
|
|
511
555
|
step,
|
|
512
556
|
...(isRoundChecks(checks) ? { checks } : {}),
|
|
557
|
+
...(isRecord(a.body.pullRequest)
|
|
558
|
+
? {
|
|
559
|
+
pullRequest: prCheckReturn(step, {
|
|
560
|
+
status: a.status,
|
|
561
|
+
body: { ok: true, ...a.body.pullRequest, at },
|
|
562
|
+
}).pr,
|
|
563
|
+
}
|
|
564
|
+
: {}),
|
|
513
565
|
// The pull request is a draft (issue 2063): the machine's table holds the
|
|
514
566
|
// unit for the ready event instead of merging or ending without a cause.
|
|
515
567
|
...(draft === true ? { draft: true } : {}),
|
|
@@ -531,11 +583,31 @@ const isRoundChecks = (v: unknown): v is RoundChecks =>
|
|
|
531
583
|
(v.expected === undefined || (Array.isArray(v.expected) && v.expected.every((n: unknown) => typeof n === "string")));
|
|
532
584
|
|
|
533
585
|
function mergeReturn(step: string, a: BotAnswer): StepReturn {
|
|
534
|
-
const { ok, outcome, by, sha, mergedAt, reason, at } = a.body;
|
|
586
|
+
const { ok, outcome, by, sha, mergedAt, mergedBy, reason, at } = a.body;
|
|
535
587
|
// The door found the pull request already merged after the approval: the
|
|
536
588
|
// merge commit and the time ride the answer, and the unit ends `by: other`.
|
|
537
589
|
if (ok === true && outcome === "merged" && by === "other" && typeof sha === "string" && typeof mergedAt === "string")
|
|
538
|
-
return {
|
|
590
|
+
return {
|
|
591
|
+
type: "merge",
|
|
592
|
+
step,
|
|
593
|
+
outcome: "merged",
|
|
594
|
+
by: "other",
|
|
595
|
+
sha,
|
|
596
|
+
mergedAt,
|
|
597
|
+
...(typeof mergedBy === "string" ? { mergedBy } : {}),
|
|
598
|
+
at,
|
|
599
|
+
};
|
|
600
|
+
if (ok === true && outcome === "recheck" && isRecord(a.body.pullRequest))
|
|
601
|
+
return {
|
|
602
|
+
type: "merge",
|
|
603
|
+
step,
|
|
604
|
+
outcome: "recheck",
|
|
605
|
+
pullRequest: prCheckReturn(step, {
|
|
606
|
+
status: a.status,
|
|
607
|
+
body: { ok: true, ...a.body.pullRequest, at },
|
|
608
|
+
}).pr,
|
|
609
|
+
at,
|
|
610
|
+
};
|
|
539
611
|
if (ok === true && outcome === "merged" && typeof sha === "string")
|
|
540
612
|
return { type: "merge", step, outcome: "merged", sha, at };
|
|
541
613
|
if (
|
|
@@ -678,6 +750,16 @@ async function perform(
|
|
|
678
750
|
await step.do(action.step, STEP_CONFIG, () => call(bot, "read-record", { ...tag, runId: action.runId })),
|
|
679
751
|
),
|
|
680
752
|
);
|
|
753
|
+
case "steer":
|
|
754
|
+
return steerReturn(
|
|
755
|
+
action.step,
|
|
756
|
+
answerOf(
|
|
757
|
+
"steer",
|
|
758
|
+
await step.do(action.step, STEP_CONFIG, () =>
|
|
759
|
+
call(bot, "steer", { ...tag, runId: action.runId, reason: action.reason }),
|
|
760
|
+
),
|
|
761
|
+
),
|
|
762
|
+
);
|
|
681
763
|
case "pr-check":
|
|
682
764
|
// `recover` rides only after a dead coding child: the bot opens the pull
|
|
683
765
|
// request from the pushed branch itself instead of answering `none`.
|
|
@@ -806,7 +888,7 @@ async function tellStepThrew(
|
|
|
806
888
|
: `in round ${at.round.index} (\`${at.step}\`)`;
|
|
807
889
|
const report =
|
|
808
890
|
`⚠️ The runner failed ${where}: ${line}\n\n` +
|
|
809
|
-
"
|
|
891
|
+
"The unit remains bound to this thread; the next reply continues it, and a pull request already approved with green checks resumes at the checks step, never at a fresh coding round.";
|
|
810
892
|
const body = {
|
|
811
893
|
...tag,
|
|
812
894
|
ending: {
|
|
@@ -939,11 +1021,17 @@ async function runUnit(
|
|
|
939
1021
|
factsStep,
|
|
940
1022
|
answerOf(
|
|
941
1023
|
"pr-check",
|
|
942
|
-
await step.do(factsStep, STEP_CONFIG, () =>
|
|
1024
|
+
await step.do(factsStep, STEP_CONFIG, () =>
|
|
1025
|
+
call(bot, "pr-check", {
|
|
1026
|
+
...tag,
|
|
1027
|
+
checks: true,
|
|
1028
|
+
...(state.pr !== undefined ? { pr: state.pr.number } : {}),
|
|
1029
|
+
}),
|
|
1030
|
+
),
|
|
943
1031
|
),
|
|
944
1032
|
);
|
|
945
|
-
if (check.type === "pr-check" && check.pr.state === "merged")
|
|
946
|
-
|
|
1033
|
+
if (check.type === "pr-check" && (check.pr.state === "merged" || check.pr.state === "closed"))
|
|
1034
|
+
state = reconcileTerminalPr(state, check.pr);
|
|
947
1035
|
else if (check.type === "pr-check" && check.pr.state === "open")
|
|
948
1036
|
endFacts = {
|
|
949
1037
|
...(check.pr.autoMergeEnabled !== undefined ? { autoMergeEnabled: check.pr.autoMergeEnabled } : {}),
|
|
@@ -973,6 +1061,7 @@ async function runUnit(
|
|
|
973
1061
|
state = reenterApprovedRebase(state);
|
|
974
1062
|
continue pipeline;
|
|
975
1063
|
}
|
|
1064
|
+
const ending = state.ending ?? note.ending;
|
|
976
1065
|
// The last coding child's run is named so the bot can put its handoff
|
|
977
1066
|
// — the deviations it recorded — on the unit's board issue beside the
|
|
978
1067
|
// ending (agent-ship item 14).
|
|
@@ -981,20 +1070,20 @@ async function runUnit(
|
|
|
981
1070
|
// Two copies (routing-and-config item 28): the full report for the
|
|
982
1071
|
// row and the board, and the thread's at the request's verbosity.
|
|
983
1072
|
ending: {
|
|
984
|
-
kind:
|
|
1073
|
+
kind: ending.kind,
|
|
985
1074
|
report: renderUnitReport(state, endFacts),
|
|
986
1075
|
threadReport: renderUnitReport(state, endFacts, state.input.verbosity ?? DEFAULT_VERBOSITY),
|
|
987
1076
|
// An idle ending carries its continuation facts (record 0051): the
|
|
988
1077
|
// bot writes them on the row's `idle` in place of an ending, with
|
|
989
1078
|
// the coding run id it already receives below.
|
|
990
|
-
...(
|
|
1079
|
+
...(ending.kind === "idle"
|
|
991
1080
|
? {
|
|
992
|
-
why:
|
|
993
|
-
renewalsLeft:
|
|
994
|
-
...(
|
|
995
|
-
spendUsd:
|
|
996
|
-
...(
|
|
997
|
-
...(
|
|
1081
|
+
why: ending.why,
|
|
1082
|
+
renewalsLeft: ending.renewalsLeft,
|
|
1083
|
+
...(ending.from !== undefined ? { from: ending.from } : {}),
|
|
1084
|
+
spendUsd: ending.spendUsd,
|
|
1085
|
+
...(ending.handoff !== undefined ? { handoff: ending.handoff } : {}),
|
|
1086
|
+
...(ending.humanGate !== undefined ? { humanGate: ending.humanGate } : {}),
|
|
998
1087
|
}
|
|
999
1088
|
: {}),
|
|
1000
1089
|
},
|
|
@@ -1002,21 +1091,21 @@ async function runUnit(
|
|
|
1002
1091
|
// A review_pending ending names the child's own last push so the next
|
|
1003
1092
|
// attempt's pre-check can start at the review round (the row's lastPush)
|
|
1004
1093
|
// — an idled one the same, off the idle's `from` (record 0051).
|
|
1005
|
-
...(
|
|
1006
|
-
? { headSha:
|
|
1007
|
-
:
|
|
1008
|
-
? { headSha:
|
|
1094
|
+
...(ending.kind === "review_pending" && ending.headSha !== undefined
|
|
1095
|
+
? { headSha: ending.headSha }
|
|
1096
|
+
: ending.kind === "idle" && ending.why === "review_pending" && ending.from !== undefined
|
|
1097
|
+
? { headSha: ending.from }
|
|
1009
1098
|
: {}),
|
|
1010
1099
|
...(state.lastCodingRunId !== undefined ? { codingRunId: state.lastCodingRunId } : {}),
|
|
1011
1100
|
// A continued ending is a segment's end, not the unit's: the bot
|
|
1012
1101
|
// writes the renewal as a row keyed by the next segment's index
|
|
1013
1102
|
// (decision 0046), so a runner reclaimed here never renews twice.
|
|
1014
|
-
...(
|
|
1103
|
+
...(ending.kind === "continued"
|
|
1015
1104
|
? {
|
|
1016
1105
|
segment: {
|
|
1017
|
-
index:
|
|
1018
|
-
...(
|
|
1019
|
-
runId:
|
|
1106
|
+
index: ending.segment,
|
|
1107
|
+
...(ending.from !== undefined ? { from: ending.from } : {}),
|
|
1108
|
+
runId: ending.runId,
|
|
1020
1109
|
},
|
|
1021
1110
|
}
|
|
1022
1111
|
: {}),
|
|
@@ -1041,14 +1130,14 @@ async function runUnit(
|
|
|
1041
1130
|
|
|
1042
1131
|
/** The report of a unit the hard stop ended before it ran (record 0060; issue 1924). */
|
|
1043
1132
|
function stoppedReport(unit: string): string {
|
|
1044
|
-
return `⏹ Stopped: the pipeline's hosted parent was hard-stopped, so ${unit} was ended without running.
|
|
1133
|
+
return `⏹ Stopped: the pipeline's hosted parent was hard-stopped, so ${unit} was ended without running. The original plan remains the durable task for any later pipeline.`;
|
|
1045
1134
|
}
|
|
1046
1135
|
|
|
1047
1136
|
function blockedReport(unit: string, dep: string, depEnding: string): string {
|
|
1048
1137
|
if (depEnding === "blocked")
|
|
1049
|
-
return `⛔ Blocked: ${unit} waits on ${dep}, which is blocked itself.
|
|
1138
|
+
return `⛔ Blocked: ${unit} waits on ${dep}, which is blocked itself. A later pipeline recognizes both units once the dependency is resolved.`;
|
|
1050
1139
|
const person = depEnding === "merge_ready";
|
|
1051
|
-
return `⛔ Blocked: ${unit} waits on ${dep}, which ended ${depEnding}${person ? " — a person's merge" : ""}.
|
|
1140
|
+
return `⛔ Blocked: ${unit} waits on ${dep}, which ended ${depEnding}${person ? " — a person's merge" : ""}. A later pipeline recognizes the dependency once it is ${person ? "merged" : "resolved"}.`;
|
|
1052
1141
|
}
|
|
1053
1142
|
|
|
1054
1143
|
/** End a unit that never entered `runUnit` under the same failure net. */
|
|
@@ -116,6 +116,7 @@ export const ROUND_STAGE = {
|
|
|
116
116
|
* issue 2100) — closes the unit the same way. */
|
|
117
117
|
export const ENDING_STAGE = {
|
|
118
118
|
merged: "merged",
|
|
119
|
+
closed: "ended",
|
|
119
120
|
already_landed: "merged",
|
|
120
121
|
merge_ready: "merge-ready",
|
|
121
122
|
held: "ended",
|
|
@@ -144,6 +145,7 @@ export const ENDING_STAGE = {
|
|
|
144
145
|
* 2100), so a new ending kind fails the build here. */
|
|
145
146
|
export const ENDING_WORDS = {
|
|
146
147
|
merged: "merged",
|
|
148
|
+
closed: "closed",
|
|
147
149
|
already_landed: "merged",
|
|
148
150
|
merge_ready: "merge-ready",
|
|
149
151
|
held: "held",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// literal where `clock:check` expects it.)
|
|
11
11
|
|
|
12
12
|
import { PLANE, minutesToMs } from "../budgets.js";
|
|
13
|
+
import type { ProviderFailureCause } from "../provider.js";
|
|
13
14
|
import type { PlaneFinding } from "./findings.js";
|
|
14
15
|
|
|
15
16
|
// ---- endings and their causes (record 0064, "Endings and the watches") ------------------------
|
|
@@ -139,6 +140,9 @@ export interface PlaneLevelRow {
|
|
|
139
140
|
side: "below" | "above";
|
|
140
141
|
reportedAt: number;
|
|
141
142
|
generation: string;
|
|
143
|
+
/** A provider row's typed down cause; absent on resident rows, provider-up,
|
|
144
|
+
* and reports from an older bot generation. */
|
|
145
|
+
cause?: ProviderFailureCause;
|
|
142
146
|
}
|
|
143
147
|
|
|
144
148
|
/** The side a resident's level reads for an observer that knows the current
|
|
@@ -300,7 +304,13 @@ export type PlaneEvent =
|
|
|
300
304
|
/** A provider's level as the model proxy reported it: `up` on a relayed
|
|
301
305
|
* success, `down` on a failure past its one retry. `up` re-issues every
|
|
302
306
|
* turn held parked on the provider, once each. */
|
|
303
|
-
| {
|
|
307
|
+
| {
|
|
308
|
+
kind: "provider_level";
|
|
309
|
+
at: number;
|
|
310
|
+
provider: string;
|
|
311
|
+
level: "up" | "down";
|
|
312
|
+
cause?: ProviderFailureCause;
|
|
313
|
+
}
|
|
304
314
|
/** A run parked on its provider (record 0064): the harness holds the turn,
|
|
305
315
|
* the lease keeps counting, and the provider's next `up` steers it once. */
|
|
306
316
|
| { kind: "park"; at: number; runId: string; provider: string }
|
|
@@ -692,7 +702,13 @@ function onHeartbeat(
|
|
|
692
702
|
* then walks the queue for anything waiting on `provider_up`. */
|
|
693
703
|
function onProviderLevel(
|
|
694
704
|
state: PlaneState,
|
|
695
|
-
event: {
|
|
705
|
+
event: {
|
|
706
|
+
kind: "provider_level";
|
|
707
|
+
at: number;
|
|
708
|
+
provider: string;
|
|
709
|
+
level: "up" | "down";
|
|
710
|
+
cause?: ProviderFailureCause;
|
|
711
|
+
},
|
|
696
712
|
): PlaneDecision {
|
|
697
713
|
const row: PlaneLevelRow = {
|
|
698
714
|
resident: event.provider,
|
|
@@ -700,6 +716,7 @@ function onProviderLevel(
|
|
|
700
716
|
side: event.level === "up" ? "below" : "above",
|
|
701
717
|
reportedAt: event.at,
|
|
702
718
|
generation: "",
|
|
719
|
+
...(event.level === "down" && event.cause !== undefined ? { cause: event.cause } : {}),
|
|
703
720
|
};
|
|
704
721
|
const levels = [...state.levels.filter((l) => !(l.resident === event.provider && l.name === "provider")), row];
|
|
705
722
|
const writes: PlaneWrite[] = [{ table: "plane_levels", op: "put", row }];
|