How an engagement actually runs
Written for the engineers who will operate this, not for the people who sign the contract. If you are evaluating us, this is the page to send to your platform team.
Getting started
An engagement begins read-only. We take source and, where available, captured input and output from the running system. Nothing is written back to your estate at any point.
# 1 — build a typed graph of the estate lightyr graph build --source ./estate --out knowledge/graph.json # 2 — measure what your existing corpus actually reaches lightyr coverage report --program CBTRN02C --corpus ./captured # 3 — run one bounded proof cell end to end lightyr factory run --work-order work-orders/intcalc.json
Step 2 is usually the one that changes the conversation. It answers a question nobody has asked before: how much of this program's decision surface has any test you own ever exercised.
Work orders
A work order is a contract, not a prompt. It declares the paths an agent may touch, the slice of the graph it may read, the gates that must pass, and the timeouts. Scope is a precondition — an agent cannot widen it at run time.
{
"id": "intcalc-repair",
"allowed_paths": ["src/interest/**"],
"graph_scope": ["CBACT04C", "TCATBAL"],
"gates": [
{ "id": "unit", "expose_output_to_builder": true },
{ "id": "holdout", "expose_output_to_builder": false }
]
}
expose_output_to_builder defaults to false and must be a real JSON boolean — a quoted "false" is rejected rather than coerced, because in Python it would evaluate as true and silently open the holdout boundary.
Verdicts and exit codes
Three verdicts, and the third is the one most tools do not have.
| Verdict | Exit | Meaning |
|---|---|---|
| faithful | 0 | Every compared field matched under the equivalence policy. |
| failed | 1 | A real divergence, classified by cause and located by field. |
| indeterminate | 2 | Nothing was verified. An operator error, never routed back to a builder as a defect. |
The separation of 1 and 2 matters operationally. A failed run means the candidate is wrong. An indeterminate run means the harness could not tell, which is a configuration problem and must not be handed to an agent as "your code is broken."
Accepted differences
Some differences are genuinely meaningless — a run timestamp, a padding convention. Each permitted one is a controlled entry with a written reason, a named owner, and a review date. The validator fails closed on a missing owner, an expired review, an undocumented rule, or a rule whose text no longer matches the code.
lightyr validate-normalizations --ledger spec/normalizations.json # NORMALIZATION_REVIEW_EXPIRED:fixed-width-padding:2026-02-22 # NORMALIZATION_GOVERNANCE_MISSING:decimal-canonical:owner # NORMALIZATION_RUNTIME_MISMATCH:copybook-filler:behavior
Prefer a shape-preserving normalization over an outright ignore. Ignoring a timestamp lets a candidate that never writes one pass; collapsing its digits still asserts format, length and punctuation.
Evidence classes
Every artifact carries a class, and the class governs what may be claimed from it.
| Class | Source | Can close an equivalence gate |
|---|---|---|
| simulated | Synthetic replay of the machinery | no |
| local_observed | Real execution, local environment | no |
| recorded | Replay of a prior capture | no |
| zos_observed | Captured from the authorised baseline | yes |
Replaying a live capture yields recorded, never live. Weak evidence cannot be promoted by round-tripping it through a mechanism, and that demotion is enforced in code rather than convention.
Coverage
We measure arc coverage, not statement coverage. A corpus can execute every line of a validation paragraph and never once take the reject branch — and reject branches are where modernization defects survive to go-live.
Arcs are classified into three populations with three different owners, because blending them produces a number that sends teams to chase the wrong work:
| Population | Owner | Acceptance |
|---|---|---|
| Business | the harness | output matches legacy under the policy |
| Resilience | NFR suite | fails safe, no partial commit, alert raised |
| Infrastructure | out of scope | documented, so it is not re-raised |
Fidelity coverage is reported over business arcs only. Where the corpus misses one, we generate the input that reaches it — then run it through the legacy system first, because a synthetic case whose expected output a human decided is not evidence.
CLI reference
lightyr graph build # typed estate graph from source lightyr graph capabilities # technology readiness and gate status lightyr coverage report # arc coverage for a program lightyr coverage close-gaps # synthesize inputs for unreached arcs lightyr compare # differential run, emits a receipt lightyr validate-normalizations lightyr factory run # one bounded work cell lightyr portfolio-plan # schedule non-conflicting cells lightyr audit verify # replay the hash-chained ledger
CI integration
The Verdict Engine is designed to be a gate, so exit codes route directly. Treat 2 as a pipeline error rather than a test failure — it means the run proved nothing.
- name: Differential verification run: | lightyr compare --expected ref/ --actual out/ --report r.json # 0 faithful · 1 divergent · 2 indeterminate - name: Reject runs that mutate tracked evidence run: git diff --exit-code
That second step is worth copying whatever tooling you use. It asserts that a verification run is side-effect free, so a suite can never quietly rewrite the evidence it is checking against.
The evidence record
Every capability ships with a published record: what it delivered, what evidence supports it, and — the part that matters — what it explicitly does not claim. Generated from the repository, so the record cannot drift from the code.
lightyr milestones build # regenerate the record from source lightyr milestones verify # catalog, hashes and boundaries lightyr receipt-claims # reject literal promotion anywhere in the tree lightyr scripts # every entry point owned, roled and twinned
Each boundary statement is deliberately unflattering. One records that ASE catalog, rows, replication and transactions are fixtures rather than live observations. If you are evaluating us, read the boundaries before the deliverables.
No documentation sections match that filter.
Built for organisations that cannot take a risk on us
We are asking a regulated business to let software work unattended on its most sensitive code. Everything here assumes you will not take that on trust after a demo.
Read-only by default
Collection is read-only. Live capture carries operator attestation and verified TLS with certificate and hostname validation, and writes nothing back to your estate.
Evidence cannot be laundered
Simulated evidence cannot satisfy an equivalence claim. Replaying a live capture yields recorded, never live — weak evidence cannot be promoted by round-tripping it.
Nothing runs loose
Checks run in a digest-pinned container with a read-only host bind. Work orders are signed, expiring, and replay-safe. Agent identities are short-lived and action-scoped.
Every step is on the record
Every event binds actor, action, subject, policy decision and evidence receipt to an exact graph identity. A reviewer can replay the evidence behind any release decision.
Your data stays yours
Comparison output contains real record values by design — that is what makes it evidence. Classification, access control and retention on run directories are agreed before the first capture, not after.
No borrowed code in the core
The verification core has zero external runtime dependencies. For a tool whose product is evidence, the dependency tree is part of what your auditor has to trust.
Four questions, answered without the original engineers
| What changed, exactly? | brokered patch + workspace hash |
| What proved it? | gate result + output digest |
| What was the agent told? | redacted diagnosis envelope |
| Can we replay it? | content-addressed run receipt |
Replayable next quarter, by someone who was not in the room when it ran.
These docs describe the shape. Your estate decides the detail.
Copybook dialects, screen conventions and clock injection all differ by site. Send us a program and we will tell you what the harness would need.
Ask an engineer