383 lines
15 KiB
Markdown
383 lines
15 KiB
Markdown
|
|
# Roadmap: Asymptotically Optimal Codebase Simplifier
|
|||
|
|
|
|||
|
|
Notes May 19 26
|
|||
|
|
- cstat mostly useful as code combing tool for an agent loop with
|
|||
|
|
extant verifiable behavior tests. Making a neruo-symbolic driver
|
|||
|
|
is not something well scoped enough, requires too much resources
|
|||
|
|
that you don't have. Instead just use the tool as-is, and find
|
|||
|
|
simple ways to add on to it as you find actual flaws when using it.
|
|||
|
|
|
|||
|
|
## Framing
|
|||
|
|
|
|||
|
|
The end goal is a tool that takes an existing codebase and reduces its
|
|||
|
|
complexity along a vector of objective structural metrics, subject to the
|
|||
|
|
constraint that observable behavior is preserved (tests pass, conformance
|
|||
|
|
specs still hold). The tool should be useful with a frontier LLM acting as
|
|||
|
|
the agent, and *more* useful when paired with a non-LLM optimizer — ideally
|
|||
|
|
neuro-symbolic, possibly co-trained, but that architecture is a downstream
|
|||
|
|
decision, not an upstream one.
|
|||
|
|
|
|||
|
|
cstat (this repo) is the starting point for the oracle side. It already
|
|||
|
|
emits a deterministic JSON state describing modularity, complexity,
|
|||
|
|
maintainability, redundancy, dead code, coupling, cohesion, and a
|
|||
|
|
diagnostic list with locations. That is the seed of the state vector. The
|
|||
|
|
improvements doc (`improvements-discussion.md`) expands the seed to
|
|||
|
|
Halstead, instability/abstractness, information surface area, scale-free
|
|||
|
|
exponents, self-similarity, and symbol/IR metrics. The current code
|
|||
|
|
operates at AST level only; the future stack will be multi-level.
|
|||
|
|
|
|||
|
|
This document is a strategic roadmap. It defines milestones and ordering,
|
|||
|
|
not implementation. Every milestone before #7 is reversible.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Operating Principles
|
|||
|
|
|
|||
|
|
These are constraints we have already committed to. They shape every
|
|||
|
|
milestone below.
|
|||
|
|
|
|||
|
|
1. **Objective metrics only.** No calibration against human taste. The
|
|||
|
|
target is the structural vector itself. Refactors invisible to the
|
|||
|
|
vector (renames, doc improvements, better error types) are out of scope
|
|||
|
|
for the optimizer — they live on the LLM-only frontier and are not
|
|||
|
|
measured.
|
|||
|
|
|
|||
|
|
2. **Multi-level representation.** The oracle must be able to consume
|
|||
|
|
information at any IR level (source, AST, HIR/MIR, LLVM IR, symbol
|
|||
|
|
table, DWARF). Moves are tagged by the level(s) at which they operate.
|
|||
|
|
Some metrics and some moves are only visible/legal at specific levels.
|
|||
|
|
|
|||
|
|
3. **Vector, not scalar.** Scores stay decomposed. The current
|
|||
|
|
`HealthScores` triple is a human display; the optimizer operates on the
|
|||
|
|
raw component bundle. No weighted sums imposed upstream of the
|
|||
|
|
optimizer.
|
|||
|
|
|
|||
|
|
4. **Pareto, not minimum.** Metrics trade against each other (collapse
|
|||
|
|
classes → fewer objects, more rigidity). The optimizer searches the
|
|||
|
|
frontier; the operator weights. Degenerate minima (delete everything,
|
|||
|
|
one God-class) are prevented by this plus the behavioral constraint.
|
|||
|
|
|
|||
|
|
5. **Tests are constraint, not objective.** Behavior preservation gates
|
|||
|
|
acceptance of a move. Folding correctness into the objective produces
|
|||
|
|
reward hacking.
|
|||
|
|
|
|||
|
|
6. **Minimize reliance on human refactor corpora inside the loop.** LLMs
|
|||
|
|
already encode that prior. Reusing it as training data confounds the
|
|||
|
|
experiment we are actually running, which is: *what does
|
|||
|
|
objective-metric-driven optimization of code structure look like, when
|
|||
|
|
the actor is not trying to imitate humans?* Human-derived data is
|
|||
|
|
acceptable during bootstrap, not in the steady-state loop.
|
|||
|
|
|
|||
|
|
7. **General actor interface.** The system should accept any actor that
|
|||
|
|
maps `(state, move_space) → ranked_moves`: a frontier LLM, a small
|
|||
|
|
distilled model, a symbolic search, or a co-trained neural policy. The
|
|||
|
|
harness is the same.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Milestone 1 — Define the Representation Stack
|
|||
|
|
|
|||
|
|
**Strategic role:** Fixes the coordinate system. Every later milestone is
|
|||
|
|
parameterized by this choice. Cost of getting it wrong is highest because
|
|||
|
|
it propagates.
|
|||
|
|
|
|||
|
|
**Decisions to make:**
|
|||
|
|
|
|||
|
|
- Which IR levels are ingested in v1 vs. deferred. Source and AST are
|
|||
|
|
given (cstat already does this). MIR and LLVM IR require either rustc
|
|||
|
|
internals (unstable) or a stable bridge (e.g. `cargo rustc -- --emit`,
|
|||
|
|
`llvm-tools-preview`, or compiler-as-library via stable JSON dumps).
|
|||
|
|
Symbol table and DWARF are accessible via `nm` / `objdump` /
|
|||
|
|
`gimli` on debug builds.
|
|||
|
|
- The oracle interface: every level contributes named scalars to a single
|
|||
|
|
flat state vector. Levels are independent ingestion modules; missing
|
|||
|
|
levels degrade the vector gracefully (NaN or omitted, not zero).
|
|||
|
|
- The move-tagging convention: every move declares a set of representation
|
|||
|
|
levels it reads from (preconditions) and writes to (effects), even if
|
|||
|
|
the actual edit is source-text. This is what later lets a planner
|
|||
|
|
reason about which moves are cheap to predict vs. which require
|
|||
|
|
re-running the oracle.
|
|||
|
|
|
|||
|
|
**Done when:** A spec document and an empty-but-typed oracle interface
|
|||
|
|
exist. Concrete metric implementations can land later; the *shape* is
|
|||
|
|
fixed.
|
|||
|
|
|
|||
|
|
**Foundational dependency:** Nothing precedes this.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Milestone 2 — Inventory the Move Space, Per Level
|
|||
|
|
|
|||
|
|
**Strategic role:** Establishes what actually acts on the state vector.
|
|||
|
|
Determines whether a symbolic DSL is feasible or whether moves are too
|
|||
|
|
ad-hoc.
|
|||
|
|
|
|||
|
|
**Approach:** Discover, do not enumerate by intuition. Apply candidate
|
|||
|
|
moves on real targets, observe what the vector does, keep what produces
|
|||
|
|
predictable, well-typed deltas.
|
|||
|
|
|
|||
|
|
**Per-level expectations (anticipated, to be verified):**
|
|||
|
|
|
|||
|
|
- *AST-level:* extract function, inline function, merge functions, delete
|
|||
|
|
unreachable function, move function across modules, split module,
|
|||
|
|
replace nested match with early returns, parameterize a struct.
|
|||
|
|
- *HIR/MIR-level:* dead basic-block elimination after lowering, collapse
|
|||
|
|
redundant match arms, simplify control flow that's only redundant
|
|||
|
|
post-desugar.
|
|||
|
|
- *LLVM IR / codegen-level:* devirtualization opportunities, monomorph
|
|||
|
|
pressure (replace generic with dyn, or the reverse, based on
|
|||
|
|
source-to-symbol ratio).
|
|||
|
|
- *Cross-level:* a single source edit (generic → dyn) can produce small
|
|||
|
|
AST delta and large symbol-table delta. These moves carry the most
|
|||
|
|
information per edit.
|
|||
|
|
|
|||
|
|
**Move record format:** name, level tags, preconditions (queryable from
|
|||
|
|
oracle), predicted effect on state vector (which components, predicted
|
|||
|
|
sign, predicted magnitude class), and confidence (deterministic vs.
|
|||
|
|
empirical).
|
|||
|
|
|
|||
|
|
**Done when:** A typed catalog of ~10–20 moves exists, with at least one
|
|||
|
|
empirical trajectory per move showing the vector delta it produces on a
|
|||
|
|
real target.
|
|||
|
|
|
|||
|
|
**Depends on:** Milestone 1.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Milestone 3 — Profile LLM Cleanup Behavior
|
|||
|
|
|
|||
|
|
**Strategic role:** Tells us where the LLM is reliable and where the
|
|||
|
|
eventual non-LLM optimizer must cover. Without this, the symbolic side is
|
|||
|
|
designed against an imagined LLM, not a real one.
|
|||
|
|
|
|||
|
|
**Method:** Controlled cleanup sessions on messy targets, varying scope:
|
|||
|
|
|
|||
|
|
- Single function (local complexity reduction).
|
|||
|
|
- Single file (intra-module restructuring).
|
|||
|
|
- Cross-module (move/split, dependency detangling).
|
|||
|
|
- Multi-step coordinated (3+ moves where intermediate states look neutral
|
|||
|
|
or worse).
|
|||
|
|
|
|||
|
|
**Recorded per session:** moves proposed, moves applied cleanly, moves
|
|||
|
|
that broke build/tests, vector deltas, where the LLM plateaued or
|
|||
|
|
hallucinated. Multiple actors, multiple seeds, multiple targets.
|
|||
|
|
|
|||
|
|
**Output:** A capability profile — per move type and per scope, how
|
|||
|
|
reliably the LLM produces a clean, correct, vector-improving edit. This
|
|||
|
|
profile is what the optimizer in #7 is designed *against* (covers gaps,
|
|||
|
|
delegates strengths).
|
|||
|
|
|
|||
|
|
**Depends on:** Milestone 2 (so we know what moves to evaluate). Can run
|
|||
|
|
in parallel with #2 once #2 has an initial move set.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Milestone 4 — Design the Test Methodology
|
|||
|
|
|
|||
|
|
**Strategic role:** Gates everything downstream that requires measurement.
|
|||
|
|
Bad methodology produces unfalsifiable results.
|
|||
|
|
|
|||
|
|
**Requirements:**
|
|||
|
|
|
|||
|
|
- Reproducible. Same target, same starting code, same metric, same
|
|||
|
|
result.
|
|||
|
|
- Non-human-judged. Success is defined by behavioral conformance, not
|
|||
|
|
taste.
|
|||
|
|
- Behavioral spec is independent of structural metric. Tests evaluate
|
|||
|
|
*what the code does*, the vector evaluates *how it is built*. The two
|
|||
|
|
must not collapse into each other.
|
|||
|
|
- Scope-graduated. Tiny targets (toy VM) for fast iteration; medium
|
|||
|
|
targets (Chip-8, NES subset, JSON parser, regex engine) for
|
|||
|
|
trajectory-shape evidence; larger targets (something approaching but
|
|||
|
|
below GBA emulator scope) noted as future once smaller scopes are
|
|||
|
|
reliable.
|
|||
|
|
|
|||
|
|
**Methodology design produced now, before any large-scope target is
|
|||
|
|
attempted.** Specifically: scoring protocol, trajectory definition
|
|||
|
|
(sequence of (state, move, new_state, behavior_test_result) tuples),
|
|||
|
|
cross-run comparison method, and what counts as a "completed" cleanup
|
|||
|
|
run.
|
|||
|
|
|
|||
|
|
**Strategic note on the emulator idea:** This is the eventual stress test.
|
|||
|
|
"Build XYZ from a spec" is reliably accomplished by current LLMs at
|
|||
|
|
sub-GBA scope. Pairing the cleanup tool against an LLM-built emulator
|
|||
|
|
gives us a target where (a) behavioral correctness is mechanically
|
|||
|
|
checkable via a conformance suite, (b) the initial code quality is
|
|||
|
|
representative of agent-generated mess, and (c) the scope is large enough
|
|||
|
|
that non-trivial restructuring matters. Note for future; the methodology
|
|||
|
|
design happens now, the large-target runs happen post-#6.
|
|||
|
|
|
|||
|
|
**Depends on:** Milestone 1 (state vector defined), #2 (moves defined for
|
|||
|
|
trajectory representation).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Milestone 5 — Design Data Collection
|
|||
|
|
|
|||
|
|
**Strategic role:** Captures the substrate that everything after #6 is
|
|||
|
|
built on. Insufficient logging is unrecoverable; over-logging is harmless.
|
|||
|
|
|
|||
|
|
**Constraint:** Minimize human-corpus reliance inside the loop (principle
|
|||
|
|
#6 above). Bootstrap from existing LLM behavior is acceptable; ongoing
|
|||
|
|
training data should come from the loop's own operation on the test
|
|||
|
|
targets from #4.
|
|||
|
|
|
|||
|
|
**Logged per step:**
|
|||
|
|
|
|||
|
|
- Full state vector before and after.
|
|||
|
|
- Representation-level snapshots referenced by the oracle (cheaply: which
|
|||
|
|
IR levels contributed, what their summary scalars were).
|
|||
|
|
- Proposed move (or moves, if multiple were ranked).
|
|||
|
|
- Applied move's diff.
|
|||
|
|
- Level tags on the applied move.
|
|||
|
|
- Behavioral test result.
|
|||
|
|
- Actor identity (which LLM, which prompt strategy, which seed) and
|
|||
|
|
optionally chain-of-thought / explanation when the actor produces one.
|
|||
|
|
- Wall-clock and oracle-recompute cost.
|
|||
|
|
|
|||
|
|
**Not logged:** Pre-stored human refactor exemplars used as targets. We
|
|||
|
|
want trajectories shaped by the metric, not by mimicry of canonical
|
|||
|
|
human-authored diffs. (If a target *happens* to be a human codebase, fine
|
|||
|
|
— but the actor's training signal should be the oracle, not the human's
|
|||
|
|
historical edits.)
|
|||
|
|
|
|||
|
|
**Depends on:** Milestones 1 (vector shape) and 2 (move shape). Runs in
|
|||
|
|
parallel with #4.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Milestone 6 — Bootstrap Loop, End-to-End
|
|||
|
|
|
|||
|
|
**Strategic role:** Produces the empirical substrate for every subsequent
|
|||
|
|
design decision. *Not* intended to produce clean codebases at this stage —
|
|||
|
|
intended to produce trajectories.
|
|||
|
|
|
|||
|
|
**Configuration:**
|
|||
|
|
|
|||
|
|
- Actor: LLM (frontier, well-instructed).
|
|||
|
|
- Oracle: full representation stack from #1.
|
|||
|
|
- Move space: catalog from #2.
|
|||
|
|
- Targets: graduated set from #4.
|
|||
|
|
- Logging: per #5.
|
|||
|
|
|
|||
|
|
**Runs:** Multiple targets × multiple seeds × multiple prompt strategies.
|
|||
|
|
Both successful and failed trajectories are useful.
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
|
|||
|
|
- A trajectory dataset.
|
|||
|
|
- An empirical answer to "how often does a single move improve the vector
|
|||
|
|
vs. requires a coordinated sequence." This is the locality question
|
|||
|
|
that drives algorithm choice in #7.
|
|||
|
|
- An empirical answer to "where does the LLM plateau, and which axes does
|
|||
|
|
it never touch." This shapes the optimizer's coverage requirements.
|
|||
|
|
- Goodhart-resistance evidence: run at least one degenerate prompt
|
|||
|
|
("minimize the vector, ignore behavior except to keep tests passing")
|
|||
|
|
and inventory the exploits found. This is methodology stress-testing,
|
|||
|
|
not a separate milestone.
|
|||
|
|
|
|||
|
|
**Done when:** Sufficient trajectory data exists to make the design
|
|||
|
|
choices in #7 evidence-based rather than guesswork.
|
|||
|
|
|
|||
|
|
**Depends on:** All of 1–5.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Milestone 7 — Optimizer Design Discussion
|
|||
|
|
|
|||
|
|
**Strategic role:** Commits to a mechanism. First non-reversible point in
|
|||
|
|
the roadmap.
|
|||
|
|
|
|||
|
|
**Inputs from earlier milestones:**
|
|||
|
|
|
|||
|
|
- Move catalog with level tags, preconditions, predicted effects (#2).
|
|||
|
|
- LLM capability profile, with strengths and gaps (#3).
|
|||
|
|
- Trajectory dataset showing locality / non-locality (#6).
|
|||
|
|
- Goodhart exploit inventory (#6).
|
|||
|
|
|
|||
|
|
**Decisions to make:**
|
|||
|
|
|
|||
|
|
- Algorithm class. Candidates include greedy descent, beam search,
|
|||
|
|
simulated annealing on the Pareto frontier, MCTS over move sequences,
|
|||
|
|
neuro-symbolic policy (symbolic move enumeration + learned move-prior
|
|||
|
|
net). Choice is informed by the locality evidence from #6, not by
|
|||
|
|
intuition.
|
|||
|
|
- Where the LLM sits in the final system: primary actor with optimizer as
|
|||
|
|
guardrail, primary optimizer with LLM as move-proposer for moves
|
|||
|
|
outside the catalog, or full delegation to a co-trained policy with
|
|||
|
|
LLM available only as fallback.
|
|||
|
|
- Training regime if a policy net is included. The trajectory dataset
|
|||
|
|
from #6 is the seed; whether on-policy data collection continues in
|
|||
|
|
steady state is a sub-decision.
|
|||
|
|
|
|||
|
|
**Done when:** An architecture is selected and a v1 build is specified.
|
|||
|
|
Build itself is post-roadmap.
|
|||
|
|
|
|||
|
|
**Depends on:** All previous milestones.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Dependency Graph
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
#1 (representation stack)
|
|||
|
|
│
|
|||
|
|
┌─────┴─────┐
|
|||
|
|
▼ ▼
|
|||
|
|
#2 #3
|
|||
|
|
(moves) (LLM profile)
|
|||
|
|
│ │
|
|||
|
|
└─────┬─────┘
|
|||
|
|
▼
|
|||
|
|
┌─────┴─────┐
|
|||
|
|
▼ ▼
|
|||
|
|
#4 #5
|
|||
|
|
(test method) (data collection)
|
|||
|
|
│ │
|
|||
|
|
└─────┬─────┘
|
|||
|
|
▼
|
|||
|
|
#6
|
|||
|
|
(bootstrap loop)
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
#7
|
|||
|
|
(optimizer design)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#1 strictly first. #2 and #3 in parallel. #4 and #5 in parallel after
|
|||
|
|
#2/#3. #6 after all of 1–5. #7 after #6.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Parked / Future
|
|||
|
|
|
|||
|
|
These are noted because they belong on the long horizon but should not
|
|||
|
|
distract from the milestone sequence above.
|
|||
|
|
|
|||
|
|
- **Co-training a neural policy with the symbolic optimizer.** Possible
|
|||
|
|
only after #7's architecture is built and #6's data collection is in
|
|||
|
|
steady state. Treat as a v2 concern.
|
|||
|
|
- **Generalization across languages.** cstat is Rust-only. The
|
|||
|
|
representation stack from #1 should not preclude other languages, but
|
|||
|
|
v1 is Rust.
|
|||
|
|
- **Temporal / git-history metrics.** Deferred per
|
|||
|
|
`improvements-discussion.md`. May re-enter as a data source for the
|
|||
|
|
bootstrap phase only (per principle #6) if useful.
|
|||
|
|
- **Agent-vs-human style classification.** Out of scope for the
|
|||
|
|
optimizer, in scope for cstat as a measurement tool.
|
|||
|
|
- **Emulator-class targets.** Designed for in #4, executed against in a
|
|||
|
|
post-#6 follow-up. The methodology is built early; the large runs come
|
|||
|
|
later.
|
|||
|
|
- **Human-codebase Pareto comparison.** Compare optimizer-cleaned
|
|||
|
|
codebases against the same codebases as cleaned by human maintainers,
|
|||
|
|
on the structural vector. Not for validation (we explicitly do not
|
|||
|
|
calibrate against human taste) but for characterization of where the
|
|||
|
|
two diverge.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Status
|
|||
|
|
|
|||
|
|
Document drafted; no milestones started. Milestone #1 is the next
|
|||
|
|
deliverable.
|