Two-model convergence · 2026-08-16

The converged parenting implementation plan.

Fable 5's psychological analysis, refined against live code, turned into a phased implementation plan by GPT-5.6-Sol (via Codex), then reviewed by Fable 5 for whether the plan actually preserves the psychology — not just the feature shape — with disagreements resolved by evidence, not by deferring to whichever model spoke last.

Round 1 Fable 5 — recommendation, refined with SSH verification Round 2 GPT-5.6-Sol / Codex — implementation plan Round 3 Fable 5 — review, verification, final convergence

Surfaced by this review, unrelated to parenting: the request_ctx bug from this morning's audit is worse than first scoped. Fable 5's independent check found the NameError is inside a try block whose own except swallows it — meaning the chat-fallback branch of _execute() fails every time it's hit today, not just on crisis/escalation turns, and those users get static last-resort text instead of a real response. Recommendation: ship the one-line fix now, independent of the parenting timeline — not batched with anything else.

Second, smaller finding in the same pass: the repo root has stale June-1 copies of coach.py and scaffold_prompts.py, and an empty stale h30.db, sitting alongside the real archetypes/ versions and data/oimy.db. An engineer editing from memory could edit the dead copy and see nothing change. Worth cleaning up in Phase 0.

·How the seven disagreements resolved

Codex's plan opened with seven places it disagreed with Fable 5's Round-1 recommendation after its own code read. Fable 5's review checked each with a fresh SSH pass — all seven held up.

Anchor rendering isn't unified on the live path. The DISC/attachment filtering Fable 5 cited is real, but only on the Ollama path — the live OpenRouter production path injects the entire raw anchor file. Dialect rendering (Phase 4) needs a shared unification step first, or it'll pass in local eval and do nothing in production.
The existing repair content can't route directly. Worse than Codex first said: the scaffold few-shot examples have the model speaking expert names in-voice ("Philippa Perry is right that...") — directly violating the corpus's own "never name experts" rule. Repair rides the fully-governed companion path with curated instructions; scaffolds are source material only, after cleanup.
The twice-daily cron can't do "next morning." It runs at 08:00/20:00 UTC only — doesn't reliably land in every user's morning. Needs an hourly touchpoint script reconciled against actual delivery, not enqueue time.
Constraint detection isn't an outcome detector. "Timers made it worse" is evidence, not proof of which loop it refers to — attribution must be explicit, not inferred.
The loop-outcome writer isn't safe as the ledger. No idempotency key, can silently insert an outcome event with no matching loop-state row, concurrent writes can clobber each other. A normalized table is canonical; the existing JSON becomes a compatibility projection.
Repair consent and follow-up consent are different decisions. "Yes, give me the repair" isn't "yes, message me tomorrow." Fable 5 conceded conflating these in Round 1 — now two separate durable consent events.
Repair completion shouldn't be an entity_fact. Would pollute family-context assembly with data-quality issues that table already has. Dedicated table instead; a vector-memory marker only after the parent reports actually using it.

·What Fable 5 changed in the review pass

Six substantive changes to Codex's draft — not just approval, real engineering and psychological corrections.

  1. The repair offer needs 3–5 variant phrasings, not one fixed sentence — masked as a set, model picks one verbatim. A single template means the second rupture gets a form letter; the mechanism is supposed to be a door left ajar after genuine acknowledgment, not a script.
  2. An ignored repair offer must never be re-voiced in the same conversation — it stays "offered" until it expires, but re-raising it is exactly the pressure the consent gate exists to prevent.
  3. Factual correction: the live loop-suppression list doesn't actually include 'worse' as a value — Phase 2 needs to add it and define the old→new outcome-enum mapping explicitly, or a family that says "that made it worse" keeps getting the same loop context injected anyway.
  4. The most important one — hash-scoped advice authorization in the Family Playbook. Codex's design would let an explicit-help turn disable the semantic advice gate broadly. That means a model could recall the family's plan AND paraphrase past it into a fresh invented strategy, and governance would wave it through — which is precisely "retrieve, don't generate" failing in exactly the way it was built to prevent. Fixed: only the recalled plan's own exact hash is authorized; everything else stays fully gated; zero new strategies allowed in recall mode; a failed check falls back to the bare recalled cue, never plan-plus-invention.
  5. request_ctx reprioritized to an immediate hotfix (see callout above), separate from the phased rollout.
  6. Stale dead-file hazard flagged for cleanup in Phase 0 (see callout above).

·The plan, phase by phase

0Prerequisite hardening2 changes

