[ZOD] gate: reachability dead-code + pkg-derived core seam + debt span fix (+ fix standing CI break)#2
Merged
Conversation
…bt span fix design-check.ts: - Replace the per-symbol dead-export refcount (and its hand-maintained ENTRY keep-alive allowlist) with REACHABILITY from real roots: package.json "exports" + the TUI app entry seed a transitive sweep over the import graph. Catches dead CLUSTERS (a<->b, nothing reaches either) a refcount keeps alive, and deletes the rotting allowlist. - Pull tests/examples/scripts into the graph as CONSUMERS (inform references + reachability) without LINTING them — a seam used only by a test reads as live with no allowlist entry. Their own link errors are out of scope (broken: is now isLinted-gated like every other check). - Derive the cross-core public barrel from package.json "exports"."." (coreBarrelFromPkg) instead of a hardcoded src/core/sdk.ts string, so the seam can't drift from what the package publishes. ponytail-debt.ts: - Fix duplicate-marker host resolution: the text-keyed map collapsed two identical // ponytail: comments onto the FIRST host, so one occurrence inherited the other's orphan/live verdict. Key text -> hosts in walk order and consume the Nth occurrence against the Nth host. Both changes ship regression tests (ponytail: non-trivial logic leaves a runnable check).
The new reachability dead-code pass (prior commit) flags what the old ENTRY keep-alive allowlist was masking — all genuinely unreferenced: - src/tui/ui/hooks.tsx (useEvent): a lifted termcast atom, never imported by anything and unreachable from any entrypoint. Delete the file. - orch-recipes.ts loopUntilDry: dead export whose comment still claimed it was 'Adopted by orch-run.orchestrate()' — but the reference graph shows zero callers (its sibling adversarialVerify IS referenced, so it wasn't flagged). Remove the export + drop the stale mention in orch.ts's header comment. Re-add either when an actual caller needs it (ponytail: deletion over a speculative keep-alive).
`bun run test` (the CI lint gate) ended with `bun scripts/tui/mock.test.ts`, which imports runtime.ts — that EAGERLY constructs the Cloudflare AxAIService at module load from CLOUDFLARE_API_TOKEN. CI sets neither that token nor RLM_MOCK, so the headless run threw 'OpenAI API key not set' and `bun run lint` has been failing on main for every recent commit (~35s fast-fail). RLM_MOCK=1 is the narrow test-only seam (documented in runtime.ts) made exactly for a headless, no-.env harness — i.e. CI. The deterministic mock test must never need a real key. Prefix only that one invocation; the rest of the suite already runs keyless.
umgbhalla
force-pushed
the
zod/yuku-reachability-dead-code
branch
from
June 23, 2026 10:56
b09636b to
2d46918
Compare
Resolve conflicts: - scripts/design-check.ts: keep the PR's dynamic reachability roots (APP_ENTRYPOINTS = chat.tsx + the pkg-exports barrel via coreBarrelFromPkg) over main's hand-maintained ENTRY set — the rest of the file (import.meta.main) already depends on APP_ENTRYPOINTS. - package.json: take main's full test + test:tui chains (the PR branch's were stale), keep the PR's RLM_MOCK=1 prefix on the test-target mock unit (the CI-break fix). Merged result verified: tsc clean, bun run lint green (design-check lean, debt 0 orphan), bun run test:tui 31/31. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
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.
What this does
Upgrades the ponytail static gate (
scripts/design-check.ts+scripts/ponytail-debt.ts) from a refcount-with-allowlist model to a reachability-driven one, fixes a latent debt-harvester bug, removes the dead code the upgrade surfaces, and fixes a standing CI break.Three commits, each independently reviewable:
feat(gate)— the linter upgraderefactor— delete the dead code the upgrade caughtfix(ci)— repair the pre-existing red CIVerified:
bun run lintpasses end-to-end in a keyless env (exact CI simulation) —tscclean, all tests pass,design-check: lean ✓,ponytail-debt: 6 markers, 0 no-trigger, 0 orphan.Upgrade paths (
design-check.ts)1. Reachability-based dead code, replacing the refcount +
ENTRYallowlist.Old dead-export check was
referencesOf(symbol).length === 0, patched with a hand-maintainedENTRYkeep-alive set (chat.tsx, orch-recipes, sdk, mock, the ui atoms…). Two failure modes: (a) a dead cluster (A↔B, nothing reaches either) keeps each other's refcount > 0 so neither is flagged; (b) the allowlist rots — it accretes justifying comments for "landed ahead of wiring" code.New: seed from the real roots (
package.jsonexports+ the TUI app entrysrc/tui/chat.tsx), transitively sweep the import graph, and flag any linted module no root reaches as dead. TheENTRYallowlist is gone.2. Tests/examples/scripts join the graph as consumers, not lint targets.
They inform the reference + reachability graph (so a seam used only by a test reads as live — no allowlist entry needed) but are not linted.
broken:link diagnostics are nowisLinted-gated like every other check, so a consumer's own stale import isn't reported as a gate finding.3. Cross-core seam derived from
package.jsonexports."."(coreBarrelFromPkg) instead of a hardcodedsrc/core/sdk.tsstring — the public boundary can't silently drift from what the package actually publishes.Upgrade path (
ponytail-debt.ts)Duplicate-marker host resolution fix. The text-keyed
hostByCommentmap collapsed two identical// ponytail:comments onto the first host, so one occurrence inherited the other's orphan/live verdict. Now keyed text → hosts in walk order, consuming the Nth occurrence against the Nth host.Both upgrades ship regression tests (ponytail's own "non-trivial logic leaves a runnable check" rule): dead-cluster detection, reachability-off-without-roots, consumer-keeps-seam-live,
coreBarrelFromPkg, and the identical-marker case.Antipatterns it caught (now removed — commit 2)
The reachability pass immediately surfaced what the allowlist was masking:
src/tui/ui/hooks.tsx(useEvent) — a lifted termcast atom, imported by nothing, unreachable from any entrypoint. Pure speculative code kept alive by anENTRYentry + a justifying comment. Deleted.orch-recipes.tsloopUntilDry— dead export whose own comment still claimed "Adopted by orch-run.orchestrate()", but the reference graph shows zero callers (its siblingadversarialVerifyis referenced, which is why a refcount never caught this). A stale lying comment on dead code. Removed + dropped the stale mention inorch.ts's header.(Two more findings were false/out-of-scope and are correctly not reported after the
isLintedgating: a type-only re-export of an external pkg inexamples/sdk-usage.ts, and a staleturnimport in theRLM_LIVE-gatedtelemetry-live.test.ts— both consumer files.)Standing CI break it exposed (fixed — commit 3)
While simulating CI I found main's CI has been red on every recent commit (~35s fast-fail).
bun run lint→bun run testends withmock.test.ts, which importsruntime.ts— that eagerly constructs the CloudflareAxAIServiceat module load fromCLOUDFLARE_API_TOKEN. CI sets neither that token norRLM_MOCK, so it throwsOpenAI API key not set.Fix: prefix that one invocation with
RLM_MOCK=1— the narrow, documented test-only seam built for exactly a headless no-.envharness (i.e. CI). The deterministic mock test should never need a real key.🧵 Discussed/converged with Codex on scope: skipped the analyzer daemon (YAGNI — tsc+tests already gate before analyze), distribution-relative budgets (anti-ponytail — adaptive thresholds rise as the repo worsens), and a broad thin-dep rule (noisy). Kept fixed ceilings as the deletion pressure.
🤖 Authored via OpenClaw (Zod).