Chapter 18 of 18

Build a Self-Improving Engineering Program

Explain this chapter with AI

Copy this prompt into ChatGPT, Claude, Gemini, a local model, or another AI.

Apply this chapter with AI

Copy this prompt into ChatGPT, Claude, Gemini, a local model, or another AI.

Build a Self-Improving Engineering Program

We can now assemble the book.

The target is not an autonomous runtime that rewrites itself, judges its own work, and deploys the result. That collapses proposal, evidence, and authority into one component.

The stronger meaning is:

A self-improving engineering program participates in a governed evidence loop: production and evaluation create auditable evidence, optimizers propose new program state, independent comparison tests the proposal, and a separate promotion boundary decides what may become active.

Self-improvement is therefore a property of the lifecycle, not permission for the currently active program to modify itself in place.

The capstone task is repository repair.

Input:

repository
issue / requested engineering change
constraints

Output:

diagnosis
evidence
proposed intervention
candidate patch
validation result
confidence / uncertainty

The real success criterion is external:

Did the change resolve the motivating problem
without causing unacceptable regressions?

1. The insufficient baseline

The smallest DSPy version is tempting:

import dspy

repair = dspy.Predict("issue, repository_context -> diagnosis, patch")

It fails for reasons the book has already exposed:

contract too vague
context too large
no tool boundary
no validation loop
no split discipline
no promotion boundary
patch similarity confused with success

So we build the real program from parts.


2. Capstone architecture

CoCoder’s current candidate_patch_generation EngineeringProgram demonstrates the same separation at a larger scale. The program definition is an explicit, versioned contract with objective, input/output schemas, constraints, runtime policy, validation contract, and optimization surface. ProgramRuntime executes one concrete version; ProgramOptimizer is a separate extension point that proposes a candidate version.

The direct runtime delegates candidate generation through the existing provider-neutral model-execution layer. Independent candidate evaluation then reconstructs the source revision in an isolated workspace, materializes the patch, applies scope and validation gates, analyzes the candidate, computes EngineeringDelta, and persists the resulting evidence.

DSPy therefore sits behind the optimization boundary. It is not the EngineeringProgram abstraction, the repository validator, or the promotion authority.


3. Program contracts

The contracts deliberately exclude promotion_decision, historical outcome fields, future repository state, and any gold patch. Those belong to evaluation and governance.

They also avoid treating self-reported confidence as correctness. The program may report uncertainty or missing evidence, but only external validation can establish whether a patch applies, satisfies the concern, and avoids regressions.


4. Validation loop

The validation contract is frozen before optimization. Each candidate attempt executes against a clean reconstruction of the case revision:


5. Optimization dataset

A repository-repair case should separate the state available when the decision was made from evidence learned afterward:


6. Choose the optimizer by failure

Do not stack optimizers for decoration.

Failure Reasonable intervention
Useful predictor-level traces can be accepted by a reliable metric BootstrapFewShot for bootstrapped demos
Trusted stage-specific labels match predictor Signatures Labeled few-shot demonstrations may be appropriate
Instructions are systematically weak and dev data is adequate MIPROv2
Scored components receive rich, non-leaking diagnostics GEPA
Evidence selection misses the root cause Improve retrieval/tools before prompt optimization
Validation cannot express the motivating concern Fix the validation contract before optimizing the program

For a composed repository-repair program, do not assume one final gold patch is automatically a labeled demo for every internal predictor. Stage labels must match the Signatures they supervise, just as in Chapter 11.

GEPA becomes attractive when validation failures can produce actionable feedback such as:


7. Frozen experiment and promotion

The manifest freezes the experimental contract:

The protocol:


8. A small executable manifest guard

The capstone needs ordinary tests around the experiment boundary.

This is not a substitute for CoCoder’s full experiment service. It demonstrates three minimum invariants: the experiment is identified by frozen configuration, case IDs are disjoint, and source groups are disjoint as well.

The guard still cannot detect semantic leakage hidden inside free text, a future repository snapshot exposed by a tool, or an answer-bearing memory record. Those require the provenance and adversarial-firewall checks from Chapter 16. The manifest guard proves structure; it does not prove innocence.


9. Production evidence loop

The finished loop:


What Usually Goes Wrong

Symptom Likely cause How to diagnose it What to change
Patch is syntactically valid but concern persists Validation checks artifact shape, not motivating behavior Compare the issue contract with executed checks Add a behavior-focused concern test before optimizing again
Revision loop keeps producing slightly different patches Failure interpretation has no bounded stopping rule Inspect attempt count, repeated evidence, and validation deltas Enforce attempt/resource budget and return insufficient evidence
Tests pass but scope changed Scope is not a hard gate Compare changed files, change-set fingerprint, and engineering delta Reject before broader promotion comparison
Bootstrap/MIPRO demos behave strangely Final repair rows do not match internal predictor Signatures Inspect predictor demo fields and source lineage Use stage-compatible labels or bootstrapped traces
GEPA improves unscored stages Optimizer can mutate components absent from the objective Compare mutation surface with metric-observed outputs Freeze those components or add valid metrics before optimization
Optimizer score improves but candidate is rejected Independent governance evidence found a regression or insufficient evidence Read per-dimension comparison and case failures Fix the program/evidence; do not tune promotion policy on the same holdout
Program uses a historical or future answer Memory, retrieval, feedback, or tools crossed the decision-time boundary Trace source revisions, memory fields, feedback lineage, and group fingerprints Reject the run and rebuild the experiment under the firewall
Candidate passes offline but cannot deploy Deployment bundle does not reconstruct evaluated dependencies Compare candidate-state and deployment fingerprints Fix deployment parity before activation
Production observations immediately become training labels Evidence-maturation boundary was skipped Trace dataset rows back to production runs and timestamps Reconstruct decision-time views and derive labels through a versioned policy
Active behavior cannot be explained Run is not tied to immutable deployment/promotion lineage Trace request โ†’ deployment โ†’ candidate โ†’ comparison โ†’ promotion Require fingerprints and durable records at every transition

Conclusion

We did not build a prompt optimizer. We built a governed engineering lifecycle around a language-model program.

The completed system has a task contract, bounded capabilities, evidence-selection policy, typed program state, validation contract, optimization dataset, metric, optimizer, frozen experiment manifest, candidate artifact, independent holdout evidence, comparison policy, promotion lineage, deployment bundle, production telemetry, feedback-maturation path, and rollback.

No single model call owns that system. The LM handles uncertainty where generative reasoning is useful. Ordinary software owns identity, boundaries, validation, persistence, comparison, and authority.

The final thesis is simple:

A language-model application becomes engineerable when behavior can be specified, evidence can be traced, changes can be proposed without self-approval, improvements can survive independent comparison, and production outcomes can become the audited evidence for the next experiment.