Skip to content

Pin every resolved edge's target per tier-1 corpus so a wrong edge fails CI - #53

Merged
aksOps merged 6 commits into
mainfrom
edge-pins
Jul 29, 2026
Merged

Pin every resolved edge's target per tier-1 corpus so a wrong edge fails CI#53
aksOps merged 6 commits into
mainfrom
edge-pins

Conversation

@aksOps

@aksOps aksOps commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

This branch pins every resolved edge's target in tier-1 corpora to guard against silent resolution failures that the primary resolution-rate gate cannot detect.

Why This Mechanism Exists

The primary resolution-rate gate compares four integers — resolved, unresolved, external, local_binding — to prevent regressions. But a reference that resolves to the wrong definition moves none of these integers. It is still Resolved, still one row, still one edge; only the target changed. The rate cannot see it, the denominator_shrank check cannot see it, and the drift checks cannot see it, because none of them read a target.

This is the exact failure mode that the upcoming type-environment work will risk at scale: resolving a call to the wrong definition silently, with every gate staying green. The pin files and their comparison gate this blind spot.

What the Pins Cover

All tier-1 corpora carrying baselines are pinned:

Go: go-codeiq, go-caddy, go-probes
Java: java-commons-lang, java-gson, java-probes
JavaScript: javascript-express, javascript-fastify, javascript-probes
Python: python-django, python-flask, python-probes
TypeScript: typescript-vue-core, typescript-zod, typescript-probes

Coverage Rule

Every tier-1 corpus with a baseline carries a pin file. Probe corpora are pinned on the same rule as any other corpus because each probe file encodes one resolver contract that was got wrong once — a shadowed binding, a renamed package, a test-package split. Those edge cases are exactly what comes back wrong under a refactor. Their rows are few but load-bearing.

One-Command Regeneration

Each pin file header documents its regeneration command:

```bash
arthron pin corpus/LANG/CORPUS --pins pins/LANG-CORPUS.pins --write
```

For example, to re-pin the Go codeiq corpus:
```bash
arthron pin corpus/go/codeiq --pins pins/go-codeiq.pins --write
```

Mutation Proofs (from tests/edge_pins.rs)

  1. target_moved: A pinned row whose target changed fails the build by name
  2. rows_rekeyed: A row whose key changed while preserving the target fails; re-keying preserves all four gated integers by construction, so no other check would catch it
  3. Coverage growth is legal: New rows appearing is flagged but does not fail
  4. Vanished rows without replacement are flagged: The counting gate owns that half via `denominator_shrank`
  5. Synchronization tests: Every committed pin file is scanned by a test; every pinned corpus has a test; every tier-1 corpus with a baseline has a pin file

The eleven comparisons (four probe corpora + seven main corpora + 2 tier-1 tier-2 tests) run in `.github/workflows/gate.yml` where `ARTHRON_REQUIRE_CORPUS=1` is set, costing 12.7 seconds of wall time against a 45-minute job.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SF9KvRKVzA2vEYqtFq23zm

@aksOps
aksOps enabled auto-merge (squash) July 29, 2026 07:44
@aksOps
aksOps merged commit 9b2705e into main Jul 29, 2026
11 of 12 checks passed
@aksOps
aksOps deleted the edge-pins branch July 29, 2026 07:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant