ADR-0002: Generate certification documents from CI output and withdraw the current false certifications - #1
Merged
Conversation
…rde defaults ResolutionConfig used #[derive(Default)], which ignores the #[serde(default = "...")] attributes on its fields and yields false/0. ResolutionConfig::default() therefore turned off parallel-group generation, critical-path computation, and cycle detection, and set max_depth to 0 -- so resolve() returned an empty parallel_groups for any successfully resolved graph. Replaces the derive with a hand-written impl matching the serde defaults, as the sibling DependencyResolverConfig and agentics-contracts::DependencyResolutionConfig already do. Fixes agents::dependency_resolver::tests::test_resolve_success.
…self-transitions Two defects in StateMachineAgent::transition, both in how a failed validation was classified: 1. Every rejected transition that had an existing source and target state was reported as Blocked, so an illegal edge such as completed -> running (completed is terminal) came back as Blocked. TransitionStatus documents Blocked as "transition was blocked by a rule" -- it is for an edge the machine permits but a guard rejects. An edge the machine does not declare is Invalid. Classification now asks the state machine directly. 2. A self-transition such as running -> running was rejected, because the machine declares no self-loop edge, and so was reported as a failure. Requesting the state an entity is already in changes nothing and cannot fail; validate_transition now treats current == target as valid, which lets transition() reach its existing NoChange branch. Fixes agents::state_machine_agent::tests::test_transition_invalid and agents::state_machine_agent::tests::test_no_change_transition.
…laims Neither document was transcribed from a real test run: they were authored on the same day against the same tree and disagree about the total test count by 39 (204+ vs 243/243), while the measured lib target has 198 tests of which 3 failed. Adds the withdrawal banner ADR-0002 specifies and corrects each false line named in its implementation plan. Figures with no defined computation -- the 100/100 score, the PLATINUM level, the A+ (98/100) grade, the 100% confidence -- are withdrawn rather than given a new hand-picked value. Implements step 1 of orchestrator/docs/adr/ADR-0002-certification-document-integrity.md.
Adds the generator ADR-0002 requires, so a document asserting a test count or pass rate is a function of a test run rather than prose. scripts/generate-test-certification.py reads a libtest-JSON event stream, aggregates per crate, extracts each failure's assertion site, and emits docs/TEST_CERTIFICATION.md with a provenance header (commit, CI run ID and URL, exact command, toolchain, UTC timestamp). It emits a single verdict line -- PASS only when nothing failed, otherwise FAIL (N failing) -- and never writes "production ready", "certified", or a grade. Its --check mode compares an existing document's measured sections against a fresh run, which is what CI uses in place of a plain `git diff --exit-code`: provenance rows change on every run by construction, so diffing the whole file would always fail. Assertion sites are normalised to repo-relative paths for the same reason -- an absolute registry path would embed the machine's home directory. The generator is a trusted component, so it ships with tests over two fixtures recorded from real nextest runs of llm-orchestrator-core: one all-pass (198/198) and one taken from the tree before the two preceding commits (195/198), asserting the generator reports FAIL (3 failing) and names every failing test with its assertion site. scripts/check-certification-integrity.py is the reintroduction guard: it fails on any file under docs/ using readiness vocabulary without a provenance header. ADRs and runbooks are exempt because they assert intent, not measurement. Implements steps 2, 3 and 5 of orchestrator/docs/adr/ADR-0002-certification-document-integrity.md.
Generated by scripts/generate-test-certification.py from a real nextest run over the workspace's lib and bin targets: 432 passed, 3 failed, 2 skipped of 437. llm-orchestrator-core is 198/198 after the two preceding fixes. The three remaining failures are pre-existing and outside ADR-0002's scope, which measured only llm-orchestrator-core. They surface here for the first time because no prior run measured anything else: two cohere_embeddings mockito tests that abort the test process, and a timing-sensitive secrets cache expiry assertion. They reproduce under plain `cargo test`, so they are not a nextest artefact. The run is scoped to --lib --bins because agentics-contracts' integration_tests target has not compiled since 63ae636 (2026-01-20); the provenance header records that exact command so the document does not overstate what was measured. Its provenance names a local run rather than a CI run, because the CI wiring that would produce it (step 4 of the ADR) could not be pushed -- see the pull request. Implements orchestrator/docs/adr/ADR-0002-certification-document-integrity.md.
… elsewhere Both withdrawn documents are reduced to a short pointer at docs/TEST_CERTIFICATION.md. They are stubbed rather than deleted so the three inbound links from the disaster-recovery docs keep working; those links now point at the generated document. The withdrawn content remains in git history and is not resurrected with new hand-written numbers. The reintroduction guard then found the same fabricated figures in three documents ADR-0002 never examined: IMMEDIATE_ACTIONS_COMPLETE.md claims 234/234, PHASE_3_IMPLEMENTATION_COMPLETE.md claims 243/243, and PHASE_4_COMPLETE.md carries a certification level and a project score. Those are a third and fourth mutually inconsistent total for the same tree. Their readiness and test-result claims are withdrawn in place; the surrounding narrative is left alone, since these are records of work done rather than certifications. Also records in ADR-0001 that promoting DependencyResolverAgent and StateMachineAgent into the live serving path is gated on those agents' tests passing, so that migration cannot swap absent orchestration for incorrect orchestration. Implements steps 7 and 8 of orchestrator/docs/adr/ADR-0002-certification-document-integrity.md.
The generator and guard landed in this branch but nothing ran them. This wires them in, which is what makes the certification self-maintaining rather than another document someone has to remember to update. The test job now runs the suite under cargo-nextest with libtest-JSON output, generates docs/TEST_CERTIFICATION.md from it, uploads it as a build artifact, and verifies the committed document still matches the run. Generation and upload use `if: always()` so the certification is produced on failing runs too -- a certification that only appears when tests pass reintroduces exactly the blind spot ADR-0002 closes. Two things a reviewer should expect to see red, both for real reasons: - The suite has three failing tests (two cohere_embeddings mockito aborts, one timing-sensitive secrets cache expiry), so the verification step exits non-zero. That is the mechanism working: ADR-0002 decision 3 makes a green suite a precondition for any readiness claim, and the job must reflect that rather than hide it. - `cargo test --all --no-run` still fails, because agentics-contracts' integration_tests target has not compiled since 63ae636 (2026-01-20). It is kept as a non-blocking step so the breakage stays on the dashboard instead of disappearing behind the narrower --lib --bins scope the certification run uses. The verification step compares only the measured sections rather than running `git diff --exit-code` as the ADR's step 4 literally specifies. The provenance header carries the commit SHA, run ID, run URL and generation timestamp, all of which differ on every run by construction, so a whole-file diff could never pass and the signal would be pure noise. The `--check` mode preserves the property the ADR is after -- a hand-edited number fails the build -- and three unit tests cover it, including a stale green document left in place after a regression. A new certification-integrity job runs the generator's own tests and the reintroduction guard. Implements step 4 of orchestrator/docs/adr/ADR-0002-certification-document-integrity.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements
docs/adr/ADR-0002-certification-document-integrity.md.What changed
Fixed the three failing tests, in the logic, not the assertions.
ResolutionConfigused#[derive(Default)], which ignores the#[serde(default = "...")]attributes on its own fields and yieldsfalse/0. SoResolutionConfig::default()disabled parallel-group generation, critical-path computation and cycle detection, and setmax_depthto 0 — andresolve()returned emptyparallel_groupsfor any graph it had just resolved successfully. Replaced with a hand-writtenimpl Defaultmatching the serde defaults, as the siblingDependencyResolverConfigandagentics_contracts::DependencyResolutionConfigalready do.StateMachineAgent::transitionreported every rejected transition with an existing source and target asBlocked.TransitionStatusdocumentsBlockedas "transition was blocked by a rule" — it is for an edge the machine permits but a guard rejects. An edge the machine does not declare isInvalid. Classification now asks the state machine directly.running → running) was rejected because the machine declares no self-loop edge. Requesting the state an entity is already in changes nothing and cannot fail;validate_transitionnow treatscurrent == targetas valid, which letstransition()reach its existingNoChangebranch.No assertion was weakened. Each fix is its own commit.
Built the generator.
scripts/generate-test-certification.pyreads a libtest-JSON event stream, aggregates per crate, extracts each failure's assertion site, and emitsdocs/TEST_CERTIFICATION.mdwith a provenance header (commit, CI run ID and URL, exact command, toolchain, UTC timestamp). One verdict line:PASSonly when nothing failed, elseFAIL (N failing). It never writes "production ready", "certified", or a grade. 19 unit tests over two fixtures recorded from real nextest runs — one all-pass (198/198), one taken from the tree before the fixes (195/198) — assert it reportsFAIL (3 failing)and names every failing test with its site.Built the reintroduction guard.
scripts/check-certification-integrity.pyfails on any file underdocs/using readiness vocabulary without a provenance header. ADRs and runbooks are exempt (they assert intent, not measurement).Withdrew and retired the false certifications, then corrected the same claims in three more documents (below).
Real test output
Command:
cargo test -p llm-orchestrator-core --libWorkspace-wide,
cargo nextest run --all --lib --bins --no-fail-fast:llm-orchestrator-coreis 198/198. The generateddocs/TEST_CERTIFICATION.mdin this PR is that run.Generator tests:
Ran 19 tests ... OK. Guard:No unprovenanced readiness claims under docs.Three things this uncovered that the ADR did not anticipate
1.
cargo test --alldoes not compile, and has not since January.crates/agentics-contracts/tests/integration_tests.rsfails with 64 errors against an API that moved out from under it (DecisionOutputs,WorkflowExecutionConfig,RetryConfiguration,DependencyResolutionOutputsno longer exist;ConstraintsAppliedrenamed its fields). Last touched by63ae636(2026-01-20). This is why the CI Test job has been failing onmain— e.g. run 22251502561 showsTest (beta)failed andTest (stable)cancelled.ADR-0002 verification criterion 1 requires
cargo test --allto be green. It is not, and this PR does not make it so. Repairing that test file is a separate body of work requiring judgement about what it should assert, so I stopped rather than guess. The certification run is scoped to--lib --binsand the provenance header records that exact command, so the document does not overstate what was measured.2. Three more real failures outside
llm-orchestrator-core. ADR-0002 only ever ran-p llm-orchestrator-core --lib, so these had never been measured:llm-orchestrator-providers::cohere_embeddings::tests::test_multilingual_modelcrates/llm-orchestrator-providers/src/cohere_embeddings.rs:601llm-orchestrator-providers::cohere_embeddings::tests::test_search_query_input_typecrates/llm-orchestrator-providers/src/cohere_embeddings.rs:433llm-orchestrator-secrets::cache::tests::test_cache_expirationcrates/llm-orchestrator-secrets/src/cache.rs:331Both cohere tests abort the process (SIGABRT, "panic in a destructor during cleanup") under mockito; the cache test asserts
misses == 2with a 100 ms TTL and a 150 ms sleep, and is timing-sensitive. All three reproduce under plaincargo test, so they are not a nextest artefact. Out of ADR-0002's scope, left unfixed, and now visible in the certification — which is the point of the mechanism.3. The false figures were in five documents, not two. The guard found
234/234inIMMEDIATE_ACTIONS_COMPLETE.md,243/243inPHASE_3_IMPLEMENTATION_COMPLETE.md, and a certification level plus a project score inPHASE_4_COMPLETE.md. That is a third and fourth mutually inconsistent total for the same tree (204+, 243, 234), strengthening the ADR's argument. I withdrew their readiness and test-result claims in place and left the surrounding narrative alone — these are records of work done, not certifications. Ten further documents carrying ungroundedN/100scores (pentest reports, phase summaries) are grandfathered in the guard as an explicit, commented debt list, so the guard lands as a ratchet rather than a rewrite of a dozen documents the ADR never examined.The push was rejected: this token is a fine-grained PAT without
workflowpermission, so.github/workflows/ci.ymlcould not be modified:The generator and guard are therefore committed but not enforced. Someone with
workflowpermission needs to apply the diff below. Until they do, criteria 3 and 4 of the ADR's Verification section are satisfied only by the generator's unit tests, not by CI.Intended
.github/workflows/ci.ymldiff (tested locally end to end)Deviations from the ADR, and why
--checkinstead ofgit diff --exit-code. Step 4 specifiesgit diff --exit-code docs/TEST_CERTIFICATION.md. That can never pass: the provenance header contains the commit SHA, CI run ID, run URL and generation timestamp, all of which differ on every run by construction, so the diff would always be non-empty and the signal would be pure noise. The generator instead grows a--checkmode comparing only the measured sections (verdict, per-crate table, failure list). This preserves the property the ADR is after — a hand-edited number fails the build — and is covered by three unit tests, including one for a stale green document left in place after the suite regressed. Assertion sites are normalised to repo-relative paths for the same reason: an absolute path would embed the runner's home directory.Documents stubbed, not deleted. Step 7 says delete. Three disaster-recovery documents link to
PRODUCTION_READINESS_CERTIFICATION.md; deleting it breaks them. Both files are reduced to a short pointer atdocs/TEST_CERTIFICATION.mdand those inbound links now target the generated document. Content remains in git history and is not resurrected with new hand-written numbers.The committed certification names a local run, not a CI run. It has to: CI cannot be wired from here. Its provenance says so explicitly rather than pretending otherwise. Once the CI diff above is applied, the first run will regenerate it; if
test_cache_expiration(timing-sensitive) behaves differently on CI hardware, the--checkstep will correctly flag the mismatch and CI's own artefact should be committed in its place.ADR Verification criteria
cargo test -p llm-orchestrator-core --lib→ 198/0cargo test --allgreenTEST_CERTIFICATION.mdtotals equal a fresh run--checkround-tripFAIL (N failing)naming itgrep -rniE "certified production-ready|243/243|204/204|100% \(all passing\)|PLATINUM" docs/clean outside the ADRThe
target/directory was removed after building; the working tree is clean.