Rot vectors and where to look first
The system is single-operator and accreted across many decisions. Some coupling is deliberate (storage routing), some is the cost of not having a v2 refactor yet. This page documents both — what to watch for, and where to start when something changes.
Adding a new domain — the 6 touch points
The model implies "just add an entry to _domains.yaml." Reality
is six places, of which only one is declarative:
-
_domains.yamlentryIndexer derives include/exclude prefixes from this. Add slug, taxonomy file, review queue file, embedding config, decay mode, lexical weight, recency boost. Declarative.
-
launchd plists
Two per domain:
com.shourjo.kb-<domain>-indexer.plist(uvicorn port allocation) + ingest plist if applicable. Lives in~/Library/LaunchAgents/. -
Slash commands (3 files)
~/.claude/commands/rx-<domain>.md(generator) +-status.md(disposition) +-history.md(action-rate). Each is hardcoded to the door's storage backend. -
/rx-boardfilter listThe
$1domain filter is a literal allowlist. New domain = edit the file. -
/rx-digestper-domain branchesThe digest generator iterates a hardcoded list of doors. Add a new branch for the new domain's storage backend.
-
/rx-analyzedomain pairCurrently hardcoded to
{fitness, finance}. Adding a new domain to the analysis loop is a manual edit.
Hardcoded coupling — find before refactoring
Renaming a domain (e.g. finance → markets) requires touching
every place the literal string appears. Inventory of known sites:
| Site | Lock type |
|---|---|
TradingV migration 0029_recommendations.sql — CHECK (domain = 'finance') | SQL constraint |
TradingV Pydantic schema — Literal["finance"] | Python type |
Supabase recommendations.domain CHECK (domain IN ('fitness','nutrition')) | SQL constraint |
Lovable WHERE-clause filter — frontend + server filter on domain IN ('fitness','nutrition') | App code |
Phase W reconciler branch — if domain == 'finance' selects backend | Slash command |
/rx-*-status regex — filename pattern check | Slash command |
RX_OPERATOR_UUID env hardcoded in .env.laptop | Env var |
kb-mcp sources.yaml port routing | MCP config |
Known limitations to plan around
Substring hypothesis ↔ rec linkage (finance)
D-046 introduced hypothesis_id resolution by searching the
rec's body markdown for the hypothesis slug. False-positive prone:
a rec mentioning "NVDA" matches every hypothesis whose slug contains
"nvda" — even unrelated ones.
Mitigation path (deferred): explicit operator-tagged linked_hypotheses frontmatter field, validated at write time.
Embedding model immutability
embedding_dim is baked into the SQLite cache schema. Changing
EMBEDDING_MODEL env without deleting the cache crashes
startup. There is no automatic re-embed sweep.
Procedure: stop indexer → rm cache-<domain>.db →
restart → wait for full re-index (minutes to tens of minutes
depending on corpus size).
Learning empty corpus
Indexer :8004 is live but the vault has no learning
content. bundle(scope="learning") returns 0 results.
The /rx-learning command tolerates this by setting
thesis_match=0 and continuing.
Mitigation: operator must populate Videos/learning/_ingest_queue.md and run an ingest.
Snooze auto-revive timezone drift
D-039 noted a timezone bug in finance auto-revive — snoozed_until
compared against NOW() at the application layer vs
NOW() at the DB layer in inconsistent ways. The fix lives
inside /rx-finance.md step 0.5 but is not codified as a
regression test. Risk: silent regression on any rewrite of the
command.
Cross-cutting commands learning-aware (resolved by D-048, 2026-05-19)
Historical: when D-047 shipped the learning slice on 2026-05-18,
/rx-board, /rx-digest, and
/rx-analyze were left enumerating
{fitness, finance, nutrition} only — invisible breakage
for any learning rec that landed.
Resolved by D-048 (Phase Q.5, 2026-05-19): all three commands are
now 4-domain. /rx-board + /rx-digest also
switched finance source from Lakshmi/rx/*.md filesystem
read to TradingV LOCAL postgres recommendations table
(D-046 contract). Degraded fallback to Lakshmi markdown mirror if
TradingV daemon unreachable. Per-domain auto-revive split across
writable surfaces (fitness Supabase UPDATE, learning markdown Edit,
finance read-only display-only).
Lovable RLS is permissive
Phase U/V shipped with USING (true) RLS policy on the
Supabase recommendations table — single-tenant assumption.
Multi-tenant safety deferred post-v1.x. Frontend + server both filter
by owner_user_id client-side. If the verocity app is
ever shared with another operator, this is the first thing to harden.
Nutrition zombie data — disposition channel unresolved
Supabase recommendations accepts domain='nutrition'
rows but no UI surface reads them (D-047 removed Lovable's nutrition
tab). If /rx-nutrition is ever wired in scaffold-to-live mode
without first re-routing storage or building a UI, the rows will sit
invisible in the table.
D-048 surfaced this as two blockers, not one: daily-log data
source (default Athena/daily_log.md per D-027, never confirmed)
AND disposition channel (no UI). Athena/rx/SPEC.md banner
now enumerates 4 resolution options:
- Markdown-only mirror of Ganesh learning pattern (Pragmatist recommendation)
- Supabase write + manual disposition (status quo, friction)
- Build local nutrition UI (Critic veto until ≥5 dispositioned recs with sustained ≥30% action-rate)
- Reverse D-047 + add Lovable nutrition tab (operator directive change)
Until operator picks, /rx-nutrition stays in scaffold
mode: reports state + decision menu, does NOT generate recs.
Where the doors-storage mapping actually lives
{fitness: supabase, nutrition: supabase, finance:
tradingv_local, learning: markdown} is not declared in any
single yaml or json file. It is reconstructable only by reading
D-045 + D-047 in rx-meta/DECISIONS-LOG.md plus the project
CLAUDE.md tables. A maintainer wishing to verify "where does
door X write?" must read those prose sources, then grep slash commands.
The closest thing to a canonical declaration is the facts inventory in
the project README.md (alongside this site) and the source-of-truth
table in AGENTS.md §3. If you change the mapping, update those
tables first — they are the only spots designed to be re-quoted.
Re-verification workflow
When source repos change, run this re-research pass:
1. Spawn 4 parallel explore agents: - TradingView app — tables, ingest sources, /rx-finance endpoints - Sho's Playgroun — 4 doors, rx artifacts, DECISIONS-LOG (latest D-NNN) - knowledge-vault — _domains.yaml, embedding pipeline, taxonomy - Lovable verocity — Supabase schema, disposition flow 2. Run an adversarial 4-voice council pass: - Skeptic (factual errors) - Architect (missing edges, failure modes) - User-advocate (clarity for non-technical readers) - Maintainer (rot vectors, hardcoded coupling) 3. Diff against this site's views/*.html. Update only affected pages. 4. Do NOT touch any source repo — this is an additive explainer.
Source-of-truth quick reference
| Question | Where to look |
|---|---|
| Latest decisions? | ~/Documents/Sho's Playgroun/rx-meta/DECISIONS-LOG.md |
| Current phase status? | ~/Documents/Sho's Playgroun/rx-meta/ROADMAP-v1_*.md |
| Domain registry? | ~/Documents/knowledge-vault/_domains.yaml |
| TradingV tables? | ~/Documents/Claude/TradingView/migrations/ (Alembic SoT, not create_all) |
| TradingV module docs? | ~/Documents/Claude/TradingView/.claude/modules/ |
| Slash commands? | ~/.claude/commands/rx-*.md |
| Embedding config? | ~/Documents/Claude/TradingView/tools/vault_indexer/config.py |
| Chunking? | ~/Documents/Claude/TradingView/tools/vault_indexer/vault.py:chunk_body() |
| Hybrid retrieval? | ~/Documents/Claude/TradingView/tools/vault_indexer/{hybrid,lexical,graph_compute}.py |
| Lovable schema? | Supabase via mcp__Lovables_verocity__list_objects |
| Reconciler logic? | Step 0.5 + 0.7 of ~/.claude/commands/rx-<door>.md |
The deletions log — what got removed
Architectural simplifications worth remembering:
| What | When | Why |
|---|---|---|
| Lovable nutrition surface | D-047 · 2026-05-17 | Operator-directed scope reduction. Lovable = fitness-only. |
| Railway deploy | ADR 018 · 2026-05-17 | Cost + complexity not justified for single-operator app. Local-only since. |
| Auto-cron snooze revive | D-032 | Surprised operator with unexpected rec re-appearance. Made lazy. |
| BackendToggle component | 2026-05-18 cleanup | Vestigial from when Railway was an alt-backend. No purpose post-ADR-018. |
| Original D-045 (Lovable for nutrition) | Overridden by D-047 | D-045 still describes storage routing correctly; only the UI surface for nutrition was changed. |
Future v1.x candidates (per ROADMAP-v1_x)
/rx-meta— cross-domain meta-recommender. Gated on ≥30% action-rate + ≥10 dispositioned recs per door (D-030).- Phase K scheduler — auto-trigger recs on threshold breaches without manual command invocation. Gated on action-rate health.
- Explicit hypothesis ↔ rec frontmatter linking (replaces substring heuristic).
- Nutrition rx generator wiring (Phase J.2) — depends on operator-chosen daily-log source.
- Learning corpus ingest at scale — depends on operator drop of URLs.