test(#1074): swap workflow size enforcement to baseline + loose hard caps (PR 2/3) (#1096)

Completes the #1074 migration for workflows. The per-file baseline (PR 1) is
now the primary anti-creep guard, so the tier-max tighten-only ceilings are
retired here.

- Delete the 'SIZE: tier anti-creep' describe (3 assertTightCeiling tests) and
  the GRACE constant — per-file baseline already guards every file by name,
  strictly stronger than max(tier).
- Convert the per-file tier test into 'SIZE: workflow tier hard caps': absolute
  red lines (XL 96 KiB / LARGE 60 KiB / DEFAULT 40 KiB) that mean 'extract, do
  not raise', each with real headroom above its high-water file.
- Add a 32 KiB (Codex project_doc_max_bytes) cap for net-new workflow files not
  yet in the baseline and not explicitly tiered.
- Rewrite the header doc comment for the new two-guard model; drop the
  assertTightCeiling import (now unused here; still exported + used by the agent
  test until PR 3).

Addresses the three PR-2 items from the #1089 review:
- Finish the enumeration consolidation (Minor #1): the tier hard-cap and
  new-file guards now read both their file list and byte sizes from
  measureWorkflows()/listWorkflowStems(), removing the inline readdirSync +
  per-file byteCount split-brain. Enumeration and measurement share one source.
- Rewrite CONTEXT.md RULESET.WORKFLOW_SIZE_BUDGET (Minor #2): stale caps
  (XL<=90000/LARGE<=54000/DEFAULT<=38000) replaced with the baseline-first
  model, current hard caps, the new-file anchor, and the size:baseline
  remediation.
- Ship docs (contract-change requirement): a Diataxis how-to + reference for
  the size guard in docs/TESTING-SUITES.md, beside the sibling regression-name
  ratchet (the 'file grew, CI red -> npm run size:baseline, commit the one-line
  diff, justify or extract lazily' workflow). CONTRIBUTING.md's workflow-tree
  note is updated to the baseline model and points at the new guide.

Negative proof: each guard fails independently when violated (new-file cap at
33 KB; hard cap with baseline current; baseline on any per-file growth).

Refs #1074. Part 2 of 3.
This commit is contained in:
Rezolv
2026-06-12 09:30:44 -04:00
committed by GitHub
parent 9e2ef2c94d
commit b055ca14e2
4 changed files with 154 additions and 91 deletions

View File

@@ -59,6 +59,59 @@ the sanctioned layout (see the #443 strategy below), not a one-off regression
pattern. If `issue-*`/`perf-*` one-offs start accumulating the same way
`bug-*` did, extend the ratchet's regex and regenerate the allowlist.
## Workflow size budget
> Tracked by issue [#1074](https://github.com/open-gsd/gsd-core/issues/1074).
> Bytes (not lines) per [#717](https://github.com/open-gsd/gsd-core/issues/717);
> LF-normalized per [#683](https://github.com/open-gsd/gsd-core/issues/683).
Workflow files (`gsd-core/workflows/*.md`) ship in the installed runtime and are
loaded into the agent's context, so their byte size is a real cost. The size
guard in `tests/workflow-size-budget.test.cjs` keeps that cost from creeping up
invisibly. It is an **anti-creep ratchet**, sibling to the regression-name
ratchet above — three layers, ordered from day-to-day to last-resort:
| Layer | What it does | Where |
|---|---|---|
| **Per-file baseline** (primary) | Pins every workflow's *exact* current size in a committed snapshot. Any growth, shrink, add, or removal fails until the snapshot is regenerated — so sub-ceiling creep is caught by name and delta, not just at the tier's single largest file. | `tests/workflow-size-baseline.json` |
| **Loose tier hard caps** (backstop) | Absolute outer red lines per tier — `XL ≤ 98304`, `LARGE ≤ 61440`, `DEFAULT ≤ 40960` bytes. Unlike the old tighten-only ceiling, a cap is **never raised** when a file approaches it: crossing it means *extract*, not bump. | `XL/LARGE/DEFAULT_CAP` |
| **New-file cap** | A workflow not yet in the baseline must stay under `32768` bytes (the Codex `project_doc_max_bytes` anchor) unless explicitly tiered into `XL_WORKFLOWS`/`LARGE_WORKFLOWS` in the same PR. Keeps net-new orchestrators from being born oversized. | `NEW_FILE_CAP` |
`discuss-phase.md` additionally has a thin-dispatcher target of `< 32000` bytes
(issue [#2551](https://github.com/open-gsd/gsd-core/issues/2551)).
### How-to: a workflow grew and CI is red
The baseline guard reports the file and the byte delta. To resolve:
1. **Regenerate the snapshot** and inspect the one-line diff:
```bash
npm run size:baseline
git diff tests/workflow-size-baseline.json
```
2. **Justify the growth in your PR** (a sentence in the description is enough) —
the committed baseline diff is the review record that the larger size was a
deliberate, seen decision, not silent drift.
3. **Or shrink it instead of baselining.** Prefer extraction when the growth is
incidental: move per-mode bodies to `workflows/<name>/modes/`, templates to
`workflows/<name>/templates/`, and shared prose to `gsd-core/references/` —
then load them **LAZILY**. Do *not* convert them to eager `@-required_reading`
includes: that shrinks the file's bytes without shrinking loaded context, so
it games the guard while making the real cost worse. See
`workflows/discuss-phase/` for the progressive-disclosure pattern.
If a hard cap (not the baseline) is what failed, regeneration will **not** help —
that is the signal to extract, per step 3.
### Reference
| Artifact | Role |
|---|---|
| `scripts/workflow-size.cjs` | Single source of truth — LF-normalized byte counter (`lfByteCount`) plus workflow enumeration (`listWorkflowStems`, `measureWorkflows`). Imported by **both** the guard and the generator so they can never measure or enumerate differently. |
| `scripts/update-size-baseline.cjs` (`npm run size:baseline`) | Regenerates `tests/workflow-size-baseline.json` — sorted keys, trailing newline, idempotent. |
| `tests/workflow-size-baseline.json` | The committed per-file snapshot (one entry per workflow). |
| `tests/workflow-size-budget.test.cjs` | The three guards above, plus the `discuss-phase` progressive-disclosure checks. |
## Running suites locally
```bash