{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "name": "data-wiring routing accuracy corpus",
  "version": "2.1.0",
  "purpose": "Routing-eval corpus for data-wiring (adia-ui-factory plugin). Each phrase declares whether data-wiring SHOULD be the routing target. Scored by the estate's TF-IDF routing-eval runner against the skill's description (heuristic token overlap).",
  "scoring_notes": "Heuristic signal, not ground truth. Treat misroutes as a prompt to tighten the skill description, never as a reason to keyword-stuff it. Real harness routing is LLM-driven. The fence exercised throughout: host-wiring owns BOOTSTRAP (registration, framework integration, route ownership, the host page); data-wiring owns STATE & DATA (signals, Service/Command, DataClient, hydration of data into already-mounted islands, CRUD wiring).",
  "license": "internal",
  "scope": "data-wiring routing \u2014 does this phrase activate data-wiring?",
  "phrases": [
    {
      "id": "data-pattern-01",
      "phrase": "wire up the data for this dashboard's summary cards",
      "expected": "data-wiring",
      "expected_shape": "pattern-selection",
      "rationale": "Canonical 'wire up the data' trigger phrase from the description \u2014 pattern choice for state, not bootstrap."
    },
    {
      "id": "data-pattern-02",
      "phrase": "pick a state pattern for this table \u2014 signals or DataClient?",
      "expected": "data-wiring",
      "expected_shape": "pattern-selection",
      "rationale": "Need->pattern table lookup (signals vs DataClient) is data-wiring's core decision surface."
    },
    {
      "id": "data-pattern-03",
      "phrase": "manage the toggle/selection state for this list-ui",
      "expected": "data-wiring",
      "expected_shape": "pattern-selection",
      "rationale": "Component-owned selection/toggle state is a single-owner fact in data-wiring's ownership checklist."
    },
    {
      "id": "data-crud-01",
      "phrase": "add CRUD with undo support to the invoice list",
      "expected": "data-wiring",
      "expected_shape": "crud-wiring",
      "rationale": "Service/Controller/Command pattern (async Service + undo-recording commands) is data-wiring's CRUD territory, not host-wiring's bootstrap."
    },
    {
      "id": "data-crud-02",
      "phrase": "add an action_source to this DataClient.mutate call",
      "expected": "data-wiring",
      "expected_shape": "crud-wiring",
      "rationale": "DataClient.mutate's action_source attribution rule is an data-wiring-owned fact (the client throws without it)."
    },
    {
      "id": "data-crud-03",
      "phrase": "connect the table-ui to the backend via typed reads and pure mappers",
      "expected": "data-wiring",
      "expected_shape": "crud-wiring",
      "rationale": "DataClient's read({type, params}) -> mappers -> projection shape is data-wiring's typed-read pattern."
    },
    {
      "id": "data-pattern-04",
      "phrase": "share this piece of state across two components that aren't in the same effect() tree",
      "expected": "data-wiring",
      "expected_shape": "pattern-selection",
      "rationale": "Shared state read by more than one component/module is the shared-app-store row's own trigger condition in the pattern-selection table (createStore(), gh#1761)."
    },
    {
      "id": "data-pattern-05",
      "phrase": "replace this hand-rolled Set-of-listeners pub/sub store with something signal-backed",
      "expected": "data-wiring",
      "expected_shape": "pattern-selection",
      "rationale": "createStore() is exactly this migration target — the blessed replacement for a hand-rolled Set-of-listeners store (reactivity review R2)."
    },
    {
      "id": "data-stream-01",
      "phrase": "feed live shared data to el.data using the property API",
      "expected": "data-wiring",
      "expected_shape": "data-stream-binding",
      "rationale": "Property-API population and the data-stream-* attribute trait are named data-wiring patterns."
    },
    {
      "id": "data-stream-02",
      "phrase": "why does my chart-ui drop rows appended after connect",
      "expected": "data-wiring",
      "expected_shape": "data-stream-binding",
      "rationale": "Catalog components populate via property-API, not post-connect children \u2014 an data-wiring-owned failure mode."
    },
    {
      "id": "data-ownership-01",
      "phrase": "audit whether this component keeps a shadow copy of the route's active view",
      "expected": "data-wiring",
      "expected_shape": "ownership-audit",
      "rationale": "Single-owner-per-piece-of-state is data-wiring's self-checked ownership fact list."
    },
    {
      "id": "data-ownership-02",
      "phrase": "the state change isn't round-tripping through the signal \u2014 mutate doesn't update the projection",
      "expected": "data-wiring",
      "expected_shape": "ownership-audit",
      "rationale": "Round-trip debugging (mutate -> projection/signal -> UI) is data-wiring's own-verified done-condition."
    },
    {
      "id": "data-ownership-03",
      "phrase": "a control keeps resetting a user-set view mode whenever a sibling changes",
      "expected": "data-wiring",
      "expected_shape": "ownership-audit",
      "rationale": "User-set state surviving unrelated sibling changes is one of data-wiring's named ownership defects."
    },
    {
      "id": "data-hydration-boundary-01",
      "phrase": "seed the server-fetched props into this SPA island's client-boot state",
      "expected": "data-wiring",
      "expected_shape": "hydration-path",
      "rationale": "Boundary direction A (host-sounding vocabulary, correctly data): 'hybrid' hydration path \u2014 server-seeded props feeding an island's own state \u2014 is explicitly data-wiring's hydration-path table row, even though it touches an SSR page."
    },
    {
      "id": "data-hydration-boundary-02",
      "phrase": "the SSR framework already fetches the data \u2014 wire the initial props into the components",
      "expected": "data-wiring",
      "expected_shape": "hydration-path",
      "rationale": "Boundary direction A: an SSR-flavored ask, but 'wire props into components' is data placement (data-wiring's own SSR hydration-path row), not framework registration (host-wiring)."
    },
    {
      "id": "data-hydration-boundary-03",
      "phrase": "wire the data flow so the mounted island's parent page can read its selection",
      "expected": "data-wiring",
      "expected_shape": "section-wiring",
      "rationale": "Boundary direction A: 'mounted island' sounds like a host bootstrap concern, but cross-section data flow after mounting is data-wiring's section-wiring territory."
    },
    {
      "id": "data-adv-01",
      "phrase": "register the client-side components for this new SPA host",
      "expected": "host-wiring",
      "rationale": "Boundary direction B (data-ish surface, actually host): registration mechanics \u2014 the side-effecting barrel import \u2014 are explicitly carved out to host-wiring in data-wiring's own Section wiring notes."
    },
    {
      "id": "data-adv-02",
      "phrase": "fix the double route owner \u2014 router-ui is mounted alongside the framework's router",
      "expected": "host-wiring",
      "rationale": "Boundary direction B: route ownership is a bootstrap concern (host-wiring's 'exactly one route owner' rule), not state or hydration."
    },
    {
      "id": "data-adv-03",
      "phrase": "getting 'HTMLElement is not defined' after upgrading to Next.js",
      "expected": "host-wiring",
      "rationale": "Boundary direction B: this is a client-only registration timing defect (host-wiring's SSR path), not a data-ownership or hydration-of-data problem."
    },
    {
      "id": "data-adv-04",
      "phrase": "manage the state for the streaming chat responses in the chat box",
      "expected": "llm-wiring",
      "rationale": "llm-wiring boundary: streaming chat state is owned by @adia-ai/llm's StreamChunk union and chat-shell wiring, not generic signals/DataClient \u2014 data-wiring's description explicitly excludes chat features."
    },
    {
      "id": "data-adv-05",
      "phrase": "build the markup for this data table's screen",
      "expected": "screen-composition",
      "rationale": "screen-composition boundary: screen markup composition from catalog primitives is explicitly NOT data-wiring's territory per its own description ('NOT for ... screen markup')."
    },
    {
      "id": "data-adv-06",
      "phrase": "pick the on-disk shape for this new rollup app",
      "expected": "project-scaffolding",
      "rationale": "Adversarial \u2014 on-disk project shape/scaffolding is project-scaffolding's territory, unrelated to state or data flow."
    }
  ],
  "minimums_per_spec": {
    "trigger_phrases": 16,
    "adversarial_phrases": 6,
    "task_shapes_covered": "pattern-selection, hydration-path, section-wiring, ownership-audit, crud-wiring, data-stream-binding",
    "adversarial_fraction": "30%",
    "boundary_coverage": "at least 3 phrases exercise the data<->host fence in each direction (positives that mention SSR/hydration/island vocabulary yet correctly stay data; adversarials that mention data-ish verbs yet correctly route to host), plus the llm-wiring boundary (streaming chat state) and the screen-composition boundary (screen markup)."
  },
  "evaluator_notes": {
    "current_state": "22 cases (16 trigger + 6 adversarial). Each of the 6 task shapes has at least 2 trigger cases; 3 of the 16 positives deliberately use host/SSR-adjacent vocabulary while remaining correctly data-routed, to exercise the data<->host fence from the 'sounds like host, is data' direction. Two positives (data-pattern-04/05) added for gh#1761's shared-app-store row — the newest `pattern-selection` sub-case, not a distinct 7th task shape.",
    "promotion_criteria": "Promote to a CI gate (warn -> hard-fail) when F1 >= 0.85 on this corpus across 3+ consecutive runs without description edits.",
    "review_cadence": "Re-run on every data-wiring description edit. Add 1-2 new cases per checkpoint reflecting newly-observed routing failure modes.",
    "known_limitations": "The 'hydrate the island' phrasing is genuinely ambiguous in isolation (data-into-mounted-island vs mount-the-island-itself); this corpus resolves it by verb object (props/data/state -> data; register/mount/boot -> host), matching the two skills' own NOT-for clauses. A phrase with neither cue attached is not included \u2014 it would need file-path or app-state context the heuristic scorer doesn't see."
  }
}
