# Objective Guard functional test matrix

Cases derive directly from capabilities. `[Inference]` indicates planned cases; `[Fact]` identifies current executable dogfooding.

| ID | Capability | Scenario | Preconditions | High-level steps | Expected result | Priority | Evidence | Trust |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| FT-001 | CAP-01 | Edit without findings | Hook installed; valid file | Edit file; execute level 0 | Emits no noise and logs event | P0 | `docs/functionality/02-capabilities-and-flows.md` CAP-01 | [Inference] |
| FT-002 | CAP-01 | Detector timeout | Detector forced to exceed timeout | Edit; await result | Loop continues; log logs `error`; no false `pass` appears | P0 | `docs/product/04-technical-architecture.md` Security and failures | [Inference] |
| FT-003 | CAP-02 | JS test newly disabled | Test active in baseline | Add `.skip`; execute hook | `weak-test` finding with file and line | P0 | `docs/product/06-roadmap-and-criteria.md` Functional criteria | [Inference] |
| FT-004 | CAP-02 | Invalid syntax | Supported parser | Introduce syntax error | Reproducible `syntax` finding | P0 | `docs/product/06-roadmap-and-criteria.md` Functional criteria | [Inference] |
| FT-005 | CAP-02 | Stub in production | Supported non-test file | Add placeholder; execute | `stub-prod` warning | P1 | `docs/product/06-roadmap-and-criteria.md` MVP | [Inference] |
| FT-006 | CAP-02 | New dependency | Supported manifest | Add dependency; execute | `new-dep` warning | P1 | `docs/product/06-roadmap-and-criteria.md` MVP | [Inference] |
| FT-007 | CAP-03 | Repeated finding | Active finding and persisted state | Execute twice without changes | Second execution does not repeat finding | P0 | `docs/product/02-product-contract.md` RF-02 | [Inference] |
| FT-008 | CAP-03 | State delta deleted | Active finding; delete state | Execute again | Can re-report, but does not silence | P1 | `docs/product/04-technical-architecture.md` Persistence | [Inference] |
| FT-009 | CAP-04 | Well-specified bugfix | Request and repo available | Create session with objective, scope, and criterion | Valid and versioned contract | P1 | `docs/product/02-product-contract.md` RF-05 | [Inference] |
| FT-010 | CAP-04 | Ambiguous intent | Request "improve this" without metric | Start session | `discovery` state; does not invent quantitative criterion | P0 | `docs/product/01-vision-and-thesis.md` Epistemic limits | [Inference] |
| FT-011 | CAP-05 | Focused internal refactor | Graph and checks available | Modify internal symbol; quick check | Executes affected checks and declares omitted | P1 | `docs/product/04-technical-architecture.md` Level 1 | [Inference] |
| FT-012 | CAP-05 | Incomplete graph | Adapter only knows paths | Execute check | Declares uncertainty and expands verification by policy | P0 | `docs/product/02-product-contract.md` RF-08 | [Inference] |
| FT-013 | CAP-06 | Bugfix without regression | Active bugfix session | Request closure without test | `unknown` criterion; final mode blocks by policy | P0 | `docs/product/02-product-contract.md` RF-07 and RF-10 | [Inference] |
| FT-014 | CAP-06 | All criteria tested | Reproducible evidence available | Execute final mode | Artifact enumerates criteria, checks, and scope | P0 | `docs/functionality/02-capabilities-and-flows.md` CAP-06 | [Inference] |
| FT-015 | CAP-07 | Approved exception | Exceptable finding; authorized actor | Request and approve with expiration | Fact preserved; decision permits approved scope | P1 | `docs/product/02-product-contract.md` RF-11 | [Inference] |
| FT-016 | CAP-07 | Expired exception | Expired approval | Execute check | Finding returns to active state | P1 | `docs/functionality/03-rules-states-and-validations.md` Finding state | [Inference] |
| FT-017 | CAP-08 | Uncalibrated statistical detector | Events available; no external validation | Calculate extreme anomaly | Logged offline and does not alert agent | P0 | `docs/product/03-signal-and-decision-model.md` Policy | [Inference] |
| FT-018 | CAP-08 | Out-of-sample evaluation | Calibration frozen | Evaluate unseen repos | Reports AUPRC, calibration, and baselines | P1 | `docs/product/05-scientific-validation.md` Metrics | [Inference] |
| FT-019 | CAP-09 | Moderate active signal | Intervention-tested detector | Exceed moderate threshold | Warns or expands checks; does not claim incorrectness | P1 | `docs/product/03-signal-and-decision-model.md` Class C | [Inference] |
| FT-020 | CAP-09 | Distribution drift | Active detector; degraded calibration | Monitoring detects drift | Signal moves to `suspended` and stops governing | P1 | `docs/functionality/03-rules-states-and-validations.md` Statistical state | [Inference] |
| FT-021 | CAP-10 | Incomplete documentation | Remove required file in test copy | Execute guard | Exit 1 and list missing file | P0 | `scripts/validate-docs.mjs` requiredFiles | [Fact] |
| FT-022 | CAP-10 | Broken relative link | Introduce non-existent link in test copy | Execute guard | Exit 1 and show source/destination | P0 | `scripts/validate-docs.mjs` markdownFiles/linkPattern | [Fact] |
| FT-023 | CAP-10 | Documentary contract satisfied | All files and fields present | Execute guard | Exit 0 and `PASS` output | P0 | `scripts/validate-docs.mjs` final output | [Fact] |
| FT-024 | CAP-11 | Valid hierarchical OKR contract | `oguard.contract.json` schema v1 | Load contract | Returns validated hierarchy and SHA-256 hash | P0 | `test/contract.test.mjs` | [Fact] |
| FT-025 | CAP-11 | Inconsistent contract | Duplicate KR, unknown reference, or incorrect parent | Load contract | Visible error; no `pass` is emitted | P0 | `test/contract.test.mjs` | [Fact] |
| FT-026 | CAP-11 | Aligned round | Material surface; candidate evidence for target KR | Execute closure | Reports surface and contribution; zero warnings | P0 | `test/alignment.test.mjs` evidence-present case | [Fact] |
| FT-027 | CAP-11 | Goal substitution replay E-001 | Material surface in non-goals/out of scope; zero target evidence | Evaluate alignment | One `goal-substitution` warning, non-blocking | P0 | `synthetic/scenarios/e001-goal-substitution.json`; `test/alignment.test.mjs` | [Fact] |
| FT-028 | CAP-11 | Legitimate incremental work | In-scope change without evidence, or tiny change | Evaluate alignment | Zero warnings | P1 | `test/alignment.test.mjs` in-scope/tiny controls | [Fact] |
| FT-029 | CAP-11 | Early query without contract | Git repository without `oguard.contract.json` | Run `oguard align --json` | `unknown`, no blocking | P1 | `test/align-cli.test.mjs` | [Fact] |
| FT-030 | CAP-11 | Early query with deviation | Material non-goal; zero KR evidence | Run `oguard align --json` | `warn`, `goal-substitution`, exit 0 | P0 | `test/align-cli.test.mjs` | [Fact] |
| FT-031 | CAP-11 | Safe contract initialization | Git repo without contract | Run `oguard init --json` twice | First creates `observe` contract; second rejects overwrite | P0 | `test/init-cli.test.mjs` | [Fact] |
| FT-032 | CAP-11 | Declared portable closure | External Git fixture with contract and explicit check | Run `oguard round-end --json` | Executes only declared checks, applies universal diff/guard, and exports evidence | P0 | `test/portable-alpha.test.mjs` | [Fact] |
| FT-033 | CAP-11 | Discovered, unauthorized test | External fixture with `scripts.test` and no `checks` | Run `oguard round-end --json` | Declares `package-test` as `skipped`; does not execute it or emit `pass` for it | P0 | `test/portable-alpha.test.mjs` | [Fact] |
| FT-034 | CAP-11 | Weakening blocks portable closure | Test active in baseline; change to `test.skip` | Run `oguard check` and `oguard round-end` | Active `weak-test` finding; closure `block` even though the declared check passes | P0 | `test/portable-alpha.test.mjs` | [Fact] |
| FT-035 | CAP-04 | Typed session start | Placeholder contract created by `init` | Run `oguard start` with objective, round, KR, scope, and type | Versions active contract; a second implicit session is rejected | P0 | `test/init-cli.test.mjs` | [Fact] |
| FT-036 | CAP-05/CAP-06 | Planner and incomplete coverage | Manifest with undeclared scripts and commands | Execute closure | Discovers relevant suite as `skipped`; emits `unknown` and `incomplete`, without executing unauthorized code | P0 | `test/check-planner.test.mjs`; `test/portable-alpha.test.mjs` | [Fact] |
| FT-037 | CAP-03 | Corrupted state preserved | Invalid `.oguard/state.json` | Execute state read | Returns explicit error and preserves the artifact for review; does not delete it | P0 | `test/state.test.mjs` | [Fact] |
| FT-038 | CAP-11 | Contract accommodation replay E-003 | Frozen baseline; change external to initial scope | Widen scope without reason after touching an external path; execute closure | `warn`, `contract-accommodation` classification, and contract-change event | P0 | `synthetic/scenarios/e003-contract-accommodation.json`; `test/contract-drift.test.mjs`; `test/portable-alpha.test.mjs` | [Fact] |
| FT-039 | CAP-06 | Semantic evidence separated from candidate paths | Criterion linked to declared check | Execute closure and export evidence | The criterion carries `evidence_kind: reproducible-check`; the KR contribution remains a path-based candidate | P0 | `test/criteria.test.mjs`; `test/evidence-export.test.mjs` | [Fact] |
| FT-040 | CAP-05 | Transitive JS consumer | A JS module relatively imports another workspace | Modify the provider; calculate impact | Includes the consumer and its workspace as candidate; declares parser limits | P0 | `test/repository-discovery.test.mjs` | [Fact] |
| FT-041 | CAP-06 | Explicit obligations by task type | Declared criteria and checks | Evaluate feature, refactor, improvement, migration, and investigation | Only referenced criteria become `proven`; a missing obligation remains `unknown` and blocks | P0 | `synthetic/scenarios/e004-task-obligations.json`; `test/criteria.test.mjs`; `test/portable-alpha.test.mjs` | [Fact] |
| FT-042 | CAP-07 | Bounded local exception | Policy warning; future exception with actor and scope | Execute closure with and without exception | Preserves warning and event; only the decision is exempted; expired/invalid is rejected | P0 | `synthetic/scenarios/e005-local-exception.json`; `test/exceptions.test.mjs`; `test/portable-alpha.test.mjs` | [Fact] |
| FT-043 | CAP-05 | Local cache for declared check | Authorized check; known inputs and contract | Repeat closure; change input and contract | Second closure is a hit; both changes invalidate; output preserves `cache.hit` | P0 | `synthetic/scenarios/e006-safe-check-cache.json`; `test/check-cache.test.mjs`; `test/portable-alpha.test.mjs` | [Fact] |
| FT-044 | CAP-08 | Passive trajectory report | Versioned `round-end` events | Generate `evidence report` | Summarizes surface, criteria, coverage, and cache hits without changing decisions | P0 | `test/evidence-report.test.mjs` | [Fact] |
| FT-045 | CAP-08 | Manual outcome label | At least one prior closure | Run `oguard outcome` with outcome and justification | Append-only event linked to contract/round; report summarizes it without altering the closure | P0 | `test/portable-alpha.test.mjs` | [Fact] |
| FT-046 | CAP-05/CAP-06 | Explicit verification modes | Checks declared for `fast` and `final`; required criterion without evidence | Run both modes | `fast` executes only its check and remains `unknown`; `final` executes only its own and blocks; everything omitted remains `skipped` | P0 | `synthetic/scenarios/e009-fast-final-modes.json`; `test/portable-alpha.test.mjs`; `test/evidence-report.test.mjs` | [Fact] |
| FT-047 | CAP-05 | Declarative Node public boundary | API with internal change and public entrypoint; declared consumer workspace | Calculate impact and execute closure | Internal change does not add a consumer via dependency; entrypoint adds only the consumer as a `skipped` candidate with visible relevance | P0 | `synthetic/scenarios/e010-declared-public-boundary.json`; `test/repository-discovery.test.mjs` | [Fact] |
| FT-048 | CAP-08 | Passive vector and separated datasets | Round events with surface, criteria, and outcomes | Export `calibration` and `evaluation` | Reproducible vector/AUS/J; disjoint partitions; log and verdicts unchanged | P0 | `synthetic/scenarios/e011-passive-trajectory-features.json`; `test/trajectory-features.test.mjs` | [Fact] |
| FT-049 | CAP-08 | Synthetic task-trajectory corpus | 30 contracts, steps, distractors, and known outcomes | Run `npm run synthetic:trajectories` | Artifact preserves 15 in-contract cases, 15 scope-deviation cases, and 60 passively extracted steps; produces no classification or alert | P0 | `synthetic/scenarios/task-trajectories-v1.mjs`; `synthetic/results/task-trajectories-v1.json`; `test/task-trajectories.test.mjs` | [Fact] |
| FT-050 | CAP-04 | Explicit round transition | Started session, matching baseline, and clean tree | Run `oguard next-round` before editing | Archives previous contract/baseline by hash, activates successor, and records `round-transition`; rejects pending diff or divergent baseline | P0 | `synthetic/scenarios/e012-round-transition.json`; `test/round-transition.test.mjs` | [Fact] |
| FT-051 | CAP-04 | Single historical baseline adoption | Clean typed contract without `session-baseline.json` | Run `oguard adopt-baseline` | Preserves contract, creates baseline and `baseline-adopted` event; a second adoption is rejected | P0 | `test/round-transition.test.mjs` | [Fact] |

## Coverage and gaps

- [Inference] FT-001 to FT-020 must become tests when complete code exists; some partial CAP-02 behaviors already have unit tests.
- [Fact] FT-021 to FT-023 can be tested today on documentary guard.
- [Fact] FT-024 to FT-028 test the first vertical slice of hierarchical alignment.
- [Ambiguity] Missing specific cases per harness and language.
- [Ambiguity] Missing concurrency, SQLite corruption, and schema migration cases.
