Verification
Every gate used to reason about the tree without ever starting it. Now the tree has to compile, the suite has to run, and the application has to boot and answer before anything is called finished.
Cheap and certain first, judgement last#
Every gate is deterministic until the final one. The table below is the same order with the failure conditions spelled out.
- 01EmptySomething was committed
- 02ScopeOnly declared paths touched
- 03ParseSource parses, wiring present
- 04BuildThe tree compiles
- 05TestsYour own suite passes
- 06TypesNo new diagnostics
- 07AcceptThe judgement call
The gate order#
The deterministic gates run first, in order. The judgement call comes last, and only sees diffs that already passed everything cheap and certain.
| # | Gate | Fails when |
|---|---|---|
| 1 | Empty build | Nothing was actually committed |
| 2 | Scope | A file outside the task’s declared scope was touched |
| 3 | Static probes | The source does not parse, or wiring is missing |
| 3b | Build | The tree does not compile |
| 4 | Tests | The repository’s own suite fails |
| 4b | Typecheck and lint | A new diagnostic appeared — pre-existing ones are ignored |
| 5 | Acceptance | The diff and its evidence do not satisfy the task |
The smoke probe#
After the branches are merged, the smoke probe runs against the integrated tree — never per task, because a service is only whole once everything is assembled.
For each service that declares a start command it installs, builds, starts the process, polls the health route, requests each declared smoke route, and tears everything down.
Constraints the probe was built with#
Each of these was learned the hard way.
- Never hangs
- A per-service readiness budget and a whole-module watchdog force-kill every tracked process group. A stuck verification phase is worse than a wrong one.
- Never leaks processes
- New sessions plus process-group kills, because a preview server spawns children that outlive the shell that started them. A test asserts the group is actually dead.
- Never touches your dashboard port
- The port your local dashboard runs on is reserved and the allocator re-rolls. It binds loopback only, never all interfaces.
- Never blocks shipping by itself
- It reports, the repair loop reacts, and the gate decides. Same trust class as the integration test.
- No new dependencies
- The standard library only. A probe is not worth a package.
- Flake discipline
- A failure is re-run once from a fresh process, and only a reproducing failure counts.
A failed probe feeds the repair loop#
A smoke failure goes into the same self-heal loop the integration tests use: up to three fixer rounds, with scope widened to every path the plan touched, re-probing after each.
Its objective names the causes that actually produce this failure — a route never mounted, a handler raising, a missing environment default, a wrong host or port binding, a build output that was never produced.
Common questions
What if my repository has no test suite?
The gate records that the suite did not run, and that is not treated as a pass. Shipping requires a suite that ran and passed.
How does Tharas know how to start my services?
From a services declaration in the repository that says what exists and how to run each one. Where it is absent, the build command is resolved from the conventions of the stack.