Skip to content

feat(ci): workflow on: blocks from a t27 spec; Website checks in five parallel jobs - #1628

Merged
gHashTag merged 4 commits into
mainfrom
feat/ci-triggers-from-t27
Oct 12, 2026
Merged

gHashTag merged 4 commits into
mainfrom
feat/ci-triggers-from-t27

Conversation

@gHashTag

@gHashTag gHashTag commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

What

Two CI levers in one change:

  1. The on: blocks of five workflows are now data in specs/ci/workflow_triggers.t27. apps/website/scripts/ci-triggers-from-spec.mjs reads the spec through the real compiler wasm, checks the constant schema (derived from the spec's own GENERATED list), evaluates the spec's test blocks, and rewrites exactly the managed on: region of each named workflow. The four prose path filters (brain-ci, ci, codegen, koschei-production), reproduce's positive build-inputs list, and ci.yml's missing workflow_dispatch existed as parked hand edits (stash docs/ci-paths-ignore-website) for a week; they now land with a gate — check:ci-triggers fails any PR whose committed YAML is not what the spec says. The crons catalog cites the no-schedule notes of codegen.yml and brain-ci.yml by line number; the generator reads the catalog and asserts those citation windows itself, so a layout change that would drift them fails at generation time, not an hour later in CI.
  2. Website checks runs in five parallel groups instead of one serial job. Measured on run 38227541848: the serial checks job took 26 min — 8m50s language audits, 3m25s explorer/corpus/render/WebGL, 7m Queen matrix/touch/dead-API, ~5m pure gates. Same steps, five groups that run side by side (pure gates + the new trigger gate; one language audit per locale; two Chrome groups over the built site), so the wall clock is the slowest group, ~8 min. The run inventory old vs new differs only by the added gate step and the per-group builds — no step was dropped.

website gate keeps its contract with branch protection: one required name, green when every group passed, skipped everywhere when the change touches nothing the checks read.

The generator runs five negative controls in memory before every write or check: a splice into a file with no on: block, a tampered output, a spec missing a constant, a spec whose own test no longer holds, and a citation window that no longer mentions cron. The missing-constant control caught a stale reference in this PR's own development; the --check mode caught a splice bug where the managed header made the region scan stop at on: itself; the citation control caught this PR's first CI failure, where the paths-ignore lists pushed the no-schedule notes out of the catalog's cited windows. A gate nobody has watched fail is not trusted on the day it matters.

{
  "version": 1,
  "head_sha": "55ccd49ba4b81537f117111b967ecea3b9614ce2",
  "summary": "The on: blocks of five workflows became data in one t27 spec with a compiler-backed generator and gate, and the Website checks job split from 26 serial minutes to five parallel groups",
  "changes": [
    "specs/ci/workflow_triggers.t27 holds the triggers of five workflows as typed pub constants, with test blocks the generator evaluates before writing anything",
    "apps/website/scripts/ci-triggers-from-spec.mjs rewrites only the managed on: region of each workflow the spec names, in write, --check and --json modes",
    "brain-ci.yml, ci.yml, codegen.yml, koschei-production.yml and reproduce.yml carry the generated blocks, including the parked paths-ignore intent and ci.yml workflow_dispatch",
    "check:ci-triggers is wired into apps/website/package.json and the pure-gates group of Website checks",
    "website-checks.yml splits the serial checks job into five parallel group jobs behind the same website gate contract with branch protection",
    "The no-schedule notes ride right after the first branches line, and the generator asserts the crons catalog citation windows for codegen.yml and brain-ci.yml",
    "Five in-memory negative controls run before every write or check, including the new citation-window control"
  ],
  "tests": [
    {
      "command": "npm --prefix apps/website run gen:ci-triggers",
      "result": "The generator wrote all five on: blocks and every negative control held",
      "status": "passed",
      "evidence": "self-test 5/5 held; spec sha256 6d7d04acdefd90d3"
    },
    {
      "command": "npm --prefix apps/website run check:ci-triggers",
      "result": "The committed workflow triggers are byte-identical to the spec output",
      "status": "passed",
      "evidence": "up to date across brain-ci, ci, codegen, koschei-production, reproduce"
    },
    {
      "command": "TRINITY_ROOT=$PWD npm --prefix apps/website run check:crons-catalog",
      "result": "The cron catalog citations re-read from source all hold after the layout fix",
      "status": "passed",
      "evidence": "Cron catalog: PASS (33 jobs, 8 source lines re-read)"
    },
    {
      "command": "diff of the five regenerated on: blocks against the parked stash intent",
      "result": "The generated blocks are semantically equal to the week-old parked hand edits",
      "status": "passed",
      "evidence": "compared against stash docs/ci-paths-ignore-website before the PR opened"
    },
    {
      "command": "gh run view 38269603272 --repo gHashTag/trinity --log-failed",
      "result": "The diagnostic identified the cron catalog citation as the only pure-gate failure; the other four parallel groups were green",
      "status": "passed",
      "evidence": "website gate log: groups=failure,success,success,success,success; AssertionError: codegen.yml:10 no longer carries a schedule"
    }
  ],
  "limitations": [
    "The catalog rows for the two Queen-dispatched workflows still cite comment lines rather than a schedule block; keeping them green is the generator's job now, and a real fix wants the crons sync to read Queen dispatch cards",
    "Each of the five groups builds its own dist, so total runner minutes rise even though wall clock falls from about 26 minutes to about 8"
  ],
  "tags": ["CIGate", "T27Specs", "GitHubActions", "WebsiteChecks"],
  "blog": {
    "title": "CI triggers became data: five workflows, one spec, no parked edits",
    "summary": "The on: blocks of five GitHub Actions workflows now live as typed constants in one t27 spec; a compiler-backed generator rewrites exactly those regions and a new gate fails any PR whose committed YAML drifted from the spec. The Website checks job splits from 26 serial minutes to five parallel groups.",
    "outline": [
      "Four workflows needed the same prose path filter and the intent sat parked in a stash for a week -- written down twice, run never, which is the defect this change exists to close.",
      "specs/ci/workflow_triggers.t27 holds the triggers as typed pub constants: branches, one shared paths-ignore list, dispatch inputs, schedules, and the intent comments that ride along as arrays read by the emitter.",
      "ci-triggers-from-spec.mjs reads the spec through the real compiler wasm, checks a constant schema derived from the spec's own GENERATED list, and rewrites only the managed on: region of the named files.",
      "The asserts in the spec's test blocks are evaluated, not trusted: typecheck.ok stays true for assert 1 > 2, so a spec whose own tests do not hold must not produce a green build.",
      "Five negative controls run in memory before every write or check -- a splice without an on: block, a tampered output, a missing constant, a flipped constant, a drifted catalog citation -- and three of them caught real bugs during this change's own development.",
      "The scheduled-jobs catalog cites schedule lines by number, so the generator reads the catalog back and asserts the same near-window the CI gate asserts; the first CI run failed exactly there and the fix rides inside the generator.",
      "check:ci-triggers gates the committed YAML against the spec inside Website checks, so a hand edit to a trigger block can no longer merge quietly while the spec says otherwise.",
      "The serial Website checks job took 26 minutes; the same steps in five parallel groups -- pure gates, one language audit per locale, two Chrome groups -- take the slowest group, about eight minutes.",
      "The gate job keeps its contract with branch protection: one required name, green when every group passed, skipped everywhere when the change touches nothing the checks read."
    ]
  }
}

🤖 Generated with Claude Code

gHashTag and others added 2 commits October 12, 2026 22:13
…w_triggers.t27

The four prose path filters (brain-ci, ci, codegen, koschei-production) and
the positive build-inputs list for reproduce existed as parked hand edits
(stash, branch docs/ci-paths-ignore-website) for a week. Now they are
constants in one spec, read through the real compiler wasm, and
ci-triggers-from-spec.mjs rewrites only the on: region of the workflows the
spec names. ci.yml also gains the workflow_dispatch it was missing, so its
verdict can be refreshed behind the new filter.

The generator runs its own negative controls before every write or check:
a splice into a file with no on: block, a tampered output, a spec missing a
constant, and a spec whose own test no longer holds. check:ci-triggers gates
the committed YAML against the spec in Website checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The serial checks job spent 8m50s in the two language audits, 3m25s in
Explorer+corpus+render+WebGL, 7m in the Queen matrix/touch/dead-API group
and the rest in pure gates, all in one queue. Same steps, five groups that
run side by side: pure gates (plus the new check:ci-triggers step), one
language audit per locale, and two Chrome groups over the built site. Each
group builds its own dist/; the Queen dead-API check stays last in its group
because it rebuilds dist/ against a dead address.

website gate now needs all five groups and keeps its contract: green when
the checks passed, skipped everywhere when the change touches nothing they
read. No step was dropped -- the run inventory old vs new differs only by
the added gate step and the per-group builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the status:in-progress 🔵 Agent working label Oct 12, 2026
@github-actions

Copy link
Copy Markdown
Contributor

X Brain Health Check

Score: 100.0/100
Status: 🟢 HEALTHY
Threshold: 80/100

X Brain is above merge threshold

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Brain Stress Test Results

Tests: 261/261 passed, 0 leaked
Status: 🟢 PASS
Gate: every test in zig build test-brain-stress passes and none leaks

@tri-claw

tri-claw Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Summary by t27-bees

Checked by the t27 compiler

t27c parse, parse-complete and typecheck on each changed .t27 file at 55ccd49. Nothing was generated, built or run. A pass means the file is well formed, not that it is right.

  • specs/ci/workflow_triggers.t27: parses and typechecks.

Read by the model

This PR does two things: (1) moves the on: blocks of five workflows into a single t27 spec (specs/ci/workflow_triggers.t27) with a compiler-backed generator (apps/website/scripts/ci-triggers-from-spec.mjs) and a gate (check:ci-triggers) that fails if committed YAML drifts from the spec; (2) splits the serial 26-minute checks job in website-checks.yml into five parallel groups (pure gates + trigger gate, language audit en, language audit ru, browser group A, browser group B), each building the site independently, reducing wall time to ~8 minutes.

Worth a look

  • .github/workflows/reproduce.yml (lines 9–41): The push trigger changed from no path filter (ran on every push to main) to a positive paths: list matching the pull_request block. Scheduled runs are unaffected, but pushes to main that only touch prose/docs will no longer trigger this workflow. The PR description calls this "reproduce's positive build-inputs list," but the old push had no filter at all — verify this reduction in trigger scope is intended.
  • apps/website/scripts/ci-triggers-from-spec.mjs (lines 287–295): splice() scans for the next top-level key starting at onIdx + 1 to avoid stopping at on: itself. The self-test only covers "workflow with no on: block"; it does not exercise the first-run path (no managed header) where start = onIdx. A malformed first run could leave the region unterminated or eat the next key.
  • apps/website/scripts/ci-triggers-from-spec.mjs (lines 307–322): citationProblem() reads public/crons/manifest.json at generation time and asserts that cited line windows still contain "cron". If the manifest is updated independently (e.g., by a separate cron-spec change), the next generator run will fail even though the workflow triggers are correct. The manifest and the generator must stay in sync, or the gate will produce false positives.
  • .github/workflows/website-checks.yml (lines 98–130, 497–660): Four of the five new check groups (checks-lang-en, checks-lang-ru, checks-browser-a, checks-browser-b) each run npm ci and npx vite build independently. This quadruples build compute (and cache pressure) to gain wall-time parallelism. The description acknowledges this trade-off, but it means a flaky build step now fails four jobs instead of one.
  • apps/website/qa/t27-world-discovery.mjs (lines 135–142): The assertion for the gate's needs list is now derived from a hard-coded GROUPS array. If a new check group is added to the workflow but not to this array, the assertion passes while the gate omits that group — the group would run but its result would be ignored by the gate. The test should also assert that every checks-* job in the workflow appears in GROUPS.

Read: 10 files, +766 -83, the whole diff. Head 55ccd49. Model: openai-compatible/nvidia/nemotron-3-ultra-550b-a55b. Commands: @t27-bees review | summary | help | pause | resume. Free for every repository.

gHashTag and others added 2 commits October 12, 2026 23:00
… is generated

The catalog (public/crons/manifest.json, gate check:crons-catalog) cites the
no-schedule note of codegen.yml:10 and brain-ci.yml:11 by line number and
reads a window around each for the word cron. The managed header plus the
paths-ignore lists pushed those notes to lines 21-22 and the gate failed.

The emitter now rides the tail note right after the first branches line, and
the generator reads the manifest itself and asserts the same near-window the
gate asserts, per managed file, in write and --check modes -- so a future
layout change that drifts a citation fails at generation time with the line
numbers in hand, not an hour later in CI. Citations resolve against the
entry's own repository, as the gate's ROOTS lookup does: the bot repository's
ci.yml:10 is not this ci.yml. A fifth negative control covers the window
check on a synthetic citation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The website gate now needs scope plus checks-pure, checks-lang-en,
checks-lang-ru, checks-browser-a and checks-browser-b; the old assert
pinned the single serial checks job and went red on the split. The new
assert names every group, so a group added to the workflow but left out
of the gate's needs list cannot pass silently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag merged commit 1693602 into main Oct 12, 2026
41 of 44 checks passed
@github-actions github-actions Bot added status:completed Done and removed status:in-progress 🔵 Agent working labels Oct 12, 2026
github-actions Bot added a commit that referenced this pull request Oct 12, 2026
feat(ci): workflow on: blocks from a t27 spec; Website checks in five parallel jobs (#1628)

* feat(ci): the five workflows' on: blocks are data in specs/ci/workflow_triggers.t27

The four prose path filters (brain-ci, ci, codegen, koschei-production) and
the positive build-inputs list for reproduce existed as parked hand edits
(stash, branch docs/ci-paths-ignore-website) for a week. Now they are
constants in one spec, read through the real compiler wasm, and
ci-triggers-from-spec.mjs rewrites only the on: region of the workflows the
spec names. ci.yml also gains the workflow_dispatch it was missing, so its
verdict can be refreshed behind the new filter.

The generator runs its own negative controls before every write or check:
a splice into a file with no on: block, a tampered output, a spec missing a
constant, and a spec whose own test no longer holds. check:ci-triggers gates
the committed YAML against the spec in Website checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ci): Website checks in five parallel jobs, 26m -> ~8m

The serial checks job spent 8m50s in the two language audits, 3m25s in
Explorer+corpus+render+WebGL, 7m in the Queen matrix/touch/dead-API group
and the rest in pure gates, all in one queue. Same steps, five groups that
run side by side: pure gates (plus the new check:ci-triggers step), one
language audit per locale, and two Chrome groups over the built site. Each
group builds its own dist/; the Queen dead-API check stays last in its group
because it rebuilds dist/ against a dead address.

website gate now needs all five groups and keeps its contract: green when
the checks passed, skipped everywhere when the change touches nothing they
read. No step was dropped -- the run inventory old vs new differs only by
the added gate step and the per-group builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ci): keep the crons catalog citations true when the trigger block is generated

The catalog (public/crons/manifest.json, gate check:crons-catalog) cites the
no-schedule note of codegen.yml:10 and brain-ci.yml:11 by line number and
reads a window around each for the word cron. The managed header plus the
paths-ignore lists pushed those notes to lines 21-22 and the gate failed.

The emitter now rides the tail note right after the first branches line, and
the generator reads the manifest itself and asserts the same near-window the
gate asserts, per managed file, in write and --check modes -- so a future
layout change that drifts a citation fails at generation time with the line
numbers in hand, not an hour later in CI. Citations resolve against the
entry's own repository, as the gate's ROOTS lookup does: the bot repository's
ci.yml:10 is not this ci.yml. A fifth negative control covers the window
check on a synthetic citation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ci): the world-discovery gate assert knows the five check groups

The website gate now needs scope plus checks-pure, checks-lang-en,
checks-lang-ru, checks-browser-a and checks-browser-b; the old assert
pinned the single serial checks job and went red on the split. The new
assert names every group, so a group added to the workflow but left out
of the gate's needs list cannot pass silently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant