Persona Engine — Lifecycle Map

Persona Engine — Action Lifecycle Map

Updated 2026-07-04 · 72 nodes · probe-honesty distribution 36 VERIFIED / 10 LYING-GREEN / 15 AMBER / 6 BROKEN / 5 DEPLOYED-UNPROBED · build 1af0a0bcd298

Probe Honesty Audit
Node colors reflect probe honesty, not throughput. Derived from docs/systems-map/TRUTH-TABLE.md. Last updated 2026-07-04.
36
VERIFIED
10
LYING-GREEN
15
AMBER
6
BROKEN
5
DEPLOYED-UNPROBED
72
NODES
Legend
VERIFIED real probe exists + passes LYING-GREEN flow counter only — misses correctness AMBER wired/coded but not yet firing — watch BROKEN code dead / misfires / structurally wrong DEPLOYED-UNPROBED shipped, no live probe yet
No status changes since last regen.
Node status:
Task priority:

Truth-Audit Node Map

72 nodes
Per-node probe-honesty status. Click a card to expand proof requirements and linked tasks.
Intel / Inputs cluster (3 nodes)
trends-scan AMBER AMBER: 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementssh claudebot@respiro-vps 'stat /home/claudebot/persona-engine/agent/research-intel.md /home/claudebot/persona-engine/agent/trend-briefing.txt' shows mtime within 48h AND research-intel.md contains '## RESEARCH INTEL' header AND 'likes' keyword (Section A) AND 'Niche Trends' or WHY-analysis keyword (Section B) AND VPS RUN_MODE=prod
Tasks
FIX-TRENDS-WHY-PROMPT-01 FIX-TRENDS-WHY-PROMPT-01
competitor-scan LYING-GREEN LYING-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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl $SUPABASE_URL/rest/v1/competitor_intel?select=commented_action_id,comment_score&persona_id=eq.respiro-brand&commented_action_id=not.is.null&limit=1 returns >=1 row AND operator_playbook.competitor_insights non-null in recent action_log by slug within 48h
Tasks
FIX-COMPETITOR-SCHEMA-MIGRATION-01 FIX-COMPETITOR-V4-INJECT-01 FIX-COMPETITOR-TRENDING-SCORE-01
backstory-memory LYING-GREEN LYING-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.
Last probed 2026-07-04T12:20:00Z
Proof requirementssh 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
Tasks
FIX-BACKSTORY-SEEDER-DEPLOY-01 FIX-BACKSTORY-SEEDER-DEPLOY-01 FIX-BACKSTORY-TIMELINE-WIRE-01 FIX-BACKSTORY-TIMELINE-WIRE-01
Pipeline nodes (69 nodes)
Discovery / feed scan VERIFIED VERIFIED — 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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
Daily is_viral recalc (persona-is-viral-recalc-<slug>.timer) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementconfirm timer fired on its 03:00 schedule (not just manual trigger) + rows re-flagged over multiple days
Tasks
FU-VIRAL-INTEL-BATCH-01
Candidate screen (7-rule filter) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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
Action arbiter (per-type due gate) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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)
Tasks
VERIFY-ACTION-ARBITER-LIVE-01 VERIFY-ACTION-ARBITER-LIVE-01
Opportunity queue builder VERIFIED VERIFIED: 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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
_pe_quick_skip global throttle (DEPRECATED) AMBER 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).
Last probed 2026-07-04T12:20:00Z
Proof requirementN/A — deprecated; no live proof required. Verify absence: journalctl on VPS should show arbiter log lines (not _pe_quick_skip) as front-of-cycle gate under LEADV2_ACTION_ARBITER=on.
Comment-only mode hack (DEPRECATED) LYING-GREEN 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementN/A — deprecated; no live proof required. Verify absence: grep _PE_COMMENT_ONLY_CLAIM in active run-cycle.sh on VPS should return 0 matches.
runner_crash / crash-recovery (per-phase cooldown) AMBER 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementAfter a crash event: curl '$SUPABASE_URL/rest/v1/persona_config?select=crash_cooldown_until,crashed_phase&persona_id=eq.respiro-brand' returns non-null crash_cooldown_until with a future timestamp AND non-null crashed_phase value (proves new crash model writing correctly, not old next_session_at path)
Tasks
CRASH-PHASE3-WORKER-TIMEOUT-01 CRASH-PHASE3-WORKER-TIMEOUT-01 VERIFY-ACTION-ARBITER-LIVE-01 VERIFY-ACTION-ARBITER-LIVE-01
Per-cycle stderr live observability (tee to journald) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementDuring 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.
Tasks
AUDIT-NEWFORMAT-PIPELINE-01
Quality track — DORMANT LYING-GREEN LYING-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.
Last probed 2026-07-04T12:20:00Z
Proof requirementssh claudebot@respiro-vps 'journalctl -u persona-engine --since "48 hours ago" | grep -c "voice-check\|llm_score_voice"' returns >=1 AND eval_log has rows with action_type=voice_quality within 48h by slug respiro-brand
Tasks
FLAG-ROLLOUT-QUALITY-01 FLAG-ROLLOUT-QUALITY-01 VOICE-CARD-REGEN-01 VOICE-CARD-REGEN-01
Claim next opportunity (CAS lock) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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 row reclaim + terminal-skip BROKEN 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. 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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).
Tasks
AUDIT-NEWFORMAT-PIPELINE-01
Comment sweeper empty-payload anchor fix VERIFIED VERIFIED — 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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.
Tasks
FIX-EMPTY-PAYLOAD-COMMENT-ANCHOR-01
Dispatch-time post-gate recheck (G0) VERIFIED VERIFIED: dispatch-gate-recheck fired 2026-07-02T17:03:00Z, blocked action 35514136 (opener_repetition rule). Prober's false-zero: searched status_reason for 'dispatch' string instead of context.dispatch_gate_block_detail field.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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).
Tasks
AUDIT-NEWFORMAT-PIPELINE-01
LLM draft — post VERIFIED VERIFIED: 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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 7d' returns >=3 DISTINCT media_id values (NOT status=eq.confirmed filter — use distinct media_id)
LLM draft — comment VERIFIED VERIFIED, 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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 redraft time budget (600s -> 900s) AMBER 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementAfter 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.
Tasks
AUDIT-NEWFORMAT-PIPELINE-01
LLM draft — reply DEPLOYED-UNPROBED DEPLOYED-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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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 gate — grounding DEPLOYED-UNPROBED DEPLOYED-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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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 VERIFIED VERIFIED (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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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 VERIFIED VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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 AMBER AMBER 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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.
Tasks
AUDIT-NEWFORMAT-PIPELINE-01
Slop judge (D7) AMBER 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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)
Unified construction-monotony detector (posts + comments) DEPLOYED-UNPROBED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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.
Tasks
AUDIT-NEWFORMAT-PIPELINE-01
Publish (Threads A/B) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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)
Engagement / signal collection VERIFIED VERIFIED: 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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)
Scoring (auto-score.sh) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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 VERIFIED VERIFIED — 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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 eval AMBER AMBER 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).
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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 + voice proposal VERIFIED VERIFIED — 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementAfter 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)
Tasks
FIX-STRATEGIST-PILLAR-SLUG-BACKFILL-01
Learning liveness (belief→prompt) AMBER 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementAfter 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
Tasks
FIX-BELIEFS-INJECT-AWK-EARLYEXIT-01
Governance applier + voice evolution VERIFIED VERIFIED: 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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.
Tasks
FIX-VOICE-DNA-VERSIONS-AUDIT-01 FIX-VOICE-DNA-AUDIT-LOG-01
Customer voice-edit (dashboard /voice) LYING-GREEN 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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
C1/ideation — chosen=true write path VERIFIED VERIFIED: 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/ideation_angles?select=chosen,angle,created_at&persona_id=eq.respiro-brand&chosen=eq.true&created_at=gte.NOW()-interval 48h' by slug returns >=1 row with chosen=true AND at least 2 distinct angle values across last 7d (proves anti-repeat is working, not same angle repeating)
C1/ideation — diversity (min_distance cosine) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/ideation_angles?select=min_distance,created_at&persona_id=eq.respiro-brand&chosen=eq.true&created_at=gte.NOW()-interval 48h' by slug returns >=1 row with min_distance between 0.1 and 0.99 (NOT 1.0 which means no-refs fallback stuck = broken)
Tasks
VERIFY-C1-COSINE-DEDUP-LIVE-01
Off-hours publish DEFER (PE_OFFHOURS_PUBLISH_DEFER) DEPLOYED-UNPROBED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/action_log?select=context->>status_reason,created_at&persona_id=eq.respiro-brand' by slug returns >=1 row with status_reason=offhours_publish_deferred (proves guard has actually fired and deferred at least one off-hours publish attempt)
Tasks
VERIFY-OFFHOURS-DEFER-LIVE-01
Off-window draft gate (FIX-OFFWINDOW-GLM-GATE-01) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementAfter 03:00 UTC off-window: action_log status_reason='offhours_draft_deferred' rows > 0, GLM 429s off-window ≈ 0 (was 26 on 2026-06-23 morning), deferred opportunities back to status=pending with action_id preserved (not null), no duplicate action_log rows. Commit 93393911, flag PE_OFFHOURS_DRAFT_DEFER=1.
Tasks
FIX-OFFWINDOW-GLM-GATE-01
topic_dedup instrumentation (TOPIC_DEDUP_PROBE) LYING-GREEN 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/action_log?select=context->>dedup_category,created_at&persona_id=eq.respiro-brand&action_type=eq.topic_dedup&created_at=gte.NOW()-interval 48h' by slug returns >=1 row with dedup_category in (deferred,exhausted) AND at least 2 distinct dedup_category values
scoring_context + LLM feature extractor (PE_LLM_FEATURE_EXTRACT) LYING-GREEN LYING-GREEN: prober's cited evidence (3 score_comment rows, bandit_updated=true) does not exist; feature has never fired even once.
Last probed 2026-07-04T12:20:00Z
Proof requirementssh claudebot@respiro-vps 'grep PE_LLM_FEATURE_EXTRACT /home/claudebot/persona-engine/.env' returns PE_LLM_FEATURE_EXTRACT=1 AND curl action_log by slug returns >=1 row with non-null llm_features within 24h (flag ON + real LLM features appearing = VERIFIED active)
Tasks
ENABLE-LLM-FEATURE-EXTRACT-01
VPS provisioning (onboarding / persona-creation) DEPLOYED-UNPROBED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementPOST /api/instances/provision/enqueue returns 202 within 120s AND provision_jobs row created with status=bootstrapping AND VPS worker claims row AND instances.status transitions provisioning→bootstrapping→running within 10min (full E2E reprobe)
Post sub-topic rotation (FIX-POST-TOPIC-ROTATION-01) AMBER 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/ideation_angles?select=angle,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 48h' by slug returns >=1 row where angle contains 'TOPIC:' AND at least 2 rows have distinct angle values (proves deterministic rotation injected and anti-repeat firing)
Tasks
FIX-POST-TOPIC-ROTATION-01 VERIFY-C1-COSINE-DEDUP-LIVE-01
Comment phrase anti-repeat + form rotation (FIX-COMMENT-DIVERSITY-01) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/action_log?select=context->>selected_comment_style,created_at&persona_id=eq.respiro-brand&action_type=eq.publish_comment&created_at=gte.NOW()-interval 48h' by slug returns >=2 rows with non-null selected_comment_style AND at least 2 distinct selected_comment_style values (proves form rotation active, not stuck on same style)
Tasks
FIX-COMMENT-DIVERSITY-01
Voice V2 config (voice_persona_v2 table) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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)
Tasks
FU-VOICE-ANGLE-DIVERSITY-01
Andrew named-character voice AMBER AMBER 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/strategy_proposals?select=id,proposal_type,status&persona_id=eq.respiro-brand&proposal_type=eq.voice_change&created_at=gte.2026-06-30T00:00:00Z' — PASS once confirmed row a753cc48 (status=applied, retro marker, added 2026-07-02) is returned by this exact query (closes the governance-bypass). Separately confirm live posts show Andrew-anchored voice_guardrails via action_log.context.draft text referencing NYC commercial real-estate / LeBron / Messi framing.
Tasks
KEYSTONE-VOICE-GUARDRAILS-ANDREW-19 CHARACTER-PROGRAM-01
Post-publish frame hook (voice_recency_frames) AMBER 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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)
Tasks
FU-VOICE-ANGLE-DIVERSITY-01
Pillar-weight wiring (focus_directive → ideation) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/ideation_angles?select=angle,pillar,created_at&persona_id=eq.respiro-brand&chosen=eq.true&created_at=gte.2026-06-26T00:00:00Z&order=created_at.desc&limit=7' — PASS if >=2 distinct pillar values among chosen angles AND distribution is non-uniform (reflects focus_directive.pillar_weights, not equal round-robin). Also confirm curl '$SUPABASE_URL/rest/v1/personas?select=config->>focus_directive&id=eq.respiro-brand' returns focus_directive.pillar_weights with non-uniform values.
Tasks
FU-VOICE-ANGLE-DIVERSITY-01
Post form sub-bandit (post_form:*) VERIFIED 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).
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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)
Tasks
FEAT-POST-FORMAT-SUITE-01
Post length sub-bandit (post_length:*) AMBER 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/action_bandits?select=action_type,alpha,beta,updated_at&persona_id=eq.respiro-brand&action_type=like.post_length:*' returns >=1 row with (alpha+beta)>2 AND action_log metadata->>post_length non-null on a scored row (same conditions as post-form-bandit)
Tasks
FEAT-POST-FORMAT-SUITE-01
Post format selector (get_recommended_arm_constrained) LYING-GREEN 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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)
Tasks
FEAT-POST-FORMAT-SUITE-01
Post form rotation (PE_FORM_ROTATION) AMBER 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/action_log?select=created_at,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 values among PUBLISHED posts.
Tasks
FIX-POST-BLOCKED-STATUS-P0-18 FU-VOICE-ANGLE-DIVERSITY-01
Post series orchestration (publish_thread_chain + post_series table) BROKEN 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/post_series?select=series_id,status,total_parts,published_part_ids&persona_id=eq.respiro-brand&status=eq.complete&created_at=gte.NOW()-interval 7d' returns >=1 row with status=complete AND published_part_ids array length = total_parts (proves series completed and part tracking intact, not partial_failed)
Tasks
FEAT-POST-FORMAT-SUITE-01
Poll publish (poll_attachment / publish_poll) AMBER 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,action_type,created_at&persona_id=eq.respiro-brand&action_type=eq.publish_poll&created_at=gte.NOW()-interval 7d' returns >=1 row with non-null media_id (numeric Threads media ID — proves poll actually published, NOT status=confirmed alone)
Tasks
FEAT-POST-FORMAT-SUITE-01
Content format config (persona_config + sidecar .content_formats) LYING-GREEN 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/persona_config?select=post_forms_enabled,post_lengths_enabled,series_enabled,polls_enabled&persona_id=eq.respiro-brand' returns >=1 row with post_forms_enabled array non-null AND ssh VPS 'cat safety-overrides.json | jq .content_formats' returns non-null block (proves M1 applied + sidecar sync active)
Tasks
FEAT-POST-FORMAT-SUITE-01
Ontology keyword screening (comment niche match) LYING-GREEN 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).
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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)
Tasks
FIX-ONTOLOGY-KEYWORD-SYNC-01
Engagement collection (auto-check-replies) BROKEN 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/action_log?select=context->>media_id,context->>publish_result,created_at&persona_id=eq.respiro-brand&action_type=eq.post&created_at=gte.NOW()-interval 7d' find a row with non-null media_id but null publish_result.url/.target — then confirm reply-check was still attempted for that row (not skipped by the unconditional continue) after the fix ships
Tasks
FIX-REPLY-HANDLING-MEDIAID-FALLBACK-01
Graph comment ID persist (graph_comment_id in action_log) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/action_log?select=context->>own_comment_media_id,context->>graph_comment_id,created_at&persona_id=eq.respiro-brand&action_type=eq.comment&created_at=gte.NOW()-interval 24h' returns >=5 rows ALL with non-null own_comment_media_id AND non-null graph_comment_id (sustained multi-day, not just 1-day proof)
Comment voice-frames hook (comment_recency_frames) BROKEN 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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)
Tasks
FIX-COMMENT-VOICE-FRAME-HOOK-DEAD-01
Ontology node label in comment draft (ontology-in-text comments) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementjournalctl or action_log: comment drafts with ideation_source=ontology show node_label non-null in context AND >=2/3 of last 6 learned comments have ideation_source=ontology (proves injection wired + sampling ratio corrected)
Tasks
FIX-ONTOLOGY-IN-TEXT-COMMENTS-01
Customer dashboard surface (web/app/(dashboard)/*) VERIFIED 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).
Last probed 2026-07-04T12:20:00Z
Proof requirementFor 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.
Auth refresh gate (platform/session/auth-refresh.sh) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementssh 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.
Circuit breaker (platform/safety/circuit-breaker.sh) VERIFIED 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).
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$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.
Injection scanner (platform/safety/injection-scanner.sh) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementssh 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.
Content studio (platform/operator/content-studio.sh) BROKEN 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementssh claudebot@respiro-vps 'journalctl -u persona-engine.service --since "48 hours ago" -o cat -g content-studio.sh' — PASS if content-studio.sh actually executes for a post action (proves 3-candidate path is live) vs 0 hits (proves llm-draft-post single-draft V4 path is the sole live path). Currently neither has been checked this pass — OPEN QUESTION, not yet answered.
Invariants watchdog (platform/quality/invariants + stability-autopilot) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementssh 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.
Drift detector (platform/eval/drift-detector.sh) BROKEN 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementcurl '$SUPABASE_URL/rest/v1/drift_detector_log?select=drift_type,created_at&persona_id=eq.respiro-brand&created_at=gte.NOW()-interval 48h' (or equivalent table per script) returns >=1 row within 48h with a non-null drift_type in {D1,D2,D3,D4}.
Weight learner (platform/eval/weight-learner.sh) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementgrep for weight-learner.sh invocation site (run-cycle.sh, a timer's ExecStart, or a wrapper script) to establish HOW it fires, THEN curl the weight-adjustment output table for a row with updated_at within the confirmed cadence window.
Ops timer fleet (19 of 20 agent/deploy/*.timer pairs) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementssh claudebot@respiro-vps 'systemctl list-timers --all | grep persona-' shows all 16 timers as loaded with a non-empty NEXT column (none disabled/dead) AND each corresponding .service has an ExecStart exit-code=0 in its last run (journalctl -u <name> -n 1).
RAG + world-context fetch (agent/pre-actions/build-rag-context.sh, build-world-context.sh, fetch-world-news.sh) VERIFIED 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.
Last probed 2026-07-04T12:20:00Z
Proof requirementssh 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.
Governance appliers fan-out (4 non-voice appliers) AMBER 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).
Last probed 2026-07-04T12:20:00Z
Proof requirementFor each of pillars/playbook/keyword/experiments-applier.sh: curl the corresponding target table (e.g. personas.config->pillars for pillars-applier, operator_playbook for playbook-applier) filtered to updated_at within 48h of a matching strategy_proposals row with status=approved AND proposal_type=<matching type> — proves that applier actually wrote the approved diff, not just that apply_approved_proposals logged a dispatch.

Flow Diagrams

12 flows
Step-rail SVGs generated at build time from flows[].steps — no client-side rendering, no CDN.
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).
BEFORE — setup and intelligence ⚠ Systemd timer fires persona-engine.timer → run-cycle.sh 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 ⚠ Preflight check platform/lifecycle/preflight-check.sh — env/keys/DB reachability ⚠ is_active gate run-cycle.sh — LYING-GREEN: fail-open on DB unreachable ⚠ Jitter delay 0–5 min run-cycle.sh — human-like timing ⚠ Cycle-conductor pre-maintenance platform/operator/cycle-conductor.sh — strategist briefing (CYCLE-CONDUCTOR-01) 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. Backstory / timeline build-persona-timeline.sh — PERSONA_TIMELINE injected into prompt; DB-backed persona_timeline + story arcs Real-world context fetch-world-news.sh → world-news-search.sh (RSS→Qdrant); PE_WORLD_CONTEXT_RAG_ENABLED flag Action arbiter (per-type due gate) platform/operator/action-arbiter.sh — writes arbiter_decisions, exports _PE_ELIGIBLE_TYPES Opportunity queue built platform/operator/opportunity-queue-builder.sh Claim next opportunity (CAS lock) opportunity-queue-builder.sh — atomic claim 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) _pe_quick_skip global throttle (DEPRECATED) run-cycle.sh — replaced by action-arbiter (ACTION-ARBITER-REDESIGN-01) DURING — draft, gate, publish 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. 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. ⚠ 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 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) ⚠ 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. ⚠ Image upload sb_upload_persona_image → threads_post_image; NO-TRAFFIC — never reached when generation fails Safety — injection scan Prompt injection scan on draft inputs; adjacent to grounding gate Circuit breaker Stops publishing if too many consecutive failures; 0 circuit_open rows ever fired Safety gate — grounding check grounding-gate.sh — layer1 PCRE live, layer2 LLM disabled Safety gate — voice check voice-check.sh — redraft_trace written to action_log Safety gate — opener quality post-gate.sh — saturation D4 checks 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 Slop judge (D7) slop-judge — unified redraft loop PE_REDRAFT_UNIFIED=1 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 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) Publish Path A or B platform/adapters/threads/api.sh or browser — Threads Graph API / mobile ⚠ action_log row written platform/lifecycle/action-log.sh 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 AFTER — record, score, learn Signal collection (4h delay) auto-collect-signals.sh Score action auto-score.sh Composite reward + bandit update auto-composite-reward.sh → auto-bandit.sh 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 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 Experiment eval Tests content variants vs baseline; 56/192 concluded_refuted with lift_pct; platform/learning/experiment-eval.sh Strategist briefing saved Writes today's learned patterns for tomorrow's strategist; platform/learning/strategist-write.sh ⚠ Voice evolution proposal Proposes voice changes based on what worked; strategy_proposals table; PROVEN LIVE 2026-06-12 Governance applier apply_approved_proposals in run-cycle.sh; applies approved strategy+voice changes; RC1 FIXED 2026-06-02 ⚠ Daily snapshot Records follower count + engagement metrics; health_snapshot table Autopilot health check Detects health breaches + spawns self-repair agent; health_snapshot table; deploy key read-only so fixes not shipped ⚠ Cycle-conductor post-maintenance platform/operator/cycle-conductor.sh — eval + reflect (CYCLE-CONDUCTOR-01)
StepWhat it doesStatusIf broken
Systemd timer firespersona-engine.timer → run-cycle.shAMBER ⚠ 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 endGREEN
probeDuring 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.
Preflight checkplatform/lifecycle/preflight-check.sh — env/keys/DB reachabilityAMBER ⚠ no evidence
is_active gaterun-cycle.sh — LYING-GREEN: fail-open on DB unreachableAMBER ⚠ no evidence
Jitter delay 0–5 minrun-cycle.sh — human-like timingAMBER ⚠ no evidence
Cycle-conductor pre-maintenanceplatform/operator/cycle-conductor.sh — strategist briefing (CYCLE-CONDUCTOR-01)AMBER ⚠ no evidence
RAG context fetchQdrant 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
probessh 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 / timelinebuild-persona-timeline.sh — PERSONA_TIMELINE injected into prompt; DB-backed persona_timeline + story arcsAMBER
probessh 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 contextfetch-world-news.sh → world-news-search.sh (RSS→Qdrant); PE_WORLD_CONTEXT_RAG_ENABLED flagGREEN
probessh 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.
Action arbiter (per-type due gate)platform/operator/action-arbiter.sh — writes arbiter_decisions, exports _PE_ELIGIBLE_TYPESGREEN
probecurl '$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 builtplatform/operator/opportunity-queue-builder.shGREEN
probecurl '$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 claimGREEN
probecurl '$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 sweeprun-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
probecurl '$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 gateplatform/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
probessh 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 QUESTIONv4-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
probecurl '$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 7d' returns >=3 DISTINCT media_id values (NOT status=eq.confirmed filter — use distinct media_id)
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 draftAMBER ⚠ no evidence
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
probecurl '$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 generationimage_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 uploadsb_upload_persona_image → threads_post_image; NO-TRAFFIC — never reached when generation failsAMBER ⚠ no evidence
Safety — injection scanPrompt injection scan on draft inputs; adjacent to grounding gateGREEN
probessh 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 breakerStops publishing if too many consecutive failures; 0 circuit_open rows ever firedGREEN
probecurl '$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.
Safety gate — grounding checkgrounding-gate.sh — layer1 PCRE live, layer2 LLM disabledAMBER
probecurl '$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 checkvoice-check.sh — redraft_trace written to action_logGREEN
probecurl '$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 qualitypost-gate.sh — saturation D4 checksGREEN
probecurl '$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 gateagent-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_shipAMBER
probecurl '$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.
Slop judge (D7)slop-judge — unified redraft loop PE_REDRAFT_UNIFIED=1AMBER
probecurl '$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 checkunified fingerprint (family_fp/exact_fp/formula) — post-gate.sh, flag PE_CONSTRUCTION_UNIFIED=1; CHECK-ONLY here, window append happens at confirmed publishAMBER
probecurl '$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)GREEN
probecurl '$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 Bplatform/adapters/threads/api.sh or browser — Threads Graph API / mobileGREEN
probecurl '$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 writtenplatform/lifecycle/action-log.shAMBER ⚠ no evidence
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 cycleAMBER
probecurl '$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.shGREEN
probecurl '$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 actionauto-score.shGREEN
probecurl '$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 updateauto-composite-reward.sh → auto-bandit.shGREEN
probecurl '$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 unwiredAMBER
probecurl '$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 occurrenceAMBER
probeAfter 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 evalTests content variants vs baseline; 56/192 concluded_refuted with lift_pct; platform/learning/experiment-eval.shAMBER
probecurl '$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 savedWrites today's learned patterns for tomorrow's strategist; platform/learning/strategist-write.shGREEN
probeAfter 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 proposalProposes voice changes based on what worked; strategy_proposals table; PROVEN LIVE 2026-06-12AMBER ⚠ no evidence
Governance applierapply_approved_proposals in run-cycle.sh; applies approved strategy+voice changes; RC1 FIXED 2026-06-02GREEN
probecurl '$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 snapshotRecords follower count + engagement metrics; health_snapshot tableAMBER ⚠ no evidence
Autopilot health checkDetects health breaches + spawns self-repair agent; health_snapshot table; deploy key read-only so fixes not shippedGREEN
probessh 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.
Cycle-conductor post-maintenanceplatform/operator/cycle-conductor.sh — eval + reflect (CYCLE-CONDUCTOR-01)AMBER ⚠ no evidence
2 Comment Lifecycle 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.
BEFORE — setup and intelligence ⚠ Cycle-conductor pre-maintenance platform/operator/cycle-conductor.sh — strategist (CYCLE-CONDUCTOR-01) Action arbiter (per-type due gate) platform/operator/action-arbiter.sh — comment in eligible_types CSV Discovery / feed scan scan-feed.sh + profile_scan — home_feed candidates 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) Candidate screen (7-rule filter) candidate-screen.sh — off_niche/low_eng/media_blocked gates Opportunity queue builder platform/operator/opportunity-queue-builder.sh Claim next opportunity (CAS lock) claim_next_opportunity — atomic claim with action_id 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) Peer 2nd-degree discovery (REMOVED) REMOVED anti-ban 1aa96b7c — Playwright auth fail DURING — draft, gate, publish LLM draft — comment v4-runner.sh — Thompson draw selects comment_style 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 Safety gate — voice check voice-check.sh Safety gate — opener quality post-gate.sh — QUOTE_OPEN Tier B gate Construction-monotony check unified fingerprint (family_fp/exact_fp/formula) — post-gate.sh, flag PE_CONSTRUCTION_UNIFIED=1; comment-path coverage added in 4d398e53 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 Publish comment Path B platform/adapters/threads/browser.sh — mobile Threads ⚠ action_log row written action-log.sh — media_id + target_author + selected_comment_style 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 AFTER — record, score, learn Score comment auto-score.sh + auto-check-replies.sh direct-score path Comment style sub-bandit update auto-bandit.sh — feed_comment_style_bandit helper (b1385948) ⚠ Cycle-conductor post-maintenance platform/operator/cycle-conductor.sh — eval + reflect
StepWhat it doesStatusIf broken
Cycle-conductor pre-maintenanceplatform/operator/cycle-conductor.sh — strategist (CYCLE-CONDUCTOR-01)AMBER ⚠ no evidence
Action arbiter (per-type due gate)platform/operator/action-arbiter.sh — comment in eligible_types CSVGREEN
probecurl '$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)
Discovery / feed scanscan-feed.sh + profile_scan — home_feed candidatesGREEN
probecurl '$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)AMBER
probecurl '$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)
Candidate screen (7-rule filter)candidate-screen.sh — off_niche/low_eng/media_blocked gatesGREEN
probecurl '$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 builderplatform/operator/opportunity-queue-builder.shGREEN
probecurl '$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_idGREEN
probecurl '$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 fixorphan-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
probecurl '$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.
LLM draft — commentv4-runner.sh — Thompson draw selects comment_styleGREEN
probecurl '$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 rowsGREEN
probecurl '$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 checkvoice-check.shGREEN
probecurl '$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 qualitypost-gate.sh — QUOTE_OPEN Tier B gateGREEN
probecurl '$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 checkunified fingerprint (family_fp/exact_fp/formula) — post-gate.sh, flag PE_CONSTRUCTION_UNIFIED=1; comment-path coverage added in 4d398e53AMBER
probecurl '$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 changeAMBER
probeAfter 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 Bplatform/adapters/threads/browser.sh — mobile ThreadsGREEN
probecurl '$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 writtenaction-log.sh — media_id + target_author + selected_comment_styleAMBER ⚠ no evidence
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-backfillRED
probecurl '$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)
Score commentauto-score.sh + auto-check-replies.sh direct-score pathGREEN
probecurl '$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)
Comment style sub-bandit updateauto-bandit.sh — feed_comment_style_bandit helper (b1385948)GREEN
probecurl '$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)
Cycle-conductor post-maintenanceplatform/operator/cycle-conductor.sh — eval + reflectAMBER ⚠ no evidence
3 Reply Lifecycle 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.
BEFORE — setup and intelligence ⚠ Cycle-conductor pre-maintenance platform/operator/cycle-conductor.sh — strategist (CYCLE-CONDUCTOR-01) Action arbiter (per-type due gate) platform/operator/action-arbiter.sh — reply in eligible_types ⚠ auto-check-replies scan auto-check-replies.sh — reads own_comment_url ⚠ pending_replies queue build_opportunity_queue — reply slots from pending_replies table DURING — draft, gate, publish LLM draft — reply v4-runner.sh Safety and voice gate pre-execute.sh + voice-check.sh Publish reply Path B platform/adapters/threads/browser.sh ⚠ action_log row written action-log.sh AFTER — record, score, learn Score reply auto-score.sh ⚠ Cycle-conductor post-maintenance platform/operator/cycle-conductor.sh — eval + reflect
StepWhat it doesStatusIf broken
Cycle-conductor pre-maintenanceplatform/operator/cycle-conductor.sh — strategist (CYCLE-CONDUCTOR-01)AMBER ⚠ no evidence
Action arbiter (per-type due gate)platform/operator/action-arbiter.sh — reply in eligible_typesGREEN
probecurl '$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 scanauto-check-replies.sh — reads own_comment_urlAMBER ⚠ no evidence
pending_replies queuebuild_opportunity_queue — reply slots from pending_replies tableAMBER ⚠ no evidence
LLM draft — replyv4-runner.shAMBER
probecurl '$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 gatepre-execute.sh + voice-check.shAMBER
probecurl '$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 Bplatform/adapters/threads/browser.shGREEN
probecurl '$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 writtenaction-log.shAMBER ⚠ no evidence
Score replyauto-score.shGREEN
probecurl '$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)
Cycle-conductor post-maintenanceplatform/operator/cycle-conductor.sh — eval + reflectAMBER ⚠ no evidence
4 Learning Loop (V4 self-learning) 2026-07-04: VERIFIED — all 5 linked nodes verified 2026-07-04
How engagement signals feed back into strategy, voice DNA, and action selection — F1-F5 flows plus successful-day detector.
BEFORE — setup and intelligence Engagement signals (action_log + ETS) auto-collect-signals.sh — 28,931 engagement_target_signals rows F1 — Strategist fires (pillar_shift) strategist-daily.sh — proposal 3ac7a0e7 pillar_shift PROVEN 2026-06-07 ⚠ 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. F2 — Voice proposal saved strategist-daily.sh writes voice_change to strategy_proposals DURING — draft, gate, publish F2 — Voice applier executes auto-voice-applier.sh — PROVEN LIVE 2026-06-12 01:24Z F3 — weight_learning_log writer auto-composite-reward.sh — 422 rows live F4 — auto-bandit arm reweight auto-bandit.sh — 10 arms; SWH 6 rows since Jun 8 F4 — Opp-scorer reads bandit arms PE_BANDIT_VALUE_WEIGHT=0.20 ENABLED 2026-06-10 AFTER — record, score, learn F5 — _os_score boost active 85 rows with learning_value; boost active since env_overrides v104
StepWhat it doesStatusIf broken
Engagement signals (action_log + ETS)auto-collect-signals.sh — 28,931 engagement_target_signals rowsGREEN
probecurl '$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)
F1 — Strategist fires (pillar_shift)strategist-daily.sh — proposal 3ac7a0e7 pillar_shift PROVEN 2026-06-07GREEN
probeAfter 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 savedstrategist-daily.sh writes voice_change to strategy_proposalsGREEN
probecurl '$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 executesauto-voice-applier.sh — PROVEN LIVE 2026-06-12 01:24ZGREEN
probecurl '$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 writerauto-composite-reward.sh — 422 rows liveGREEN
probecurl '$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 reweightauto-bandit.sh — 10 arms; SWH 6 rows since Jun 8GREEN
probecurl '$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 armsPE_BANDIT_VALUE_WEIGHT=0.20 ENABLED 2026-06-10GREEN
probecurl '$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 active85 rows with learning_value; boost active since env_overrides v104GREEN
probecurl '$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
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.
BEFORE — setup and intelligence scan-feed.sh writes opportunity_candidates scan-feed.sh — 500 candidates/7d, nmc=0 rate 92% opportunity-queue-builder.sh writes operator_opportunity_queue reads candidates + scoring_weight_history; writes OOQ DURING — draft, gate, publish v4-runner.sh reads/writes action_log reads opp from opportunity_candidates; writes draft rows AFTER — record, score, learn auto-collect-signals.sh writes engagement_target_signals 28,931 ETS rows live; reads confirmed action_log strategist-daily.sh writes strategy_proposals + strategist_briefing reads engagement_aggregates; daily cadence confirmed auto-voice-applier.sh writes voice_dna_versions reads approved strategy_proposals; BA-6: VDV audit row missing
StepWhat it doesStatusIf broken
scan-feed.sh writes opportunity_candidatesscan-feed.sh — 500 candidates/7d, nmc=0 rate 92%GREEN
probecurl '$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
opportunity-queue-builder.sh writes operator_opportunity_queuereads candidates + scoring_weight_history; writes OOQGREEN
probecurl '$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
v4-runner.sh reads/writes action_logreads opp from opportunity_candidates; writes draft rowsGREEN
probecurl '$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 7d' returns >=3 DISTINCT media_id values (NOT status=eq.confirmed filter — use distinct media_id)
auto-collect-signals.sh writes engagement_target_signals28,931 ETS rows live; reads confirmed action_logGREEN
probecurl '$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)
strategist-daily.sh writes strategy_proposals + strategist_briefingreads engagement_aggregates; daily cadence confirmedGREEN
probeAfter 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)
auto-voice-applier.sh writes voice_dna_versionsreads approved strategy_proposals; BA-6: VDV audit row missingGREEN
probecurl '$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.
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.
BEFORE — setup and intelligence Score action (auto-score.sh) confidence floor 0.3 for comment/reply Composite reward (auto-composite-reward.sh) post: zero_signal_omit; comment: cr=1.12-1.60 on got_reply DURING — draft, gate, publish weight_learning_log written 422 rows; comment arm success rows; post arm failure-only auto-bandit.sh — arm update 10 arms; post alpha=8/beta=178; comment alpha=45/beta=318 scoring_weight_history written 6 rows since Jun 8; 3 domains updated Jun 09T04:04 AFTER — record, score, learn opp-scorer reads arms — bandit_value bandit_value=0.5 in 66 rows; PE_BANDIT_VALUE_WEIGHT=0.20 ENABLED _os_score boost to claim ordering learning_value in 85 rows; boost active since env_overrides v104 Voice evolution — PROVEN LIVE 2026-06-12 auto-voice-applier.sh — applied_at=2026-06-12T01:24Z; voice-dna-comments.md updated
StepWhat it doesStatusIf broken
Score action (auto-score.sh)confidence floor 0.3 for comment/replyGREEN
probecurl '$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_replyGREEN
probecurl '$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 written422 rows; comment arm success rows; post arm failure-onlyGREEN
probecurl '$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 update10 arms; post alpha=8/beta=178; comment alpha=45/beta=318GREEN
probecurl '$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 written6 rows since Jun 8; 3 domains updated Jun 09T04:04GREEN
probecurl '$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_valuebandit_value=0.5 in 66 rows; PE_BANDIT_VALUE_WEIGHT=0.20 ENABLEDGREEN
probecurl '$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 orderinglearning_value in 85 rows; boost active since env_overrides v104GREEN
probecurl '$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
Voice evolution — PROVEN LIVE 2026-06-12auto-voice-applier.sh — applied_at=2026-06-12T01:24Z; voice-dna-comments.md updatedGREEN
probecurl '$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.
7 Draft Intel (7a/7b/7c) 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).
BEFORE — setup and intelligence Action arbiter (per-type due gate) platform/operator/action-arbiter.sh — determines action type before intel assembly DURING — draft, gate, publish v4_runner_draft call site v4-runner.sh — v4di_inject_draft_intel called before session intel ⚠ Budget gate (32k total / 6.8k intel) intel-blocks.sh — BG2 + BG1 byte caps Per-action-type profiles injected intel-blocks.sh — BANDIT_ALLOC/BANDIT_REC/WLL_FORMAT/PILLAR_FORCE/LANGUAGE_DIRECTIVE 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) LLM call with enriched prompt v4-runner.sh — _v4_inject_session_intel lands last assemble-prompt.sh (DEAD) LEGACY — not used by respiro-brand V4 path
StepWhat it doesStatusIf broken
Action arbiter (per-type due gate)platform/operator/action-arbiter.sh — determines action type before intel assemblyGREEN
probecurl '$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 sitev4-runner.sh — v4di_inject_draft_intel called before session intelGREEN
probecurl '$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 7d' returns >=3 DISTINCT media_id values (NOT status=eq.confirmed filter — use distinct media_id)
Budget gate (32k total / 6.8k intel)intel-blocks.sh — BG2 + BG1 byte capsAMBER ⚠ no evidence
Per-action-type profiles injectedintel-blocks.sh — BANDIT_ALLOC/BANDIT_REC/WLL_FORMAT/PILLAR_FORCE/LANGUAGE_DIRECTIVEGREEN
probeAfter 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 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
probecurl '$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 promptv4-runner.sh — _v4_inject_session_intel lands lastGREEN
probecurl '$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 7d' returns >=3 DISTINCT media_id values (NOT status=eq.confirmed filter — use distinct media_id)
8 Comment Style Sub-Bandit 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).
BEFORE — setup and intelligence Arbiter — comment eligible platform/operator/action-arbiter.sh — comment in _PE_ELIGIBLE_TYPES DURING — draft, gate, publish Thompson draw — comment_style arm _v4cs_select_comment_arm — reads bandit_arms action_type=comment_style:* LLM draft with selected style v4-runner.sh — style injected into prompt AFTER — record, score, learn Comment scored (direct-score path) auto-check-replies.sh + auto-score.sh — feed_comment_style_bandit helper Bandit arm update bandits.sh — alpha/beta increment for selected arm
StepWhat it doesStatusIf broken
Arbiter — comment eligibleplatform/operator/action-arbiter.sh — comment in _PE_ELIGIBLE_TYPESGREEN
probecurl '$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)
Thompson draw — comment_style arm_v4cs_select_comment_arm — reads bandit_arms action_type=comment_style:*GREEN
probecurl '$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 stylev4-runner.sh — style injected into promptGREEN
probecurl '$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 scored (direct-score path)auto-check-replies.sh + auto-score.sh — feed_comment_style_bandit helperGREEN
probecurl '$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 updatebandits.sh — alpha/beta increment for selected armGREEN
probecurl '$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)
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.
BEFORE — setup and intelligence Content format config persona_config.post_forms_enabled/post_lengths_enabled/series_enab led/polls_enabled (M1); customer toggles via /settings/content 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. DURING — draft, gate, publish Post format selector get_recommended_arm_constrained() in bandits.sh — Thompson sample ∩ enabled set; cold-start fallback = first allowed arm 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) 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 AFTER — record, score, learn Outcome collection (4h delay) auto-collect-signals.sh — engagement signals; series: post_series.status=complete required for reward Auto-score (score ≥50 = success) auto-score.sh — composite engagement 0-100; same threshold as comment_style 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 Strategist reads form/length performance reads action_bandits post_form:*/post_length:* alpha/beta + post_series table; proposes format_shift via strategy_proposals Governance applier apply_approved_proposals — applies approved format_shift to persona_config (never direct write — invariant #4)
StepWhat it doesStatusIf broken
Content format configpersona_config.post_forms_enabled/post_lengths_enabled/series_enabled/polls_enabled (M1); customer toggles via /settings/contentAMBER
probecurl '$SUPABASE_URL/rest/v1/persona_config?select=post_forms_enabled,post_lengths_enabled,series_enabled,polls_enabled&persona_id=eq.respiro-brand' returns >=1 row with post_forms_enabled array non-null AND ssh VPS 'cat safety-overrides.json | jq .content_formats' returns non-null block (proves M1 applied + sidecar sync active)
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
probecurl '$SUPABASE_URL/rest/v1/persona_config?select=post_forms_enabled,post_lengths_enabled,series_enabled,polls_enabled&persona_id=eq.respiro-brand' returns >=1 row with post_forms_enabled array non-null AND ssh VPS 'cat safety-overrides.json | jq .content_formats' returns non-null block (proves M1 applied + sidecar sync active)
Post format selectorget_recommended_arm_constrained() in bandits.sh — Thompson sample ∩ enabled set; cold-start fallback = first allowed armAMBER
probecurl '$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 + lengthv4-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
probecurl '$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)
Publish (post / thread_chain / poll)Existing publish_post / publish_thread_chain (agent-tool:1408) / publish_poll (agent-tool:1506); per-part safety gate not bypassedGREEN
probecurl '$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 rewardGREEN
probecurl '$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 banditGREEN
probecurl '$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 updatefeed_post_format_bandits() in bandits.sh — idempotent via metadata.post_form stamp (M3); series: only reward status=completeGREEN
probecurl '$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)
Strategist reads form/length performancereads action_bandits post_form:*/post_length:* alpha/beta + post_series table; proposes format_shift via strategy_proposalsGREEN
probeAfter 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 applierapply_approved_proposals — applies approved format_shift to persona_config (never direct write — invariant #4)GREEN
probecurl '$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.
BEFORE — setup and intelligence Niche ontology screening @0.60 candidate-screen.sh — 348-node wellness ontology rejects off-niche (tau=0.60); GREEN but screening-only (does not reach draft text) DURING — draft, gate, publish ⚠ GAP: ontology not in draft prompt assemble-prompt.sh — 0 refs to niche ontology; screens targets but never informs comment wording (FORMAT-GAP-01) Voice V2 frames injected assemble-prompt.sh — PE_COMMENT_VOICE_V2=1; comment_recency_frames=7 prohibitions prepended; GREEN comment_style bandit draw (5 arms) bandits.sh — 5 arms real alpha/beta (sharp_question/reframe/data_cite/challenge/lived_experience); Thompson draw active RECENT_COMMENT_OPENERS + anti-template assemble-prompt.sh:1949 — opener list injected; rhetorical-formula block active; anti-template GREEN LLM draft text generated v4-runner.sh — engagement.md prompt; 40/40 distinct bodies; 5 styles; GREEN (last fire 2026-06-21T14:43Z) Critic + safety gates voice-check.sh + post-gate.sh — voice-filter + opener gate firing GREEN (36 drafts blocked/48h, 1 passed) ⚠ TARGET: ontology node label → draft prompt TARGET: inject niche ontology wellness angle into assemble-prompt.sh comment prompt to inform wording (FORMAT-GAP-01 fix) AFTER — record, score, learn Publish → own_comment_media_id browser.sh — 79/408 7d (19%); 860 status=learned all-time; GREEN publish path Engagement feedback — THIN auto-check-replies.sh — 11/860 all-time have feedback; signal sparse (AMBER; limits bandit learning)
StepWhat it doesStatusIf broken
Niche ontology screening @0.60candidate-screen.sh — 348-node wellness ontology rejects off-niche (tau=0.60); GREEN but screening-only (does not reach draft text)GREEN
probecurl '$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 promptassemble-prompt.sh — 0 refs to niche ontology; screens targets but never informs comment wording (FORMAT-GAP-01)RED ⚠ no evidence
Voice V2 frames injectedassemble-prompt.sh — PE_COMMENT_VOICE_V2=1; comment_recency_frames=7 prohibitions prepended; GREENGREEN
probecurl '$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 activeGREEN
probecurl '$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-templateassemble-prompt.sh:1949 — opener list injected; rhetorical-formula block active; anti-template GREENGREEN
probecurl '$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 generatedv4-runner.sh — engagement.md prompt; 40/40 distinct bodies; 5 styles; GREEN (last fire 2026-06-21T14:43Z)GREEN
probecurl '$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
Critic + safety gatesvoice-check.sh + post-gate.sh — voice-filter + opener gate firing GREEN (36 drafts blocked/48h, 1 passed)GREEN
probecurl '$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)
TARGET: ontology node label → draft promptTARGET: inject niche ontology wellness angle into assemble-prompt.sh comment prompt to inform wording (FORMAT-GAP-01 fix)AMBER ⚠ no evidence
Publish → own_comment_media_idbrowser.sh — 79/408 7d (19%); 860 status=learned all-time; GREEN publish pathGREEN
probecurl '$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 — THINauto-check-replies.sh — 11/860 all-time have feedback; signal sparse (AMBER; limits bandit learning)GREEN
probecurl '$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.
BEFORE — setup and intelligence Opportunity seed (~60/day) operator_opportunity_queue — ~60 seeds/day (overproduces vs 2-4/day cadence; AMBER) ⚠ 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) ⚠ TARGET: spacing defer → opportunity requeue TARGET: spacing_guard_max_defers path → requeue to OOQ (not terminal skip); gives deferred opportunities a second chance DURING — draft, gate, publish Bandit format draw (form + length) bandits.sh — post_form:*/post_length:* Thompson draw; form-suite code deployed (AMBER pending first scored post) Opener-block injection v4di_opener_block in draft-intel — steers opener type away from recent repeats (FIX-POST-GEN-VARIETY-01) ⚠ 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) ⚠ 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 ⚠ 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) LLM draft via GLM backend v4-runner.sh — content.md prompt; text written to action_log.context.text (NOT payload.text) ⚠ 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 Safety gates (grounding/voice/slop) grounding-gate + voice-check + slop-judge — binding post-2026-06-26 (dissonance-formula + phrase-saturation walls) ⚠ 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 ⚠ TARGET: ontology → post draft prompt TARGET: inject wellness ontology node label/angle into content.md + draft-intel post prompt (FORMAT-GAP-01 fix) ⚠ 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 ⚠ 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) AFTER — record, score, learn 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 ⚠ 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) ⚠ TARGET: 48h backfill revived TARGET: repair signal_48h backfill job; feeds engagement quality signal into post scoring + bandit loop
StepWhat it doesStatusIf broken
Opportunity seed (~60/day)operator_opportunity_queue — ~60 seeds/day (overproduces vs 2-4/day cadence; AMBER)GREEN
probecurl '$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 CHOKEPOINTv4-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 requeueTARGET: spacing_guard_max_defers path → requeue to OOQ (not terminal skip); gives deferred opportunities a second chanceAMBER ⚠ no evidence
Bandit format draw (form + length)bandits.sh — post_form:*/post_length:* Thompson draw; form-suite code deployed (AMBER pending first scored post)AMBER
probecurl '$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 injectionv4di_opener_block in draft-intel — steers opener type away from recent repeats (FIX-POST-GEN-VARIETY-01)GREEN
probecurl '$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 promptcontent.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 firedvoice_recency_frames=0; framing_angle null all posts — post-publish hook needs >=1 published V2 post to seed angle prohibitionsRED ⚠ no evidence
GAP: form-rotation not in draft promptPE_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 backendv4-runner.sh — content.md prompt; text written to action_log.context.text (NOT payload.text)GREEN
probecurl '$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 7d' returns >=3 DISTINCT media_id values (NOT status=eq.confirmed filter — use distinct media_id)
GAP: zombie-sweeper reads payload.textrun-cycle.sh:483-498 — sweeper reads payload.text (empty), not context.text → 803/24h orphaned rows; no redraft path for stuck claimed actionsRED ⚠ no evidence
Safety gates (grounding/voice/slop)grounding-gate + voice-check + slop-judge — binding post-2026-06-26 (dissonance-formula + phrase-saturation walls)AMBER
probecurl '$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 fallbackTARGET: zombie-sweeper (run-cycle.sh:483-498) fallback to context.text when payload.text empty; unblocks 803/24h orphaned row queueAMBER ⚠ no evidence
TARGET: ontology → post draft promptTARGET: 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_framesTARGET: post-publish hook fires after first V2 post; seeds voice_recency_frames prohibitions for angle diversity auto-loopAMBER ⚠ no evidence
TARGET: form-rotation → draft prompt instructionTARGET: 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 mismatchGREEN
probecurl '$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 DEADsignal_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 revivedTARGET: repair signal_48h backfill job; feeds engagement quality signal into post scoring + bandit loopAMBER ⚠ 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.
BEFORE — setup and intelligence ⚠ Queue / approvals pages web/app/(dashboard)/queue + queue-health — customer reviews pending posts, approves/rejects; web/app/api/dashboard/queue/* routes ⚠ Safety + health pages web/app/(dashboard)/safety + health + system-health — gate overrides, health signals; web/app/api/dashboard/safety/* health/* routes 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) DURING — draft, gate, publish ⚠ Analytics / growth / funnel pages web/app/(dashboard)/analytics + growth + funnel + efficiency + focus — performance metrics surfaces ⚠ 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 ⚠ 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 AFTER — record, score, learn ⚠ Settings / topics / stories / experiments pages web/app/(dashboard)/settings + topics + stories + experiments + notifications + fleet — 7 remaining page groups not mapped above
StepWhat it doesStatusIf broken
Queue / approvals pagesweb/app/(dashboard)/queue + queue-health — customer reviews pending posts, approves/rejects; web/app/api/dashboard/queue/* routesGREEN ⚠ no evidence
probeFor 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 pagesweb/app/(dashboard)/safety + health + system-health — gate overrides, health signals; web/app/api/dashboard/safety/* health/* routesGREEN ⚠ no evidence
probeFor 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)AMBER
probecurl '$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
Analytics / growth / funnel pagesweb/app/(dashboard)/analytics + growth + funnel + efficiency + focus — performance metrics surfacesGREEN ⚠ no evidence
probeFor 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 returnGREEN ⚠ no evidence
probeFor 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 stubsGREEN ⚠ no evidence
probeFor 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 pagesweb/app/(dashboard)/settings + topics + stories + experiments + notifications + fleet — 7 remaining page groups not mapped aboveGREEN ⚠ no evidence
probeFor 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.

Watch in 24h

7 watches
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)
curl '$SUPABASE_URL/rest/v1/strategy_proposals?select=id,proposal_type,status,created_at&persona_id=eq.respiro-brand&proposal_type=eq.format_shift&created_at=gte.NOW()-interval 96h' — PASS if >=1 row. Strategist reads action_bandits post_form:*/post_length:* alpha/beta.
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.
[WATCH-FIX3-BATCH-LIVE-PROOF-01] FIX3-BUILD-MISSION (F1-F7) shipped 2026-07-02 — needs live-proof soak (re-check 2026-07-03)
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.