Not a product phase — the reliability floor the parenting features would otherwise stand on top of and quietly compound. Fixes 8 of this morning's 14 audit findings: request_ctx, fallback context-dropping, governance accepting residual violations, the bridge bypassing governance, expired-outbox delivery, shared SQLite connections, never-expiring session constraints, and 504-workers committing state after their own deadline.

All eight independently re-verified live this round. Kill switch: OIMY_DISABLE_PARENTING_STRATEGY=1 gates everything downstream of this phase.

1Repair Engine2 changes

New archetypes/repair_engine.py, a ParentingCoordinator placed after profile construction and before the bridge-force check in the request lifecycle, new tables parenting_repair_cases / parenting_touchpoints. Detects rupture disclosure → presence-first acknowledgment (turn-mode instructions confirmed live: "Do NOT give advice, tips, suggestions, scripts, or next steps" stays in force on the disclosure turn) → one of 3–5 masked consent-gated offer phrasings → age-resolved, dialect-rendered repair script through the fully governed companion path → next-morning follow-through via a new hourly touchpoint scheduler, separately consented.

One offer per rupture; an unanswered offer goes quiet, not repeated. No clinical-language exemption, ever. Smallest build of the five phases, highest confidence — most of the machinery (rupture detection, presence gating, kitchen-table language enforcement) already ships today for other reasons.

2Loop-outcome ledger closure1 change

New archetypes/loop_outcomes.py, normalized loop_outcomes table with a unique idempotency key, hardened thread-local _conn() for loop_state.py (currently bare sqlite3.connect, no timeout/WAL), record_loop_outcome() rewritten under BEGIN IMMEDIATE with an existence check. trend_json becomes a compatibility projection over the new table, not the source of truth. handle_loop_outcome() stays unwired until its stop-condition logic — currently a string search for four hardcoded tokens, ignoring the actual condition — gets redesigned.

No backfill from the 3,920 historical activations that never got an outcome — start clean going forward. The 'worse' suppression fix (change #3 above) ships in this phase.

3Family Playbook — authoring & recall1 change

New archetypes/family_playbook.py. Immutable plan versions, one active plan per loop enforced by a partial unique index, draft→confirm→activate authoring flow in calm. On recall: retrieval keyed to which loop actually matched this turn (not the current arbitrary "first two active rows" injection), one plan max per response, a ledger-exclusion preflight before the model call, and — the critical fix — advice_authorized scoped to the exact hash of the recalled plan text only, with the semantic advice checker staying fully active on everything else and zero new strategies allowed. Also replaces the hardcoded "OiMy has no persistent memory between sessions" line, which becomes false the moment plan retrieval ships.

Canary uses the existing multi-day loop0_whitaker_4 test lineage, extended to score cross-cycle plan retrieval specifically.

4Dialect axes & consent flagsaligned, no changes

Additive columns on h30_profile (guarded by PRAGMA table_info checks, not H30's existing broad-except migration pattern), populated only from explicit signal — never inferred from engagement or DISC — NULL means unknown, never shown back to the parent as a label. Precedence ladder: safety > current explicit request > hard consents > explicit dialect > BCT tone > DISC/attachment. Blocked on the shared anchor-rendering unification from the disagreement above. Canary gate: no increase in unsolicited-advice or emotional-bypass eval failures.

5Anticipatory guidancealigned, no changes

Smallest, correctly last. In-conversation only to start (outbound stays behind a separate switch and separate consent), one sentence maximum, only when it helps answer the current question — never a milestone lecture. Windows ≥24 months wide (integer-year ages can't support narrower), confidence ≥0.85 and ≤90-day freshness required on stored age facts; a current-turn stated age can bypass that for the current turn only. Never fires during crisis, VENTING, BE_PRESENT, PROBE_FIRST, or explicit don't-fix turns.

·Release sequence

OrderDeliverableNotes
Nowrequest_ctx hotfixLive user-facing defect — ships independently, immediately
0Foundation hardeningOIMY_DISABLE_PARENTING_STRATEGY=1 gates everything below
1 / 1BRepair core / follow-upFollow-up gated on the outbox-expiry fix + separate outbound consent
2Loop outcomesIncludes the 'worse' suppression fix
3Playbook authoring/recallWith hash-scoped advice authorization
4DialectAnchor-render unification is the blocker
5In-conversation anticipationOutbound stays off

The closing invariant, as Fable 5 put it: presence and consent decide whether OiMy may intervene; durable state decides what it may recall; governance still decides what it may say.

Every citation in the review pass was re-checked against production HEAD 976b318 over live SSH, not assumed from either model's prior output. Full engineering detail (schemas, near-diffs, exact function names) exists in the underlying session transcripts — this page is the converged plan Bharath asked for; ask for the full technical appendix if an engineer needs to start building directly from it.