# v2.0 prep baseline (worklist for v1.9.11)

Pre-flight enumeration of artefacts that need work before v2.0
tags. This is the concrete target for v1.9.11. Each item links to
a quality bar in `docs/roadmap.md` and is checkable by a reviewer
without trusting the maintainer's word.

## 1. EXPERIMENTAL labels — current baseline

The v2.0 quality bar requires zero user-facing EXPERIMENTAL hits.
Current count: 38 hits across 14 files (test markers excluded).
v1.9.11's job is to bring this to zero.

### Per-file count

| File | Hits | Surface |
|---|---|---|
| `docs/correlation.md` | 14 | Tech reference doc |
| `recon_tool/models.py` | 5 | Field docstrings (JSON schema source) |
| `recon_tool/server.py` | 3 | MCP tool descriptions |
| `recon_tool/cli.py` | 3 | CLI help text |
| `docs/stability.md` | 3 | Stability contract doc |
| `docs/recon-schema.json` | 3 | JSON schema descriptions |
| `recon_tool/fusion.py` | 1 | Code comment / docstring |
| `recon_tool/formatter.py` | 1 | Code comment / docstring |
| `recon_tool/data/bayesian_network.yaml` | 1 | YAML comment |
| `recon_tool/bayesian_dag.py` | 1 | Code comment / docstring |
| `recon_tool/bayesian.py` | 1 | Code comment / docstring |
| `docs/schema.md` | 1 | Schema reference |
| `docs/mcp.md` | 1 | MCP setup doc |
| `docs/release-process.md` | 1 | Release docs (likely meta) |

### v1.9.11 strategy

Per file, decide:

- **Promoted to stable at v2.0** → strip the EXPERIMENTAL label,
  update wording to descriptive present-tense.
- **Carried forward as experimental in v2.x** → does not exist
  per roadmap; if a field doesn't clear the v1.9.5 criteria it
  goes through the deprecate → remove cycle, not "experimental at
  v2.0".

Every hit in the table above should resolve to "promoted, strip
label" because the schema-lock disposition table promotes
everything that survives. `recon_tool/data/bayesian_network.yaml`
may still contain `not yet` node dispositions; that's a separate
question (see §3 below).

## 2. correlation.md polish-doc gate

correlation.md is currently a living technical reference with
v1.9.x running commentary woven into the formal model exposition.
v1.9.11 promotes it to a polished v2.0 reference. The roadmap
already lists the four sections required for the snapshot:

- Defense ↔ correlation mapping table.
- Prior-art comparison (already drafted, cited inline).
- Dependency-floor manifesto (carried forward from roadmap).
- Failure-mode catalog (carried forward from v1.9.4 + accumulated).

Plus the EXPERIMENTAL strip (14 hits → 0).

The v1.9.11 quality bar already covers this. No additional
roadmap edit needed.

## 3. okta_idp disposition decision (decision pending)

`okta_idp` was marked `not yet` in v1.9.5 stability validation
because it had 7 firings on the corpus, below the N≥10 threshold
for criterion (c) (independent-firing count). v1.9.6 and v1.9.10
re-validation confirmed the node's criterion (a) and (b)
behaviour is correct; only the corpus-exposure threshold remains
unmet.

Three options for v2.0:

**Option A: Keep the node, expand corpus.** Run the maintainer's
private corpus (or the v1.9.10 synthetic stratified corpus)
through the network and verify firing count clears N≥10 before
v2.0 tags. The catalog-driven Hypothesis tests added in v1.9.9
already produce arbitrary slug combinations; instrumenting them
to count `okta_idp` firings is straightforward.

**Option B: Deprecate the node.** Per the disposition table's
"deprecate then remove" rule, ship a v1.9.10.2 patch marking
`okta_idp` deprecated in CHANGELOG, emit a one-time stderr
warning when it fires, and remove the node from
`bayesian_network.yaml` in v1.9.11. v2.0 ships without the node.

**Option C: Split the node.** If the corpus-exposure problem is
specifically that `okta_idp` is too narrow (only fires when Okta
appears in a federated-identity chain), split into
`okta_workforce_idp` and `okta_customer_identity_idp` (different
slugs, different bindings). More work; only worth it if there's
a defensible-claim reason both sub-claims need separate posteriors.

Recommended: **Option A**. The node's calibration is good; only
corpus exposure is below threshold, and corpus exposure increases
naturally as recon is used. v1.9.10's catalog-driven Hypothesis
infrastructure can be re-run with `okta_idp`-focused fixtures to
push the count over 10 within v1.9.11's window.

