UNPKG

pi-lens

Version:

Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo

178 lines (161 loc) • 11.2 kB
# Fixer contract Read first: the engineering principles (`docs/engineering-principles.md`), then `AGENTS.md`, then `docs/pi-lens-subagent.md`, then this contract. Then read the issue with its comments (`gh issue view <N> --comments`): its acceptance criteria are the contract. Rules the principles or `AGENTS.md` already state are not repeated here. Lane mechanics (checkout, `TMPDIR`, push forms, Git grants, summary shape) are `docs/pi-lens-subagent.md` "Orchestrator lane mechanics"; a brief supplies only `lane=<name>`, scope, and the grant. ## Before code - Trace the production entry point and reproduce the defect through it (principles §1, "Premise first"). Name no seam before the reproduction; the red reproduction is your feedback loop, built before any theory of the fix. - Climb the minimalism ladder before screening against the `AGENTS.md` catalog: the catalog says what must not break, never what to add. - Check which open PRs touch your files (`gh pr list`, `gh pr diff`), design to compose, and flag merge order in the PR body. Branch `fix/<N>-<slug>` from `origin/master` unless the brief names a branch. Preserve contributor authorship on a contributor's branch. - Write the failure list in the PR body before the first edit (principles §2): inputs, states, orderings, and platforms; a space with two axes is a table. The tests cover that list, not only the happy path. For a change to N of M members, the list also names M, the excluded default, and the planned generalization verdict: *widen in this PR*, *follow-up issue* with its seam group, or *stay specific* with the reason (#3622). - When a gate becomes fail-closed, sweep every construction site that reaches it, test doubles included, and prove the sweep with the behaviour suites (#3622). - A change on a lifecycle, timing, or identity seam extends or adds a TLA+ model in this step (#3802; the rule itself is in `AGENTS.md`). Find the family in `formal/coverage-map.json`, write the invariant the change preserves or tightens, and show the violating config red on the pre-fix model and green after, or carry `TLA+ unaffected: <family> — <reason>` in the PR body. A row is any-of (one listed family's model move or declaration satisfies it); a row of 4+ families only prints a note until hunk-level matching exists (#3878). The map owner is the lane that adds a `formal/<family>/`: it adds the family and its map row in the same PR, and `validateCoverageMap` reds the Unit tests lane otherwise. - Seams are named in the brief before the round. A fixer that needs an unconfirmed seam stops and reports it as a finding, not as a test. ## Scope - A fix round does not deepen: no refactor, helper extraction, or rename beyond the fix's own lines; deepening is its own slice under the owning umbrella (#3178). Every hunk serves a finding or an acceptance box. Orphans your change created come out; dead code you only noticed goes to the follow-up section. - A behaviour-preserving move is its own commit: callers keep exact results and tests stay green; put any behaviour change in a separate commit (#3817). - Delete vacuous tests in the files you touch (a case that reds on no mutation, asserts a constant, or duplicates a sibling), with the sweep transcript quoted in `Test assessment`. A redundant test that still guards goes only with the named survivor that covers it. - Apply folded review follow-ups per `docs/pi-lens-subagent.md` "Follow-ups", and list filed residuals in one **Residuals** section of the PR body. ## Evidence - Use `scripts/mutate.mjs` for bounded hand mutations; it restores the target automatically, but only while the file still holds the mutated bytes. A leftover journal (`<file>.mutate-backup`) blocks the next run on that file; recover with `--restore`, which refuses and prints the three hashes when the file was edited since. If a crash left the file already at its original bytes, `--restore` also refuses; check the printed hashes and delete the journal by hand. `--restore` is crash recovery only: run against a live `mutate.mjs` run on the same file, it pulls that run's mutation, and that run then reports ERROR (exit 4). - Witness rule (ADR 0007): #1605 owns the witness lanes, and their fixtures live under `tests/fixtures/witness/<slice>/`. - A PR claiming it "reduces failures" runs `node scripts/ci-test-diff.mjs <jobA> <jobB>`, quotes its summary, and explains any NEW failures before claiming a reduction. - Red-first has one stated exception: when the only red-first path needs broad harness setup, brittle mocks, or a test you would delete right after it proves the fix (shape 7: #1114, #1759), state the exception in `Tests`, name the closest executable check you used, and expect the reviewer to dispute it. A silent omission is a defect. - With Git authority, commit the code once the targeted suite is green and after every proven step, before any checkout-based proof; add evidence in a later commit (#3268). Produce a red by restoring only the mutated source path from the pre-fix SHA (`git checkout <sha> -- clients/…`), never `tests` (#3166) and never uncommitted work, and run `git status` after any bulk restore. Without Git authority, use a saved patch. - Hand-mutate only the NEW guard, branch, filter, or cap the PR is about, both directions, one row per direction, and quote the compile-valid red. The new test is the only red under at least one mutation. This is the whole PR mutation layer (AGENTS.md, #4005): there is no per-PR Stryker job, comment, or `MUTATION` line, and no survivor triage. The nightly Stryker report on master is exploratory and is not read here. Use bounded hand probes locally; never run a full Stryker campaign in a worktree. - Every record the `Observability` section names is asserted by a test in the diff and quoted in the body (#2642, #2647, #2649, #2654). - Every behavioural sentence (a docstring invariant, a memo, a registry justification) maps to a test or a probe, or is deleted (#2643, #2654). - Name where new state sits in its ladder and what happens to it at `session_start` (#2649, #2654). - A measured constant names its measuring command and keeps raw output as a tracked artifact pinned by a test (#3648). Run `git check-ignore -v` on every new artifact path before citing it (#3648). - A CI-lane or workflow fix is accepted only when that lane's own run on the exact head completes inside its `timeout-minutes`, with the acceptance surface quoted from its log; any self-bound sits below the job cap by a stated margin. ## Required checks - Run every test that mocks or deep-equals a changed module or record, and the spawn-heavy lanes for real child or LSP tests. - Before pushing, run `npm run astgrep:self-scan`; the pre-push hook runs the same scan over tracked files, after its build. - Reproduce CI-only failures in the CI command shape. - Run `npx oxfmt --check` on every touched file with the symlinked pinned devDependency. Never `npm install oxfmt --no-save`: it replaces the linked `node_modules`. - Run release-QA end to end when a release-QA row changes. - Run the reviewer's standing probes (`docs/pi-lens-reviewer.md`) that the diff can trip, and quote their output in the PR body. ## Fix rounds - On `FIX ROUND` findings, reproduce each finding before fixing it, add a red-first test for every behavioural fix, rebuild, re-run the targeted suites plus anything the findings touched, and push the same branch. If the PR reads DIRTY, merge `origin/master` with additive resolutions and screen the merged result semantically: master may have moved the seam you built on. - A reviewer's prescribed remedy is a hypothesis. Test it against your own table of the seam; if it is insufficient, ship the correct shape and quote the red the prescription alone leaves (#2642). - When a verify finds a NEW defect on your fix, the next round carries a table enumerated from grep: every writer and reader of the key with the exact expression that derives it, and every call into an external sink or timer with "if it throws" and "if it never returns" columns (#2642, #2649). Fix everything the table exposes; a table that finds nothing is quoted too. - Name every governance exemption a round adds, with the reason and whether it is a registration or silencing; it is a finding until the reviewer clears it (#2654). - Spot-check one prior round's mutation on the new head (#2583). - Re-read the changelog fragment for any claim the round retracts (#3155), then add an honest review-round section to the PR body. ## Before the report Re-climb the minimalism ladder on what you built. Challenge anything unnecessary or unverified with a probe, delete what can go, and simplify what remains: prefer deleting over simplifying, simplifying over optimizing, and optimizing over automating. If the diff survives, leave it alone; churn is not rigor (#2599). ## Handoff - The PR body is the whole `.github/PULL_REQUEST_TEMPLATE.md`, every heading present in order: `## Why` (one sentence), `## Notes for the reviewer`, `## Change outline`, `## Summary`, `## Type of change`, `## Area`, `## Checklist`, `## Tests`, `## Blast radius`, `## Observability` (a record literal from the runtime diff, `none: <reason>`, or exactly `No new failure path; no record added.`, which a new decision branch on a session, lifecycle or delivery seam refuses, #3875), `## Class sweep`, and `## Test assessment`. A brief that names only some headings does not shorten this list. The closing keyword lives in the body; GitHub ignores it in a title. - Run `node scripts/check-pr-body.mjs --lint-local PR_BODY.md` and `node scripts/check-changelog-fragments.mjs` before the hand-back; both must pass, and the hand-back quotes them. A red `PR body (advisory)` check is a fix-before-review item. A changelog fragment is `---` / `section: <Added|Changed|Deprecated|Removed|Fixed|Security>` / `audience: <user|internal>` / `---` / blank / one `- ` bullet. `audience` is required: `user` is anything a pi-lens user or agent can observe (tools, diagnostics, messages, config, install, performance, a fixed bug they could hit); `internal` is CI, tests, `formal/`, contributor docs, orchestration, and refactors with no observable change. `npm run changelog:check` checks the rollup, not fragments (#2456). - Every code fact in the PR body is a `` `path:line` `` citation the check verifies: the file must be in the committed tree (never an untracked or git-ignored path, which CI cannot read), and a fenced quote after it must match within ±20 lines. Every test, probe, or fixture id in a body table is a grep-able `it(` title or file name in the tree (#2868, #2877). - With Git authority, the hand-back carries the commit SHA; a dirty tree is an incomplete round. - Report outcome first: branch, PR URL, the root cause in two sentences, red-run evidence, test totals, every mutation result, skipped check, and environment block, and what the orchestrator must decide (merge order, deferred scope, follow-up issues).