Skip to content

refactor(surface): delete five stranded module groups and their suites - #647

Merged
drewstone merged 3 commits into
mainfrom
growth-autopsy
Aug 19, 2026
Merged

refactor(surface): delete five stranded module groups and their suites#647
drewstone merged 3 commits into
mainfrom
growth-autopsy

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Deletes five stranded module groups and their suites: 14 files, 2,482 lines, zero public-API change.

Builds on #643 (branched from its head). The diff shows only this PR's deletions once #643 merges.

What is deleted and why each is safe

Every module here fails the same four checks. None is in the package exports map, so no external consumer can resolve it.

Module group Files Evidence
src/prm/* (5 files + own suite) 7 No ./prm export. Zero src importers (word-boundary grep). Only tests/prm.test.ts + src/prm/inference.test.ts import it. Zero hits for agent-eval/prm in agent-runtime src+bench.
src/registry.ts (ScenarioRegistry) 2 Not exported. Zero src importers — src/analyst/registry.ts is a different, live module and stays. Only tests/registry.test.ts imports it.
src/auto-pr.ts 2 Not exported. The live auto-PR path is src/campaign/auto-pr.ts (exported via ./campaign, used by run-improvement-loop.ts). The root copy is the stranded original.
src/adapters/otel.ts 2 Not exported. Zero src importers. src/adapters/http.ts stays — examples/distributed-driver/* imports it.
src/knowledge/index.ts 1 Two-line barrel with no export path. knowledge/readiness.ts and knowledge/types.ts stay — the root barrel re-exports them.

src/prm/builtin-rubrics.ts also carried the fifth divergent canonical-JSON encoder; #646 tracks the four live ones.

Proof

  • Before (this branch, pre-deletion): 374 test files passed | 2 skipped, 5,278 tests passed | 3 skipped, 98.3s, exit 0.
  • After: suite tail in the PR comment below.
  • tsc --noEmit: exit 0 after deletion.
  • FAIL count both runs: 0.

Part of the growth-autopsy census; the full duplicate table and root causes are in the autopsy report.

0.145.3 tiered the root barrel to consumer-imported symbols and
documented front doors. Twelve modules lost their last export path in
that pass and kept their source files. Each one is unreachable from all
28 build entry points, so none has shipped in dist for three published
versions, and the only importer each retains is its own test.

Deleted with their tests: reviewer, analyst/knowledge-capture,
multi-toolchain-layer, dual-agent-bench, workspace-inspector,
golden-matcher, ui-finding, slo, adapters/langchain, judge-runner,
cost-report, worker-driver-seed.

The public export surface does not move: a build of the parent commit
and a build of this commit both declare 3,447 export entries, and the
two lists are identical. dist loses 753 bytes, all of it doc-comment
text that named a deleted symbol.

Four doc comments named a deleted symbol and now describe the surviving
behaviour instead: multi-layer-verifier (twice), fuzz/types,
contract/self-improve, plus the docs/feature-guide feature map.
fuzz/explorer-cost asserts the ledger total directly rather than
through the deleted cost-report projection.

Evidence for the deletion: 106 canonical checkouts under ~/code, 98
after deduplicating by origin remote, each fetched and grepped at
refs/remotes/origin/HEAD on word boundaries. 84 clean, 12 hits, 1 self,
0 unresolved failures. Eleven of the twelve hits define the name
locally or import it from their own module. The twelfth, starter-foundry,
imports runAssertions, WorkspaceAssertion and WorkspaceSnapshot from
this package while declaring no dependency on it, and has been
incompatible since 0.145.3 removed them from dist. Eleven published
dependent tarballs at current latest were extracted and grepped with 0
extract failures; starter-foundry is the only hit.
Version locked across package.json, clients/python/pyproject.toml,
clients/python/src/agent_eval_rpc/__init__.py and clients/python/uv.lock.

The analyst dependency-lock digest is repinned because all four manifests
it covers moved. The implementation digest does not move: the deletion
touched no file in the analyst benchmark manifest.
Each module fails four checks: no exports-map entry, zero non-test src
importers, zero external importers in tests/scripts/examples, zero fleet
importers in agent-runtime. The knowledge test now imports the concrete
modules because the two-line barrel is gone.

Suite before: 374 files passed, 5278 tests, exit 0.
Suite after: 369 files passed, 5222 tests, exit 0.
tsc --noEmit: exit 0.

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Auto-approved drewstone PR — 7ec89628

This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.

This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.

tangletools · auto-approval · reason: drewstone_author · 2026-08-18T21:24:43Z

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Value Audit — sound-with-nits

Verdict sound-with-nits
Coverage 2 of 2 lenses (value, usefulness)
Concerns 2 (2 weak-concern)
Heuristic 0.0s
Duplication 0.0s
Interrogation 267.9s (2 bridge agents)
Total 267.9s

💰 Value — sound-with-nits

Deletes five verifiably-stranded module groups (2,484 lines, no exports-map entry, zero src importers) with their suites; a clean dead-code subtraction in the grain of the repo's ongoing surface-debris campaign, leaving one stale doc behind.

  • What it does: Commit 7ec8962 removes src/prm/* (5 files + src/prm/inference.test.ts + tests/prm.test.ts), src/registry.ts (ScenarioRegistry), src/auto-pr.ts, src/adapters/otel.ts, and the two-line src/knowledge/index.ts barrel, plus their suites (15 files, 2,484 lines). tests/knowledge-readiness.test.ts now imports the concrete knowledge/readiness and knowledge/types modules. The sibling version-bump commit (34
  • Goals it achieves: Shrink maintenance surface by deleting code no consumer can reach: every group fails the exports map (verified: no ./prm, ./registry, ./auto-pr, ./adapters/otel, or ./knowledge entry in package.json), has zero non-test src importers (verified by grep on the pre-deletion tree), and has a live counterpart where needed — campaign/auto-pr.ts (imported via './auto-pr' in src/campaign/index.ts:35 and ru
  • Assessment: Good change on its merits. I independently reproduced the safety checks rather than trusting the PR body: (1) exports map contains none of the five paths; (2) pre-deletion-tree greps for importers of each module return only the deleted suites themselves — the apparent '../auto-pr' and './auto-pr' hits resolve to the live src/campaign/auto-pr.ts, and 'trace/otel' hits are the separate live src/trac
  • Better / existing approach: none — this is the right approach. Deletion is correct for unreachable modules; exporting or repointing them would add surface for code no consumer uses. I searched for existing equivalents of each deleted capability and confirmed the live twins (src/campaign/auto-pr.ts, src/analyst/registry.ts, src/contract/intake/otel-spans.ts, src/trace/otel.ts) already cover every live use.
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 5
  • Bridge warning: opencode/kimi-for-coding/k2p7: opencode: opencode error

🎯 Usefulness — sound-with-nits

Deletes 2,484 lines of provably stranded surface (five module groups, none in the exports map, zero src importers) with live counterparts intact and typecheck plus the touched test green.

  • Integration: Verified reachable-surface removal, not capability removal. All five groups are absent from the 28-entry package.json exports map (nothing external can resolve them) and zero non-test importers remain: grep of src/tests/scripts/examples for 'prm', root 'registry', root 'auto-pr', 'adapters/otel', and the knowledge barrel found only imports resolving to the live counterparts (src/analyst/kinds/cont
  • Fit with existing patterns: Fits the codebase's established deletion campaign exactly: parent #643 (commit 357bbf9) deleted twelve stranded modules, this removes five more of the same kind, and CHANGELOG.md records the pattern. The change follows the repo's lean-substrate doctrine by removing stranded originals where a live, exported, in-use counterpart exists (campaign/auto-pr, analyst/registry, adapters/http, knowledge/rea
  • Real-world viability: Pure deletion of unreachable code with no runtime behavior change; the only executable risk is dangling references, and tsc exit 0 plus the modified test passing rule that out. The deleted otel bridge's error handling and edge cases are moot since no consumer existed or could exist (it would throw ERR_PACKAGE_PATH_NOT_EXPORTED from npm, as the doc itself stated). Git history retains all deleted co
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 2

🎯 Usefulness Audit

🟡 docs/adapters-observability.md still describes the deleted otel bridge as existing in source [integration] ``

docs/adapters-observability.md:44-63 says 'A bridge exists in source but is not published: createOtelBridge (src/adapters/otel.ts)' and includes a usage snippet. This PR deletes that file, so the section now describes code that no longer exists anywhere. Per repo CLAUDE.md ('Update the doc closest to the change'), trim or rewrite that TraceAI note in this PR; the rest of the doc is unaffected. Does not gate shipping.

💰 Value Audit

🟡 docs/adapters-observability.md still documents the deleted otel bridge [maintenance] ``

docs/adapters-observability.md:45 names 'src/adapters/otel.ts' and line 57 shows 'import { createOtelBridge from .../adapters/otel'' — the module this PR deletes. The doc already admitted (line 49) the export path never resolved, but now the source file itself is gone; a reader gets a 150-line walkthrough of nothing. Also src/campaign/provenance.ts:19,771 comment references '/adapters/otel'. Delete or rewrite the doc (and reword the two comments) in this PR or its follow-up; does not gate shippi


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260818T212945Z

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Value Audit — sound

Verdict sound
Coverage 1 of 2 lenses (usefulness)
Concerns 1 (1 weak-concern)
Heuristic 0.0s
Duplication 0.0s
Interrogation 211.0s (2 bridge agents)
Total 211.0s

⚠️ Partial audit — the verdict covers only usefulness. value: cli-bridge admission rejected (queue saturated). Treat the missing lens as unexamined, not as clear.

💰 Value — error

value agent never ran: the CLI bridge refused admission (no model was started).

  • Model: opencode/deepseek/deepseek-v4-pro
  • Bridge attempts: 4
  • Bridge error: opencode/kimi-for-coding/k2p7: Bridge returned 503: bridge at capacity (queue_timeout, lane=reserved): active=20/20 queued=5/48 — no model was started

🎯 Usefulness — sound

Deletes 2,484 lines of verified-unreachable surface (five module groups plus their suites) with zero public-API change, correctly rewiring the one test that touched the knowledge barrel; every stranded claim was independently re-verified.

  • Integration: Deletion-only change; nothing reachable depended on any deleted module. Verified no exports-map entry exists for any of the five groups before or after (package.json exports list), zero src/tests/scripts/examples importers (word-boundary grep on 7ec8962^), and the live counterparts are confirmed in use: src/analyst/registry.ts (re-exported via ./analyst), src/campaign/auto-pr.ts (used by src/campa
  • Fit with existing patterns: Directly in the established grain: this is the second pass of the same cleanup pattern #643 set (commit 64ee404 deleted twelve modules stranded by the barrel tiering; this deletes five more of the same class, per the growth-autopsy census). It follows the repo's substrate doctrine (no dead surface, exports map is the contract) and reduces the duplicate canonical-JSON encoder count from five to the
  • Real-world viability: Pure deletion of unreachable code with typecheck green and the touched test green carries no runtime risk: no caller exists to hit an error path. The PR's before/after suite numbers (374->369 files, 5278->5222 tests, 0 FAIL) are consistent with what this sandbox could partially verify (3083 passed, 0 related failures). Deleted-with-history means the OTel bridge design is recoverable if the hosted
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1

🎯 Usefulness Audit

🟡 docs/adapters-observability.md still documents the deleted OTel bridge as existing in source [problem-fit] ``

docs/adapters-observability.md:44-63 says 'A bridge exists in source but is not published: createOtelBridge (src/adapters/otel.ts)' and includes an import snippet plus a status note scoped to 'As of 0.140.x'. After this PR the file no longer exists, so the paragraph's premise is false. The doc already framed the code as unreachable, so no user is broken, but CLAUDE.md's rule ('update the doc closest to the change') says this paragraph should have been updated or removed in the same commit. Fix:


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260818T214155Z

@tangletools

Copy link
Copy Markdown
Contributor

✅ No Blockers — 7ec89628

Review health 100/100 · Reviewer score 77/100 · Confidence 95/100 · 6 findings (6 low)

glm: Correctness 77 · Security 77 · Testing 77 · Architecture 77

Reviewer score is advisory once the run is complete and the verdict has no blockers.

Full multi-shot audit completed 8/8 planned shots over 12 changed files. Global verifier still owns final merge decision.

🟡 LOW [Unreleased] records none of the five module-group deletions this PR's head commit introduces — CHANGELOG.md

Head commit 7ec8962 deletes src/auto-pr.ts (504 lines), the src/prm suite (inference, rubric, builtin-rubrics, training-export plus tests), src/adapters/otel.ts (254 lines, 505 test lines), the experiment-evidence and profile-matrix examples, and trims src/registry.ts and src/knowledge/index.ts — roughly 2.8k of the PR's 2,835 deleted lines. At head, the [Unreleased] section (line 7) is empty and the 0.149.0 entry documents only the twelve modules from 357bbf9. The file header promises 'All notable changes', and both 0.147.0 and 0.149.0 set the precedent of documenting every module deletion with export-surface evidence. The deletion is user-visible in at least one place: docs/adap

🟡 LOW Hardcoded version fallback can silently drift from pyproject version — clients/python/src/agent_eval_rpc/__init__.py

Lines 53-56: try: __version__ = version("agent-eval-rpc") except PackageNotFoundError: __version__ = "0.149.0". The fallback constant is bumped only by the manual release ritual (commit 347d934 bumps it in lockstep, which this diff does correctly), and no test asserts it equals pyproject's version. A future release that forgets this line ships a stale version string when the package runs uninstalled from source. Pre-existing pattern, not introduced or worsened here; suggest a one-line CI/test check comparing agent_eval_rpc.__version__ (via forcing the fallback path) to pyproject. No action required for this PR.

🟡 LOW Shot premise does not hold: net diff for docs/feature-guide.md is empty — docs/feature-guide.md

git diff 8fb6b96..7ec8962 -- docs/feature-guide.md produces no output; blob hash is 245ea0d7 at both commits. The in-range commit 357bbf9 edits the file (docs/feature-guide.md:155, dropping 'JudgeRunner' from the Verification row of the Feature Map), but the stated base already contains that exact edit via 64ee404 (PR #643). Impact: none on correctness — the edit is idempotent; the risk-tiering metadata ('1 changed file(s)') counted a commit-level touch, not the net base..head diff. Action for the global verifier: dedupe this file's review against PR #643's already-merged doc change; no re-review needed. The doc content itself was independently verified accurate at head (all referenced exports and examples exist).

🟡 LOW Release commit message overstates which lock manifests moved — src/analyst/benchmark-implementation.ts

Commit 347d934 says 'all four manifests it covers moved', but git diff 99ed9b8..7ec8962 shows pnpm-lock.yaml unchanged; only package.json, clients/python/pyproject.toml, and clients/python/uv.lock changed. No code impact: the digest is a joint hash over all four files, so repinning was still required, and the new pin 3e17b679... verified equal to the head-tree digest while the old pin 5c7e5561... verified equal to the merge-base digest. Fix is optional: correct the provenance claim in the commit message; nothing to change in the file.

🟡 LOW Shot premise mismatch: both listed files are unchanged in this PR — src/fuzz/types.ts

Evidence: git rev-parse 8fb6b96:src/fuzz/types.ts and 7ec8962:src/fuzz/types.ts both yield blob 2f4202731b1d93fbd2fadfef7a546ecfe115b5cd; explorer-cost.test.ts yields 922eb504036b22fd414a40f575080352ebe7bd88 at both commits; git diff <base> <head> -- src/fuzz/ is empty. The risk=14 assignment against these two files is spurious. Impact: none for merge safety — the verifier should re-allocate this audit budget to the 25 files actually deleted/modified. No code change needed.

🟡 LOW Test now coupled to internal module layout instead of public surface — tests/knowledge-readiness.test.ts

The test imports '../src/knowledge/readiness' and '../src/knowledge/types' directly. Since src/index.ts:468-480 re-exports all of these symbols, importing from '../src/index' would keep the test on the public surface and immune to future internal file moves. Deliberate per commit message (barrel was stranded), so informational only; no correctness impact.


tangletools · 2026-08-18T21:42:19Z · trace

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Approved — 6 non-blocking findings — 7ec89628

Full multi-shot audit completed 8/8 planned shots over 12 changed files. Global verifier still owns final merge decision.

Full immutable report for this review: trace

Summary comment for this run: full summary


tangletools · 2026-08-18T21:42:19Z · immutable trace

@tangletools

Copy link
Copy Markdown
Contributor

✅ No Blockers — 7ec89628

Review health 100/100 · Reviewer score 80/100 · Confidence 95/100 · 5 findings (5 low)

glm: Correctness 80 · Security 80 · Testing 80 · Architecture 80

Reviewer score is advisory once the run is complete and the verdict has no blockers.

Full multi-shot audit completed 8/8 planned shots over 12 changed files. Global verifier still owns final merge decision.

🟡 LOW Shot premise mismatch: CHANGELOG.md has zero diff in the stated range — CHANGELOG.md

Evidence: git rev-parse 8fb6b96:CHANGELOG.md and git rev-parse 7ec89628:CHANGELOG.md both return 42b0b6edfe43f9719e147985803eca57f9f4d8c5, and git diff <base> <head> -- CHANGELOG.md outputs nothing. The release-note commit in the range (347d934) re-adds 22 lines the base already carries via the parallel merge, so content is identical. Impact: none to merge correctness; only the shot partitioner's file list is stale. Fix: none needed in the PR; the verifier should drop CHANGELOG.md from this PR's changed-file set for these SHAs.

🟡 LOW Net diff vs stated base is empty; shot is a no-op for merge — clients/python/pyproject.toml

git diff 8fb6b96 7ec8962 -- clients/python/ yields 0 bytes; all three files are md5-identical at base and head because the same 0.149.0 release bump exists on both branches (base via 64ee404, head via 347d934). No action needed — informational, so the global verifier can weight this shot's risk near zero. If the PR merges by rebase, the duplicate release commit may drop out cleanly; if by merge commit, git resolves the identical hunks without conflict.

🟡 LOW Shot assignment lists a file with zero diff in the reviewed range — src/analyst/benchmark-implementation.ts

Evidence: git diff 8fb6b96d 7ec89628 -- src/analyst/benchmark-implementation.ts produces no output; git ls-tree shows blob c8e5dac32737a612f341ecadec4cc76a7ecdf79d for this path at both commits. The range actually changes 25 files (+11/-2835). Impact: this shot's risk budget (risk=12) was spent on an unchanged file; the multi-shot router should recompute file lists from the base..head diff. No code action required — the file's integrity at head was independently proven (digest checker exit 0 with both pinned digests matching, tsc exit 0).

🟡 LOW Doc verb 'wrap' understates direct usability of llmJudge — src/contract/self-improve.ts

The new comment says 'Bring your own, or wrap llmJudge.' llmJudge(name, prompt, opts) already returns a JudgeConfig<TArtifact, TScenario> (src/llm-judge.ts:97-101), which is exactly what judge: JudgeConfig<TArtifact, TScenario> accepts — callers pass its result directly, no wrapping needed. Impact: cosmetic imprecision only; a reader might assume an adaptation layer is required when it is not. Fix: 'Bring your own, or use llmJudge.' Not merge-blocking.

🟡 LOW Replacement assertion is plain arithmetic over list(), not an aggregation-API check — src/fuzz/explorer-cost.test.ts

The old assertion exercised costReport(ledger).perModel, a projection over the ledger; the new one sums entry.costUsd from ledger.list() directly. Since cost-report is deleted this loses nothing user-visible, and per-entry fields are pinned by the loop at lines 89-96 plus the enforced costUsd===actualCostUsd invariant, so the sum check cannot mask a wrong per-entry cost. Optional nit: assert entry.costUsd === 0.5 inside the loop to pin the field directly instead of relying on the schema invariant. No action required for merge.


tangletools · 2026-08-18T21:51:39Z · trace

@drewstone
drewstone merged commit 92772a7 into main Aug 19, 2026
2 checks passed
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.

2 participants