VERIFIED real probe exists + passesLYING-GREEN flow counter only — misses correctnessAMBER wired/coded but not yet firing — watchBROKEN code dead / misfires / structurally wrongDEPLOYED-UNPROBED shipped, no live probe yetNode color = probe honesty. Flow chip below = separate throughput state.
Watch in 24h — re-check items flagged at last session
[WATCH-PFS-STRATEGIST-FORMAT-SHIFT-01] FEAT-POST-FORMAT-SUITE-01 — strategist proposes a format_shift (re-check after 2026-07-04; bandit arms moved 06-26, give strategist daily cycles to react)
Secondary: Bandit prerequisite now SATISFIED (post_form/post_length arms moved 06-26 06:27Z). Strategist proposes sparsely (last=pillar_shift 06-21 applied); not yet fired format_shift. Not a bug — observe only. BLOCKED on FIX-POST-DRAFT-CHOKEPOINT-01 (posts at 4% publish, gate-stack burns all 3 redraft iters) — cannot measure until posts flow. KEEP — due date extended 2026-07-01 (TRACKING-APPLY), recheck 2026-07-04 after P0 gate-stack fix ships. 2026-07-02 recheck: 0 format_shift proposals in last 96h (still before 07-04 due date); posts=0 today (walls: stuck_approved_timeout x3 + runner_session_budget_deferred, empty_payload wall fixed cb88d0d6). KEEP, recheck 07-04 as scheduled.
[WATCH-FORM-ROTATION-01] FU-VOICE-ANGLE-DIVERSITY-01 (C4) — published posts use ROTATING forms, not all story/prose (re-check after a full working day 2026-06-29)
curl '$SUPABASE_URL/rest/v1/action_log?select=created_at,status,context&persona_id=eq.respiro-brand&action_type=eq.post&created_at=gte.NOW()-interval 24h' | jq '[.[]|select(.context.media_id!=null)|.context.selected_post_form]|unique' — PASS if >=2 distinct selected_post_form values among PUBLISHED posts AND no "'X' structure used 3+ times consecutively" blocks in action_log. PE_FORM_ROTATION=on live 2026-06-28. FIELD FIX 2026-07-01: there is no post_structure key — the real field is context.selected_post_form.
Secondary: C4 deterministic form rotation (never-seen=1.0 ... last-used=0.0 weights); 6 forms map 1:1 to classify_structure vocab. Watch the structure-history file rotates, not monotone story. BLOCKED on FIX-POST-DRAFT-CHOKEPOINT-01 (posts at 4% publish) — cannot measure until posts flow. 2026-07-02 recheck: 7d window only 1 distinct non-null selected_post_form ('question'); still BLOCKED, posts=0 today. KEEP.
[WATCH-DRAFT-DEDUP-01] FIX-TOPIC-DEDUP-DRAFT-CONTENT-01 — runner_topic_dedup_deferred share DROPS and posts/day climbs from 0 (re-check after a full working day 2026-06-29)
ssh claudebot@204.168.169.186, curl action_log action_type=eq.post last 24h status+context.status_reason — PASS if runner_topic_dedup_deferred is a MINORITY of post attempts AND >=1 published post (context.media_id) on an active day; eyeball no near-duplicate topics. New qdrant collection post_content_dedup_prod should fill (1 point per published post).
Secondary: Dedup switched coarse pillar topic_hint -> draft-text 300-char gist on ISOLATED collection. PE_DRAFT_DEDUP_ENABLED=1 live 2026-06-28; PE_DEDUP_POST_CONTENT_THRESHOLD=0.82 -> 0.80 after 7d cosine data. Cold-start: empty 45d window = relaxed dedup, INTENDED to unblock posts; watch for dupes slipping. Rollback = flag off. BLOCKED on FIX-POST-DRAFT-CHOKEPOINT-01 (posts at 4% publish) — cannot measure until posts flow. 2026-07-02 recheck: runner_topic_dedup_deferred ABSENT from 48h status_reason distribution (0/25 attempts) — dedup no longer the active wall; new walls are stuck_approved_timeout x3 + runner_session_budget_deferred (BATCH2 empty-payload wall fixed cb88d0d6, count frozen 49 since 05:00Z). Still 0 published posts in 48h — unmeasurable. KEEP.
F3/F2 reclaim: curl action_log status=eq.approved&created_at=lt.NOW()-interval 30min by slug — PASS if 0 rows persist across a multi-day window. F7 tee: journalctl -f during a live V4 session shows stderr lines in real time, not a silent 50min gap. F1 opener-soft-ship refusal: curl action_log context->>opener_soft_ship for refused:true rows + blocked_by[]. F6 block_detail: curl action_log for post_gate_blocked:* status_reason on gate-blocks previously mislabeled runner_execute_failed.
Secondary: All 6 fixes (F1 Guard-C observability, F2a/b terminal-skip + CAS fail-closed, F3 stuck-approved reclaim widen, F4 honest defer label, F6 case-insensitive block_detail, F7 stderr live-tee+rotation) are DEPLOYED-UNPROBED — 42/42 unit tests pass (incl. 6 anti-tautology source-grep assertions added after an accidental git-checkout revert wiped and re-required F1/F2a), but none has a live-production occurrence confirmed yet. New nodes: cycle-stderr-live-tee, approved-row-reclaim-sweeper (both DEPLOYED-UNPROBED). 2026-07-02 recheck: F6 PROVEN LIVE (1x post_gate_blocked:structure_repetition status_reason observed in 48h, previously would mislabel as runner_execute_failed). F3 NOT YET zero — 2 approved rows currently >30min old (transient, needs multi-day recheck). F1 opener_soft_ship: 0 occurrences via context.opener_soft_ship in 7d window (inconclusive — may need nested-path check). KEEP, recheck 07-03.
[WATCH-POST-RHETORICAL-VARIETY-SOAK-01] FIX-POST-GEN-VARIETY-01 + BUG-POST-TEXT-MONOTONY-01 soak — >=3 distinct rhetorical_formula labels in published posts (re-check 2026-06-29 or after >=3 posts publish)
curl '$SUPABASE_URL/rest/v1/action_log?select=context,created_at&persona_id=eq.respiro-brand&action_type=eq.post&created_at=gte.NOW()-interval 7d' | jq '[.[]|select(.context.media_id!=null)|.context.draft.rhetorical_formula]|unique' — PASS if >=3 distinct non-null rhetorical_formula labels among published posts. Query by slug.
Secondary: AMBER node anti-template; classifier vocab mismatch (8 hardcoded neuroscience patterns don't cover current wellness-critique style); all 10 last published posts classify to 'other'; RHETORICAL_FORMULA_BLOCK structurally empty every draft. BLOCKED on P1-D-1 fix (expand classifier vocab) AND FIX-POST-DRAFT-CHOKEPOINT-01 (posts at 4% publish). FIELD FIX 2026-07-01: rhetorical_formula lives at context.draft.rhetorical_formula, not top-level context.rhetorical_formula — prior check string false-zeroed. 2026-07-02 recheck: 7d window only 1 distinct non-null rhetorical_formula ('other'); still BLOCKED (need >=3), posts=0 today. KEEP.
[WATCH-POST-STRUCTURE-MONOTONY-SOAK-01] FIX-POST-STRUCTURE-MONOTONY-01 business soak — >=2 distinct post_structure values in published posts (re-check 2026-06-29)
curl '$SUPABASE_URL/rest/v1/action_log?select=context&persona_id=eq.respiro-brand&action_type=eq.post&created_at=gte.NOW()-interval 24h' | jq '[.[]|select(.context.media_id!=null)|.context.selected_post_form]|unique' — PASS if >=2 distinct selected_post_form values among PUBLISHED posts AND no single form repeated 3+ times consecutively. v4di_structure_block blocklist alive and emitting (8/10 number_anchor etc. confirmed).
Secondary: FIX-POST-STRUCTURE-MONOTONY-01 (24ec7a9b) shipped; structure dedup via in-prompt v4di_structure_block; live blocklist proven (8/10). Business soak (>=2 distinct selected_post_form in published posts) BLOCKED on FIX-POST-DRAFT-CHOKEPOINT-01 (posts at 4% publish). Recheck once P0 gate-stack fix ships. FIELD FIX 2026-07-01: there is no post_structure key — the real field is context.selected_post_form. 2026-07-02 recheck: 24h window returned 0 published posts (empty distinct-form list); still BLOCKED on posts=0, new walls stuck_approved_timeout/runner_session_budget_deferred. KEEP.
[WATCH-VALIDATION-WALL-ORGANIC-TRUST-01] VALIDATION-WALL-01 organic soak — first ORGANIC working-hours trust.score (non-n/a, non-synthetic) from real stage data (armed 2026-07-03)
curl '$SUPABASE_URL/rest/v1/health_snapshot?probe_key=eq.trust.score&order=created_at.desc&limit=1' — PASS if latest row inside 07:00-23:00 NY has status in {ok,degraded,broken} with meta.synthetic absent, plus 5 fresh stage.* rows with real counts. status=broken organic = system WORKING (report worst_stage), not failing.
Secondary: VALIDATION-WALL-01 CLOSED 2026-07-03 live-verified 6/6 (synthetic green->red->green TG alerts + close-gate exit1/exit0). HEAD 80cd6544, flags ON: PE_PIPELINE_HEARTBEAT=1 PE_TRUST_SCORE=1 PE_TRUST_DIGEST=1 PE_TRUST_ALERT=on. Pending only ORGANIC emission (soak-watchlist item 14). AMBER until first organic non-n/a trust.score row.
Per-node probe-honesty status. Click any node to expand its invariant clauses with file:line evidence from gap-matrix.md. Node color = probe honesty of the current monitoring (not throughput health).
BA-3: strategy_proposal_id dead column — action_log.strategy_proposal_id exists but 0 rows non-null all-time; 24 applied proposals, none link back to action_log; FK relationship proposal→action permanently untracked
BA-6: voice_dna_versions↔proposal audit linkage UNPROVEN: applier refactored — _ava_backup_version sets proposal_id=vep.id and is called (L973); _ava_revert keys off vep_id (L816). Both existing vdv rows are pre-fix null (06-14/06-22); no live apply since to confirm. Proof = next voice_change apply yields a vdv row with proposal_id NOT NULL.
Flag-Gated V4 Stages — dashed border = inert until flag flip
FLAG-GATED EXPERIMENTS LIFECYCLE — fix shipped 2026-06-26 (UNBLOCK-POSTS-01 3b3eb564: F1/F2/F3 + daily owns E1-E5); UNPROVEN until next daily run 06-27; bf158665 CAP-blocks the 5 proposed until ends_at 07-06Dead-letter flag — inert until flipped
trends-scanAMBER: research-intel.md mtime 2026-06-24 13:36:31 UTC (10 days old). No recent trends-scan activity found in engine logs. File access time 2026-07-04 00:45 suggests read, not write. Cannot conclusively prove node is working within 48h window. Tasks: FIX-TRENDS-WHY-PROMPT-01FIX-TRENDS-WHY-PROMPT-01AMBER
Expand node in gap-matrix.md for per-clause detail.
competitor-scanLYING-GREEN confirmed via correct query (prober's own evidence was a wrong-field false-zero): scan is healthy and fires daily, but operator_playbook.scoring_weights.competitor_insights never appears in 30 recent rows incl. today. Tasks: FIX-COMPETITOR-SCHEMA-MIGRATION-01FIX-COMPETITOR-V4-INJECT-01FIX-COMPETITOR-TRENDING-SCORE-01LYING-GREEN
Expand node in gap-matrix.md for per-clause detail.
backstory-memoryLYING-GREEN confirmed: mechanism code works (manual run built correct file, 423 posts/104d/phase=brand_voice) but live pipeline never produces it — file absent/stale 4+ days despite hourly TTL and frequent cycles. Tasks: FIX-BACKSTORY-SEEDER-DEPLOY-01FIX-BACKSTORY-SEEDER-DEPLOY-01FIX-BACKSTORY-TIMELINE-WIRE-01FIX-BACKSTORY-TIMELINE-WIRE-01LYING-GREEN
Expand node in gap-matrix.md for per-clause detail.
Pipeline Nodes (69 nodes)
Discovery / feed scanVERIFIED — re-probe found fresher evidence than prober cited (scanned_at now 14:30:09Z, discovery_sessions ended_at 14:33Z error_code=null, ~30min cadence unbroken). 37 is_viral rows in 48h (>=10 req), 88 distinct home_feed authors in 48h (>=50 req, via surface=home_feed/features->>author since author_handle col doesn't exist — proof_requirement string is stale on column names but claim holds). RUN_MODE=prod confirmed on VPS.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Daily is_viral recalc (persona-is-viral-recalc-<slug>.timer)VERIFIED, not DEPLOYED-UNPROBED: prober checked wrong signal (action_log posts). Timer active/enabled, last fired 2026-07-04T03:00 UTC, journal shows real HTTP 204 writes; DB confirms is_viral=true rows as recent as 2026-07-04T14:00Z. Tasks: FU-VIRAL-INTEL-BATCH-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Candidate screen (7-rule filter)VERIFIED: confirmed and strengthened. 186 opportunity_candidates rows in last 24h with diverse screen_state (ready/rejected) and varied policy_reasons (niche_mismatch, media_type_blocked, is_reply, below_min_engagement, disqualified_pattern), all run_mode=prod. Latest arbiter fire 14:09:16Z, latest screen row 14:38:34Z — both newer than prober's cited 09:37:49Z, so not stale/cherry-picked.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Action arbiter (per-type due gate)VERIFIED: independently re-queried arbiter_decisions (fresher row exists, 14:09:16Z), cross-matched 1:1 with VPS journalctl cycle_ids, RUN_MODE=prod on VPS, and confirmed a real published comment (14:37:50Z, media_id+graph_comment_id) inside an eligible window. Not lying-green. Tasks: VERIFY-ACTION-ARBITER-LIVE-01VERIFY-ACTION-ARBITER-LIVE-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Opportunity queue builderVERIFIED: live re-probe at 14:53Z found a fresh claim_next_opportunity fire at 14:53:35Z (16s old) AND independent DB proof — operator_opportunity_queue shows 36 distinct build batches (29-38 rows each) in last 24h, latest 14:12:57Z, plus a claimed row timestamped 14:53:37Z matching the log exactly. Builder is genuinely alive, not counter-only.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
_pe_quick_skip global throttle (DEPRECATED)AMBER confirmed correct — deprecated node, no false-negative. Arbiter authoritative live (fires every ~15min, varying eligible_types), legacy _pe_quick_skip only dormant behind LEADV2_ACTION_ARBITER=off flag (which is =on in prod).AMBER
Expand node in gap-matrix.md for per-clause detail.
Comment-only mode hack (DEPRECATED)LYING-GREEN: _PE_COMMENT_ONLY_CLAIM flag removed from code (verified 0 matches), but comment fallback behavior still active via comment_anti_starvation+orchestrator. Node represents stale flag marker tracking obsolete implementation.LYING-GREEN
Expand node in gap-matrix.md for per-clause detail.
runner_crash / crash-recovery (per-phase cooldown)AMBER confirmed, not a false-zero. Prober's cooldown-expired claim is real but last_fire is stale — journal shows 6+ more "crash"-labeled events since, latest 2026-07-04T02:35:51Z (13h ago), all rc=0/non-fatal draft_failed, 100% recovered to learned status. Tasks: CRASH-PHASE3-WORKER-TIMEOUT-01CRASH-PHASE3-WORKER-TIMEOUT-01VERIFY-ACTION-ARBITER-LIVE-01VERIFY-ACTION-ARBITER-LIVE-01AMBER
Expand node in gap-matrix.md for per-clause detail.
Per-cycle stderr live observability (tee to journald)VERIFIED, not DEPLOYED-UNPROBED: run-cycle.sh:1441 wires `2> >(tee -a $_crash_stderr_tmp >&2)` — real live per-line tee to journald+file. Newest log now 15:04Z (fresher than prober's 12:35), content is structured 122-line real cycle trace 14:13:10→14:25:05, rotation active. Tasks: AUDIT-NEWFORMAT-PIPELINE-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Quality track — DORMANTLYING-GREEN: prober's "last_fire" is an unrelated post-learning timestamp, not the quality track; its "4 eval_log rows/2d" claim is false — eval_log has been silent (v4_enabled=false) since 2026-05-08, ~57d, not days. Tasks: FLAG-ROLLOUT-QUALITY-01FLAG-ROLLOUT-QUALITY-01VOICE-CARD-REGEN-01VOICE-CARD-REGEN-01LYING-GREEN
Expand node in gap-matrix.md for per-clause detail.
Claim next opportunity (CAS lock)VERIFIED: node fires live in prod; found real more-recent claims after prober's cited last_fire, confirming freshness not staleness. RUN_MODE=prod confirmed.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Stuck-approved row reclaim + terminal-skipBROKEN confirmed (partially, not as prober framed it): 2 of the 3 cited rows (2026-06-24T13:46:06Z, 14:27:56Z, status_reason=auto-approved) are still status=approved after 10 days — sweeper genuinely fails on these despite matching its own gate. The 3rd row (07-04T11:48:22Z) was a false positive: it was only 17min old at probe time (younger than the 30min guard) and journalctl proves the sweeper cleared it 2h21m later (14:09:01Z WARN stuck_approved_timeout) — exactly the PASS condition in proof_requirement. Sweeper process is alive and cycling hourly; it just isn't universal. Tasks: AUDIT-NEWFORMAT-PIPELINE-01BROKEN
Expand node in gap-matrix.md for per-clause detail.
Comment sweeper empty-payload anchor fixVERIFIED — comment-type empty_payload_rejected stopped after real deploy (11:44Z 07-02, not 05:00Z as doc claims), and 30 comment rows since then landed offhours_draft_deferred instead, latest today 10:58Z. Prober's own evidence_cmd was broken (checked non-existent context.status_reason) but corrected query confirms the claim. Tasks: FIX-EMPTY-PAYLOAD-COMMENT-ANCHOR-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Expand node in gap-matrix.md for per-clause detail.
LLM draft — postVERIFIED: llm-draft-post produces real content and reaches publish+learn. 3 posts drafted+published+scored in last ~19h (2026-07-03 17:12-23:33Z), each with distinct media_id and 260-480 char generated text. Prober's single rate-limit-deferred log line was actually a FAILED draft attempt (retry path), not evidence of health.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
LLM draft — commentVERIFIED, but on corrected evidence: prober's 2 cited "claimed" lines were pre_screen_skip intake events, not LLM draft firings. Real proof: action_log row 471f5641 @14:37:50Z status=confirmed w/ draft+own_comment_media_id+graph_comment_id.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Comment redraft time budget (600s -> 900s)AMBER: session_budget_deferred label not in prod; last entry 2026-06-18, not after. Last 48h shows 0 session_budget_deferred for comments (only offhours_draft_deferred:33 + runner_draft_failed:20). Budget bump 600→900s pending deploy confirmed. Tasks: AUDIT-NEWFORMAT-PIPELINE-01AMBER
Expand node in gap-matrix.md for per-clause detail.
LLM draft — replyDEPLOYED-UNPROBED confirmed: action_type is "reply" not "publish_reply" (prober's query name was wrong, correcting it changes nothing). All 27 reply rows for respiro-brand/prod are status=expired(26)/failed(1), zero successes; the 26 expired rows are hardcoded "REPLY-SEED-01 synthetic test reply" seed data blocked pre-draft ("Already commented/replied"), not real organic drafts. No path to a genuine LLM-drafted, successfully-published reply exists in prod data.DEPLOYED-UNPROBED
Expand node in gap-matrix.md for per-clause detail.
Safety gate — groundingDEPLOYED-UNPROBED CONFIRMED: Feature deployed but intentionally disabled (PE_GROUNDING_GATE_ENABLED=false). Zero grounding_check entries across entire action_log (1000+ rows all-time, 289 in 48h window). No active fire history in prod.DEPLOYED-UNPROBED
Expand node in gap-matrix.md for per-clause detail.
Safety gate — voice checkVERIFIED (refuting prober): 22 action_log rows with context.redraft_trace containing critique/voice checks in last 48h, most recent 2026-07-04T02:25:33Z. Prober's curl used invalid PostgREST syntax (gte.NOW()-interval 48h isn't valid), silently false-zeroed. Also prober's "1 total row all-time" is wrong: table has 8873 rows for respiro-brand.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Safety gate — opener qualityVERIFIED CONFIRMED. Gate is live and working correctly. 0 blocks = successful opener diversity enforcement. Code deployed (post-gate.sh:660-674), FIX-POST-GEN-VARIETY-01 shipped 2026-06-26. Prober's DEPLOYED-UNPROBED verdict was false.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Opener soft-ship at publish gateAMBER confirmed. Only 1 lifetime fire in 14d (07-01T21:40:40Z, by slug respiro-brand): downgrade logic worked correctly, but that same action later expired (status_reason=stale_approved_timeout, media_id null) — never actually published. Co-fire guard C still unobserved. Tasks: AUDIT-NEWFORMAT-PIPELINE-01AMBER
Expand node in gap-matrix.md for per-clause detail.
Slop judge (D7)AMBER confirmed. Mechanism is real (platform/safety/slop-judge.sh + agent-tool:1204-1234) but is a narrow secondary appeal gate, only invoked when post_gate already BLOCKED on structure_repetition or 6 specific marginal rules — not a universal per-post check. 0 judge_result rows since 2026-07-01T00:53:54Z (~3d silence), consistent with those specific rules simply not tripping recently, not a break.AMBER
Expand node in gap-matrix.md for per-clause detail.
Unified construction-monotony detector (posts + comments)DEPLOYED-UNPROBED: detector enabled (PE_CONSTRUCTION_UNIFIED=1) but produces no measurable output in production. All 333 blocked entries (last 7d) have context.failing_rule=null; zero redraft_trace records exist. Code is deployed but execution path writes no data to action_log. Tasks: AUDIT-NEWFORMAT-PIPELINE-01DEPLOYED-UNPROBED
Expand node in gap-matrix.md for per-clause detail.
Publish (Threads A/B)VERIFIED — false-zero: prober filtered action_type=publish_post (doesn't exist). Real types post/image_post show media_id 18111379798740189 published 2026-07-03T23:33Z (~15h ago) + a comment published 3 min before this probe.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Engagement / signal collectionVERIFIED: prober false-zero'd on a stale/wrong query. action_type=score_comment never existed (0 rows all-time), but auto-collect-signals fires every cycle in prod (stamp updated 14:06Z, ~11 fires today) and writes real reply/like signals into comment context.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Scoring (auto-score.sh)VERIFIED. respiro-brand ideation_angles: 155 selected/48h, 125 distinct topics, cosine diversity gate active (min_distance 0.526–0.665), last fire 2026-07-04 02:57 UTC. Prober's AMBER was false-zero from UUID-column slug query + non-existent pillar column.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Composite reward + banditVERIFIED — prober's 0-rows was a filter-bug false-zero (exact match on 'comment_style' vs real namespaced 'comment_style:challenge' etc). Correct query shows 5 comment_style bandits + post/comment bandits updated as recently as today 07:45Z, with fresh confirmed comment reward data at 14:37Z ready to feed next cycle.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Experiment evalAMBER confirmed, not false-zero. 183 experiments/respiro-brand, 0 concluded_supported, last concluded 2026-06-30T16:54:15Z verified independently. Worse: NO new experiment rows created since 2026-06-17 (17d) despite strategist_weekly firing 06-21/06-30/07-02. assemble-prompt.sh:573 order=source.asc confirmed real (alphabetical, not recency).AMBER
Expand node in gap-matrix.md for per-clause detail.
Strategist briefing + voice proposalVERIFIED — strategist_briefing has 87 rows for respiro-brand/prod, last fired TODAY 2026-07-04T04:09:13Z. Prober's "0 rows" came from a malformed select=count() call that PostgREST rejects (PGRST123), not real absence. Tasks: FIX-STRATEGIST-PILLAR-SLUG-BACKFILL-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Learning liveness (belief→prompt)AMBER: prober's "0 rows/UNPROBED" is a false-zero — identical query returns 1 real row (2026-07-01T10:15:38Z); but original 13-event/07-02 claim also overstated, and last real fire is 3 days stale. Tasks: FIX-BELIEFS-INJECT-AWK-EARLYEXIT-01AMBER
Expand node in gap-matrix.md for per-clause detail.
Governance applier + voice evolutionVERIFIED: prober's 0-row query used UUID a4b7d5f8-... but voice_dna_versions.persona_id is TEXT slug; re-query by slug=respiro-brand returns 2 rows (run_mode=prod), latest created_at=2026-06-22T18:59:47Z matches reported last_fire exactly. Tasks: FIX-VOICE-DNA-VERSIONS-AUDIT-01FIX-VOICE-DNA-AUDIT-LOG-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Customer voice-edit (dashboard /voice)LYING-GREEN confirmed (agree with prober). Both real code paths for customer voice-edit (strategy_proposals/voice_change + the actually-wired voice_evolution_proposals review route) show zero completed customer-initiated dashboard edits ever, despite the prober's own supporting query being malformed.LYING-GREEN
Expand node in gap-matrix.md for per-clause detail.
C1/ideation — chosen=true write pathVERIFIED: prober queried wrong table (opportunity_candidates.c1_ideation_angles, doesn't exist) and slug-vs-UUID mismatch. Real table ideation_angles.chosen=true fired 5x in last 46min, action_id correctly links to action_log (not orphan), one row status=confirmed with real graph_comment_id — full write→publish chain live.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
C1/ideation — diversity (min_distance cosine)VERIFIED: node is live, not UNPROBED. Prober's query used persona_id=eq.respiro-brand (slug) but ideation_angles.persona_id is a UUID (inverse of the usual rule) — false-zero. 853 chosen=true rows total, last_fire=2026-07-04T14:53:41Z (~3min ago), min_distance 0.55-0.63. Tasks: VERIFY-C1-COSINE-DEDUP-LIVE-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Off-hours publish DEFER (PE_OFFHOURS_PUBLISH_DEFER)DEPLOYED-UNPROBED confirmed: code+flag+RUN_MODE all correct, but the publish-time race window it guards (post approved in-hours, dispatched after 23:00 NY) never occurred in 6d of logs — not a false-zero. Tasks: VERIFY-OFFHOURS-DEFER-LIVE-01DEPLOYED-UNPROBED
Expand node in gap-matrix.md for per-clause detail.
Off-window draft gate (FIX-OFFWINDOW-GLM-GATE-01)VERIFIED: gate live and firing far more recently than prober cited; 34 deferrals in last 48h, last fire 2026-07-04T10:58Z (06:58 NY), and real publish (media_id) at 10:37 NY same day proves gate isn't perpetual-block. Tasks: FIX-OFFWINDOW-GLM-GATE-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
topic_dedup instrumentation (TOPIC_DEDUP_PROBE)LYING-GREEN: action_log has ZERO rows ever with action_type ilike '*dedup*' or context.dedup_category set (any persona, any window, all-time). Prober's "10+ verdicts, cosine 0.497-0.727, DUPLICATE@06-27" does not exist in prod DB.LYING-GREEN
Expand node in gap-matrix.md for per-clause detail.
scoring_context + LLM feature extractor (PE_LLM_FEATURE_EXTRACT)LYING-GREEN: prober's cited evidence (3 score_comment rows, bandit_updated=true) does not exist; feature has never fired even once. Tasks: ENABLE-LLM-FEATURE-EXTRACT-01LYING-GREEN
Expand node in gap-matrix.md for per-clause detail.
VPS provisioning (onboarding / persona-creation)DEPLOYED-UNPROBED, not plain UNPROBED. provision-worker.timer IS live on VPS (enabled since 2026-06-22, fires clean every 2min, zero errors) but provision_jobs table is genuinely 0 rows repo-wide (confirmed no filter/slug issue) — no persona has ever gone through this async onboarding pipeline since respiro-brand's VPS predates the table by 2+ months.DEPLOYED-UNPROBED
Expand node in gap-matrix.md for per-clause detail.
Post sub-topic rotation (FIX-POST-TOPIC-ROTATION-01)AMBER: prober's evidence_cmd is non-executable as written (col "angle" doesn't exist, persona_id=eq.slug on a uuid column → 42703/22P02) and last_fire (07-01) is stale vs real latest fire 2026-07-04. Rotation looks healthy on a corrected query, but not proven by the cited evidence. Tasks: FIX-POST-TOPIC-ROTATION-01VERIFY-C1-COSINE-DEDUP-LIVE-01AMBER
Expand node in gap-matrix.md for per-clause detail.
Comment phrase anti-repeat + form rotation (FIX-COMMENT-DIVERSITY-01)VERIFIED, and stronger than the prober's own evidence: 72 real published comments (status=learned+own_comment_media_id) 06-29→07-03 show 5 styles, 0 consecutive repeats; engine still firing today 07-04 14:58Z, RUN_MODE=prod confirmed. Tasks: FIX-COMMENT-DIVERSITY-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Voice V2 config (voice_persona_v2 table)VERIFIED: voice_v2_status=active, 8 style_axes; live post 2026-07-03T23:33Z (media_id 18111379798740189) has context.inject_provenance.voice.branch=v2_active, axes_count=8, guardrails_present=true — direct causal proof v2 card drove generation, not just a flag. Tasks: FU-VOICE-ANGLE-DIVERSITY-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Andrew named-character voiceAMBER confirmed (worse than prober's evidence suggested). Prober's last_fire=2026-05-15 was itself stale — real last activity 2026-07-02. Andrew-character diff WAS applied to voice-dna.md (commit 3996fa99, 2026-06-30) and voice_persona_v2.voice_guardrails DOES contain "CHARACTER: Andrew..." (updated 2026-06-27). But voice_persona_v2.brand_description still says "anonymous brand...not a person" and style_axes personal_I_vs_brand_observer=0.70 toward impersonal-observer — directly contradicting Andrew's first-person voice within the same active row. Live proof: 8 most-recent respiro-brand posts (up to 2026-07-03T23:33) show zero Andrew signature (no NYC/LeBron/Messi/first-person "I"), still old impersonal skeptical-brand-observer voice. Data layer updated; generation pipeline not manifesting it — classic write-only/runtime-disconnect, not a false-zero. Tasks: KEYSTONE-VOICE-GUARDRAILS-ANDREW-19CHARACTER-PROGRAM-01AMBER
Expand node in gap-matrix.md for per-clause detail.
Post-publish frame hook (voice_recency_frames)AMBER: voice_recency_frames table empty (0 rows); action_log confirms 0 published posts in 7-day window (posts_today=0, posts_total=0 per engine logs 2026-07-04T14:37Z). Hook mechanism is intact and wired, but dormant due to zero post supply. Not broken; no triggering events. Tasks: FU-VOICE-ANGLE-DIVERSITY-01AMBER
Expand node in gap-matrix.md for per-clause detail.
Pillar-weight wiring (focus_directive → ideation)VERIFIED. Engine RUN_MODE=prod confirmed. Pillar-weight-wiring actively running: 155 ideation angles chosen in 48h, 125 distinct ontology nodes, cosine diversity gating active (min_distance 0.526–0.665). Last fire 2026-07-04 02:57 UTC. System functioning correctly. Tasks: FU-VOICE-ANGLE-DIVERSITY-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Post form sub-bandit (post_form:*)VERIFIED: post_form bandit is live-updating from real publishes, even fresher than prober reported (updated_at 2026-07-04T07:45:37Z, alpha=1/beta=13, vs prober's 07-01 snapshot). 3 recent action_log rows have real media_id + status=learned + scored_at. Caveat: only arm "question" ever selected in 48h (allowed_csv constraint or content-format config, not a bandit-mechanism defect). Tasks: FEAT-POST-FORMAT-SUITE-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Post length sub-bandit (post_length:*)AMBER confirmed — post_length:short bandit arm exists (alpha=1, beta=13, updated 2026-07-04T07:45:37Z) but has never fired. Zero post_length actions in action_log across entire history despite active engine cycles logging auto-bandit steps. Tasks: FEAT-POST-FORMAT-SUITE-01AMBER
Expand node in gap-matrix.md for per-clause detail.
Post format selector (get_recommended_arm_constrained)LYING-GREEN: node fires (fields populate, media_id present, form∈enabled set) but the "selector" has pulled exactly ONE arm ever (question/short) out of 5 forms×3 lengths configured, since feature launch 9+ days ago — zero exploration, not a functioning selector. Tasks: FEAT-POST-FORMAT-SUITE-01LYING-GREEN
Expand node in gap-matrix.md for per-clause detail.
Post form rotation (PE_FORM_ROTATION)AMBER confirmed, worse than prober said: 12d/300-row window, 21 published posts, selected_post_form is ALWAYS "question" (31/31 non-null picks); list/story/hot_take/mini_guide are enabled in safety-overrides.json but NEVER once selected. Not a sample-size issue — bandit arm starvation. Tasks: FIX-POST-BLOCKED-STATUS-P0-18FU-VOICE-ANGLE-DIVERSITY-01AMBER
Expand node in gap-matrix.md for per-clause detail.
Post series orchestration (publish_thread_chain + post_series table)BROKEN (worse than AMBER): series NOT disabled — persona_config prod row has series_enabled=true, PE_POST_FORMAT_SUITE_ENABLED=1. Opportunity generator DOES fire (86 thread_chain opps since 07-01, latest 14:57Z today) but 0/86 ever convert to action_log/post_series — 0% conversion vs ~100%/55% for post/comment. Real broken pipeline stage, not a disabled toggle. Tasks: FEAT-POST-FORMAT-SUITE-01BROKEN
Expand node in gap-matrix.md for per-clause detail.
Poll publish (poll_attachment / publish_poll)AMBER, not DEPLOYED-UNPROBED: poll is a double fail-closed gated feature (persona_config.polls_enabled=false AND THREADS_POLL_CAPABLE unset on VPS) — 0 fires is BY DESIGN, code exists (api.sh:1083 threads_post_poll, run-agent.sh:511 _ra_publish_poll), not an untested deploy. Tasks: FEAT-POST-FORMAT-SUITE-01AMBER
Expand node in gap-matrix.md for per-clause detail.
Content format config (persona_config + sidecar .content_formats)LYING-GREEN: config in DB/VPS matches (5 forms, 3 lengths, series=true), but ALL 23 post rows w/ selected_post_form in last 60 posts (Jul1-4) show question/short only, 0 series mentions — config never actually drives runtime variety. Tasks: FEAT-POST-FORMAT-SUITE-01LYING-GREEN
Expand node in gap-matrix.md for per-clause detail.
Ontology keyword screening (comment niche match)LYING-GREEN: prober checked niche_match_count variance (local-JSON path, never disputed) but node's OWN proof_requirement is persona_niche_keywords.hits_total>0 — that returns 0/200 rows, exactly the documented dead-data bug (FIX-ONTOLOGY-KEYWORD-SYNC-01, still open). Tasks: FIX-ONTOLOGY-KEYWORD-SYNC-01LYING-GREEN
Expand node in gap-matrix.md for per-clause detail.
Engagement collection (auto-check-replies)BROKEN confirmed via independent (corrected) evidence: comments ARE published (action_type=comment, not publish_comment as prober queried), but 0 confirmed comments since ~2026-04-06 carry own-comment engagement fields (reply_count/like_count); matches open backlog task #6 reply-pipeline fix. Tasks: FIX-REPLY-HANDLING-MEDIAID-FALLBACK-01BROKEN
Expand node in gap-matrix.md for per-clause detail.
Graph comment ID persist (graph_comment_id in action_log)VERIFIED — graph_comment_id/own_comment_media_id persist fine on terminal status=learned (not confirmed); 183/1000 comment rows learned in last 30d, all sampled non-null, last fire 2026-07-03T22:37:54Z.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Comment voice-frames hook (comment_recency_frames)BROKEN confirmed (independently, not via prober's log): write-hook _comment_v2_record_frame never fires — no /tmp/comment-voice-v2.log despite ~100 comments reaching learned since 6/27. Read-path is alive but stuck serving the same 6 stale backfilled rows. Tasks: FIX-COMMENT-VOICE-FRAME-HOOK-DEAD-01BROKEN
Expand node in gap-matrix.md for per-clause detail.
Ontology node label in comment draft (ontology-in-text comments)VERIFIED: independently re-queried by slug, found fresher fire (14:53:37Z > prober's 12:35:34Z), 15 GraphQL-verified learned comments in 48h with ontology angles, and published_text semantically reflects the topic (not just dead metadata). RUN_MODE=prod confirmed. Tasks: FIX-ONTOLOGY-IN-TEXT-COMMENTS-01VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Customer dashboard surface (web/app/(dashboard)/*)VERIFIED — prober's "personas empty" was a false-zero; respiro-brand exists with action_log rows 16min old, and 18 (not 16) dashboard route groups have real API routes wired to Supabase (e.g. queue/queue-health).VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Auth refresh gate (platform/session/auth-refresh.sh)VERIFIED — prober false-zero: queried nonexistent action_type=publish_post. Real signal is action_type=api_gate_check (confirmed, fires every ~15-60min, latest 2026-07-04T14:13Z) paired with real publish_post media_id 11min later same cycle (2026-07-03T23:22→23:33Z). Gate is live and working.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Circuit breaker (platform/safety/circuit-breaker.sh)VERIFIED: circuit-breaker is live, wired code (not a table). check_publish_failure_circuit runs unconditionally as F4 in pre_execute_check on EVERY publish attempt; VPS has PE_PUBLISH_CIRCUIT_ENFORCE=1, RUN_MODE=prod; gate executed again today (comment confirmed 14:37 UTC).VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Injection scanner (platform/safety/injection-scanner.sh)VERIFIED — false-zero. Scanner logs only on hit (silent pass on clean), so 0 BLOCKED lines in 7d just means 0 real injection attempts, not non-execution. Wired into 3 hot-path callers, v4-runner ran 2733x/48h, 0 source-load failures, and live functional test on the deployed VPS file correctly detected+redacted a real injection payload.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Content studio (platform/operator/content-studio.sh)BROKEN (upgraded from AMBER): content-studio.sh is structurally dead code, not just log-absent. Call graph shows content_studio_generate has 0 inbound callers and the file itself has 0 inbound imports/sources anywhere in the repo. run-cycle.sh and daemon.sh (the two real entrypoints) never reference it. No systemd timer/cron invokes it directly either. Last real commit 2026-06-01 (33 days stale). 0 log lines in both 7d and 30d windows.BROKEN
Expand node in gap-matrix.md for per-clause detail.
Invariants watchdog (platform/quality/invariants + stability-autopilot)VERIFIED: watchdog fires every 30min w/ 9 real probes (varying values, not stub), detected a real BREACH (learning_examples_emitted_24h) 12:00Z and sent a live Telegram alert (rc=0 http=200) — full pipeline proven, not unprobed.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Drift detector (platform/eval/drift-detector.sh)BROKEN, not DEPLOYED-UNPROBED: timer fires daily on schedule but persona-loop glob personas/*/persona.json matches 0 files (no persona.json exists anywhere) so D1-D4 detectors never run; 0 eval_log rows ever for envelope_drift_alert.BROKEN
Expand node in gap-matrix.md for per-clause detail.
Weight learner (platform/eval/weight-learner.sh)VERIFIED: weight-learner fires daily inside strategist-daily.sh; scoring_weight_history + operator_playbook.scoring_weights show real computed post_content weights (n=200) dated 2026-07-04T04:09Z, chain unbroken since >=2026-06-06.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Ops timer fleet (19 of 20 agent/deploy/*.timer pairs)VERIFIED: independently re-ran list-timers+journalctl on VPS ~2.5h after prober; 18 enabled timers all show live NEXT schedules and exit=0 on last fire, heartbeat/watchdog/candidate-screen actively cycling.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
RAG + world-context fetch (agent/pre-actions/build-rag-context.sh, build-world-context.sh, fetch-world-news.sh)VERIFIED, not AMBER: rag context fetch fires on every post for 30h+ (10/10 consecutive posts 07-02 17:51→07-03 23:33), passages_used=7 real varying top_score 0.49-0.69, fallback_triggered=false, RUN_MODE=prod confirmed on VPS.VERIFIED
Expand node in gap-matrix.md for per-clause detail.
Governance appliers fan-out (4 non-voice appliers)AMBER CONFIRMED with major caveat: prober's evidence (keyword/playbook proposals) is false; actual data shows only pillar_shift/voice_rule appliers have proof of execution; 2 other appliers (keyword, playbook) have zero proposals in system. Pillar_shift last_fire=2026-06-21T04:10:09Z verified. Cannot promote to VERIFIED without proving all 4 non-voice appliers actually write approved proposals (missing keyword/playbook inventory makes 2 of them uncheckable).AMBER
Expand node in gap-matrix.md for per-clause detail.
FOUNDER PRIORITY
AUDIT-NEWFORMAT-PIPELINE-01 | in_progress | NORTH STAR: rebuild all comment+post nodes GREEN under Andrew named-character + no-template philosophy. Active multi-session initiative.
REPLIES-FULLY-LIVE-01 | pending | P3: Replies pipeline fully live — confirm replies publishing end-to-end in prod
CYCLE-OP-ISOLATION-01 | pending | None
CRITICAL
KEYSTONE-VOICE-GUARDRAILS-ANDREW-19 | in_progress | #19 KEYSTONE: voice_guardrails 17,957 chars to <=5K — apply Andrew character. Rewrite proposal ready.
NICHE-TOPIC-DIVERSITY-DECISION-01 | deployed-observing | Infra fixed; residual=topic-monotony (dedup working-as-designed). Founder must pick A=broaden-niche or B=diversity-injection before next session.
CRASH-PHASE3-WORKER-TIMEOUT-01 | deployed-observing | DEPLOYED commit 392c1372 (PE_PHASE3_WAIT_TIMEOUT=300 live respiro-vps). SOAK: runner_crash=0 / ~30min, engine healthy, 1 confirmed post post-deploy. Kill-mechanism armed, not yet needed. Soak young (4 rows) — observing.
HIGH
CHARACTER-PROGRAM-01 | pending | #20 CHARACTER-PROGRAM-01: Andrew named character + 8 corpus moves. Depends on KEYSTONE-19.
VOICE-CARD-REGEN-01 | deployed-observing | DEPLOYED commit 51cd92c0 (respiro-vps HEAD matches): regenerated compact card + per-pillar register + 3 non-somatic examples. SOAK PENDING: 18:31Z post was on OLD card; need a post drafted AFTER deploy -> content-novelty judge (somatic-dropped? per-pillar diversity?) before flag rollout.
FLAG-ROLLOUT-QUALITY-01 | pending | None
EVAL-GLM-5.2-DRAFT-01 | pending | VERIFIED 2026-06-14 (glm-5.2-probe-findings.md): glm-5.2 LIVE on our endpoint+key; glm-5/glm-5.1 alias->5.2 so draft path ALREADY on 5.2; DEFAULT glm-5.2 = ~1M ctx (778K ok, ~1.05M exceeded), [1m] id=400 not needed; needle@350K read correctly. CAVEATS: latency ~25s@350K (threatens orch budget!), gateway body ~5-6MB cap (000 reset), over-limit=200+stop_reason=model_context_window_exceeded (client must handle). Bet A=no-op (already on 5.2). Bet B (1M full-ctx draft mode) UNBLOCKED today, gated on latency-bound+body+novelty-gate => architect design.
STRATEGIST-WEEKLY-GATE-PERSONA-FILTER-01 | pending | strategist-weekly.sh:86-88 learning_loop_health gate filters component+skipped only, no persona_id -> cross-persona suppression latent bug (harmless while respiro is sole active persona).
SWH-SAMPLE-SIZE-ZERO-01 | pending | scoring_weight_history rows write sample_size=0/confidence=0 - no scored-action samples yet to compute real weights. Confirm samples populate as scored actions accumulate.
DEPLOY-DIRTY-TREE-RUNTIME-ARTIFACTS-01 | pending | VPS run-cycle writes untracked runtime caches (.sync-*, autopilot-ledger, notification-prefs, breach-state) that ad-hoc git commits can sweep in. Gitignore them (PO-LEADV2-001 F4 dirty-tree).
FU-COMMENT-ENRICH-TUNE-01 | pending | Folded into 09:07NY re-probe: compute enriched/day vs 60, bump cap if <1.5x
CHORE-DROP-DEAD-MICRO-PROMPTS-01 | pending | None
CHORE-ADD-7-WATCH-COVERAGE-01 | pending | None
Synced with docs/tasks.yaml · Last full actualization 2026-07-04 · 105 non-closed tasks. Active sprint: POSTS-TOPIC-DIVERSITY-01 (6/day cadence + defer-orphan fix). Run: /leadv2 "<TASK-ID>"
Every time the engine runs (triggered by a systemd timer, roughly hourly), it follows a three-part cycle:
BEFORE — gather intelligence and select a target;
DURING — draft content, validate it through safety gates, and publish;
AFTER — record what happened, score it, and (theoretically) feed that score back into the AI's future decisions.
The three diagrams below trace this lifecycle separately for Posts, Comments, and Replies. Each step is coloured by its current health in production:
green = working,
amber = partially working,
red = broken / zero output in production.
Node colours below reflect the current production state.
SCOREBOARD — live prod state · green = verified working
Composite reward for comments — got_reply/reply_count → cr>0 with gradient (reply_count 6/8/10 → 1.12/1.36/1.60). The bandit's only real fuel now produces reward.
Post-enqueue cadence-floor rebuild path (FIX-POST-ENQUEUE-CADENCE-01 a8524ce7) — FIXED: build_opportunity_queue at cadence-floor + floor-refill sites now receives synthetic op_context with correct remaining_posts; cadence_floor_no_candidate eliminated. Post opps verified 0→14.
Experiment input-volume — sample sizes unmet by deadline (upstream cadence, not the eval).
🔴 RED — broken / zero output:
Post publish — VERIFIED LIVE 2026-06-16T21:41Z. media_id=18044727599592480, status=confirmed, slug=respiro-brand. Bugs fixed this session: rc=4 empty-draft expire guard (e400fd43), GLM 429 retry-budget (bc4a2988), classify_structure topic/structure conflation (dee9848a). Earlier: dedup perf VERIFIED (d8d7caed), opp-recycle VERIFIED (PE_EXPIRE_ON_SIGTERM_CLAIMED=1), crash №1+2 FIXED. QUALITY=DORMANT residual: stale voice-card (V4_VOICE_CARD=1 reads un-regenerated voice-card.md) + engine flags all =0 → published post is somatic slop. Tasks: VOICE-CARD-REGEN-01, FLAG-ROLLOUT-QUALITY-01.
Comment publish — 0 comments / 7d, UNPROBED. Likely blocked by same crash №2 on comment cycles. FIX-COMMENT-CADENCE-01 (7af4258c) code correct. No confirmed comment publish since crash №2 root-caused.
Post engagement — near-zero. ~4/346 posts get any engagement; views arrive, no interaction. Strategy/niche problem (Respiro-Niche-Too-Narrow), not reward plumbing.
Image generation — FAL_KEY restored in DB 2026-06-10 (fal_key_enc re-encrypted, desired_state v104). Pending first image_post live cycle. F5 bandit→scorer ENABLED (PE_BANDIT_VALUE_WEIGHT=0.20 via env_overrides).
Real-world context injection — fetch + Qdrant built but never wired into the draft prompt.
Reply claim path unblocked 2026-06-10 — FIX-REPLY-CLAIM-PRIORITY-01 SHIPPED 18c5bc75 (B3 reply slot flag + budget-gated cap 2, PE_REPLY_BYPASS_CADENCE=1 live); cadence-floor preempt + nmc≥1 exclusion both fixed. Exhaust guard shipped 2026-06-11 (a1893d1c+98a983ab). Awaiting first confirmed live reply (0 published as of 2026-06-11).
Node colours reflect current prod state. Post publish VERIFIED LIVE — media_id=18044727599592480, 2026-06-16T21:41Z; bugs fixed: rc=4 empty-draft (e400fd43), GLM 429 retry-budget (bc4a2988), classify_structure gate (dee9848a). QUALITY DORMANT residual — stale voice-card + engine flags all =0; published post is somatic slop. NOT green on quality. Dedup VERIFIED (d8d7caed, PE_DEDUP_FAST=1). Opp-recycle VERIFIED (PE_EXPIRE_ON_SIGTERM_CLAIMED=1). Comments 0 / 7d, unprobed. Prior fixes: safety batch (2e69228d), watchdog cron (f897265d), voice PROVEN LIVE 2026-06-12 01:24Z, PE_BANDIT_VALUE_WEIGHT=0.20 ENABLED.
Health legend Working in prod (live-proven traffic/signal) Partial / degraded — OR — shipped <sha> <date> awaiting live proof Broken / zero output (genuinely open/broken)No-traffic (code wired; upstream starved)COLOR RULE: GREEN = live-proven; AMBER = shipped but no live proof yet; RED = genuinely broken
1
Post Lifecycle
2026-07-04: BROKEN — approved-row-reclaim-sweeper: BROKEN confirmed (partially, not as prober framed it): 2 of the 3 cited rows (2026-06-24T13:46:06Z, 14:27:56Z, status_reason=auto-approved) are still status=approved after 10 days — sweeper genuinely fails on these despite matching its own gate.
An original post published to the persona's own Threads feed (text or image).
%%{init: {"theme": "dark", "themeVariables": {"primaryColor": "#161b22", "primaryBorderColor": "#30363d", "edgeLabelBackground": "#1c2128", "tertiaryColor": "#161b22", "fontSize": "11px"}, "flowchart": {"nodeSpacing": 18, "rankSpacing": 26, "wrap": true, "htmlLabels": true}}}%%
flowchart TD
classDef green fill:#161b22,stroke:#3fb950,stroke-width:2px,color:#e6edf3
classDef amber fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3
classDef red fill:#161b22,stroke:#f85149,stroke-width:2px,color:#e6edf3
classDef dead fill:#161b22,stroke:#6e7681,stroke-width:1px,color:#8b949e,stroke-dasharray:5 3
classDef notraffic fill:#161b22,stroke:#7c5a00,stroke-width:2px,color:#e6edf3
classDef unprobed fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3,stroke-dasharray:4 3
subgraph BEFORE["BEFORE — Setup and intelligence"]
post_post_b1_timer["⚠ Systemd timer fires persona-engine.timer → run-cycle.sh"]:::unprobed
post_post_b1b_stderr_tee["Cycle stderr live-tee (observability) run-cycle.sh:1307-1316 — F7 tee's the whole V4-session stderr to journald live instead of buffering it until session end"]:::green
post_post_b2_preflight["⚠ Preflight check platform/lifecycle/preflight-check.sh — env/keys/DB reachability"]:::unprobed
post_post_b3_isactive["⚠ is_active gate run-cycle.sh — LYING-GREEN: fail-open on DB unreachable"]:::unprobed
post_post_b4_jitter["⚠ Jitter delay 0–5 min run-cycle.sh — human-like timing"]:::unprobed
post_post_b5_conductor_pre["⚠ Cycle-conductor pre-maintenance platform/operator/cycle-conductor.sh — strategist briefing (CYCLE-CONDUCTOR-01)"]:::unprobed
post_post_b5b_rag["RAG context fetch Qdrant vector search — 7 passages for posts + comment-tone; platform/knowledge/rag-fetch.sh. AUDIT-NEWFORMAT-PIPELINE-01 (E2E-PIPELINE-STATUS.md) 2026-07-01: rag-inject re-checked AMBER — original probe's RED verdict was FALSIFIED on its central claim (success marker does fire); narrower real gap found: run-cycle.sh:~1250-1252 tail -300 $_crash_stderr_tmp truncates full per-cycle stderr before journald, obscuring RAG failures + v4-runner.sh interaction. No dedicated nodes[] entry exists for rag-inject — recorded here on the flow step only."]:::green
post_post_b5c_backstory["Backstory / timeline build-persona-timeline.sh — PERSONA_TIMELINE injected into prompt; DB-backed persona_timeline + story arcs"]:::amber
post_post_b5d_worldctx["Real-world context fetch-world-news.sh → world-news-search.sh (RSS→Qdrant); PE_WORLD_CONTEXT_RAG_ENABLED flag"]:::green
post_post_b6_arbiter["Action arbiter (per-type due gate) platform/operator/action-arbiter.sh — writes arbiter_decisions, exports _PE_ELIGIBLE_TYPES"]:::green
post_post_b7_oqb["Opportunity queue built platform/operator/opportunity-queue-builder.sh"]:::green
post_post_b8_claim["Claim next opportunity (CAS lock) opportunity-queue-builder.sh — atomic claim"]:::green
post_post_b8b_reclaim["Stuck-approved reclaim sweep run-cycle.sh stuck-approved sweeper — reclaims rows orphaned in status=approved past an 80-min age guard (any status_reason, not just auto-approved*); never double-publishes (gates on context.media_id IS NULL)"]:::red
post_post_b_qskip_deprecated["_pe_quick_skip global throttle (DEPRECATED) run-cycle.sh — replaced by action-arbiter (ACTION-ARBITER-REDESIGN-01)"]:::dead
end
subgraph DURING["DURING — Draft, gate, publish"]
post_post_d1_auth["Auth pre-publish gate platform/adapters/threads/auth-refresh.sh. AUDIT-NEWFORMAT-PIPELINE-01 (E2E-PIPELINE-STATUS-PART2.md) 2026-07-01: auth-transport re-run by slug ~10min after original probe — GENUINE BUSINESS PROOF: real publish 2026-07-01T00:53:54Z, image_post status=live, real graphql-verified comment. No RED root; Threads auth/transport confirmed healthy end-to-end. No dedicated nodes[] entry exists for auth-transport — recorded here on the flow step; kept AMBER at node_style pending a formal nodes[] entry, but this is the one audit item with an actual media_id-backed outcome."]:::green
post_post_d2_draft["LLM draft generated — content-studio (3-candidate) vs llm-draft-post (V4 single) — OPEN QUESTION v4-runner.sh — GLM backend via llm-client.sh. MAP-COVERAGE-APPLY-01 (2026-07-02): two real, distinct draft architectures exist in-repo — platform/operator/content-studio.sh (3-candidate generate+rank+gate) and this V4 single-draft path. Which one actually fires for respiro-brand today is an OPEN QUESTION not resolved this pass — do NOT assert either as canonical; see new node content-studio (AMBER) for the runtime check needed."]:::green
post_post_d2f_rhetorical_classify["⚠ Rhetorical-formula classify (P1-D-1 — AMBER) post-gate.sh classify_rhetorical_formula() + v4di_rhetorical_formula_block — deployed a7712a88; AMBER: classifier vocab mismatch; 8 hardcoded neuroscience patterns don't cover current wellness-critique style; all 10 recent posts classify to 'other'; RHETORICAL_FORMULA_BLOCK structurally empty every draft"]:::unprobed
post_post_d2g_voicev2_inject["Voice V2 block inject (FU-VOICE-ANGLE-DIVERSITY-01 — AMBER) v4-runner.sh _v4_load_voice_v2_or_fallback — 3-layer V2 block: (a) brand_description, (b) style_axes 8 dims, (c) voice_recency_frames auto-prohibitions; AMBER: PE_VOICE_V2=1 + voice_v2_status=active; draft-path proven; never live-fired in prod (posts blocked)"]:::green
post_post_d2b_imggen["⚠ Image generation image_post action_type only: FAL (Kontext/FLUX) via _ra_image_fal_generate; degrades to text_only_post on failure. AUDIT-NEWFORMAT-PIPELINE-01 (E2E-PIPELINE-STATUS-PART2.md) 2026-07-01: UNCONFIRMED this wave — probe evidence field was literally 'test' (placeholder), NOT independently re-verified. Treat as unconfirmed AMBER; re-probe before relying on it. No dedicated nodes[] entry exists for image-gen — recorded here on the flow step only."]:::unprobed
post_post_d2c_imgupload["⚠ Image upload sb_upload_persona_image → threads_post_image; NO-TRAFFIC — never reached when generation fails"]:::unprobed
post_post_d2d_inject["Safety — injection scan Prompt injection scan on draft inputs; adjacent to grounding gate"]:::green
post_post_d2e_circuit["Circuit breaker Stops publishing if too many consecutive failures; 0 circuit_open rows ever fired"]:::green
post_post_d3_grounding["Safety gate — grounding check grounding-gate.sh — layer1 PCRE live, layer2 LLM disabled"]:::amber
post_post_d4_voice["Safety gate — voice check voice-check.sh — redraft_trace written to action_log"]:::green
post_post_d5_opener["Safety gate — opener quality post-gate.sh — saturation D4 checks"]:::green
post_post_d5b_opener_softship["Opener soft-ship at publish gate agent-tool Guard C — downgrades opener-family BLOCKED to WARN for post/image_post ONLY when it is the sole blocking rule; refuses (fail-closed) when a non-opener rule co-fires; F1 logs refusal+co-firing rule to context.opener_soft_ship"]:::amber
post_post_d6_slop["Slop judge (D7) slop-judge — unified redraft loop PE_REDRAFT_UNIFIED=1"]:::amber
post_post_d6b_construction["Construction-monotony check unified fingerprint (family_fp/exact_fp/formula) — post-gate.sh, flag PE_CONSTRUCTION_UNIFIED=1; CHECK-ONLY here, window append happens at confirmed publish"]:::amber
post_post_d6c_dispatch_gate["Dispatch-time post-gate recheck (G0) v4-runner.sh (~:8785) — second independent post-gate.sh pass in PE_POST_GATE_CHECK_ONLY=1 check-only mode immediately before the Threads publish call; rc=7 blocks without writing history/sidecar state; closes the draft-time-to-dispatch-time drift window (BATCH2 378d9289)"]:::green
post_post_d7_publish["Publish Path A or B platform/adapters/threads/api.sh or browser — Threads Graph API / mobile"]:::green
post_post_d8_log["⚠ action_log row written platform/lifecycle/action-log.sh"]:::unprobed
post_post_d9_frame_hook["Post-publish frame hook (FU-VOICE-ANGLE-DIVERSITY-01) platform/orchestrator/post-publish-hook.sh — haiku writes voice_recency_frames row (1-sentence angle frame); fn_vrf_max7 trigger keeps max-7; feeds V2 voice auto-prohibitions next cycle"]:::amber
end
subgraph AFTER["AFTER — Record, score, learn"]
post_post_a1_signals["Signal collection (4h delay) auto-collect-signals.sh"]:::green
post_post_a2_score["Score action auto-score.sh"]:::green
post_post_a3_reward["Composite reward + bandit update auto-composite-reward.sh → auto-bandit.sh"]:::green
post_post_a3h_experiment_attr["Experiment attribution write (P1-B-1 — RED) experiment_applications write path — decrement actions_taken/actions_scored on active experiment row after post publish+score; currently RED: actions_taken=0 despite 2 published posts; attribution path undefined or unwired"]:::amber
post_post_a3i_belief_update["Belief update trigger (P1-B-2 — RED) beliefs table write on publish+score signal — belief_attribution trigger; currently RED: beliefs table 6d stale (last 2026-06-15); trigger undefined; no write path from publish event to beliefs row. BATCH2 2026-07-02 (378d9289): the 2>/dev/null swallow on the beliefs-attribution RPC call was removed (strategist-daily.sh:1050, strategist-weekly.sh:590, generate-reports.sh:428) — errors now surface as WARN instead of being silently hidden, but the write path itself is still unproven; stays amber/RED-labeled pending a live occurrence"]:::amber
post_post_a3b_experiment["Experiment eval Tests content variants vs baseline; 56/192 concluded_refuted with lift_pct; platform/learning/experiment-eval.sh"]:::amber
post_post_a3c_strat_save["Strategist briefing saved Writes today's learned patterns for tomorrow's strategist; platform/learning/strategist-write.sh"]:::green
post_post_a3d_voice_prop["⚠ Voice evolution proposal Proposes voice changes based on what worked; strategy_proposals table; PROVEN LIVE 2026-06-12"]:::unprobed
post_post_a3e_gov["Governance applier apply_approved_proposals in run-cycle.sh; applies approved strategy+voice changes; RC1 FIXED 2026-06-02"]:::green
post_post_a3f_snapshot["⚠ Daily snapshot Records follower count + engagement metrics; health_snapshot table"]:::unprobed
post_post_a3g_health["Autopilot health check Detects health breaches + spawns self-repair agent; health_snapshot table; deploy key read-only so fixes not shipped"]:::green
post_post_a4_conductor_post["⚠ Cycle-conductor post-maintenance platform/operator/cycle-conductor.sh — eval + reflect (CYCLE-CONDUCTOR-01)"]:::unprobed
end
post_post_b1_timer --> post_b1b_stderr_tee
post_post_b1b_stderr_tee --> post_b2_preflight
post_post_b2_preflight --> post_b3_isactive
post_post_b3_isactive --> post_b4_jitter
post_post_b4_jitter --> post_b5_conductor_pre
post_post_b5_conductor_pre --> post_b5b_rag
post_post_b5b_rag --> post_b5c_backstory
post_post_b5c_backstory --> post_b5d_worldctx
post_post_b5d_worldctx --> post_b6_arbiter
post_post_b6_arbiter -->|post in eligible_types| post_b7_oqb
post_post_b7_oqb --> post_b8_claim
post_post_b8_claim --> post_b8b_reclaim
post_post_b8b_reclaim --> post_d1_auth
post_post_d1_auth --> post_d2_draft
post_post_d2_draft --> post_d2f_rhetorical_classify
post_post_d2f_rhetorical_classify --> post_d2g_voicev2_inject
post_post_d2g_voicev2_inject --> post_d2b_imggen
post_post_d2b_imggen -->|image_post only| post_d2c_imgupload
post_post_d2c_imgupload --> post_d2d_inject
post_post_d2d_inject --> post_d2e_circuit
post_post_d2e_circuit --> post_d3_grounding
post_post_d3_grounding --> post_d4_voice
post_post_d4_voice --> post_d5_opener
post_post_d5_opener --> post_d5b_opener_softship
post_post_d5b_opener_softship --> post_d6_slop
post_post_d6_slop --> post_d6b_construction
post_post_d6b_construction --> post_d6c_dispatch_gate
post_post_d6c_dispatch_gate --> post_d7_publish
post_post_d7_publish --> post_d8_log
post_post_d8_log --> post_d9_frame_hook
post_post_a1_signals --> post_a2_score
post_post_a2_score --> post_a3_reward
post_post_a3_reward --> post_a3h_experiment_attr
post_post_a3h_experiment_attr --> post_a3i_belief_update
post_post_a3i_belief_update --> post_a3b_experiment
post_post_a3b_experiment --> post_a3c_strat_save
post_post_a3c_strat_save --> post_a3d_voice_prop
post_post_a3d_voice_prop --> post_a3e_gov
post_post_a3e_gov --> post_a3f_snapshot
post_post_a3f_snapshot --> post_a3g_health
post_post_a3g_health --> post_a4_conductor_post
Step
What it does (plain language)
Status
If broken, what's lost
Step
What it does
Status
If broken
Systemd timer fires
persona-engine.timer → run-cycle.sh
AMBER⚠ no evidence
Cycle stderr live-tee (observability)
run-cycle.sh:1307-1316 — F7 tee's the whole V4-session stderr to journald live instead of buffering it until session end
GREENprobeDuring a long-running V4 session (>10min), 'ssh claudebot@respiro-vps journalctl -u persona-engine.service -f' should show stderr lines appearing in real time (not a silent gap followed by a burst at session end). Cross-check /tmp/pe-cycle-stderr.<persona>-*.log exists and rotation keeps only the 5 newest files.
Qdrant vector search — 7 passages for posts + comment-tone; platform/knowledge/rag-fetch.sh. AUDIT-NEWFORMAT-PIPELINE-01 (E2E-PIPELINE-STATUS.md) 2026-07-01: rag-inject re-checked AMBER — original probe's RED verdict was FALSIFIED on its central claim (success marker does fire); narrower real gap found: run-cycle.sh:~1250-1252 tail -300 $_crash_stderr_tmp truncates full per-cycle stderr before journald, obscuring RAG failures + v4-runner.sh interaction. No dedicated nodes[] entry exists for rag-inject — recorded here on the flow step only.
GREENprobessh claudebot@respiro-vps 'journalctl -u persona-engine.service --since "24 hours ago" -o cat -g rag.fetch\|world.context' shows both scripts invoked per cycle AND action_log.context for a subsequent draft contains a Qdrant-sourced passage or world-news snippet distinguishable from static prompt boilerplate.
Backstory / timeline
build-persona-timeline.sh — PERSONA_TIMELINE injected into prompt; DB-backed persona_timeline + story arcs
AMBERprobessh claudebot@respiro-vps 'find /home/claudebot/persona-engine/agent -name persona-timeline-respiro-brand-*.md | head -1' returns a file AND stat of that file shows mtime within 48h AND action_log.context contains PERSONA_TIMELINE with post count matching current action_log count by slug respiro-brand
Real-world context
fetch-world-news.sh → world-news-search.sh (RSS→Qdrant); PE_WORLD_CONTEXT_RAG_ENABLED flag
GREENprobessh claudebot@respiro-vps 'journalctl -u persona-engine.service --since "24 hours ago" -o cat -g rag.fetch\|world.context' shows both scripts invoked per cycle AND action_log.context for a subsequent draft contains a Qdrant-sourced passage or world-news snippet distinguishable from static prompt boilerplate.
GREENprobecurl '$SUPABASE_URL/rest/v1/arbiter_decisions?select=persona_id,eligible_types,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 2h' returns >=1 row with non-empty eligible_types (proves arbiter is running and writing explainability journal in prod)
Opportunity queue built
platform/operator/opportunity-queue-builder.sh
GREENprobecurl '$SUPABASE_URL/rest/v1/opportunity_candidates?select=created_at,wellness_pillar,niche_match_count&persona_id=eq.respiro-brand&run_mode=eq.prod&created_at=gte.NOW()-interval 48h' returns >=200 rows with >=10 distinct wellness_pillar values within 48h
Claim next opportunity (CAS lock)
opportunity-queue-builder.sh — atomic claim
GREENprobecurl '$SUPABASE_URL/rest/v1/opportunity_candidates?select=claimed_at,status&persona_id=eq.respiro-brand&status=eq.claimed&claimed_at=gte.NOW()-interval 2h' returns >=1 row with claimed_at matching a corresponding action_log 'post approved' event by slug within same minute
Stuck-approved reclaim sweep
run-cycle.sh stuck-approved sweeper — reclaims rows orphaned in status=approved past an 80-min age guard (any status_reason, not just auto-approved*); never double-publishes (gates on context.media_id IS NULL)
REDprobecurl '$SUPABASE_URL/rest/v1/action_log?select=id,status,status_reason,context,created_at&persona_id=eq.respiro-brand&status=eq.approved&created_at=lt.NOW()-interval 30min' — PASS if this returns 0 rows over a multi-day window (nothing stays stuck past the age guard) OR if a formerly-stuck row transitions to status=blocked with context.media_id still null (proves the sweeper resolved it without double-publishing).
Auth pre-publish gate
platform/adapters/threads/auth-refresh.sh. AUDIT-NEWFORMAT-PIPELINE-01 (E2E-PIPELINE-STATUS-PART2.md) 2026-07-01: auth-transport re-run by slug ~10min after original probe — GENUINE BUSINESS PROOF: real publish 2026-07-01T00:53:54Z, image_post status=live, real graphql-verified comment. No RED root; Threads auth/transport confirmed healthy end-to-end. No dedicated nodes[] entry exists for auth-transport — recorded here on the flow step; kept AMBER at node_style pending a formal nodes[] entry, but this is the one audit item with an actual media_id-backed outcome.
GREENprobessh claudebot@respiro-vps 'journalctl -u persona-engine.service --since "24 hours ago" -o cat -g auth-refresh' shows the script invoked AND a subsequent publish call in the same cycle succeeds (context.media_id non-null) by slug respiro-brand — proves the gate ran and did not silently fail-open.
LLM draft generated — content-studio (3-candidate) vs llm-draft-post (V4 single) — OPEN QUESTION
v4-runner.sh — GLM backend via llm-client.sh. MAP-COVERAGE-APPLY-01 (2026-07-02): two real, distinct draft architectures exist in-repo — platform/operator/content-studio.sh (3-candidate generate+rank+gate) and this V4 single-draft path. Which one actually fires for respiro-brand today is an OPEN QUESTION not resolved this pass — do NOT assert either as canonical; see new node content-studio (AMBER) for the runtime check needed.
GREENprobecurl '$SUPABASE_URL/rest/v1/voice_persona_v2?select=voice_v2_status,style_axes&persona_id=eq.respiro-brand' returns >=1 row with voice_v2_status=active AND style_axes non-null (8 dims) AND curl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,created_at&persona_id=eq.respiro-brand&action_type=eq.post&run_mode=eq.prod&created_at=gte.2026-06-26T22:00:00Z' returns >=1 row with non-null media_id (proves >=1 published post with V2 voice active)
Image generation
image_post action_type only: FAL (Kontext/FLUX) via _ra_image_fal_generate; degrades to text_only_post on failure. AUDIT-NEWFORMAT-PIPELINE-01 (E2E-PIPELINE-STATUS-PART2.md) 2026-07-01: UNCONFIRMED this wave — probe evidence field was literally 'test' (placeholder), NOT independently re-verified. Treat as unconfirmed AMBER; re-probe before relying on it. No dedicated nodes[] entry exists for image-gen — recorded here on the flow step only.
AMBER⚠ no evidence
Image upload
sb_upload_persona_image → threads_post_image; NO-TRAFFIC — never reached when generation fails
AMBER⚠ no evidence
Safety — injection scan
Prompt injection scan on draft inputs; adjacent to grounding gate
GREENprobessh claudebot@respiro-vps 'journalctl -u persona-engine.service --since "48 hours ago" -o cat -g injection.scan' shows the scanner invoked on every draft AND at least one synthetic-injection test case (feed content with a known injection pattern) is rejected before reaching the LLM prompt — currently unverified in either direction.
Circuit breaker
Stops publishing if too many consecutive failures; 0 circuit_open rows ever fired
GREENprobecurl '$SUPABASE_URL/rest/v1/circuit_breaker_state?select=*&persona_id=eq.respiro-brand' (or equivalent table per script) returns a row showing the breaker has been evaluated recently (updated_at within 48h) AND a synthetic/observed failure-burst test shows it transitions to open at the documented threshold — currently 0 rows/evidence of either state.
AMBERprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context,created_at&persona_id=eq.respiro-brand&action_type=eq.grounding_check&created_at=gte.NOW()-interval 14d' by slug returns >=1 row with layer2_verdict=block OR layer1_hits>0 (proves gate is actively blocking, not just counting)
Safety gate — voice check
voice-check.sh — redraft_trace written to action_log
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>redraft_trace,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 48h' by slug returns >=5 rows with non-null redraft_trace containing check=critique (NOT eval_log table — that table is wrong)
Safety gate — opener quality
post-gate.sh — saturation D4 checks
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>status_reason,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 7d' by slug returns >=1 row with status_reason=opener_type_saturated (proves saturation gate has actually blocked a post, not just wired)
Opener soft-ship at publish gate
agent-tool Guard C — downgrades opener-family BLOCKED to WARN for post/image_post ONLY when it is the sole blocking rule; refuses (fail-closed) when a non-opener rule co-fires; F1 logs refusal+co-firing rule to context.opener_soft_ship
AMBERprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>opener_soft_ship,created_at&persona_id=eq.respiro-brand&action_type=eq.post&created_at=gte.NOW()-interval 7d' by slug — look for context.opener_soft_ship.refused=true rows and inspect blocked_by[] to identify the co-firing gate; separately confirm >=1 published post (context.media_id) that previously would have hard-blocked on opener_repetition alone.
AMBERprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>judge_result,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 48h' by slug returns >=1 row with non-null judge_result containing verdict=clearly_ai that was actually blocked (not just logged)
Construction-monotony check
unified fingerprint (family_fp/exact_fp/formula) — post-gate.sh, flag PE_CONSTRUCTION_UNIFIED=1; CHECK-ONLY here, window append happens at confirmed publish
AMBERprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>status_reason,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 14d' by slug — PASS on first live occurrence of status_reason=construction_repetition (or equivalent block reason) tied to a real repeat draft, proving the gate fires in production traffic, not just replay.
Dispatch-time post-gate recheck (G0)
v4-runner.sh (~:8785) — second independent post-gate.sh pass in PE_POST_GATE_CHECK_ONLY=1 check-only mode immediately before the Threads publish call; rc=7 blocks without writing history/sidecar state; closes the draft-time-to-dispatch-time drift window (BATCH2 378d9289)
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>status_reason,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 7d' by slug — PASS on first live occurrence of a dispatch-time block distinct from the original draft-time gate block (proves G0 recheck fired independently, not just the draft-time gate).
Publish Path A or B
platform/adapters/threads/api.sh or browser — Threads Graph API / mobile
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,created_at&persona_id=eq.respiro-brand&action_type=eq.publish_post&created_at=gte.NOW()-interval 48h' by slug returns >=2 rows with DISTINCT non-null media_id values (numeric Threads media IDs, NOT status=eq.confirmed filter)
AMBERprobecurl '$SUPABASE_URL/rest/v1/voice_recency_frames?select=frame_text,created_at&persona_id=eq.respiro-brand&created_at=gte.2026-06-26T22:00:00Z&order=created_at.desc&limit=5' returns >=1 row with non-null frame_text (proves hook fired after a V2-era publish AND haiku wrote the frame to close the angle-diversity loop)
Signal collection (4h delay)
auto-collect-signals.sh
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>reply_count,scored_at&persona_id=eq.respiro-brand&action_type=eq.score_comment&scored_at=gte.NOW()-interval 48h' by slug returns >=5 rows with VARYING reply_count values (not all same integer = proves real engagement collection not counter-only)
Score action
auto-score.sh
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>score,scored_at&persona_id=eq.respiro-brand&scored_at=gte.NOW()-interval 48h&scored_at=not.is.null' by slug returns >=5 rows with VARYING score values (at least 2 distinct scores = proves real scoring not stuck counter)
Composite reward + bandit update
auto-composite-reward.sh → auto-bandit.sh
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
Experiment attribution write (P1-B-1 — RED)
experiment_applications write path — decrement actions_taken/actions_scored on active experiment row after post publish+score; currently RED: actions_taken=0 despite 2 published posts; attribution path undefined or unwired
AMBERprobecurl '$SUPABASE_URL/rest/v1/experiments?select=status,concluded_at&persona_id=eq.respiro-brand' by slug returns >=1 row with status=concluded_supported (proves experiment lifecycle completes successfully, not stuck in proposed/running)
Belief update trigger (P1-B-2 — RED)
beliefs table write on publish+score signal — belief_attribution trigger; currently RED: beliefs table 6d stale (last 2026-06-15); trigger undefined; no write path from publish event to beliefs row. BATCH2 2026-07-02 (378d9289): the 2>/dev/null swallow on the beliefs-attribution RPC call was removed (strategist-daily.sh:1050, strategist-weekly.sh:590, generate-reports.sh:428) — errors now surface as WARN instead of being silently hidden, but the write path itself is still unproven; stays amber/RED-labeled pending a live occurrence
AMBERprobeAfter FIX-BELIEFS-INJECT-AWK-EARLYEXIT-01 ships: curl '$SUPABASE_URL/rest/v1/action_log?select=context->>draft,created_at&persona_id=eq.respiro-brand&action_type=eq.post&created_at=gte.NOW()-interval 48h' shows draft text containing a belief-sourced phrase traceable to a beliefs row (proves injection reaches the LLM, not just fetch) AND beliefs table has >=1 fresh row within 48h
Experiment eval
Tests content variants vs baseline; 56/192 concluded_refuted with lift_pct; platform/learning/experiment-eval.sh
AMBERprobecurl '$SUPABASE_URL/rest/v1/experiments?select=status,concluded_at&persona_id=eq.respiro-brand' by slug returns >=1 row with status=concluded_supported (proves experiment lifecycle completes successfully, not stuck in proposed/running)
Strategist briefing saved
Writes today's learned patterns for tomorrow's strategist; platform/learning/strategist-write.sh
GREENprobeAfter FIX-STRATEGIST-PILLAR-SLUG-BACKFILL-01 ships: curl '$SUPABASE_URL/rest/v1/personas?select=config->pillars&handle=eq.respiro-brand' shows every pillar object with a non-null .slug key AND a subsequent strategist-daily.sh run's daily_plan.pillar_weights is non-empty (proves selection no longer degrades to fallback)
Voice evolution proposal
Proposes voice changes based on what worked; strategy_proposals table; PROVEN LIVE 2026-06-12
AMBER⚠ no evidence
Governance applier
apply_approved_proposals in run-cycle.sh; applies approved strategy+voice changes; RC1 FIXED 2026-06-02
GREENprobecurl '$SUPABASE_URL/rest/v1/voice_dna_versions?select=proposal_id,created_at&persona_id=eq.respiro-brand' returns >=1 row with non-null proposal_id (proves audit trail intact and BA-6 fixed — proposal_id=null means backup writes failing). NOTE: this only certifies the voice_change path — see governance-appliers-fanout for the other 4 proposal types.
Daily snapshot
Records follower count + engagement metrics; health_snapshot table
AMBER⚠ no evidence
Autopilot health check
Detects health breaches + spawns self-repair agent; health_snapshot table; deploy key read-only so fixes not shipped
GREENprobessh claudebot@respiro-vps 'systemctl list-timers | grep -i invariant' to resolve the naming discrepancy, THEN 'journalctl -u persona-stability-autopilot.service --since "24 hours ago" -o cat' shows at least one invariant-breach evaluation cycle AND, on a real breach, a self-repair agent spawn log line.
2026-07-04: BROKEN — comment-recency-frames: BROKEN confirmed (independently, not via prober's log): write-hook _comment_v2_record_frame never fires — no /tmp/comment-voice-v2.log despite ~100 comments reaching learned since 6/27.
A comment posted on someone else's Threads post — the engagement arm.
%%{init: {"theme": "dark", "themeVariables": {"primaryColor": "#161b22", "primaryBorderColor": "#30363d", "edgeLabelBackground": "#1c2128", "tertiaryColor": "#161b22", "fontSize": "11px"}, "flowchart": {"nodeSpacing": 18, "rankSpacing": 26, "wrap": true, "htmlLabels": true}}}%%
flowchart TD
classDef green fill:#161b22,stroke:#3fb950,stroke-width:2px,color:#e6edf3
classDef amber fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3
classDef red fill:#161b22,stroke:#f85149,stroke-width:2px,color:#e6edf3
classDef dead fill:#161b22,stroke:#6e7681,stroke-width:1px,color:#8b949e,stroke-dasharray:5 3
classDef notraffic fill:#161b22,stroke:#7c5a00,stroke-width:2px,color:#e6edf3
classDef unprobed fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3,stroke-dasharray:4 3
subgraph BEFORE["BEFORE — Setup and intelligence"]
comment_cmt_b1_conductor_pre["⚠ Cycle-conductor pre-maintenance platform/operator/cycle-conductor.sh — strategist (CYCLE-CONDUCTOR-01)"]:::unprobed
comment_cmt_b2_arbiter["Action arbiter (per-type due gate) platform/operator/action-arbiter.sh — comment in eligible_types CSV"]:::green
comment_cmt_b3_feed["Discovery / feed scan scan-feed.sh + profile_scan — home_feed candidates"]:::green
comment_cmt_b3b_ontology_screen["Ontology keyword screen (P1-C-1) candidate-screen.sh _sf_niche_match_count — niche keyword match + Supabase hit-counter increment; currently split-brain dead-data (local JSON only, DB never written)"]:::amber
comment_cmt_b4_screen["Candidate screen (7-rule filter) candidate-screen.sh — off_niche/low_eng/media_blocked gates"]:::green
comment_cmt_b5_queue["Opportunity queue builder platform/operator/opportunity-queue-builder.sh"]:::green
comment_cmt_b6_claim["Claim next opportunity (CAS lock) claim_next_opportunity — atomic claim with action_id"]:::green
comment_cmt_b6b_sweep_anchor["Planned-row sweeper anchor fix orphan-recovery.sh recover_recent_planned/recover_stale_planned + opportunity-queue-builder.sh cleanup_stuck_planned_actions — now honor offhours_draft_deferred before reclaiming; action-log.sh _pe_payload_empty uses a metadata-anchor discriminator (has("target_url")) for comments instead of blanket-rejecting (FIX-EMPTY-PAYLOAD-COMMENT-ANCHOR-01, cb88d0d6)"]:::green
comment_cmt_b_peer_deprecated["Peer 2nd-degree discovery (REMOVED) REMOVED anti-ban 1aa96b7c — Playwright auth fail"]:::dead
end
subgraph DURING["DURING — Draft, gate, publish"]
comment_cmt_d1_draft["LLM draft — comment v4-runner.sh — Thompson draw selects comment_style"]:::green
comment_cmt_d1b_style_attribution["Comment style attribution (P1-A-1 — RED) v4-runner.sh — ACTION_ID export before assemble-prompt.sh; sb_merge_jsonb write of selected_comment_style; currently broken: ACTION_ID not exported, guard 2>/dev/null silently skips, metadata.comment_style=null on all recent rows"]:::green
comment_cmt_d2_voice["Safety gate — voice check voice-check.sh"]:::green
comment_cmt_d3_opener["Safety gate — opener quality post-gate.sh — QUOTE_OPEN Tier B gate"]:::green
comment_cmt_d3b_construction["Construction-monotony check unified fingerprint (family_fp/exact_fp/formula) — post-gate.sh, flag PE_CONSTRUCTION_UNIFIED=1; comment-path coverage added in 4d398e53"]:::amber
comment_cmt_d3c_redraft_budget["Redraft time budget (600s, pending bump to 900s) V4_COMMENT_REDRAFT_BUDGET_MAX_S — real root of the comment publish 'stall' (mislabeled as topic-dedup); F4 fixed the label to session_budget_deferred, the 600->900s bump itself is a pending founder-decision env change"]:::amber
comment_cmt_d4_publish["Publish comment Path B platform/adapters/threads/browser.sh — mobile Threads"]:::green
comment_cmt_d5_log["⚠ action_log row written action-log.sh — media_id + target_author + selected_comment_style"]:::unprobed
comment_cmt_d6_frame_write["Comment voice-frame write (P1-A-3 — RED) auto-score.sh _comment_v2_record_frame subshell — haiku writes 1-sentence frame to comment_recency_frames; currently DEAD: 2>/dev/null + 8s kill silences all Haiku LLM calls; 0 new frames in 28h post-backfill"]:::red
end
subgraph AFTER["AFTER — Record, score, learn"]
comment_cmt_a1_score["Score comment auto-score.sh + auto-check-replies.sh direct-score path"]:::green
comment_cmt_a2_bandit["Comment style sub-bandit update auto-bandit.sh — feed_comment_style_bandit helper (b1385948)"]:::green
comment_cmt_a3_conductor_post["⚠ Cycle-conductor post-maintenance platform/operator/cycle-conductor.sh — eval + reflect"]:::unprobed
end
comment_cmt_b1_conductor_pre --> comment_cmt_b2_arbiter
comment_cmt_b2_arbiter -->|comment in eligible_types| comment_cmt_b3_feed
comment_cmt_b3_feed --> comment_cmt_b3b_ontology_screen
comment_cmt_b3b_ontology_screen --> comment_cmt_b4_screen
comment_cmt_b4_screen --> comment_cmt_b5_queue
comment_cmt_b5_queue --> comment_cmt_b6_claim
comment_cmt_b6_claim --> comment_cmt_b6b_sweep_anchor
comment_cmt_b6b_sweep_anchor --> comment_cmt_d1_draft
comment_cmt_d1_draft --> comment_cmt_d1b_style_attribution
comment_cmt_d1b_style_attribution --> comment_cmt_d2_voice
comment_cmt_d2_voice --> comment_cmt_d3_opener
comment_cmt_d3_opener --> comment_cmt_d3b_construction
comment_cmt_d3b_construction --> comment_cmt_d3c_redraft_budget
comment_cmt_d3c_redraft_budget --> comment_cmt_d4_publish
comment_cmt_d4_publish --> comment_cmt_d5_log
comment_cmt_d5_log --> comment_cmt_d6_frame_write
comment_cmt_a1_score --> comment_cmt_a2_bandit
comment_cmt_a2_bandit --> comment_cmt_a3_conductor_post
platform/operator/action-arbiter.sh — comment in eligible_types CSV
GREENprobecurl '$SUPABASE_URL/rest/v1/arbiter_decisions?select=persona_id,eligible_types,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 2h' returns >=1 row with non-empty eligible_types (proves arbiter is running and writing explainability journal in prod)
GREENprobecurl '$SUPABASE_URL/rest/v1/feed_posts?select=is_viral,scanned_at&persona_id=eq.respiro-brand&is_viral=eq.true&scanned_at=gte.NOW()-interval 48h' returns >=10 rows (proves viral detection wired in live scan, not just backfill) AND curl opportunity_candidates source_type=home_feed returns >=50 distinct author_handle values within 48h AND VPS RUN_MODE=prod
Ontology keyword screen (P1-C-1)
candidate-screen.sh _sf_niche_match_count — niche keyword match + Supabase hit-counter increment; currently split-brain dead-data (local JSON only, DB never written)
AMBERprobecurl '$SUPABASE_URL/rest/v1/persona_niche_keywords?select=keyword,hits_total,last_hit_at&persona_id=eq.respiro-brand&hits_total=gt.0' returns >=10 rows with non-zero hits_total AND last_hit_at within 24h (proves DB read path live + hit counters incrementing)
GREENprobecurl '$SUPABASE_URL/rest/v1/opportunity_candidates?select=policy_reasons,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 24h' returns >=100 rows with varied policy_reasons (not all same value) AND at least 3 distinct reject reason types within 24h
Opportunity queue builder
platform/operator/opportunity-queue-builder.sh
GREENprobecurl '$SUPABASE_URL/rest/v1/opportunity_candidates?select=created_at,wellness_pillar,niche_match_count&persona_id=eq.respiro-brand&run_mode=eq.prod&created_at=gte.NOW()-interval 48h' returns >=200 rows with >=10 distinct wellness_pillar values within 48h
Claim next opportunity (CAS lock)
claim_next_opportunity — atomic claim with action_id
GREENprobecurl '$SUPABASE_URL/rest/v1/opportunity_candidates?select=claimed_at,status&persona_id=eq.respiro-brand&status=eq.claimed&claimed_at=gte.NOW()-interval 2h' returns >=1 row with claimed_at matching a corresponding action_log 'post approved' event by slug within same minute
Planned-row sweeper anchor fix
orphan-recovery.sh recover_recent_planned/recover_stale_planned + opportunity-queue-builder.sh cleanup_stuck_planned_actions — now honor offhours_draft_deferred before reclaiming; action-log.sh _pe_payload_empty uses a metadata-anchor discriminator (has("target_url")) for comments instead of blanket-rejecting (FIX-EMPTY-PAYLOAD-COMMENT-ANCHOR-01, cb88d0d6)
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>status_reason,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 48h' by slug — PASS if empty_payload_rejected count stays flat (no new rows) over a full multi-day window post-deploy AND >=1 comment row that would previously have been mislabeled empty_payload now proceeds past the sweeper with status_reason=offhours_draft_deferred instead.
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,context->>draft&persona_id=eq.respiro-brand&action_type=eq.publish_comment&created_at=gte.NOW()-interval 48h' returns >=10 DISTINCT media_id values AND >=3 distinct comment_style values by slug respiro-brand
Comment style attribution (P1-A-1 — RED)
v4-runner.sh — ACTION_ID export before assemble-prompt.sh; sb_merge_jsonb write of selected_comment_style; currently broken: ACTION_ID not exported, guard 2>/dev/null silently skips, metadata.comment_style=null on all recent rows
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
Safety gate — voice check
voice-check.sh
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>redraft_trace,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 48h' by slug returns >=5 rows with non-null redraft_trace containing check=critique (NOT eval_log table — that table is wrong)
Safety gate — opener quality
post-gate.sh — QUOTE_OPEN Tier B gate
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>status_reason,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 7d' by slug returns >=1 row with status_reason=opener_type_saturated (proves saturation gate has actually blocked a post, not just wired)
Construction-monotony check
unified fingerprint (family_fp/exact_fp/formula) — post-gate.sh, flag PE_CONSTRUCTION_UNIFIED=1; comment-path coverage added in 4d398e53
AMBERprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>status_reason,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 14d' by slug — PASS on first live occurrence of status_reason=construction_repetition (or equivalent block reason) tied to a real repeat draft, proving the gate fires in production traffic, not just replay.
Redraft time budget (600s, pending bump to 900s)
V4_COMMENT_REDRAFT_BUDGET_MAX_S — real root of the comment publish 'stall' (mislabeled as topic-dedup); F4 fixed the label to session_budget_deferred, the 600->900s bump itself is a pending founder-decision env change
AMBERprobeAfter deploy: curl '$SUPABASE_URL/rest/v1/action_log?select=context->>status_reason,created_at&persona_id=eq.respiro-brand&action_type=eq.comment&created_at=gte.NOW()-interval 24h' by slug — PASS if session_budget_deferred (not runner_topic_dedup_deferred) is the label on redraft-timeout defers, AND (once V4_COMMENT_REDRAFT_BUDGET_MAX_S=900 is live) comment publish rate holds or improves vs pre-bump baseline.
Publish comment Path B
platform/adapters/threads/browser.sh — mobile Threads
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,created_at&persona_id=eq.respiro-brand&action_type=eq.publish_post&created_at=gte.NOW()-interval 48h' by slug returns >=2 rows with DISTINCT non-null media_id values (numeric Threads media IDs, NOT status=eq.confirmed filter)
auto-score.sh _comment_v2_record_frame subshell — haiku writes 1-sentence frame to comment_recency_frames; currently DEAD: 2>/dev/null + 8s kill silences all Haiku LLM calls; 0 new frames in 28h post-backfill
REDprobecurl '$SUPABASE_URL/rest/v1/comment_recency_frames?select=frame_text,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 24h' returns >=3 rows with non-null frame_text created AFTER fix ships (proves hook survives kill + writes frames on live comment publish)
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>score,scored_at&persona_id=eq.respiro-brand&scored_at=gte.NOW()-interval 48h&scored_at=not.is.null' by slug returns >=5 rows with VARYING score values (at least 2 distinct scores = proves real scoring not stuck counter)
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
2026-07-04: AMBER — llm-draft-reply: DEPLOYED-UNPROBED confirmed: action_type is "reply" not "publish_reply" (prober's query name was wrong, correcting it changes nothing).
A reply to someone who commented on the persona's post or to a comment the persona left.
platform/operator/action-arbiter.sh — reply in eligible_types
GREENprobecurl '$SUPABASE_URL/rest/v1/arbiter_decisions?select=persona_id,eligible_types,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 2h' returns >=1 row with non-empty eligible_types (proves arbiter is running and writing explainability journal in prod)
auto-check-replies scan
auto-check-replies.sh — reads own_comment_url
AMBER⚠ no evidence
pending_replies queue
build_opportunity_queue — reply slots from pending_replies table
AMBER⚠ no evidence
LLM draft — reply
v4-runner.sh
AMBERprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>draft,context->>media_id,run_mode&persona_id=eq.respiro-brand&action_type=eq.publish_reply&run_mode=eq.prod' returns >=1 row with non-empty draft text (NOT status=eq.expired filter — status=expired hides real LLM drafts)
Safety and voice gate
pre-execute.sh + voice-check.sh
AMBERprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context,created_at&persona_id=eq.respiro-brand&action_type=eq.grounding_check&created_at=gte.NOW()-interval 14d' by slug returns >=1 row with layer2_verdict=block OR layer1_hits>0 (proves gate is actively blocking, not just counting)
Publish reply Path B
platform/adapters/threads/browser.sh
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,created_at&persona_id=eq.respiro-brand&action_type=eq.publish_post&created_at=gte.NOW()-interval 48h' by slug returns >=2 rows with DISTINCT non-null media_id values (numeric Threads media IDs, NOT status=eq.confirmed filter)
action_log row written
action-log.sh
AMBER⚠ no evidence
Score reply
auto-score.sh
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>score,scored_at&persona_id=eq.respiro-brand&scored_at=gte.NOW()-interval 48h&scored_at=not.is.null' by slug returns >=5 rows with VARYING score values (at least 2 distinct scores = proves real scoring not stuck counter)
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>reply_count,scored_at&persona_id=eq.respiro-brand&action_type=eq.score_comment&scored_at=gte.NOW()-interval 48h' by slug returns >=5 rows with VARYING reply_count values (not all same integer = proves real engagement collection not counter-only)
GREENprobeAfter FIX-STRATEGIST-PILLAR-SLUG-BACKFILL-01 ships: curl '$SUPABASE_URL/rest/v1/personas?select=config->pillars&handle=eq.respiro-brand' shows every pillar object with a non-null .slug key AND a subsequent strategist-daily.sh run's daily_plan.pillar_weights is non-empty (proves selection no longer degrades to fallback)
F1 — Successful-day detector (UNSHIPPED)
reactive_trigger_queue — P13 not shipped; 0 rows ever. CROSS-REF (MAP-COVERAGE-APPLY-01): do not confuse with the drift-detector node (platform/eval/drift-detector.sh, DEPLOYED-UNPROBED) — that is a DIFFERENT, real, already-running module (D1-D4 voice/perf drift, daily cadence). This step is the unshipped 'successful-day' trigger, unrelated code.
AMBER⚠ no evidence
F2 — Voice proposal saved
strategist-daily.sh writes voice_change to strategy_proposals
GREENprobecurl '$SUPABASE_URL/rest/v1/voice_dna_versions?select=proposal_id,created_at&persona_id=eq.respiro-brand' returns >=1 row with non-null proposal_id (proves audit trail intact and BA-6 fixed — proposal_id=null means backup writes failing). NOTE: this only certifies the voice_change path — see governance-appliers-fanout for the other 4 proposal types.
F2 — Voice applier executes
auto-voice-applier.sh — PROVEN LIVE 2026-06-12 01:24Z
GREENprobecurl '$SUPABASE_URL/rest/v1/voice_dna_versions?select=proposal_id,created_at&persona_id=eq.respiro-brand' returns >=1 row with non-null proposal_id (proves audit trail intact and BA-6 fixed — proposal_id=null means backup writes failing). NOTE: this only certifies the voice_change path — see governance-appliers-fanout for the other 4 proposal types.
F3 — weight_learning_log writer
auto-composite-reward.sh — 422 rows live
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
F4 — auto-bandit arm reweight
auto-bandit.sh — 10 arms; SWH 6 rows since Jun 8
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
F4 — Opp-scorer reads bandit arms
PE_BANDIT_VALUE_WEIGHT=0.20 ENABLED 2026-06-10
GREENprobecurl '$SUPABASE_URL/rest/v1/opportunity_candidates?select=created_at,wellness_pillar,niche_match_count&persona_id=eq.respiro-brand&run_mode=eq.prod&created_at=gte.NOW()-interval 48h' returns >=200 rows with >=10 distinct wellness_pillar values within 48h
F5 — _os_score boost active
85 rows with learning_value; boost active since env_overrides v104
GREENprobecurl '$SUPABASE_URL/rest/v1/opportunity_candidates?select=created_at,wellness_pillar,niche_match_count&persona_id=eq.respiro-brand&run_mode=eq.prod&created_at=gte.NOW()-interval 48h' returns >=200 rows with >=10 distinct wellness_pillar values within 48h
2026-07-04: VERIFIED — all 4 linked nodes verified 2026-07-04
Intel injection into the LLM prompt: call sites + budget gates (7a), post profile sections (7b), comment/reply sections (7c).
%%{init: {"theme": "dark", "themeVariables": {"primaryColor": "#161b22", "primaryBorderColor": "#30363d", "edgeLabelBackground": "#1c2128", "tertiaryColor": "#161b22", "fontSize": "11px"}, "flowchart": {"nodeSpacing": 18, "rankSpacing": 26, "wrap": true, "htmlLabels": true}}}%%
flowchart TD
classDef green fill:#161b22,stroke:#3fb950,stroke-width:2px,color:#e6edf3
classDef amber fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3
classDef red fill:#161b22,stroke:#f85149,stroke-width:2px,color:#e6edf3
classDef dead fill:#161b22,stroke:#6e7681,stroke-width:1px,color:#8b949e,stroke-dasharray:5 3
classDef notraffic fill:#161b22,stroke:#7c5a00,stroke-width:2px,color:#e6edf3
classDef unprobed fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3,stroke-dasharray:4 3
subgraph BEFORE["BEFORE — Setup and intelligence"]
draft_intel_di_b1_arbiter["Action arbiter (per-type due gate) platform/operator/action-arbiter.sh — determines action type before intel assembly"]:::green
end
subgraph DURING["DURING — Draft, gate, publish"]
draft_intel_di_d1_callsite["v4_runner_draft call site v4-runner.sh — v4di_inject_draft_intel called before session intel"]:::green
draft_intel_di_d2_budget["⚠ Budget gate (32k total / 6.8k intel) intel-blocks.sh — BG2 + BG1 byte caps"]:::unprobed
draft_intel_di_d3_profiles["Per-action-type profiles injected intel-blocks.sh — BANDIT_ALLOC/BANDIT_REC/WLL_FORMAT/PILLAR_FORCE/LANGUAGE_DIRECTIVE"]:::green
draft_intel_di_d3b_voice_v2["Voice V2 block prepended (FU-VOICE-ANGLE-DIVERSITY-01) _v4_load_voice_v2_or_fallback — brand_description + style_axes + recency_frames prohibitions; few-shot examples removed (PE_VOICE_V2=1, respiro active 2026-06-26)"]:::green
draft_intel_di_d4_llm["LLM call with enriched prompt v4-runner.sh — _v4_inject_session_intel lands last"]:::green
draft_intel_di_b_legacy_assemble["assemble-prompt.sh (DEAD) LEGACY — not used by respiro-brand V4 path"]:::dead
end
draft_intel_di_b1_arbiter --> draft_intel_di_d1_callsite
draft_intel_di_d1_callsite --> draft_intel_di_d2_budget
draft_intel_di_d2_budget --> draft_intel_di_d3_profiles
draft_intel_di_d3_profiles --> draft_intel_di_d3b_voice_v2
draft_intel_di_d3b_voice_v2 --> draft_intel_di_d4_llm
Component
Detail
Status
Step
What it does
Status
If broken
Action arbiter (per-type due gate)
platform/operator/action-arbiter.sh — determines action type before intel assembly
GREENprobecurl '$SUPABASE_URL/rest/v1/arbiter_decisions?select=persona_id,eligible_types,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 2h' returns >=1 row with non-empty eligible_types (proves arbiter is running and writing explainability journal in prod)
v4_runner_draft call site
v4-runner.sh — v4di_inject_draft_intel called before session intel
GREENprobeAfter FIX-STRATEGIST-PILLAR-SLUG-BACKFILL-01 ships: curl '$SUPABASE_URL/rest/v1/personas?select=config->pillars&handle=eq.respiro-brand' shows every pillar object with a non-null .slug key AND a subsequent strategist-daily.sh run's daily_plan.pillar_weights is non-empty (proves selection no longer degrades to fallback)
GREENprobecurl '$SUPABASE_URL/rest/v1/voice_persona_v2?select=voice_v2_status,style_axes&persona_id=eq.respiro-brand' returns >=1 row with voice_v2_status=active AND style_axes non-null (8 dims) AND curl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,created_at&persona_id=eq.respiro-brand&action_type=eq.post&run_mode=eq.prod&created_at=gte.2026-06-26T22:00:00Z' returns >=1 row with non-null media_id (proves >=1 published post with V2 voice active)
LLM call with enriched prompt
v4-runner.sh — _v4_inject_session_intel lands last
2026-07-04: VERIFIED — all 4 linked nodes verified 2026-07-04
Thompson-sampling bandit for comment_style arm selection — wired post-DIAG-COMMENT-SCORING-THROUGHPUT-01 (b1385948).
%%{init: {"theme": "dark", "themeVariables": {"primaryColor": "#161b22", "primaryBorderColor": "#30363d", "edgeLabelBackground": "#1c2128", "tertiaryColor": "#161b22", "fontSize": "11px"}, "flowchart": {"nodeSpacing": 18, "rankSpacing": 26, "wrap": true, "htmlLabels": true}}}%%
flowchart LR
classDef green fill:#161b22,stroke:#3fb950,stroke-width:2px,color:#e6edf3
classDef amber fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3
classDef red fill:#161b22,stroke:#f85149,stroke-width:2px,color:#e6edf3
classDef dead fill:#161b22,stroke:#6e7681,stroke-width:1px,color:#8b949e,stroke-dasharray:5 3
classDef notraffic fill:#161b22,stroke:#7c5a00,stroke-width:2px,color:#e6edf3
classDef unprobed fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3,stroke-dasharray:4 3
subgraph BEFORE["BEFORE — Setup and intelligence"]
comment_subbandit_csb_b1_arbiter["Arbiter — comment eligible platform/operator/action-arbiter.sh — comment in _PE_ELIGIBLE_TYPES"]:::green
end
subgraph DURING["DURING — Draft, gate, publish"]
comment_subbandit_csb_d1_draw["Thompson draw — comment_style arm _v4cs_select_comment_arm — reads bandit_arms action_type=comment_style:*"]:::green
comment_subbandit_csb_d2_draft["LLM draft with selected style v4-runner.sh — style injected into prompt"]:::green
end
subgraph AFTER["AFTER — Record, score, learn"]
comment_subbandit_csb_d3_score["Comment scored (direct-score path) auto-check-replies.sh + auto-score.sh — feed_comment_style_bandit helper"]:::green
comment_subbandit_csb_a1_update["Bandit arm update bandits.sh — alpha/beta increment for selected arm"]:::green
end
comment_subbandit_csb_b1_arbiter --> comment_subbandit_csb_d1_draw
comment_subbandit_csb_d1_draw --> comment_subbandit_csb_d2_draft
comment_subbandit_csb_d2_draft --> comment_subbandit_csb_d3_score
comment_subbandit_csb_d3_score --> comment_subbandit_csb_a1_update
Step
Detail
Status
Step
What it does
Status
If broken
Arbiter — comment eligible
platform/operator/action-arbiter.sh — comment in _PE_ELIGIBLE_TYPES
GREENprobecurl '$SUPABASE_URL/rest/v1/arbiter_decisions?select=persona_id,eligible_types,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 2h' returns >=1 row with non-empty eligible_types (proves arbiter is running and writing explainability journal in prod)
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
LLM draft with selected style
v4-runner.sh — style injected into prompt
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,context->>draft&persona_id=eq.respiro-brand&action_type=eq.publish_comment&created_at=gte.NOW()-interval 48h' returns >=10 DISTINCT media_id values AND >=3 distinct comment_style values by slug respiro-brand
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>score,scored_at&persona_id=eq.respiro-brand&scored_at=gte.NOW()-interval 48h&scored_at=not.is.null' by slug returns >=5 rows with VARYING score values (at least 2 distinct scores = proves real scoring not stuck counter)
Bandit arm update
bandits.sh — alpha/beta increment for selected arm
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
5
Data Flow — Supabase Tables
2026-07-04: VERIFIED — all 6 linked nodes verified 2026-07-04
Which scripts read/write which tables. Derived from verdicts.json 2026-06-10 + SYNTHESIS.md. Only probe-confirmed tables shown.
GREENprobecurl '$SUPABASE_URL/rest/v1/feed_posts?select=is_viral,scanned_at&persona_id=eq.respiro-brand&is_viral=eq.true&scanned_at=gte.NOW()-interval 48h' returns >=10 rows (proves viral detection wired in live scan, not just backfill) AND curl opportunity_candidates source_type=home_feed returns >=50 distinct author_handle values within 48h AND VPS RUN_MODE=prod
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>reply_count,scored_at&persona_id=eq.respiro-brand&action_type=eq.score_comment&scored_at=gte.NOW()-interval 48h' by slug returns >=5 rows with VARYING reply_count values (not all same integer = proves real engagement collection not counter-only)
GREENprobeAfter FIX-STRATEGIST-PILLAR-SLUG-BACKFILL-01 ships: curl '$SUPABASE_URL/rest/v1/personas?select=config->pillars&handle=eq.respiro-brand' shows every pillar object with a non-null .slug key AND a subsequent strategist-daily.sh run's daily_plan.pillar_weights is non-empty (proves selection no longer degrades to fallback)
GREENprobecurl '$SUPABASE_URL/rest/v1/voice_dna_versions?select=proposal_id,created_at&persona_id=eq.respiro-brand' returns >=1 row with non-null proposal_id (proves audit trail intact and BA-6 fixed — proposal_id=null means backup writes failing). NOTE: this only certifies the voice_change path — see governance-appliers-fanout for the other 4 proposal types.
Blue = Supabase table. Script color = verified health of writer (green/amber/red). Edges from probe evidence + SYNTHESIS.md only — no invented tables.
6
Reward / Bandit Closure Loop
2026-07-04: VERIFIED — all 4 linked nodes verified 2026-07-04
The composite-reward to auto-bandit to opp-scorer boost chain. PE_BANDIT_VALUE_WEIGHT=0.20 ENABLED 2026-06-10.
%%{init: {"theme": "dark", "themeVariables": {"primaryColor": "#161b22", "primaryBorderColor": "#30363d", "edgeLabelBackground": "#1c2128", "tertiaryColor": "#161b22", "fontSize": "11px"}, "flowchart": {"nodeSpacing": 18, "rankSpacing": 26, "wrap": true, "htmlLabels": true}}}%%
flowchart TD
classDef green fill:#161b22,stroke:#3fb950,stroke-width:2px,color:#e6edf3
classDef amber fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3
classDef red fill:#161b22,stroke:#f85149,stroke-width:2px,color:#e6edf3
classDef dead fill:#161b22,stroke:#6e7681,stroke-width:1px,color:#8b949e,stroke-dasharray:5 3
classDef notraffic fill:#161b22,stroke:#7c5a00,stroke-width:2px,color:#e6edf3
classDef unprobed fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3,stroke-dasharray:4 3
subgraph BEFORE["BEFORE — Setup and intelligence"]
reward_bandit_rb_score["Score action (auto-score.sh) confidence floor 0.3 for comment/reply"]:::green
reward_bandit_rb_reward["Composite reward (auto-composite-reward.sh) post: zero_signal_omit; comment: cr=1.12-1.60 on got_reply"]:::green
end
subgraph DURING["DURING — Draft, gate, publish"]
reward_bandit_rb_wll["weight_learning_log written 422 rows; comment arm success rows; post arm failure-only"]:::green
reward_bandit_rb_bandit["auto-bandit.sh — arm update 10 arms; post alpha=8/beta=178; comment alpha=45/beta=318"]:::green
reward_bandit_rb_swh["scoring_weight_history written 6 rows since Jun 8; 3 domains updated Jun 09T04:04"]:::green
end
subgraph AFTER["AFTER — Record, score, learn"]
reward_bandit_rb_scorer["opp-scorer reads arms — bandit_value bandit_value=0.5 in 66 rows; PE_BANDIT_VALUE_WEIGHT=0.20 ENABLED"]:::green
reward_bandit_rb_boost["_os_score boost to claim ordering learning_value in 85 rows; boost active since env_overrides v104"]:::green
reward_bandit_rb_voice["Voice evolution — PROVEN LIVE 2026-06-12 auto-voice-applier.sh — applied_at=2026-06-12T01:24Z; voice-dna-comments.md updated"]:::green
end
reward_bandit_rb_score --> reward_bandit_rb_reward
reward_bandit_rb_reward --> reward_bandit_rb_wll
reward_bandit_rb_wll --> reward_bandit_rb_bandit
reward_bandit_rb_bandit --> reward_bandit_rb_swh
reward_bandit_rb_swh --> reward_bandit_rb_scorer
reward_bandit_rb_scorer --> reward_bandit_rb_boost
Hop
Status (2026-06-10)
Evidence
Open gap
Step
What it does
Status
If broken
Score action (auto-score.sh)
confidence floor 0.3 for comment/reply
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>score,scored_at&persona_id=eq.respiro-brand&scored_at=gte.NOW()-interval 48h&scored_at=not.is.null' by slug returns >=5 rows with VARYING score values (at least 2 distinct scores = proves real scoring not stuck counter)
Composite reward (auto-composite-reward.sh)
post: zero_signal_omit; comment: cr=1.12-1.60 on got_reply
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
weight_learning_log written
422 rows; comment arm success rows; post arm failure-only
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
auto-bandit.sh — arm update
10 arms; post alpha=8/beta=178; comment alpha=45/beta=318
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
scoring_weight_history written
6 rows since Jun 8; 3 domains updated Jun 09T04:04
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
opp-scorer reads arms — bandit_value
bandit_value=0.5 in 66 rows; PE_BANDIT_VALUE_WEIGHT=0.20 ENABLED
GREENprobecurl '$SUPABASE_URL/rest/v1/opportunity_candidates?select=created_at,wellness_pillar,niche_match_count&persona_id=eq.respiro-brand&run_mode=eq.prod&created_at=gte.NOW()-interval 48h' returns >=200 rows with >=10 distinct wellness_pillar values within 48h
_os_score boost to claim ordering
learning_value in 85 rows; boost active since env_overrides v104
GREENprobecurl '$SUPABASE_URL/rest/v1/opportunity_candidates?select=created_at,wellness_pillar,niche_match_count&persona_id=eq.respiro-brand&run_mode=eq.prod&created_at=gte.NOW()-interval 48h' returns >=200 rows with >=10 distinct wellness_pillar values within 48h
GREENprobecurl '$SUPABASE_URL/rest/v1/voice_dna_versions?select=proposal_id,created_at&persona_id=eq.respiro-brand' returns >=1 row with non-null proposal_id (proves audit trail intact and BA-6 fixed — proposal_id=null means backup writes failing). NOTE: this only certifies the voice_change path — see governance-appliers-fanout for the other 4 proposal types.
9
Post Format Suite (FEAT-POST-FORMAT-SUITE-01)
2026-07-04: AMBER — content-format-config: LYING-GREEN: config in DB/VPS matches (5 forms, 3 lengths, series=true), but ALL 23 post rows w/ selected_post_form in last 60 posts (Jul1-4) show question/short only, 0 series mentions — config never actually drives runtime variety.
Content-format selection, bandit learning, and governance loop for post_form (question/list/story/hot_take/mini_guide/thread_chain/poll) and post_length (short/medium/long). Customer controls via /settings/content; bandit optimizes within enabled set; strategist proposes shifts via governance.
%%{init: {"theme": "dark", "themeVariables": {"primaryColor": "#161b22", "primaryBorderColor": "#30363d", "edgeLabelBackground": "#1c2128", "tertiaryColor": "#161b22", "fontSize": "11px"}, "flowchart": {"nodeSpacing": 18, "rankSpacing": 26, "wrap": true, "htmlLabels": true}}}%%
flowchart TD
classDef green fill:#161b22,stroke:#3fb950,stroke-width:2px,color:#e6edf3
classDef amber fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3
classDef red fill:#161b22,stroke:#f85149,stroke-width:2px,color:#e6edf3
classDef dead fill:#161b22,stroke:#6e7681,stroke-width:1px,color:#8b949e,stroke-dasharray:5 3
classDef notraffic fill:#161b22,stroke:#7c5a00,stroke-width:2px,color:#e6edf3
classDef unprobed fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3,stroke-dasharray:4 3
subgraph BEFORE["BEFORE — Setup and intelligence"]
post_format_suite_pfs_cfg["Content format config persona_config.post_forms_enabled/post_lengths_enabled/series_enabled/polls_enabled (M1); customer toggles via /settings/content"]:::amber
post_format_suite_pfs_sidecar["Sidecar sync (.content_formats) run-agent.sh sidecar writer → safety-overrides.json .content_formats block (mirrors .visual.* pattern). VERIFIED 2026-06-24: DB→sidecar leg proven end-to-end (config-chain-proof.md) — PATCH persona_config → 35s control-sync → sidecar reflected, restored clean."]:::amber
end
subgraph DURING["DURING — Draft, gate, publish"]
post_format_suite_pfs_selector["Post format selector get_recommended_arm_constrained() in bandits.sh — Thompson sample ∩ enabled set; cold-start fallback = first allowed arm"]:::amber
post_format_suite_pfs_draft["LLM draft with form + length v4-runner.sh ~591 — form prompt-variant injected, length char-target parameterized; arms persisted to action_log.context (one read-merge-write with comment_style — N4 fix)"]:::amber
post_format_suite_pfs_publish["Publish (post / thread_chain / poll) Existing publish_post / publish_thread_chain (agent-tool:1408) / publish_poll (agent-tool:1506); per-part safety gate not bypassed"]:::green
end
subgraph AFTER["AFTER — Record, score, learn"]
post_format_suite_pfs_outcome["Outcome collection (4h delay) auto-collect-signals.sh — engagement signals; series: post_series.status=complete required for reward"]:::green
post_format_suite_pfs_autoscore["Auto-score (score ≥50 = success) auto-score.sh — composite engagement 0-100; same threshold as comment_style bandit"]:::green
post_format_suite_pfs_bandit["Post form + length bandit update feed_post_format_bandits() in bandits.sh — idempotent via metadata.post_form stamp (M3); series: only reward status=complete"]:::green
post_format_suite_pfs_strategist["Strategist reads form/length performance reads action_bandits post_form:*/post_length:* alpha/beta + post_series table; proposes format_shift via strategy_proposals"]:::green
post_format_suite_pfs_governance["Governance applier apply_approved_proposals — applies approved format_shift to persona_config (never direct write — invariant #4)"]:::green
end
post_format_suite_pfs_cfg --> post_format_suite_pfs_sidecar
post_format_suite_pfs_sidecar --> post_format_suite_pfs_selector
post_format_suite_pfs_selector -->|arm ∈ enabled set| post_format_suite_pfs_draft
post_format_suite_pfs_draft --> post_format_suite_pfs_publish
post_format_suite_pfs_publish --> post_format_suite_pfs_outcome
post_format_suite_pfs_outcome --> post_format_suite_pfs_autoscore
post_format_suite_pfs_autoscore --> post_format_suite_pfs_bandit
post_format_suite_pfs_bandit --> post_format_suite_pfs_strategist
post_format_suite_pfs_strategist --> post_format_suite_pfs_governance
post_format_suite_pfs_governance -->|updates enabled set| post_format_suite_pfs_cfg
Step
What it does
Status
If broken
Content format config
persona_config.post_forms_enabled/post_lengths_enabled/series_enabled/polls_enabled (M1); customer toggles via /settings/content
get_recommended_arm_constrained() in bandits.sh — Thompson sample ∩ enabled set; cold-start fallback = first allowed arm
AMBERprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>selected_post_form,context->>selected_post_length,created_at&persona_id=eq.respiro-brand&action_type=in.(publish_post,publish_poll,thread_chain)&created_at=gte.NOW()-interval 48h' returns >=1 row with BOTH selected_post_form AND selected_post_length non-null AND selected_post_form value is in enabled set from persona_config (not a disabled form)
LLM draft with form + length
v4-runner.sh ~591 — form prompt-variant injected, length char-target parameterized; arms persisted to action_log.context (one read-merge-write with comment_style — N4 fix)
AMBERprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>selected_post_form,context->>selected_post_length,created_at&persona_id=eq.respiro-brand&action_type=in.(publish_post,publish_poll,thread_chain)&created_at=gte.NOW()-interval 48h' returns >=1 row with BOTH selected_post_form AND selected_post_length non-null AND selected_post_form value is in enabled set from persona_config (not a disabled form)
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,created_at&persona_id=eq.respiro-brand&action_type=eq.publish_post&created_at=gte.NOW()-interval 48h' by slug returns >=2 rows with DISTINCT non-null media_id values (numeric Threads media IDs, NOT status=eq.confirmed filter)
Outcome collection (4h delay)
auto-collect-signals.sh — engagement signals; series: post_series.status=complete required for reward
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>reply_count,scored_at&persona_id=eq.respiro-brand&action_type=eq.score_comment&scored_at=gte.NOW()-interval 48h' by slug returns >=5 rows with VARYING reply_count values (not all same integer = proves real engagement collection not counter-only)
Auto-score (score ≥50 = success)
auto-score.sh — composite engagement 0-100; same threshold as comment_style bandit
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>score,scored_at&persona_id=eq.respiro-brand&scored_at=gte.NOW()-interval 48h&scored_at=not.is.null' by slug returns >=5 rows with VARYING score values (at least 2 distinct scores = proves real scoring not stuck counter)
Post form + length bandit update
feed_post_format_bandits() in bandits.sh — idempotent via metadata.post_form stamp (M3); series: only reward status=complete
GREENprobecurl '$SUPABASE_URL/rest/v1/action_bandits?select=action_type,alpha,beta,updated_at&persona_id=eq.respiro-brand&action_type=like.post_form:*' returns >=1 row with (alpha+beta)>2 (moved past cold-start 1,1 init) AND action_log row with metadata->>post_form non-null AND scored_at non-null within 48h (causal stamp + bandit update prove loop closed)
GREENprobeAfter FIX-STRATEGIST-PILLAR-SLUG-BACKFILL-01 ships: curl '$SUPABASE_URL/rest/v1/personas?select=config->pillars&handle=eq.respiro-brand' shows every pillar object with a non-null .slug key AND a subsequent strategist-daily.sh run's daily_plan.pillar_weights is non-empty (proves selection no longer degrades to fallback)
Governance applier
apply_approved_proposals — applies approved format_shift to persona_config (never direct write — invariant #4)
GREENprobecurl '$SUPABASE_URL/rest/v1/voice_dna_versions?select=proposal_id,created_at&persona_id=eq.respiro-brand' returns >=1 row with non-null proposal_id (proves audit trail intact and BA-6 fixed — proposal_id=null means backup writes failing). NOTE: this only certifies the voice_change path — see governance-appliers-fanout for the other 4 proposal types.
10
Comment Writing Path — Current + Target
2026-07-04: VERIFIED — all 5 linked nodes verified 2026-07-04
How comment draft TEXT is composed under the new persona format. GREEN = live-proven. RED = format gap (not yet in wording). TARGET nodes show the fix destination for each gap.
candidate-screen.sh — 348-node wellness ontology rejects off-niche (tau=0.60); GREEN but screening-only (does not reach draft text)
GREENprobecurl '$SUPABASE_URL/rest/v1/opportunity_candidates?select=policy_reasons,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 24h' returns >=100 rows with varied policy_reasons (not all same value) AND at least 3 distinct reject reason types within 24h
GAP: ontology not in draft prompt
assemble-prompt.sh — 0 refs to niche ontology; screens targets but never informs comment wording (FORMAT-GAP-01)
RED⚠ no evidence
Voice V2 frames injected
assemble-prompt.sh — PE_COMMENT_VOICE_V2=1; comment_recency_frames=7 prohibitions prepended; GREEN
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,context->>draft&persona_id=eq.respiro-brand&action_type=eq.publish_comment&created_at=gte.NOW()-interval 48h' returns >=10 DISTINCT media_id values AND >=3 distinct comment_style values by slug respiro-brand
comment_style bandit draw (5 arms)
bandits.sh — 5 arms real alpha/beta (sharp_question/reframe/data_cite/challenge/lived_experience); Thompson draw active
GREENprobecurl '$SUPABASE_URL/rest/v1/bandit_arms?select=alpha,beta,updated_at&persona_id=eq.respiro-brand&arm_type=eq.comment_style' returns updated_at within 2h of a corresponding score event in action_log (proves causal bandit update, not stale counter)
RECENT_COMMENT_OPENERS + anti-template
assemble-prompt.sh:1949 — opener list injected; rhetorical-formula block active; anti-template GREEN
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,context->>draft&persona_id=eq.respiro-brand&action_type=eq.publish_comment&created_at=gte.NOW()-interval 48h' returns >=10 DISTINCT media_id values AND >=3 distinct comment_style values by slug respiro-brand
LLM draft text generated
v4-runner.sh — engagement.md prompt; 40/40 distinct bodies; 5 styles; GREEN (last fire 2026-06-21T14:43Z)
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,context->>draft&persona_id=eq.respiro-brand&action_type=eq.publish_comment&created_at=gte.NOW()-interval 48h' returns >=10 DISTINCT media_id values AND >=3 distinct comment_style values by slug respiro-brand
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,context->>draft&persona_id=eq.respiro-brand&action_type=eq.publish_comment&created_at=gte.NOW()-interval 48h' returns >=10 DISTINCT media_id values AND >=3 distinct comment_style values by slug respiro-brand
Engagement feedback — THIN
auto-check-replies.sh — 11/860 all-time have feedback; signal sparse (AMBER; limits bandit learning)
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>reply_count,scored_at&persona_id=eq.respiro-brand&action_type=eq.score_comment&scored_at=gte.NOW()-interval 48h' by slug returns >=5 rows with VARYING reply_count values (not all same integer = proves real engagement collection not counter-only)
11
Post Writing Path — Current + Target
2026-07-04: AMBER — post-format-selector: LYING-GREEN: node fires (fields populate, media_id present, form∈enabled set) but the "selector" has pulled exactly ONE arm ever (question/short) out of 5 forms×3 lengths configured, since feature launch 9+ days ago — zero exploration, not a functioning selector.
How post draft TEXT is composed — and where the new format has NOT landed. 4% publish rate (17/424 7d). RED = live gap causing publish failures or missing format injection. TARGET nodes show the fix destination.
%%{init: {"theme": "dark", "themeVariables": {"primaryColor": "#161b22", "primaryBorderColor": "#30363d", "edgeLabelBackground": "#1c2128", "tertiaryColor": "#161b22", "fontSize": "11px"}, "flowchart": {"nodeSpacing": 18, "rankSpacing": 26, "wrap": true, "htmlLabels": true}}}%%
flowchart TD
classDef green fill:#161b22,stroke:#3fb950,stroke-width:2px,color:#e6edf3
classDef amber fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3
classDef red fill:#161b22,stroke:#f85149,stroke-width:2px,color:#e6edf3
classDef dead fill:#161b22,stroke:#6e7681,stroke-width:1px,color:#8b949e,stroke-dasharray:5 3
classDef notraffic fill:#161b22,stroke:#7c5a00,stroke-width:2px,color:#e6edf3
classDef unprobed fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3,stroke-dasharray:4 3
subgraph BEFORE["BEFORE — Setup and intelligence"]
post_writing_path_pwp_b1_seed["Opportunity seed (~60/day) operator_opportunity_queue — ~60 seeds/day (overproduces vs 2-4/day cadence; AMBER)"]:::green
post_writing_path_pwp_b2_spacing["⚠ Spacing preflight CHOKEPOINT v4-runner.sh:2437-2537 — defer loop; max 3 defers → spacing_guard_max_defers terminal SKIP; most actions never reach draft (RED chokepoint)"]:::unprobed
post_writing_path_pwp_t2_spacing_requeue["⚠ TARGET: spacing defer → opportunity requeue TARGET: spacing_guard_max_defers path → requeue to OOQ (not terminal skip); gives deferred opportunities a second chance"]:::unprobed
end
subgraph DURING["DURING — Draft, gate, publish"]
post_writing_path_pwp_d3_bandit["Bandit format draw (form + length) bandits.sh — post_form:*/post_length:* Thompson draw; form-suite code deployed (AMBER pending first scored post)"]:::amber
post_writing_path_pwp_d4_opener["Opener-block injection v4di_opener_block in draft-intel — steers opener type away from recent repeats (FIX-POST-GEN-VARIETY-01)"]:::green
post_writing_path_pwp_d5_gap_ontology["⚠ GAP: ontology not in post prompt content.md / draft-intel — 0 refs to niche ontology; post draft never informed by wellness angle (FORMAT-GAP-01)"]:::unprobed
post_writing_path_pwp_d6_gap_voice_frame["⚠ GAP: voice-frame hook not yet fired voice_recency_frames=0; framing_angle null all posts — post-publish hook needs >=1 published V2 post to seed angle prohibitions"]:::unprobed
post_writing_path_pwp_d7_gap_form_rotation["⚠ GAP: form-rotation not in draft prompt PE_FORM_ROTATION=on but 0 refs in draft prompt; structure goes via kind_hint only — rotation instruction not injected (FORMAT-GAP-02)"]:::unprobed
post_writing_path_pwp_d8_llm["LLM draft via GLM backend v4-runner.sh — content.md prompt; text written to action_log.context.text (NOT payload.text)"]:::green
post_writing_path_pwp_d9_sweeper_gap["⚠ GAP: zombie-sweeper reads payload.text run-cycle.sh:483-498 — sweeper reads payload.text (empty), not context.text → 803/24h orphaned rows; no redraft path for stuck claimed actions"]:::unprobed
post_writing_path_pwp_d10_gates["Safety gates (grounding/voice/slop) grounding-gate + voice-check + slop-judge — binding post-2026-06-26 (dissonance-formula + phrase-saturation walls)"]:::amber
post_writing_path_pwp_t1_sweeper_fix["⚠ TARGET: sweeper → context.text fallback TARGET: zombie-sweeper (run-cycle.sh:483-498) fallback to context.text when payload.text empty; unblocks 803/24h orphaned row queue"]:::unprobed
post_writing_path_pwp_t3_ontology["⚠ TARGET: ontology → post draft prompt TARGET: inject wellness ontology node label/angle into content.md + draft-intel post prompt (FORMAT-GAP-01 fix)"]:::unprobed
post_writing_path_pwp_t4_voice_frame["⚠ TARGET: voice-frame hook → voice_recency_frames TARGET: post-publish hook fires after first V2 post; seeds voice_recency_frames prohibitions for angle diversity auto-loop"]:::unprobed
post_writing_path_pwp_t5_form_rotation["⚠ TARGET: form-rotation → draft prompt instruction TARGET: inject explicit PE_FORM_ROTATION instruction into post draft prompt (not only kind_hint) (FORMAT-GAP-02 fix)"]:::unprobed
end
subgraph AFTER["AFTER — Record, score, learn"]
post_writing_path_pwp_a1_publish["Publish — 4% success (17/424 7d) Threads A/B — 4% publish rate; last media_id 18106955225095647 (2026-06-21); 96% blocked by spacing chokepoint + sweeper mismatch"]:::green
post_writing_path_pwp_a2_backfill_gap["⚠ GAP: 48h engagement backfill DEAD signal_48h null since ~06-21; backfill job dead — post quality feedback loop broken (FIX-PROD-SILENT-DEGRADATIONS-BUNDLE-01)"]:::unprobed
post_writing_path_pwp_t6_backfill["⚠ TARGET: 48h backfill revived TARGET: repair signal_48h backfill job; feeds engagement quality signal into post scoring + bandit loop"]:::unprobed
end
post_writing_path_pwp_b1_seed --> post_writing_path_pwp_b2_spacing
post_writing_path_pwp_b2_spacing --> post_writing_path_pwp_d3_bandit
post_writing_path_pwp_b2_spacing --> post_writing_path_pwp_t2_spacing_requeue
post_writing_path_pwp_d3_bandit --> post_writing_path_pwp_d4_opener
post_writing_path_pwp_d4_opener --> post_writing_path_pwp_d8_llm
post_writing_path_pwp_d5_gap_ontology -->|→ TARGET| post_writing_path_pwp_t3_ontology
post_writing_path_pwp_d6_gap_voice_frame -->|→ TARGET| post_writing_path_pwp_t4_voice_frame
post_writing_path_pwp_d7_gap_form_rotation -->|→ TARGET| post_writing_path_pwp_t5_form_rotation
post_writing_path_pwp_d8_llm --> post_writing_path_pwp_d9_sweeper_gap
post_writing_path_pwp_d8_llm --> post_writing_path_pwp_d10_gates
post_writing_path_pwp_d9_sweeper_gap -->|→ TARGET| post_writing_path_pwp_t1_sweeper_fix
post_writing_path_pwp_d10_gates --> post_writing_path_pwp_a1_publish
post_writing_path_pwp_a1_publish --> post_writing_path_pwp_a2_backfill_gap
post_writing_path_pwp_a2_backfill_gap -->|→ TARGET| post_writing_path_pwp_t6_backfill
Step
What it does
Status
If broken
Opportunity seed (~60/day)
operator_opportunity_queue — ~60 seeds/day (overproduces vs 2-4/day cadence; AMBER)
GREENprobecurl '$SUPABASE_URL/rest/v1/opportunity_candidates?select=created_at,wellness_pillar,niche_match_count&persona_id=eq.respiro-brand&run_mode=eq.prod&created_at=gte.NOW()-interval 48h' returns >=200 rows with >=10 distinct wellness_pillar values within 48h
Spacing preflight CHOKEPOINT
v4-runner.sh:2437-2537 — defer loop; max 3 defers → spacing_guard_max_defers terminal SKIP; most actions never reach draft (RED chokepoint)
RED⚠ no evidence
TARGET: spacing defer → opportunity requeue
TARGET: spacing_guard_max_defers path → requeue to OOQ (not terminal skip); gives deferred opportunities a second chance
AMBERprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>selected_post_form,context->>selected_post_length,created_at&persona_id=eq.respiro-brand&action_type=in.(publish_post,publish_poll,thread_chain)&created_at=gte.NOW()-interval 48h' returns >=1 row with BOTH selected_post_form AND selected_post_length non-null AND selected_post_form value is in enabled set from persona_config (not a disabled form)
Opener-block injection
v4di_opener_block in draft-intel — steers opener type away from recent repeats (FIX-POST-GEN-VARIETY-01)
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>status_reason,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 7d' by slug returns >=1 row with status_reason=opener_type_saturated (proves saturation gate has actually blocked a post, not just wired)
GAP: ontology not in post prompt
content.md / draft-intel — 0 refs to niche ontology; post draft never informed by wellness angle (FORMAT-GAP-01)
RED⚠ no evidence
GAP: voice-frame hook not yet fired
voice_recency_frames=0; framing_angle null all posts — post-publish hook needs >=1 published V2 post to seed angle prohibitions
RED⚠ no evidence
GAP: form-rotation not in draft prompt
PE_FORM_ROTATION=on but 0 refs in draft prompt; structure goes via kind_hint only — rotation instruction not injected (FORMAT-GAP-02)
RED⚠ no evidence
LLM draft via GLM backend
v4-runner.sh — content.md prompt; text written to action_log.context.text (NOT payload.text)
AMBERprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>judge_result,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 48h' by slug returns >=1 row with non-null judge_result containing verdict=clearly_ai that was actually blocked (not just logged)
TARGET: sweeper → context.text fallback
TARGET: zombie-sweeper (run-cycle.sh:483-498) fallback to context.text when payload.text empty; unblocks 803/24h orphaned row queue
AMBER⚠ no evidence
TARGET: ontology → post draft prompt
TARGET: inject wellness ontology node label/angle into content.md + draft-intel post prompt (FORMAT-GAP-01 fix)
AMBER⚠ no evidence
TARGET: voice-frame hook → voice_recency_frames
TARGET: post-publish hook fires after first V2 post; seeds voice_recency_frames prohibitions for angle diversity auto-loop
AMBER⚠ no evidence
TARGET: form-rotation → draft prompt instruction
TARGET: inject explicit PE_FORM_ROTATION instruction into post draft prompt (not only kind_hint) (FORMAT-GAP-02 fix)
AMBER⚠ no evidence
Publish — 4% success (17/424 7d)
Threads A/B — 4% publish rate; last media_id 18106955225095647 (2026-06-21); 96% blocked by spacing chokepoint + sweeper mismatch
GREENprobecurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,created_at&persona_id=eq.respiro-brand&action_type=eq.publish_post&created_at=gte.NOW()-interval 48h' by slug returns >=2 rows with DISTINCT non-null media_id values (numeric Threads media IDs, NOT status=eq.confirmed filter)
GAP: 48h engagement backfill DEAD
signal_48h null since ~06-21; backfill job dead — post quality feedback loop broken (FIX-PROD-SILENT-DEGRADATIONS-BUNDLE-01)
RED⚠ no evidence
TARGET: 48h backfill revived
TARGET: repair signal_48h backfill job; feeds engagement quality signal into post scoring + bandit loop
AMBER⚠ no evidence
12
Customer Dashboard (web/app/(dashboard)/*)
2026-07-04: AMBER — customer-voice-edit: LYING-GREEN confirmed (agree with prober).
Compact overview of the customer-facing product surface: 16 dashboard page groups + ~40 API route dirs. All steps AMBER — zero live-evidence probes exist yet for any step except /voice (LYING-GREEN, covered separately by customer-voice-edit node). MAP-COVERAGE-APPLY-01: added to make this subsystem visible; /lifecycle-refresh evidence-probe pass required before any step can be promoted.
%%{init: {"theme": "dark", "themeVariables": {"primaryColor": "#161b22", "primaryBorderColor": "#30363d", "edgeLabelBackground": "#1c2128", "tertiaryColor": "#161b22", "fontSize": "11px"}, "flowchart": {"nodeSpacing": 18, "rankSpacing": 26, "wrap": true, "htmlLabels": true}}}%%
flowchart TD
classDef green fill:#161b22,stroke:#3fb950,stroke-width:2px,color:#e6edf3
classDef amber fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3
classDef red fill:#161b22,stroke:#f85149,stroke-width:2px,color:#e6edf3
classDef dead fill:#161b22,stroke:#6e7681,stroke-width:1px,color:#8b949e,stroke-dasharray:5 3
classDef notraffic fill:#161b22,stroke:#7c5a00,stroke-width:2px,color:#e6edf3
classDef unprobed fill:#161b22,stroke:#d29922,stroke-width:2px,color:#e6edf3,stroke-dasharray:4 3
subgraph BEFORE["BEFORE — Setup and intelligence"]
customer_dashboard_cd_ui_queue["⚠ Queue / approvals pages web/app/(dashboard)/queue + queue-health — customer reviews pending posts, approves/rejects; web/app/api/dashboard/queue/* routes"]:::unprobed
customer_dashboard_cd_ui_safety["⚠ Safety + health pages web/app/(dashboard)/safety + health + system-health — gate overrides, health signals; web/app/api/dashboard/safety/* health/* routes"]:::unprobed
customer_dashboard_cd_ui_voice["Voice edit page (LYING-GREEN) web/app/(dashboard)/voice — the ONE previously mapped page; API /api/dashboard/voice-proposal exists but 0 UI calls it (customer-voice-edit node, LYING-GREEN)"]:::amber
end
subgraph DURING["DURING — Draft, gate, publish"]
customer_dashboard_cd_ui_analytics["⚠ Analytics / growth / funnel pages web/app/(dashboard)/analytics + growth + funnel + efficiency + focus — performance metrics surfaces"]:::unprobed
customer_dashboard_cd_api_routes["⚠ Dashboard API routes (~40 dirs) web/app/api/dashboard/* — ~40 route dirs (filesystem-confirmed 2026-07-02); each should call Supabase; none individually probed for live data return"]:::unprobed
customer_dashboard_cd_supabase["⚠ Supabase reads (action_log / personas / strategy_proposals) API routes query action_log, personas, strategy_proposals, opportunity_candidates etc. — confirmed tables; NOT confirmed that all 40 routes actually call them rather than returning stubs"]:::unprobed
end
subgraph AFTER["AFTER — Record, score, learn"]
customer_dashboard_cd_ui_settings["⚠ Settings / topics / stories / experiments pages web/app/(dashboard)/settings + topics + stories + experiments + notifications + fleet — 7 remaining page groups not mapped above"]:::unprobed
end
customer_dashboard_cd_ui_queue --> customer_dashboard_cd_ui_safety
customer_dashboard_cd_ui_safety --> customer_dashboard_cd_ui_voice
customer_dashboard_cd_ui_voice --> customer_dashboard_cd_ui_analytics
customer_dashboard_cd_ui_analytics --> customer_dashboard_cd_api_routes
customer_dashboard_cd_api_routes --> customer_dashboard_cd_supabase
customer_dashboard_cd_supabase --> customer_dashboard_cd_ui_settings
GREEN⚠ no evidenceprobeFor each dashboard page group: confirm the page component actually calls its /api/dashboard/<group> route (grep web/app/(dashboard)/<group>/*.tsx for a fetch/action call to the matching route) AND the route handler performs a real Supabase read/write (not a stub) — mirrors the customer-voice-edit LYING-GREEN probe pattern. See new flow 'customer-dashboard' for the compact per-group breakdown.
Safety + health pages
web/app/(dashboard)/safety + health + system-health — gate overrides, health signals; web/app/api/dashboard/safety/* health/* routes
GREEN⚠ no evidenceprobeFor each dashboard page group: confirm the page component actually calls its /api/dashboard/<group> route (grep web/app/(dashboard)/<group>/*.tsx for a fetch/action call to the matching route) AND the route handler performs a real Supabase read/write (not a stub) — mirrors the customer-voice-edit LYING-GREEN probe pattern. See new flow 'customer-dashboard' for the compact per-group breakdown.
Voice edit page (LYING-GREEN)
web/app/(dashboard)/voice — the ONE previously mapped page; API /api/dashboard/voice-proposal exists but 0 UI calls it (customer-voice-edit node, LYING-GREEN)
AMBERprobecurl '$SUPABASE_URL/rest/v1/strategy_proposals?select=applied_at,source,auto_action_on_timeout&persona_id=eq.respiro-brand&proposal_type=eq.voice_change' returns >=1 row with applied_at non-null AND source=dashboard (not orchestrator) — proves a real customer dashboard edit was applied end-to-end
GREEN⚠ no evidenceprobeFor each dashboard page group: confirm the page component actually calls its /api/dashboard/<group> route (grep web/app/(dashboard)/<group>/*.tsx for a fetch/action call to the matching route) AND the route handler performs a real Supabase read/write (not a stub) — mirrors the customer-voice-edit LYING-GREEN probe pattern. See new flow 'customer-dashboard' for the compact per-group breakdown.
Dashboard API routes (~40 dirs)
web/app/api/dashboard/* — ~40 route dirs (filesystem-confirmed 2026-07-02); each should call Supabase; none individually probed for live data return
GREEN⚠ no evidenceprobeFor each dashboard page group: confirm the page component actually calls its /api/dashboard/<group> route (grep web/app/(dashboard)/<group>/*.tsx for a fetch/action call to the matching route) AND the route handler performs a real Supabase read/write (not a stub) — mirrors the customer-voice-edit LYING-GREEN probe pattern. See new flow 'customer-dashboard' for the compact per-group breakdown.
Supabase reads (action_log / personas / strategy_proposals)
API routes query action_log, personas, strategy_proposals, opportunity_candidates etc. — confirmed tables; NOT confirmed that all 40 routes actually call them rather than returning stubs
GREEN⚠ no evidenceprobeFor each dashboard page group: confirm the page component actually calls its /api/dashboard/<group> route (grep web/app/(dashboard)/<group>/*.tsx for a fetch/action call to the matching route) AND the route handler performs a real Supabase read/write (not a stub) — mirrors the customer-voice-edit LYING-GREEN probe pattern. See new flow 'customer-dashboard' for the compact per-group breakdown.
Settings / topics / stories / experiments pages
web/app/(dashboard)/settings + topics + stories + experiments + notifications + fleet — 7 remaining page groups not mapped above
GREEN⚠ no evidenceprobeFor each dashboard page group: confirm the page component actually calls its /api/dashboard/<group> route (grep web/app/(dashboard)/<group>/*.tsx for a fetch/action call to the matching route) AND the route handler performs a real Supabase read/write (not a stub) — mirrors the customer-voice-edit LYING-GREEN probe pattern. See new flow 'customer-dashboard' for the compact per-group breakdown.