Observation-class finding, recorded while bumping the objectui pin on #12687 (PR #12955). Sharpened after a second instance turned up as a real CI red on that PR — the original filing understated this as a single-gate gap.
The claim
An .objectui-sha diff derives no pin-critical gate at all. This is not one unreachable gate; it is a class, and the class is characterised by something worse than an oversight: the gates a pin bump most needs are the ones that cannot be path-filtered, and path derivation is blind to exactly that.
Two instances, two different mechanisms, same consequence.
Instance 1 — Console Pin Gate, filtered one indirection away
It selects itself on a dorny/paths-filter job output, not a workflow-level pull_request: paths: filter:
# .github/workflows/ci.ymlconsole:
- '.objectui-sha'
- 'scripts/build-console.sh'…
---
name: Console Pin Gateneeds: filterif: ${{ !cancelled() && needs.filter.outputs.console != 'false' }}The population is real, correct, and sitting in the workflow file — just expressed one hop from where the derivation reads.
Instance 2 — check:objectui-pin-citations, deliberately UNFILTERED (this is the sharp one)
pnpm --filter @objectstack/spec check:objectui-pin-citations, run in Type Check · source gates (lint.yml:3701). It declares no path population on purpose, and the step's own comment says why:
Reads src/ and the root pin file only — no build — so it belongs in this pre-build source-audit group. Unfiltered and required: a paths filter on packages/spec/** would go dormant on exactly the PR that moves .objectui-sha, which is the PR this exists to catch.
That is the whole finding in one sentence. The gate is unfiltered because filtering it would break it — and being unfiltered is precisely what makes it invisible to a derivation that works from declared paths. The correctness requirement and the derivability requirement are in direct opposition here.
Measured, on PR #12955
| diff | families derived | pin gates named |
|---|
.objectui-sha + .changeset/…md (2 files) | 8 | none — all 8 matched via the changeset file; .objectui-sha matched nothing |
after adding 3 × packages/spec/src/** (5 files) | 33 | still none |
The second row is the damning one: the diff now edits the very files check:objectui-pin-citations scans and the pin file it compares them against, the family grew from 8 to 33 — and the gate is still not named.
Residue placement (--residue), which is why a dev skips them:
check:objectui-pin-citations → Undetermined ("source names no path at all — NOT known irrelevant"), 34 familiescheck:console-sha → Undetermined, same bucketcheck:console-injection → Silent ("source names paths, none of which cover yours — the weakest verdict"), 111 families
All three sit in the two buckets whose own labels say they are not clearances — and which, at 34 + 111 families, no one reads.
It is not hypothetical — it shipped a red
PR #12955 ran every derived gate green locally, plus the console pair by hand (read out of ci.yml, because the derivation would not name them). check:objectui-pin-citations was neither derived nor guessed, and CI went red:
✗ 8 spec source(s) assert an objectui pin this repo does NOT build against.
.objectui-sha = 9602dc820450dda956843c6cfe5b329bcf88c757
packages/spec/src/data/api-methods-batch-conformance.test.ts:64 cites `190fbd01d`
packages/spec/src/ui/component.test.ts:281 / :366 / :2437 cites `190fbd01d`
packages/spec/src/ui/component.zod.ts:642 / :1649 / :1825 / :2393 cites `190fbd01d`
Type Check · source gates (job 98826433330) failed; the required TypeScript Type Check context went red purely as its rollup (verified from the aggregator's own OS_NEEDS: one lane failure, three success).
Note the shape: this gate exists specifically to fire on pin bumps and is required — so the one card it was built for is the one card whose dev is not told to run it.
Why a pin bump makes this expensive
A pin bump's entire risk is the console build and the cross-repo records that describe it. The failure is not "a gate went red" but the cost of the round trip: re-measuring 8 records against a 359-commit objectui range is real work, and check:objectui-pin-citationsrefuses a mechanical fix by design (no gen:, NO_GENERATOR in the check:generated ledger) — it demands a human/agent re-derivation. Learning that from CI rather than from the dispatch list costs a full patch round every time.
Not proposing the fix
Two candidate directions, both wider than a special case, neither costed here:
- Follow
needs.<job>.outputs.<name> back to the dorny/paths-filter block that defines it — covers instance 1 and every other filtered job in ci.yml at once. - Give deliberately-unfiltered-but-path-relevant gates a way to declare a derivation population distinct from their execution filter — the point being that a gate can be correct to run always and still know which diffs make it interesting. That is instance 2, and the
ROOT_DIR_WATCH_HINTS marker idiom the residue output already mentions looks like the nearest existing seam.
Filed unassigned.
Generated by Claude Code
Observation-class finding, recorded while bumping the objectui pin on #12687 (PR #12955). Sharpened after a second instance turned up as a real CI red on that PR — the original filing understated this as a single-gate gap.
The claim
An
.objectui-shadiff derives no pin-critical gate at all. This is not one unreachable gate; it is a class, and the class is characterised by something worse than an oversight: the gates a pin bump most needs are the ones that cannot be path-filtered, and path derivation is blind to exactly that.Two instances, two different mechanisms, same consequence.
Instance 1 —
Console Pin Gate, filtered one indirection awayIt selects itself on a
dorny/paths-filterjob output, not a workflow-levelpull_request: paths:filter:The population is real, correct, and sitting in the workflow file — just expressed one hop from where the derivation reads.
Instance 2 —
check:objectui-pin-citations, deliberately UNFILTERED (this is the sharp one)pnpm --filter @objectstack/spec check:objectui-pin-citations, run inType Check · source gates(lint.yml:3701). It declares no path population on purpose, and the step's own comment says why:That is the whole finding in one sentence. The gate is unfiltered because filtering it would break it — and being unfiltered is precisely what makes it invisible to a derivation that works from declared paths. The correctness requirement and the derivability requirement are in direct opposition here.
Measured, on PR #12955
.objectui-sha+.changeset/…md(2 files).objectui-shamatched nothingpackages/spec/src/**(5 files)The second row is the damning one: the diff now edits the very files
check:objectui-pin-citationsscans and the pin file it compares them against, the family grew from 8 to 33 — and the gate is still not named.Residue placement (
--residue), which is why a dev skips them:check:objectui-pin-citations→ Undetermined ("source names no path at all — NOT known irrelevant"), 34 familiescheck:console-sha→ Undetermined, same bucketcheck:console-injection→ Silent ("source names paths, none of which cover yours — the weakest verdict"), 111 familiesAll three sit in the two buckets whose own labels say they are not clearances — and which, at 34 + 111 families, no one reads.
It is not hypothetical — it shipped a red
PR #12955 ran every derived gate green locally, plus the console pair by hand (read out of
ci.yml, because the derivation would not name them).check:objectui-pin-citationswas neither derived nor guessed, and CI went red:Type Check · source gates(job 98826433330) failed; the requiredTypeScript Type Checkcontext went red purely as its rollup (verified from the aggregator's ownOS_NEEDS: one lanefailure, threesuccess).Note the shape: this gate exists specifically to fire on pin bumps and is required — so the one card it was built for is the one card whose dev is not told to run it.
Why a pin bump makes this expensive
A pin bump's entire risk is the console build and the cross-repo records that describe it. The failure is not "a gate went red" but the cost of the round trip: re-measuring 8 records against a 359-commit objectui range is real work, and
check:objectui-pin-citationsrefuses a mechanical fix by design (nogen:,NO_GENERATORin thecheck:generatedledger) — it demands a human/agent re-derivation. Learning that from CI rather than from the dispatch list costs a full patch round every time.Not proposing the fix
Two candidate directions, both wider than a special case, neither costed here:
needs.<job>.outputs.<name>back to thedorny/paths-filterblock that defines it — covers instance 1 and every other filtered job inci.ymlat once.ROOT_DIR_WATCH_HINTSmarker idiom the residue output already mentions looks like the nearest existing seam.Filed unassigned.
Generated by Claude Code