ci: timeout-minutes on every job of every reusable workflow (BSE-001 wave 1) - #63
Merged
Merged
Conversation
noahgift
force-pushed
the
bse-m1-wave1
branch
2 times, most recently
from
September 5, 2026 08:04
7cb816a to
cde0625
Compare
noahgift
force-pushed
the
bse-m1-wave1
branch
from
September 5, 2026 08:07
cde0625 to
8569653
Compare
…T-230) BSE-05 (BSE-001 wave 1): callee jobs of unified-gate.yml, ci.yml, pr-gate.yml (sovereign-ci.yml already timed every job); a uses: caller cannot carry a timeout, so these are the bound on every fleet caller. Pre-existing explicit timeouts untouched; plain insertions. Pmat-Ticket: PMAT-230
noahgift
force-pushed
the
bse-m1-wave1
branch
from
September 5, 2026 08:14
8569653 to
4000603
Compare
… validate before ci / gate (Refs PMAT-230) BSE-09c v1.2 scope (infra PMAT-239). Fail-closed: absent pmat or a pmat without 'work validate' is RED; no roadmap is the only NOT-RUN and says so. 'pmat work validate' exists since v3.0.6 (measured: git grep on tags v3.31.0..v3.37.0 in the pmat tree), so the fleet pin 3.31.0 carries it. Whether pmat is on PATH inside this job on the fleet runners is UNMEASURED (no sovereign-ci job used pmat before); the step searches /opt/fleet-bin/bin, ~/.cargo/bin and /usr/local/cargo/bin first. Placed in job 'security' (bare metal, no container). Pmat-Ticket: PMAT-230 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…hat it did not measure (Refs PMAT-230) D1 quorum 3/3 (conversations 191e5995-56c1-4b73-abb6-fb863a7172ce, 102b7eaa-262c-4e3a-b9ed-8191d406d378, ffc32360-714d-47d1-8686-a8f72f9e7f40): the step sat after the if: always() ownership-restore teardown and so inherited success() behind it; moved above it, straight after checkout. Q4c: a roadmap-like file off pmat's canonical path is now named in a ::warning:: NOT-RUN line rather than silently passed; it is not made RED because eleven sovereign-ci callers carry a root-level roadmap.yaml today (measured) and that decision is Noah's. Measured blast radius at merge: every caller with docs/roadmaps/roadmap.yaml validates (rc=0 across 27 checkouts); no caller goes red for validation. Q2/Q3 clean 3/3. Pmat-Ticket: PMAT-230 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…l closed (Refs PMAT-234) The `validate` job's 'Lint workflow YAML' step ran `uvx yamllint -d relaxed .github/workflows/` on the intel runners and died with `ModuleNotFoundError: No module named 'yamllint.cli'` — a broken ephemeral uv environment reported as a lint failure, on every PR to this repo (#63). The linter is now PROVISIONED: infra's `stack-tool-yamllint` (PMAT-234) pins yamllint 1.38.0 into /opt/fleet-bin, which is root-owned, first on the runner PATH and survives a rust-cache prune. One declared version, installed once, not resolved per job — the same argument that moved cargo-audit, cargo-deny and cargo-mutants out of per-run installs. The step prepends /opt/fleet-bin/bin, REFUSES when the linter is absent (naming the resource that installs it, so the remedy is one line and not a bisect), and prints `yamllint --version` before the verdict — a green from an unknown linter version is a claim nobody can reproduce. `|| true` is not coming back and there is no "skip if missing" branch: an absent verifier is a NO-GO, never a pass. The comment keeps the whole history (pip install -> uvx -> fleet-bin) including the measurement that made arming this step safe in the first place: yamllint exits 0 on this tree, 0 errors and 279 line-length warnings, and warnings do not affect its exit status. MEASURED, not asserted. The step's own shell was extracted from this file and executed against two fixtures: PATH with no yamllint -> exit 1 with the ::error:: line; PATH with a yamllint that prints a version -> exit 0. actionlint -shellcheck= -pyflakes= exits 0 on the tree. Pmat-Ticket: PMAT-234 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…fallback (Refs PMAT-234) D1 lane 1 (agy 31a2cad5-d161-427a-b632-597b671e8214): command -v could match any other yamllint on PATH if fleet-bin's were absent, defeating the fail-closed claim. The provisioned tool is now named by its path. Pmat-Ticket: PMAT-234 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
noahgift
marked this pull request as ready for review
September 5, 2026 18:39
noahgift
enabled auto-merge (squash)
September 5, 2026 18:39
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BSE-001 wave 1 — .github
Spec: paiml/infra
docs/specifications/build-system-enhancement.md§4 wave 1 (BSE-05/06). Ticket: PMAT-230 (infra; this repo has no .pmat). Bundled per D4.Decision record (spec §0, Noah 2026-09-04): "Lets implement entire list of suggestions using paiml-implement and assume fable 5.1 will orchestrate from inside of ~/src/infra, but will delegate all work to sub-agents (i.e. 3 max and heavily use "agy" and focus on minimal token usage)." Prompt line:
/paiml-implement docs/specifications/build-system-enhancement.md M1 --budget-turns 60 --quorum auto --status-every 10 D1=yes D2=180/2 D4=bundle D5=3 D6=keep D7=15.What changed
timeout-minuteson every job that is not a reusable-workflow call (auses:job cannot carry one — GitHub's schema forbids it, measured with actionlint; the callee jobs in paiml/.github carry theirs in that repo's wave-1 PR)..github/actionlint.yamldeclares the fleet's self-hosted labels soactionlintcan serve as the acceptance linter (without it everyclean-roomruns-on is an unknown-label error).ci / gateevery fleet repo calls; callers cannot set a timeout on auses:job, so these callee timeouts are the only bound on forjar'sci/bench/authorizeand every other caller. Pre-existing values (security 10, provenance 5, gate 5, bench 60) are kept as they were. Two pre-existing labels (gpu,lambda-labson unified-gate.yml gpu-gates) are declared for actionlint but NOT changed: lambda-labs must never be a runner (fleet rule), so that job targets a label with no runner — recorded in the infra receipt as a follow-up, out of this ticket's scope.Basis (
basis=)PMAT-230 — timeout-minutes for every job in paiml/.github's workflows
Commands run
Only rows shaped
<caller job> / <callee job>were used as history for areusable-workflow job (GitHub's own naming for a
uses:call). Bare jobnames (no
/) are a caller repo's own unrelated job that happens to sharea name (e.g.
infra's ownci.ymlhas jobs literally namedvalidateandgate, coincidentally identical to this repo'sci.yml— that data wasexcluded, since
infradoes not callpaiml/.github/ci.yml;ci.ymlherehas no
workflow_call:trigger at all and is never invoked by another repo).T = max(15, ceil(1.5·p99), p99+20), never below an existing explicit value.ci.yml (own CI, push+pull_request only — never called by another repo)
pr-gate.yml (
workflow_call)authorize / authorizemax(15, ceil(1.5*1.83)=3, 1.83+20=21.83)→ 22.sovereign-ci.yml (
workflow_call) — existing explicit values are floorsci / testci / lintci / coveragebench / benchci / securityci / provenanceci / gate+bench / gateAll ≤ the 90-minute PR/merge-group cap; none is
workspace-test; none isschedule-only.
unified-gate.yml (
workflow_call; no fleet caller ran in the 2026-07-24+window —
whisper.apr/release.ymlcalls it but has 0 completedReleaseruns in the sampled window, and
paiml-mcp-agent-toolkit's caller isrelease.yml.disabled)make -f .../clean-room/Makefile)make -f .../clean-room/Makefile)make -f .../clean-room/Makefile)actionlint.yaml deviation from the brief
Brief's list was
[clean-room, perf-solo, merge-queue, intel].actionlintstill reported
gpuandlambda-labsas unknown (unified-gate.yml:453,the
gpu-gatesjob'sruns-on: [self-hosted, gpu, lambda-labs], pre-existingand unchanged by this ticket). Both were added so the file matches what this
repo's
runs-on:actually uses; named inopen_questionsper the ticket'sown instruction ("If actionlint then reports a self-hosted label this repo
uses that is not in that list, add it and name it in open_questions").
Verification (Fable re-ran every claim)
for f in .github/workflows/*.yml; do yq -e '[.jobs[]|select(has("uses")|not)|select(has("timeout-minutes")|not)]|length==0' $f; done && actionlint -shellcheck= -pyflakes=→ exit 0timeout-minutes→ acceptance exit 1 (observed, reverted); drop the pool label from one runs-on → exit 1 (observed, reverted)cargo test --workspaceis the discovered fallback gate and was not run for a workflow-only diff; CI on the required check is the gate (spec §2.3 rule 7)Merge
Touches
.github/workflows/*: web-UI merge click (spec §2.4). Order: wave 1 merges before infra's wave-2 deploy (spec §5).pvcontract: NotRun (workflow YAML, named).🤖 Generated with Claude Code
https://claude.ai/code/session_01CBLhQPF2KihBqK6Y34Sec1
roadmap-valid (standing brief 2026-09-05, infra PMAT-239)
One step at the end of the
securityjob (bare metal, no container): ifdocs/roadmaps/roadmap.yamlexists,pmat work validatedecides; no roadmap is the only NOT-RUN and prints so; an absent pmat, or a pmat withoutwork validate, is RED — never a silent skip. Measured:pmat work validateexists since pmat v3.0.6 (git grep on tags v3.31.0…v3.37.0), so the fleet pin (3.31.0 today, 3.37.0 after BSE-10b) carries it; pmat exits 2 on an unknown subcommand; the step's shell was executed on the workstation against four fixtures (no roadmap → 0; valid → 0;notes:as a sequence → 1; no pmat on PATH → 1). Unmeasured: whether pmat is on PATH inside this job on the fleet runners — no sovereign-ci job used pmat before — so the step prepends/opt/fleet-bin/bin,~/.cargo/binand/usr/local/cargo/bin; if it is absent there, every caller'sci / gategoes RED at merge, by design, and the fix is the fleet-bin deploy, not a skip. Consequence at merge: any caller whose roadmap fails validation is red atci / gate— paiml-mcp-agent-toolkit master until #1192 merges (its PMAT-671 row), infra main validates. Thevalidatered on this PR is unchanged: a runner ENV defect (infra PMAT-234).D1 quorum on the step (3 lanes, 3/3 FAIL on placement; conversations 191e5995-56c1-4b73-abb6-fb863a7172ce, 102b7eaa-262c-4e3a-b9ed-8191d406d378, ffc32360-714d-47d1-8686-a8f72f9e7f40), and what changed: the step sat after the
if: always()ownership-restore teardown → moved straight after checkout (d592f55). Q4c "a roadmap off the canonical path is a silent pass" → the NOT-RUN line now names every roadmap-like file it found and did not validate (::warning::); it is not made red because eleven sovereign-ci callers carry a root-levelroadmap.yamltoday (aprender, bashrs, decy, entrenar, pmat, pforge, probar, renacer, simular, trueno-graph, ruchyruchy) and turning them red is Noah's decision, not the step's. Q6 "rehost outsidesecurity" → kept: it is the first bare-metal job with a checkout, and pmat's presence inside the containerised jobs is unmeasured; a red there for a missing binary would block the fleet for the wrong reason. Measured blast radius (27 caller checkouts on this workstation,pmat work validate): every caller that hasdocs/roadmaps/roadmap.yamlvalidates; no caller goes red for validation at merge. Q2/Q3 clean 3/3. The step's shell was executed against five fixtures after the move (no roadmap → 0; misplacedroadmap.yaml→ 0 with the warning; valid → 0;notes:as a sequence → 1; no pmat → 1).