SPEC-015 — v1 Parity Tracking

The parity-tracking specification — methodology and category definitions.

Source: docs/design/spec-015-v1-parity-tracking.md

SPEC-015 — V1 Parity Tracking

Field Value
Status Draft v1
Owner kris.ganjam@gmail.com
Date 2026-04-29
Depends on SPEC-001, SPEC-006
Pillar Cross-cutting

TL;DR

v2 cutover is gated on functional parity with v1 for the surface area we choose to preserve. This spec defines an explicit parity inventory — every v1 page, route, MCP tool, driver, and behavioral capability — and tracks each through parity_target artifacts in the substrate. Cutover is blocked until all “must-have” parity targets are green. v1 is treated as read-only reference throughout the build; the substrate’s own dogfood (artifacts + signals + Senate gate) tracks parity.

1. Why an explicit parity tracker

v1 has accumulated ~95 HTML pages, ~841 routes, ~58 Forge tools, ~39 economics drivers, multiple MCP servers, and a Skills system. Without an explicit checklist, “feature parity” is a guess. Specifically we need to:

  • Decide what parity means for each v1 capability (must-have / nice-to-have / intentionally retired).

  • Track v2 implementation status per capability.

  • Catch capabilities that were load-bearing but not specified in any spec.

  • Keep cutover honest: the gate is “all must-haves green”, not “we feel ready.”

2. The parity_target artifact type

Tracking parity uses the substrate itself. Each v1 capability is a parity_target artifact.

{
  "type": "parity_target",
  "schema_version": 1,
  "id_strategy": { "format": "parity-{slug}", "stable": true },
  "lock_mode": "content_hash",
  "mutability": "mutable_with_history",
  "content_schema": {
    "type": "object",
    "required": ["title", "category", "v1_locator", "tier", "status"],
    "properties": {
      "title":         { "type": "string" },
      "category":      { "enum": ["html_page", "json_route", "mcp_tool", "driver", "verb", "skill", "tool", "behavior"] },
      "v1_locator":    { "type": "string", "description": "URL, file:line, or symbol in v1" },
      "v2_locator":    { "type": "string", "description": "PR/spec reference in v2 once implemented" },
      "tier":          { "enum": ["must_have", "nice_to_have", "retired"] },
      "status":        { "enum": ["planned", "in_progress", "implemented", "verified", "skipped"] },
      "notes":         { "type": "string" },
      "spec_refs":     { "type": "array", "items": { "type": "string" } },
      "verified_by":   { "type": "string", "description": "test name or human reviewer ref" }
    }
  },
  "links": {
    "implements_in_v2": { "to_types": ["*"] },
    "blocked_by":       { "to_types": ["parity_target"] }
  },
  "signals": {
    "vote": { "values": [-1, 1], "aggregation": "replace", "description": "Reviewer attests parity met" }
  },
  "lifecycle": {
    "states": ["proposed", "active", "verified", "skipped"]
  }
}

3. Inventory categories

3.1 HTML pages (~95)

Per SPEC-003 §10 tier list. Each tier-1/tier-2 page becomes a parity_target with category=html_page. Tier-3 sunset routes are parity_target with tier=retired (recorded so we don’t accidentally rebuild them).

