{"type":"transition_applied","payload":{"type":"transition_applied","status":"running","residency_state":"resident"}}
{"type":"assistant_message","payload":{"text":"I read this as an investigation - I will trace the r20 rehearsal, preseal, and live rollback evidence to identify the missing real surface and produce a recurrence-proof PASS gate."}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":true}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"read","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"tool_execution","payload":{"tool":"bash","is_error":false}}
{"type":"assistant_message","payload":{"text":"I read this as an investigation - I traced r20's sealed controller, rehearsal, live authority chain, and rollback evidence without making changes.\n\n## Decisive finding\n\nThe rejection was local and pre-network, not a Telegram provider failure.\n\nr20 changed `task26-candidate-digest` to `3dab...5090`, but preserved a `task26-authority-pin.json` that pointed to the external authority chain whose current candidate remained the predecessor `6c9c...6a92`.\n\nThe adapter loads that pin during `connect()`, then rejects unless the external chain's `current_qualified_candidate` equals the credential candidate. The exact guard is in:\n\n- `gateway/platforms/task26_runtime_authority.py:104-149` - reads paired `candidate-authority/registry.json` and `qualification-ledger.json`; rejects with `runtime candidate is not current or was revoked`.\n- `gateway/platforms/telegram.py:2918-2958` - loads that authority before network connection and fails activation on any exception.\n\nRead-only inspection of the pinned real authority showed:\n\n- `current_qualified_candidate`: `6c9c...6a92` (the predecessor)\n- r20 digest appears in events: `false`\n- r20 digest is current: `false`\n- r20 digest is invalidated: `false`\n\nSo the missing surface was **not merely a credential**. It was the complete external, append-only current-authority publication:\n\n1. a paired `qualify` event/ledger row for the fresh candidate,\n2. a matching authority pin with the new registry head, ledger head, and event count,\n3. systemd credentials that reference that new pin and the same candidate digest.\n\n`switch_postimages()` explicitly rewrote only `candidate-digest` and `task26-candidate-digest`; every other credential, including `task26-authority-pin.json`, was copied unchanged. See `scripts/nutricoach_v150_host_operations.py:127-143`.\n\n## Why the passes were not contradictory\n\n- The 13-case rehearsal was explicitly `loopback-only` and passed a `DisposableService`, not the live adapter against its external authority chain:\n  - `.omo/evidence/nutricoach-v150-combined/task-v14r20-rehearsal/report.json`\n  - `scripts/nutricoach_v150_sealed_target.py:43-74`\n  - The rehearsal contains zero `candidate-authority` files; it only has copied runtime credentials.\n\n- The sealed target authorized no external or Telegram customer events, and channel inbox was disabled:\n  - `sealed-target.json` has `channel_inbox_authorized: false`, `external_events_authorized: 0`, `provider_events_authorized: 0`, and `telegram_customer_events_authorized: 0`.\n\n- The independent audit was a pre-live closure audit, not a live-authority PASS gate. Its own output records:\n  - `live_authorization_root_absent: true`\n  - `live_execution_root_absent: true`\n  - `live_successor_root_absent: true`\n  - `authorization_state: AWAITING_FRESH_OWNER_INSTRUCTION`\n  - Source: `.omo/evidence/nutricoach-v150-combined/task-v14r20-independent-audits.json`\n\n- r20's candidate qualification also said `QUALIFIED_PENDING_LIVE_AUTHORIZATION`, not deployable.\n\nThe live run proves the gap: r20 reached `COMMITTED` with the successor service running, then manual adapter QA rejected authority and rollback restored the predecessor. No provider or customer event occurred.\n\n- `.omo/evidence/nutricoach-v150-combined/task-v14r20-live-outcome.json`\n- `/home/cube/.hermes/migrations/.../nutricoach-v150-v14-live-representative-59-3dab1a55/postcommit-rollback-receipt.json`\n\n## False assumptions to remove\n\n1. **\"Rebinding the candidate credential makes it current.\"**  \n   False. Currentness is determined only by the external paired authority chain and its pin.\n\n2. **\"A loopback/service-state rehearsal exercises Telegram adapter startup.\"**  \n   False. The rehearsal tested controller stages and a filesystem service state machine, not `TelegramPlatform.connect()` against the pinned authority root.\n\n3. **\"Independent audit PASS is authorization to consume the live one-use ledger.\"**  \n   False. The audit explicitly excluded all live roots.\n\n4. **\"The immutable source closure covered the authority behavior.\"**  \n   False. r20's wheel contains `task26_candidate_authority.py` and `task26_runtime_authority.py`, but both are absent from its `source_inventory` and frozen `controller-source`. The source audit therefore could not independently inspect the code that rejected r20.\n\n5. **\"A postcommit manual adapter check is an acceptable first authority check.\"**  \n   False. It consumed r20's one-use ledger before finding the missing authority publication.\n\n## Fresh-successor PASS gate\n\nDo not authorize a successor unless every item is evidenced before ledger consumption:\n\n- [ ] New digest and new one-use authorization. r20 is consumed (`CONSUMED/SUCCEEDED`) and must never be replayed.\n- [ ] Full wheel-to-source closure: every executable wheel module, especially both Task26 authority modules, has a sealed source path and hash.\n- [ ] A new external authority root exists outside profile, package, wheelhouse, candidate, and registry roots; it has required private ownership/modes.\n- [ ] Its paired registry/ledger chains validate; the successor has an appended `qualify` entry and is the sole `current_qualified_candidate`.\n- [ ] The new authority pin matches that root's source ID, genesis, registry head, ledger head, and event count.\n- [ ] Installed successor credentials prove the same candidate digest in `task26-candidate-digest` and the new pin in `task26-authority-pin.json`.\n- [ ] An offline, disposable **installed-wheel + real credential-surface** test invokes the actual authority loader and adapter activation path: it must accept the successor and reject a stale, missing, revoked, or pin-stale candidate. No `DisposableService`, direct field injection, or mocked authority source qualifies.\n- [ ] Only if channel inbox is enabled: a separately authorized test-bot probe runs the adapter's actual three read-only Bot API checks (`getMe`, direct-message `getChat`, parent-channel `getChatMember`) and records exact bot, parent, privilege, and candidate bindings. Permit zero customer updates/messages.\n- [ ] The controller performs the authority-loader check **before** marking the one-use ledger `SUCCEEDED`; failure leaves the ledger unconsumed and the predecessor untouched.\n\n## Safe disposable-clone checks\n\nThe recorded regression command is safe but insufficient; it tests controller behavior only:\n\n```bash\nPYTHONDONTWRITEBYTECODE=1 PYTHONPATH='dualcoach/profile:.' \\\nuv run pytest -q \\\n  tests/test_nutricoach_v150_v14_safety.py \\\n  tests/test_nutricoach_v150_live_binding.py\n```\n\nAlso safe, but mock-only, are:\n\n```bash\nPYTHONDONTWRITEBYTECODE=1 uv run pytest -q \\\n  tests/gateway/test_telegram_channel_inbox_adapter.py \\\n  tests/gateway/test_multi_customer_candidate_authority.py\n```\n\nThe successor must add and pass the credential-surface authority test described above; neither existing command can authorize deployment."}}
{"type":"transition_applied","payload":{"type":"transition_applied","status":"completed","residency_state":"resident"}}
{"type":"transition_applied","payload":{"type":"transition_applied","status":"completed","residency_state":"persisted_only"}}
{"type":"suspended","payload":{"reason":"quit"}}
