v1.0.0 — Shadow Score Spec Level 4 (Adversarial Independence) - #27
Merged
Conversation
v0.1.0 assigned the same model (claude-sonnet-4.6) to both `qa_sealed` and `lead_eng` — the same model family on both sides of a test designed to measure independence. Hiding the tests answers "can the builder see them"; it does not answer "does the builder think like the test author". Correlated blind spots mean the sealed test is never written, the score reads 0%, and the bug ships green. The bias always points toward overclaiming quality. This release makes cross-family separation a machine-checked invariant and builds out the pipeline that separation makes possible. Added - invariants.cross_family_required, enforced at Phase 0 (abort) and in CI - config.families + config.model_capabilities; unsupported reasoning_effort / context_tier params are omitted, never defaulted - seal plurality: N sealed suites from N families - Phase 2.5a spec-ambiguity gate (AMBIGUITY.md) — contradiction vs divergence - Phase 2.5b Arch Critic (rubber-duck), cross-family from the architect - Phase 4.5 Red Team (security-review); findings classed spec-gap vs impl-bug - tournament + pareto modes with judge-independence enforcement - autonomy modes (dark/supervised/manual) + evidence-printing threshold gates - cross-run learning loops A/B/C via session_store_sql; cost tracking - SHADOW-REPORT.json with Spec §5.2 fields + independence provenance - hardening_velocity (Level 3 requirement, previously uncomputable) - .github/scripts/validate_conformance.py — 10 checks wired into CI - protocols/model-independence.md; 5 new templates; ADR-0006..0013 Changed - sealed tests never enter the builder's workspace; validation runs in a disposable verify worktree (deliberate divergence from Spec v1.0.0 §4.3) - vault moved outside the repo to ~/.factory-vault with a canary - hardening is multi-turn via write_agent; ladder escalates effort→model→family - progressive disclosure: final rung may reveal assertions, never test source - safety.summarize_artifacts defaults to false; caps are emergency backstops - express detection uses a classifier, not word count - premium is per-role — a single premium_model collapsed the pipeline into one family and silently voided the score - purpose-built agent types replace blanket general-purpose dispatch - config.models.* → config.roles.* with per-role effort and context tier Fixed - runtime-breaking mismatch: qa-validator wrote GAP-REPORT.md, SKILL.md read SHADOW-REPORT.md — Phase 5/6/7 all broke. Residual gap-score naming removed. - unearned Level 3 badge: §6 requires tracked hardening velocity, which the schema could not compute - missing Spec §5.2 required fields (shadow_score_spec_version, level) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9cb0b232-bb14-47a5-a150-00e71bdddcae
The documented SHADOW-REPORT.json contract drifted from the spec in two ways, both of which validated cleanly and neither of which was caught: - seal_families should be seal_author_families (symmetric with implementer_family / implementer_model) - conformance_level sat at the document root instead of under report The second is the dangerous one. The spec's Level 4 conditional keys off report.conformance_level, so a value written at the root is invisible to it: the provenance requirement never fires and the report claims Level 4 having been checked for nothing. A permissive schema ignores the misspelling and reports success. Adds check 11 to the conformance validator: parses the JSON blocks in the documented report contract and rejects renamed fields, fields at the wrong depth, and missing Level 4 provenance. Verified it fails on the exact drift being fixed here, then passes once corrected. Nests the README and model-independence provenance snippets under report so they cannot be copied to the wrong depth. Internal identifiers (SKILL.md pseudocode, the SQL column, validator locals) keep the shorter seal_families name — they are not wire format. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9cb0b232-bb14-47a5-a150-00e71bdddcae
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.
Summary
v0.1.0 assigned the same model —
claude-sonnet-4.6— to bothqa_sealedandlead_eng. That is the same model family on both sides of a test designed to measure independence.Hiding the tests answers "can the builder see the tests?" It does not answer "does the builder think like the test author?" Two instances of one family share training data, reasoning priors, and — critically — failure modes. If the family doesn't think to test Unicode homographs, it also doesn't think to normalise them. The sealed test is never written, the code is never hardened, the score reads 0%, and the bug ships with a green light.
The bias is not random. It always points toward 0% — the system overclaims quality exactly when it is least entitled to.
This PR makes cross-family separation a machine-checked invariant, then builds out the capabilities that separation makes possible. Target: Shadow Score Spec v2.0 — Level 4 (Adversarial Independence).
The three bugs this also fixes
agents/qa-validator.mdwroteGAP-REPORT.md;SKILL.mdreadSHADOW-REPORT.mdcperrored, Phase 7 had no input. Fallout from a half-finishedgap-score-spec→shadow-score-specrename.shadow_score_spec_versionandlevelWhat's new
invariants.cross_family_required, enforced at Phase 0 (abort) and in CI.config.families+config.model_capabilities— unsupportedreasoning_effort/context_tierare omitted, never defaulted.AMBIGUITY.md. Where two families read the same PRD and assert opposite behaviour, the spec is ambiguous. Distinguishes contradiction (the signal) from divergence (the coverage dividend).rubber-duckagent, cross-family from the architect, reviewsARCH.mdbefore any code exists.security-reviewagent attacks what the spec forgot. Findings classed spec gap vs implementation bug — the class decides whether the PM or the engineer learns from it.dark/supervised/manual. Gates print the measured value, the threshold, and the evidence. A breach that can't explain itself isn't actionable.session_store_sql.SHADOW-REPORT.jsonwith §5.2 fields + provenance (independence,seal_families,implementer_family).hardening_velocitynow computable.Notable design decisions
Bias direction matters more than "everything must differ." A pairing that biases the score upward is conservative and tolerable; one that biases it downward hides defects.
PM == seal authoris allowed with disclosure;PM == implementeris forbidden. Blanket difference rules miss this.Deliberate divergence from Spec v1.0.0 §4.3. The spec says to copy sealed tests into the implementation workspace at validation time. That's safe only when validation is terminal — Dark Factory hardens in a loop, so after cycle 1 the tests sit in a directory the builder can
grep, and the Lead Engineer has unscopedbash/glob/grep. v1.0 runs validation in a disposable worktree built from the engineer's commit, and moved the vault outside the repo. Isolation has to be filesystem topology, not prompt wording.invariants.workspace_isolation: legacyrestores the old behaviour.Summarisation is now harmful.
safety.summarize_artifactsdefaults tofalseand the line caps became emergency backstops (2000/5000). With long-context tiers, routine summarisation lossy-compresses the contract that both the sealed tests and the implementation derive from — requirements drop out of the middle and the Shadow Score ends up measuring the summariser.premiumis per-role now. A singlepremium_modelapplied to every role collapses the pipeline into one family and silently voids the score. Premium raises capability within each role's family.Verification
New CI steps: Level 4 conformance, every agent catalogued, every
SKILL.mdreference resolves.Follow-up
A companion PR to
shadow-score-specshould promote Level 4 into the spec itself (model independence, seal plurality, workspace isolation, calibration, and the new report fields). This PR ships the reference implementation; the spec should follow.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com