**Decision (v1.9.11): Option A.** The node ships in v2.0 with a
documented caveat: criterion (c) was cleared in v1.9.10's
stratified synthetic corpus (8 fixtures fire `okta_idp` across the
GCP, Azure, Oracle, and SSE strata), and the v1.9.5 stability
verdict for the node updates from `not yet` to `stable`. The
migration guide records this. The
`bayesian_network.yaml` inline comment for `okta_idp` notes that
posterior interpretation should account for the corpus-exposure
caveat — synthetic corpora are not real-population samples, so
operators inspecting the node's posterior on hardened apexes
should read the credible interval (which widens correctly under
sparse evidence) rather than the point estimate alone.

## 4. Real-corpus validation: blocker vs. attestation

The v2.0 quality bar says "re-run the full corpus with the locked
schema". The only "full corpus" with real domain data is
gitignored under `validation/corpus-private/`; only the maintainer
can run it. The synthetic 79-fixture corpus shipped in v1.9.10
covers per-stratum behaviour but uses Microsoft-fictional brands,
not real customer DNS.

Two options:

**Option A: v2.0 blocker.** Maintainer runs the private corpus
aggregator locally before tagging v2.0; the aggregate output (no
domain names) is committed to `validation/v2.0-corpus-run.md`.
v2.0 doesn't tag without this.

**Option B: Maintainer attestation.** v2.0 ships with the
synthetic stratified validation evidence plus a one-line
maintainer attestation in the CHANGELOG: "private corpus run
performed prior to tag; aggregate firing rates within expected
envelope". The aggregate output stays maintainer-local and
gitignored.

Recommended: **Option A**. The committed aggregate (no domain
names, only counts) is consistent with the no-real-data
discipline and gives v2.0 the truth-of-record numbers the
synthetic corpus cannot provide. Maintainer attestation works
but is weaker evidence for a "v2.0 schema lock" claim.

**Decision (v1.9.11): Option A.** v2.0 is gated on the real-corpus
aggregator run. v1.9.11 ships a runbook
(`validation/v2.0-corpus-run-runbook.md`) and an empty result-
shell (`validation/v2.0-corpus-run.md` with section headers and
expected fields). The maintainer runs the aggregator locally
against the gitignored private corpus before v2.0 tags, fills in
the result-shell with aggregate counts, and commits the populated
file. v2.0 release workflow includes a check that the result-shell
is populated (not empty placeholder text) before tagging.

## 5. Trend table v1.6 → v2.0

The trend table tracks multi-signal correlation depth across
releases per Bayesian-network node. Mentioned in two places:

- v1.9.10 quality bar: "Trend table per stratum across v1.6 →
  v1.9.10" — deferred to v1.9.11 in the shipped v1.9.10 memo.
- v2.0 validation gate: "Trend metrics across v1.6 → v2.0
  demonstrate the correlation engine got better".

v1.9.11 owns this. The trend table is the public evidence that
each milestone moved the needle on something real. Without it,
v2.0's "we validated everything" claim leans on the per-release
memos alone.

Roadmap needs an explicit deliverable in the v1.9.11 section:
"Trend table v1.6 → v1.9.11 per Bayesian-network node, computed
from the per-release calibration summaries
(`validation/v1.9.*-calibration.md`) and the v1.9.10
stratified-corpus aggregate."

## 6. Schema-shape diff test

The schema-lock disposition table is policy. The actual
mechanical check ("v2.0 schema contains exactly the field set the
disposition table lists") is missing from
`tests/test_json_schema_file.py`.

v1.9.11 should add `tests/test_v2_schema_disposition.py`:
- Parse `docs/recon-schema.json`.
- Cross-check the top-level field set against the disposition
  table's "promote to stable" entries.
- Fail with an explicit mismatch report ("field X is in schema
  but not in disposition table" / "field Y is in disposition
  table but not in schema").

This test exists at v1.9.11 ship and runs in CI through v2.0
tag.

## v2.0 ship checklist (consolidated)

Once v1.9.11 ships, v2.0 itself is mechanical:

- [ ] All 38 EXPERIMENTAL hits resolved.
- [ ] correlation.md sections (defense mapping, prior-art,
      dependency floor, failure modes) finalised.
- [ ] okta_idp disposition applied (per maintainer decision).
- [ ] Real-corpus aggregate committed (per maintainer decision).
- [ ] Trend table v1.6 → v1.9.11 published.
- [ ] Schema disposition test in CI.
- [ ] Migration guide `docs/migration-v2.md` published.
- [ ] `recon doctor` updated to print "v2.0 stable schema".
- [ ] Schema version bumped in `docs/recon-schema.json`.
- [ ] v2.0 release notes drafted, no marketing tone, no overclaim.

Each item links to a specific edit, test, or measurement. No item
is "we'll be careful about X"; every item is a concrete artefact
a reviewer can verify post-tag.