Execution Queue

105 open tasks
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.
FIX-POST-BLOCKED-STATUS-P0-18 | in_progress | #18 P0: posts blocked at status=blocked starving posts+comments — session-budget-bail + pre-blocked-row bug + OOQ pool exhaustion.
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.
FIX-OPENER-GATE-CONVERSION-01 | in_progress | #17 FIX-OPENER-GATE-CONVERSION-01 — opener gate conversion fix (in_progress, partially delivered)
FIX-STRATEGIST-PILLARS-REGRESSION-16 | pending | #16 R4-followup: strategist recommended_pillars regression — pillar weights stale/incorrect after R4 changes.
QA-ONBOARDING-EXISTING-ACCOUNT-E2E-01 | pending | QA-ONBOARDING-EXISTING-ACCOUNT-E2E-01
RESEARCH-PERSONA-PHOTO-REALISM-01 | pending | RESEARCH-PERSONA-PHOTO-REALISM-01
BUG-OUTCOME-WATCH-BASELINE-01 | deployed-observing | None
BUG-COMMENT-TARGET-LOW-ENGAGEMENT-01 | deployed-observing | None
BUG-COMMENT-IMAGE-VIDEO-TARGETS-01 | deployed-observing | None
FIX-OQ-STALE-EXPIRE-RACE-01 | deployed-observing | None
FIX-COMPETITOR-TRENDING-SCORE-01 | deployed-observing | None
FIX-COMPETITOR-V4-INJECT-01 | deployed-observing | None
FIX-BACKSTORY-TIMELINE-WIRE-01 | deployed-observing | None
FIX-BACKSTORY-SEEDER-DEPLOY-01 | deployed-observing | None
KEYSTONE-B-COMMENT-GRAPH-ID-LIVE-01 | pending | None
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.
FIX-GRAVEYARD-SIGNAL-DEADLINKS-01 | pending | VERIFIED PARTIAL 2026-06-15 (P1): signal-swallow real (pe_log DEBUG<INFO claim success path v4-runner.sh:1221 + run-cycle.sh:1007); probe REFUTED. Fix=DEBUG->INFO.
FIX-IS-ACTIVE-FAIL-CLOSED-01 | pending | VERIFIED CONFIRMED 2026-06-15 (P1): is_active fail-OPEN on DB error (run-cycle.sh:146-154 + 887-889). Fix=cache last-known + fail-closed.
FIX-V4-LEARNING-LOOP-WIRING-01 | pending | VERIFIED PARTIAL 2026-06-15 (P1): select_action_arms 0 callers (dead); V4 output not parsed->correction_episodes empty; DRAFT_INTEL_ENABLED=1 live.
FIX-PROD-SILENT-DEGRADATIONS-BUNDLE-01 | deployed-observing | VERIFIED 3/4 2026-06-15 (P1): (a) voice-card.md never rendered w/ V4_VOICE_CARD=1 (v4-runner.sh:283); (b) backfill-engagement 0 callers; (d) qdrant embed asymmetry (client.sh:792). (c) REFUTED.
QUALITY-POST-TOPIC-DIVERSITY-01 | pending | None
QUALITY-COMMENT-TARGET-POPULARITY-01 | pending | None
QUALITY-COMMENT-FORMAT-DIVERSITY-01 | pending | None
FIX-V4-CRASH-LOCALISATION-01 | pending | None
BUG-REDRAFT-EXHAUSTION-01 | pending | None
STAB-AUTOPILOT-V2-BUILD-BRAIN-01 | pending | None
FU-COMMENT-SUPPLY-STARVATION-01 | pending | None
THROUGHPUT-6x60 | in_progress | None
PILLAR-MONOTONY | pending | None
COMMENT-TARGET-QUALITY | pending | None
LEARNING-LOOP-APPLY | deployed-observing | None
VERIFY-UNBLOCK-POSTS-01-LIVE | pending | None
VERIFY-STRATEGIST-DAILY-REBUILD-01 | pending | None
DECIDE-EXPERIMENT-CAP-BF158665-01 | pending | None
DIAG-COMPETITOR-TRENDING-SCORE-DEADDEPLOY-01 | pending | None
FIX-POST-DRAFT-CHOKEPOINT-01 | pending | None
FIX-48H-ENGAGEMENT-BACKFILL-DEAD-01 | pending | None
FIX-POST-VOICE-V2-FRAME-HOOK-DEAD-01 | pending | None
FEAT-WIRE-ONTOLOGY-INTO-WRITING-PROMPT-01 | pending | None
FIX-POST-GATE-RETRY-RECOVERY | deployed-observing | None
FIX-POST-CRASH-FALSE-NEGATIVE | deployed-observing | None
FIX-POST-SELFFORK-REEXEC-01 | deployed-observing | None
MEDIUM
BUG-V4-COMMENT-CAP-BYPASS-JQ-01 | pending | None
AUDIT-D11-FAL | deployed-observing | None
AUDIT-S11-WORLDNEWS | pending | None
BACKFILL-TARGET-AUTHOR-01 | pending | None
FIX-POST-SKIP-REQUEUE-01 | deployed-observing | None
FIX-COMMENT-STYLE-V4-INJECT-01 | pending | None
FU-STRATEGY-PROPOSALS-JSON-INJECT-01 | pending | None
FU-VOICE-APPLIER-QUALIFY-HARDENING-01 | pending | None
FIX-ORPHAN-RECOVERY-01 | pending | None
FU-IMAGE-CEILING-PERSONA-SCOPE-01 | pending | None
FIX-VOICE-DNA-VERSIONS-AUDIT-01 | pending | None
FIX-STRATEGY-PROPOSAL-ATTRIBUTION-01 | pending | None
FIX-TRENDS-WHY-PROMPT-01 | pending | None
SCORING-RESAMPLE-24H-48H-01 | pending | None
FIX-VOICE-DNA-AUDIT-LOG-01 | pending | VERIFIED PARTIAL 2026-06-15: OPENER_TYPE bug already fixed; remaining=_ava_backup_version omits persona_id/run_mode (auto-voice-applier.sh:155) -> audit rows unqueryable. Observability-only, 2-field payload fix.
SYS-GC-EPHEMERA-TTL-01 | pending | None
SYS-UNIFIED-SEARCH-MEMORY-01 | pending | None
TOPIC-DEDUP-INSTRUMENTATION-01 | pending | None
SCORING-CONTEXT-LLM-FEATURES-01 | pending | None
FU-COMMENT-REPLY-PIPELINE-STALE-01 | pending | None
COMMENT-SPACING-FAILOPEN | pending | None
BACKLOG-SAFETY-AUDIT | pending | None
FU-PFS-SERIES-REWARD-PROBE-01 | pending | None
VERIFY-6X60-SOAK-NIGHT-01 | pending | None
VERIFY-BLOCK-DETAIL-LIVE-01 | pending | None
FU-VOICE-ANGLE-DIVERSITY-01 | pending | None
RISK-7-PERSIST-MERGE-RACE-01 | pending | None
RISK-8-DRAFT-UNIQUE-NULL-01 | pending | None
FIX-POST-BLOCK-REASON-OBSERVABILITY-01 | pending | None
FIX-FORM-ROTATION-NOT-IN-WRITING-PROMPT-01 | pending | None
FIX-SOAK-DASHBOARD-TZ | deployed-observing | None
FIX-COMMENT-BLOCK-DETAIL-PERSIST-02 | pending | None
SHIP-P1-A-3-COMMENT-RECENCY-FRAMES | pending | None
FIX-EXPERIMENT-VARIANT-LABEL | pending | None
FIX-OFFHOURS-DEFER-GATE-WIRING | pending | None
FIX-DEPLOY-SCRIPT-RECONCILE-01 | pending | None
LOW
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).
BUG-LOG-STDERR-AS-ERROR | pending | None
BUG-NICHE-PENDING-PGRST102-GUARD-01 | pending | BUG-NICHE-PENDING-PGRST102-GUARD-01
BUG-NICHE-PROFILESCAN-QUALITY-WATCH-01 | pending | BUG-NICHE-PROFILESCAN-QUALITY-WATCH-01
AUDIT-A7-BRIEFING-LINK | pending | None
FIX-TCR5-SCREENER-HARNESS-01 | pending | None
FU-STRATEGY-PROPOSALS-RLS-BYPASS-01 | pending | None
FU-RETAG-MIGRATION-COLUMN-COSMETIC-01 | pending | None
FU-V4-RUNNER-LOG-HYGIENE-01 | pending | None
FU-STRATEGY-PROPOSALS-REPAIR-MIGRATION-STATUS-01 | pending | None
FIX-DRAFT-INTEL-BLOCKED-TOPIC-HINT-01 | pending | None
FU-IDEATION-REVIEW-TAILS-01 | pending | None
REPLIES-FIXED-01 | pending | None
LEARNING-LOOP-E2E-01 | pending | None
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. Run: /leadv2 "<TASK-ID>"