3.2 JSON routes (~563 /api/*)

The polymorphic verbs in SPEC-001 cover the read/write/search/links/signals patterns. Per-type routes (/api/forge/tools/roi, /api/atlas/coverage, etc.) get one parity_target each. Most map to must_have (verb call) or retired (legacy aggregation now expressed as a query).

3.3 MCP tools

v1 MCP servers (scidex_mcp_server.py, scidex_pantheon_mcp_server.py) expose ~25 tools. Each tool is a parity_target mapped to a v2 verb or skill.

3.4 Drivers (~39 economics drivers)

Each driver in v1 economics_drivers/ becomes a parity_target mapped to either:

  • A v2 driver (still implemented, but reading from substrate verbs).

  • A signal aggregation view (some drivers reduce to “compute X over signals”).

  • retired (some drivers were experimental).

3.5 Skills + tools

v1’s personas/ (9 founding personas) and skills/ (23 tool skills) and vendor/kdense-skills/ (k-dense bundles) all need parity in v2 per SPEC-013. Each is a parity_target mapping to a v2 skill artifact.

v1’s 58 Forge tools each get a parity_target mapping to a v2 tool artifact per SPEC-002.

3.6 Behaviors

Cross-cutting behaviors (live search debounce, mermaid wiki rendering, JWT cookie auth, OAuth flow, fleet watchdog, post-merge guard) get parity_target of category=behavior. These are caught manually via inventory walk, not by counting routes.

3.7 Live agent population (SPEC-020)

v1’s vibrancy is materially driven by its 59 Pantheon personas + 14 founding agents continuously acting on the system (10K+ actions for the founding 4 alone). v2 must replicate this aliveness or new visitors will see an empty room. Per SPEC-020:

  • Each v1 persona becomes a parity_target of category=agent_persona. Mapping is to (agent row + skill-persona-<slug> artifact + agent-worker container) triple in v2.

  • Wave 1 (12 personas + 3 role agents) gates the cutover from “v2 is technically running” to “v2 is alive”.

  • Wave 2/3 fill out the long tail.

  • Role agents (scidex-janitor, scidex-curator, scidex-onboarder, etc.) have no v1 counterpart but track here as tier=must_have for v2’s housekeeping behaviors.

Seed data lives in data/v1-personas.yaml (per SPEC-020 §12.1). The parity tracker auto-generates parity_target rows from that file on each cutover-readiness check.

3.8 Corpus content (v1 PG → v2 substrate)

v1 holds ~17.5K wiki pages, 2.4K hypotheses, 29.6K papers, 710K knowledge edges, 879 debates, 3.5K knowledge gaps, and 119 contributors in PG database scidex (same cluster, accessible via SCIDEX_PG_RO_DSN replica). Per the migration recommendation (Option 1a — PG→PG ETL), each of the top content tables becomes a parity_target of category=corpus:

  • wiki_pages (17,790) → v2 wiki_page artifact type

  • hypotheses (2,369) → v2 hypothesis artifact type

  • papers (29,566) → v2 paper artifact type

  • knowledge_edges (710,066) → v2 KG link rows (typed cites / extends / refutes predicates)

  • analyses (479) → v2 analysis artifact type

  • canonical_entities (49,342) → v2 entity-typed wiki backbone

Cutover gate: every category=corpus parity_target with tier=must_have must reach status=verified before the cutover script (SPEC-006 §3) will rename scidex.ai → v1.scidex.ai and re-route scidex.ai to v2.

4. Inventory mechanism

Two complementary approaches. The LLM-agent path is primary because it understands semantics; the mechanical script is a coverage backup that catches the long tail.

4.1 Primary: LLM-agent intelligent verification

Orchestra dispatches a recurring [Parity] quest (per SPEC-016 §4.1). The quest spawns one-shot tasks of the form “Audit v1 area X for parity-relevant capabilities.”

Each one-shot:

  • Reads v1 code, templates, and routes with full LLM context (semantic understanding, not just regex matching).

  • Identifies capabilities at the right granularity — a load-bearing analytics endpoint vs. a debug aggregation, a user-facing form vs. an admin-only sub-tool.

  • Proposes parity_target artifacts via scidex.create:

    • title, category, v1_locator (file:line or URL)

    • tier proposal with reasoning in notes (why must_have / nice_to_have / retired)

    • v2_locator proposal — relevant SPEC sections, anticipated PRs

    • cross-references to existing v2 work that already covers this capability

  • Posts a Senate review comment (scidex.comment) for human or reviewer-agent confirmation.

Why this beats a pure script: semantic judgment about tier, intelligent grouping (collapse 8 forge endpoints into one verb-based parity_target), proactive identification of v1-isms that should retire (not just rebuild). And it dogfoods the substrate — uses the same verbs, signals, comments machinery to track its own migration.

Quest cadence: every 24h initially, dropping to weekly once the inventory stabilizes.

4.2 Backup: comprehensive coverage script

A complementary scripts/parity-coverage-check.py walks v1 mechanically:

  • Greps @app.get/@app.post/@app.put/@app.delete/@app.api_route decorators in api.py.

  • Lists files in personas/, skills/, economics_drivers/, scidex_tools/, vendor/kdense-skills/.

  • Lists MCP tool registrations in scidex_mcp_server.py and scidex_pantheon_mcp_server.py.

  • Lists submodule contents.

Output: a flat list of v1 surface elements. The script then queries scidex.list(type='parity_target') and computes the diff:

  • Items in coverage list but NOT in parity_target → uncovered; flagged as gaps.

  • Items in parity_target but NOT in coverage → ambient behaviors or specs that were added by judgment (expected; not a problem).

A weekly recurring quest runs the script and creates one-shot LLM-agent tasks for any new gaps. The script is a coverage check, not a source of truth — it flags blind spots; the agent path does the intelligent work of categorization.

4.3 Curation pass

A reviewer (human or Senate-class agent) walks proposals:

  • Confirms or revises tier (must_have / nice_to_have / retired).

  • Adds notes for retired choices so we don’t accidentally rebuild them.

  • Cross-references the relevant v2 spec (spec_refs).

  • Approves via scidex.signal(kind='vote', value=1) — accepted parity targets enter lifecycle.active.

4.4 Implementation tracking

As v2 PRs land, each PR includes “Closes parity-{slug}” in its description. CI scans merged PRs for this footer and updates the parity_target.status to implemented.

A human reviewer flips status=verified after manual / agent-acceptance verification (per SPEC-007 §6).

4.5 Cutover gate

The cutover script (per SPEC-006 §3) refuses to run if any parity_target with tier=must_have has status != verified. Output:

PARITY GATE: 7 must-have targets unverified.
  - parity-graph-explorer (in_progress, no PR)
  - parity-debate-replay-stream (planned)
  - parity-jwt-google-oauth (implemented, not verified)
  ...
Cutover refused.

tier=nice_to_have targets don’t gate cutover; they get a warning.

5. Parity dashboard (in Prism)

A Senate-side page at /senate/parity renders a live view of the inventory:

  • Pie chart: status distribution per tier.

  • Table: filterable by category, tier, status.

  • Recent transitions: which targets just flipped state.

  • Cutover-readiness summary: “X of Y must-haves verified.”

Subscribed to parity_target.* events; updates in real-time per SPEC-001 §13.

6. Validating parity for specific kinds

6.1 HTML page parity

For each parity_target of category html_page:

  • v1 page rendered → screenshot stored.

  • v2 page rendered → screenshot stored.

  • Diff verified by reviewer (visual; doesn’t have to be pixel-perfect).

  • Behavioral checklist: forms work, links resolve, live search works, mobile-responsive.

6.2 Verb parity

For each route → verb mapping:

  • v1 route returns shape X.

  • v2 verb returns shape Y.

  • Mapping documented; consumer-side translator if shape differs.

  • Agent-acceptance test (per SPEC-007 §6) exercises the verb.

6.3 Skill / tool parity

  • Skill: scidex.search(types=['skill'], query=...) returns the skill.

  • Tool: scidex.tool.invoke(name, args) runs successfully on a sample input.

  • Outputs validate against schemas.

6.4 Driver parity

  • v2 driver runs end-to-end on sample data.

  • Output matches v1 driver’s output for the same inputs (or differs in a documented way).

  • If retired: explicit note that the function is now expressed as a substrate aggregation view.

7. Open questions

  1. Granularity — should every /api/* route be a separate parity_target, or grouped (e.g., “all /api/forge/* routes”). Recommendation: group by intent; ~150-200 targets total, not 600.

  2. Soft-launch — do we open v2 to a small test population before full cutover? If so, how does parity gating apply? Default: no soft-launch; full cutover when must-haves are green.

  3. Visual-regression budget — how much pixel-difference is acceptable on Prism vs v1? Probably permissive (look-and-feel close enough; the goal is functional, not pixel-perfect).

  4. Drift after cutover — when v2 ships a new feature, do we add parity_target artifacts retroactively? No — parity_target is a v1→v2 migration concept. New features track via normal artifact lifecycle.

8. Interaction with other specs

  • SPEC-001: parity_target is just another artifact type.

  • SPEC-006: cutover gate references the must-have parity status.

  • SPEC-007: parity verification is part of the test strategy (Layer 5 agent acceptance).

  • SPEC-016: the parity-inventory curation quest runs in the substrate.