Onboard new Indian stocks into the "Paise se Paisa" Action Dashboard end-to-end, using the v2 vault-aligned machinery (understanding gate → quality-gated conviction with ROIC+runway → conservative IV range → conviction-scaled margin-of-safety vs opportunity cost → reformed verdict). Use when the user says "add stocks", "add the next batch", "onboard <tickers>", "grow the dashboard", "re-rank", or wants to extend the TO-BUY/study list. Workspace: /Users/Dhiraj/dev/invest, sheet fileId 1N87younF990u-YGMOAiT8q6X-EtZ3jVovlWCF44orEY. Charlie Munger & Warren Buffett (the Obsidian vault) are the binding CIO; the vault gates conviction/verdict/MoS, it is not narrative decoration.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Instruções da origem · Visualização somente leitura
name
stock-onboarding-pipeline
description
Onboard new Indian stocks into the "Paise se Paisa" Action Dashboard end-to-end, using the v2 vault-aligned machinery (understanding gate → quality-gated conviction with ROIC+runway → conservative IV range → conviction-scaled margin-of-safety vs opportunity cost → reformed verdict). Use when the user says "add stocks", "add the next batch", "onboard <tickers>", "grow the dashboard", "re-rank", or wants to extend the TO-BUY/study list. Workspace: /Users/Dhiraj/dev/invest, sheet fileId 1N87younF990u-YGMOAiT8q6X-EtZ3jVovlWCF44orEY. Charlie Munger & Warren Buffett (the Obsidian vault) are the binding CIO; the vault gates conviction/verdict/MoS, it is not narrative decoration.
Stock Onboarding Pipeline (v2 — vault-aligned)
The single source of truth for adding stocks to the Action Dashboard. Follow the stages in order.
v2 machinery adopted 2026-06-12 after a CIO review (Munger/Buffett via the vault) found v1
"looked Buffett but ranked like a quant trading desk", and that the vault only fed narrative.
See [[reference-paise-se-paisa-sheet]] and [[feedback-indian-mentors-lens]] in memory. The live
process is documented in the sheet's ⚙️ Machinery v2 tab; per-stock grades in 🔍 Conviction & MoS v2.
Retrieval plumbing upgraded 2026-06-12 (brain-densification Phase 4): all vault consultation now goes
through data/scripts/32_consult_brain.py (scoped, cited, structured) — the v2 logic itself is unchanged.
North star
The dashboard is a STUDY LIST in search of ONE strictly-lifelong hold (FOREVER) — not a buy-list,
and not a 45-name basket (Munger: 1–3 wonderful businesses suffice; act rarely). Indian Substack
analysts (Vaibhav & Gaurav Tambade = "India's Buffett/Munger"; plus Karan Shah, The Megatrend Investor,
Dhruva) supply the bull thesis + ground-truth context; Charlie Munger & Warren Buffett (the vault) are
the FINAL, BINDING arbiters. Finding zero FOREVER names — and finding that nothing clears the
margin-of-safety bar at today's prices — is an acceptable, expected result. Patience is the edge.
See also — ETFs / REITs / InvITs: this pipeline is for individual stocks → the 🎯 Action Dashboard.
For a fund (ETF, REIT, InvIT) use etf-reit-onboarding instead — it evaluates funds like stocks but
publishes to the 🌍 Global & Passive Base tab and NEVER touches the LOCKED Action Dashboard.
HARD RULES (never violate)
Never re-grill / re-dossier stocks already done. Existing dossiers in vault/research/dossiers/*.md
are frozen inputs. Only dossier the NEW stocks. (Exception A — DATA FIX: a stock whose dossier had a data error —
e.g. wrong price — may be corrected; that is a fix, not a re-grill.) (Exception B — EVENT REFRESH: when
data/scripts/70_detect_material_events.py flags a MATERIAL event on a dashboard/HELD name, the dossier HEAD WINDOW may be
refreshed under the news-results-refresh skill. Only the head window is touched — research PROSE stays frozen.
L0 staleness-stamp (last_event_checked) + L1 one-line catalyst/"Why" refresh AUTO-apply.
L2 — IV / conviction / verdict-DEMOTION / within-tier flips / MoS recompute now ALSO AUTO-apply AND AUTO-re-rank the
LOCKED Action Dashboard through the guarded loop (user override, 2026-06-25): an earning-power event passes
coln_iv_event_gate.py → 71_refresh_orchestrator.py runs a targeted Stage-3 re-grade (binding-vault consult +
80_estimate_iv.py price-independent IV + conviction gates + MoS/buy_below recompute + verdict re-derive + board
sanity-check) → re-freezes the dossier head → 73_refresh_cycle.sh stage 3c invokes 82_rerank_guard.py --tag headwindow (once per cycle, after the reindex) to re-rank + publish the whole set behind a 3-tab
backup + dry-run-diff + ticker-keyed checksum + auto-revert + maker≠checker, gated by env RERANK_AUTO=1 AND brain-healthy post-reindex AND ≥1 L1 applied this cycle (71 never calls 82 — the re-rank is once-per-cycle in 73).
RERANK_AUTO is DEFAULT-OFF: the capability shipped (PR #33) and is now wired into the loop (73 stage 3c), but stays off pending a supervised first-enable — until
then 73 doesn't even invoke 82; if run manually, 82 dry-runs + asserts + prints the order-diff and STOPS (no live re-rank). RERANK_AUTO is NOT set in the plist — enabling it is the user's explicit supervised toggle. (A re-rank CARRIES the live col-D verdict + col-M conv byte-for-byte; reconcile a stale D/M cell to the dossier oracle first with the sanctioned writer sync_col_dm.py → write_col_dm.mjs, else 82's carried-cell assertion ABORTS.) SOLE human gate: a FOREVER promotion
(Stage-4 adversarial "strictly-lifelong" inversion a cron can't do) — and any needs_review/board-contradiction — routes
to data/state/pending_reviews/<TICKER>.json and is NEVER auto-applied. Price / FII / MF flows / ratings / buy-calls
move live MoS + Upside (cols I/J/K) ONLY — they NEVER trigger IV or a re-grade.)
Autonomy-ladder ratification. Ratified 2026-07-03 (PW-13): the daily loop auto-consults fresh (≤2d)
RED+MATERIAL events, hard-capped at CYCLE_CONSULT_BUDGET=25/cycle, RED-first-oldest-first. L1 auto-applies;
L2 IV/conviction/verdict changes including upgrades up through COMPOUND auto-apply under 82_rerank_guard.
FOREVER promotion remains the sole permanent human gate. Backlog (>2d) events consult only under DRAIN_GO=1
(founder-gated). The value-digest reports these changes (email); it never grades.
CONSULTING THE BRAIN (data/scripts/32_consult_brain.py — the ONE retrieval entrypoint)
set -a && source /Users/Dhiraj/dev/invest/.env && set +a && /Users/Dhiraj/dev/invest/.venv/bin/python \
/Users/Dhiraj/dev/invest/data/scripts/32_consult_brain.py \
--company "<name>" \
--model <bank|insurance|consumer-brand|commodity-cyclical|utility-psu|capital-goods|platform|general> \
--step <circle|conviction|intrinsic-value|margin-of-safety|opportunity-cost|verdict|inversion|capital-allocation|sizing> \
[--corpus <binding|blended>] [--entities <peer-slugs,comma-sep>] [--k 8] --json-out extracted/grilling/<TICKER>_<step>.json
What it does: derives 2-3 model-aware retrieval questions from the stock context, routes internally
(specific model or entities → ScopedLanceDBBackend with caller-supplied scope, 0 Azure calls;
general + no entities → hybrid + GPT rerank, 1 Azure call/question — the two are NEVER stacked,
measured worse), RRF-merges + dedupes, and hygiene-filters to mentors' atomics/raws + _synthesis
(hubs, MOCs, _system, dossiers, positions excluded; every path verified on disk).
How to read the output:principles: [{claim, path, slug, citation, mentor, note_type, source_note, applies_to_model, applies_to_filter, rrf_score}]. claim = the principle to apply; citation/slug =
the ONLY tokens permitted in cites_principles; source_note = traceability to the raw transcript/letter.
Empty principles → vault is thin here → ABSTAIN + flag, never pad.
FINANCE-DESK SPECIALISTS (additive advisory layer — they inform; the binding CIO at 0/3/4 decides)
Dispatch these sharpened skills at the stages below to SHARPEN the analysis. They are an additive, --corpus blended-informed
advisory layer (blended surfaces desk-synthesis atomics + perspectives ALONGSIDE binding); the perspectives they surface are
pitch-side / down-weighted and NEVER reverse a --corpus binding verdict. The Munger/Buffett CIO at Stages 0/3/4 stays THE arbiter.
Skill
Stage
Role
primary-research-sentiment
1
DD/sentiment harvest (ValuePickr/Reddit/concall), framed as disconfirmation-seeking
forensic-accounting-redflags
1
governance-integrity gate → CLEAN/CAUTION/RED (CAUTION caps conviction; RED hard-fails to AVOID/TOO_HARD)
moat-analysis
3
enriches the moat call in conviction/verdict
capital-allocation-judge
3
6-axis CEO scorecard; consults --step capital-allocation --corpus blended
valuation-dcf-longrunway
3 (& 1 step 4)
IV method for operating cos (conservative range); operationalized price-free by 80_estimate_iv.py (multi-stage DCF) for the news-loop IV re-grade
bank-valuation
3 (& 1 step 4)
IV method for banks/NBFCs (justified-P/B); operationalized price-free by 80_estimate_iv.py (justified-P/B / excess-return) — fixes the least-grounded IVs
decision-journal
4
behavioral decision artifact + inversion enrichment; records sentiment-cycle locus + FOREVER re-decision cadence
Understanding gate + triage: for each name ask "would I own the whole business 10 years with the market shut?"
Ground the call: 32_consult_brain.py --company "<name>" --model <model> --step circle and apply the returned
circle-of-competence principles (cite their slugs). Genuinely too-hard → TOO_HARD bucket, off the buy-list.
Verify NSE symbol (live ≈ expected ±5%; .BO/BSE for InvITs).
STAGE 1 — N parallel dossier workers (Workflow, Sonnet) — NEW stocks only
Each writes vault/research/dossiers/<TICKER>.md to IGI-depth (read vault/research/dossiers/IGI.md as the
template; frontmatter per vault/CLAUDE.md). Steps: (1) WebFetch article + Substack comments; (2) fresh web
research (latest quarter, price, splits, governance); (3) brain consult (32_consult_brain.py --company "<name>" --model <model> --step conviction --json-out extracted/grilling/<TICKER>_conviction.json, then likewise
--step margin-of-safety — both mentors arrive in one call, mentor carried per-principle; use ONLY returned
slugs); (4) method-appropriate IV as a conservative range (ground with --step intrinsic-value if needed); (5) "Author's voice" + "Comment-thread
red flags" sections; (6) verdict + kill-criteria (inversion) + honesty flags. Barrier: all dossiers exist.
Desk specialists (advisory): run primary-research-sentiment (disconfirmation-seeking DD harvest) and the
forensic-accounting-redflags integrity gate (CLEAN/CAUTION/RED — CAUTION caps conviction, RED hard-fails to AVOID/TOO_HARD);
valuation-dcf-longrunway / bank-valuation may build the conservative IV range in step 4. They inform; the binding gate decides.
STAGE 2 — Fundamentals fetch (mechanical) — the compounding-quality data
For ALL stocks (old + new), fetch via yfinance statements (NOT .info — it rate-limits): ROCE
(EBIT / (Stockholders Equity + Total Debt)), ROE (Net Income / Equity), and 4-year FCF (Free Cash Flow,
count positive years + latest FCF/PAT). This is the owner-earnings + returns-on-capital evidence conviction needs.
Add a 0.3s sleep between tickers. Output /tmp/fundamentals_v2.json.
One agent per stock over the FULL set. Each reads its dossier + gets its fundamentals (ROCE/ROE/FCF) + the
binding vault principles — the per-stock 32_consult_brain.py output for steps conviction,
margin-of-safety and (where IV is contested) intrinsic-value/verdict; embed the returned claims+citations
in the prompt, cites_principles ⊂ returned slugs — + the conviction rubric & MoS thresholds, then
applies JUDGMENT (not a formula) and returns structured: {understanding (in|too_hard), conviction_v2 (1-5) + rationale, roic_runway_note, iv_low/iv_base/iv_high, mos_pct, required_mos_pct, clears_bar, buy_below_v2, verdict_v2, sell_logic}. Honest + conservative — "nothing clears the bar" is the expected answer. (Existing
dossiers are frozen inputs; re-grading their conviction/verdict against the whole set is allowed and required.)
Desk specialists (advisory):moat-analysis sharpens the moat call, capital-allocation-judge runs the 6-axis CEO
scorecard (--step capital-allocation --corpus blended), and valuation-dcf-longrunway / bank-valuation supply the IV
method. They inform the re-grade; the --corpus binding conviction/verdict gate remains the arbiter.
For every FOREVER candidate: a skeptic pulls disconfirming vault principles
(32_consult_brain.py --company "<name>" --model <model> --step inversion — moat erosion, management failure,
MoS as protection against being wrong) and checks for bias
(mere-association, overconfidence, market-prediction focus), and argues the strongest case it is NOT strictly
lifelong (moat that can't be lost overnight, clean owner-earnings, aligned long-horizon owner, price not heroic).
Survive all axes → FOREVER; else demote. Default = demote. No standing Chairman FOREVER overrides — the prior IGI & CAMS override was REVOKED 2026-06-17 (both graded to WATCH on the merits; the FOREVER tier is currently EMPTY). Grade every name honestly, IGI/CAMS included, no exceptions.
Desk specialists (advisory):decision-journal records the behavioral decision artifact + inversion enrichment (sentiment-cycle locus,
standing FOREVER re-decision cadence), and portfolio-sizing informs the Max-size (col-M) call (--step sizing --corpus blended).
They inform; the --corpus binding FOREVER gate decides — desk perspectives never lift a name into FOREVER.
STAGE 5 — Price engine as a CLERK (mechanical, optional, informational only)
The Family-D engine (data/scripts/30_d_engine.py) may be run to answer "is a buyable entry plausible / where
is the MoS line" — but it is demoted: volatility ≠ risk, it does NOT set verdict, conviction, or the rank.
Its sheet tab (🧮 D-Engine, gid 1487890548) is annotated DEMOTED. Skip if not needed.
STAGE 6 — Final sort & publish (mechanical, no rework)
⚠️ READ BEFORE TOUCHING THE SHEET — the cockpit is hand-tuned & LOCKED ([[feedback-sheet-is-locked]]). The live sheet is canonical; if a helper disagrees, FIX THE HELPER, never the sheet, and NEVER bypass a helper with raw sheets_update_cells for new/reordered rows (raw writes lose number-formats, banding, verdict colors, sparkline colors → broke the dashboard 2026-06-17). The Action Dashboard is 18 columns A–R: A Rank·B Stock·C Company·D Verdict·E Buy-below·F Avg·G Live·H Sell·I Status·J To-buy·K Upside·L Sparkline·M Conv·N Why·O Dossier·P P/E (TTM)·Q P/S·R EV/Sales. Locked format spec: dashboards/action-dashboard-style.json (re-capture via introspect-dashboard.js when layout changes).
Rank key = lexicographic (verdict_tier [FOREVER<COMPOUND<WATCH<AVOID<TOO_HARD], −conviction_v2, −mos_pct). No other tiebreakers (not author, not legacy sheet order, not D-engine). Within WATCH, higher conviction always ranks above lower; within same verdict+conviction, higher MoS% ranks above lower (even if MoS is negative). TOO_HARD quarantined off the buy-list. Two-rank gotcha: the Dashboard EXCLUDES TOO_HARD; companion tabs (Conv, Deep) INCLUDE them → compute TWO orders (companion = same sort with TOO_HARD appended last; non-TOO_HARD companion rank MUST equal dashboard rank so dashboard col-O range=A<rank+1> resolves in the Deep tab). To re-derive mos for EXISTING rows from the dashboard alone: iv_base = buy_below / (1 − req_mos/100), mos% = (iv_base − live)/iv_base × 100 (req_mos by conv: 5→10,4→15,3→25,2→40,1→55).
PUBLISH RUNBOOK (every batch, in order): (1) BACK UP all 3 tabs to extracted/dengine/backup_<tag>_<ts>/ (values+grid) — a revert point is mandatory. (2) Re-rank the WHOLE set + insert new rows with the CANONICAL helpers in /Users/Dhiraj/dev/invest/tools/sheets-bridge/: multi_insert_dashboard.js is the reliable multi-row insert (reads full grid, carries col-B author hyperlinks byte-for-byte, regenerates row-relative I/J/K/L, re-stamps A rank + O dossier link, colors new col-B by author_rgb; NEW non-Substack names → PLAIN black ticker, no hyperlink). It takes orderFile=[{rank,ticker,verdict,conv,mos,is_new}] + newStocksFile={TICKER:{symbol,company,verdict,buyBelow,sell,conv,why,priceFallback,exch,(source_url+author_rgb only if Substack)}}. why MUST come from dossier ## One-line thesis — never Obsidian [!info] callouts. Writes A–O only. Always --dry-run first (manual onboarding); the news loop runs this same runbook UNATTENDED via 82_rerank_guard.py, where "dry-run first" becomes an automated dry-run-diff gate that ABORTS on any unexpected diff — 82 backs up all 3 tabs, dry-runs the order, asserts ONLY row-order + col-A rank changed and each row's verdict/conv/IV matches its re-graded dossier (checksum keyed by ticker, not row), and auto-reverts on anomaly; the live write is armed by RERANK_AUTO=1 (code default OFF; ENABLED in the LaunchAgent plist 2026-06-25 → live on the scheduled loop). Do NOT use republish.js (drops HYPERLINK rows) and do NOT use for batches (single-row); raw is BANNED for new/reordered rows. (3) Companion tabs: (🔍 Conviction & MoS v2) + (Buffett-Munger Deep Ranking — needed for dossier links). (2b) — mandatory after every reorder: re-key from dossier () and from by ticker on col B (reorder leaves P/Q/R on stale physical rows). across (PR #31/#32 + col-N-for-every-row 2026-06-26): the maker is (drives a sweep universe via ), the checker (Gate 8 re-derives the 📰 segment from so news is never fabricated and never precedes the verdict word; ), and the via . 79 publishes whenever a VALID col-N can be synthesized and skips ONLY: , a genuinely THIN dossier (BOTH best AND worst NEEDS_REVIEW), no rendered string, or head_overflow. A board contradiction / governance flag / within-tier is a CONTESTED GRADE that still publishes the current verdict's col-N and is RECORDED for human adjudication (78's + ), never withheld. The 📰 clause is verdict-NEUTRAL reportage (, ~80-char budget), appended LAST so truncation never eats verdict/best/worst. On an L1 head edit, chains 77 re-synth → 79 re-publish (col-N-only). — each with a single-column assert + inverted checksum (excluded live-col set ) + per-row diff + backup + auto-revert + env flag ( / ); now renders a diagnosable sparkline fallback instead of a silent blank. (4) if layout changed, → refresh (must be ); then to extend banding/CF — running lock with a stale capture corrupts the sheet. (5) only if Substack names were added. (6) Reindex (next bullet) → → verify.
Scripts: brain consult data/scripts/32_consult_brain.py (the BINDING gate — scoped+cited, see CONSULTING
THE BRAIN); free-form vault RAG 29_vault_chat.py (ad-hoc Q&A only); index 26_build_lancedb_index.py;
price-engine clerk 30_d_engine.py (demoted); fundamentals = yfinance statements (ROCE/ROE/FCF, not .info).
Dynamic-IV + news machinery (PR #30–#34, the news-results-refresh loop drives these):data/scripts/80_estimate_iv.py (price-INDEPENDENT fundamental IV by brain_model: multi-stage DCF for compounders /
justified-P/B for banks-NBFC-insurance / mid-cycle DCF for cyclicals; binding-brain-grounded slugs; compute_iv is a
cold-start fallback only — --test proves two prices → identical IV); data/scripts/coln_iv_event_gate.py
(earning-power-vs-sentiment discriminator — only a structural results delta / capacity / durable order-book / restatement
arms an IV re-grade; price/FII/MF/ratings/buy-calls → False); data/scripts/82_rerank_guard.py (the ONLY thing allowed to
re-rank the LOCKED dashboard — 3-tab backup + dry-run-diff + ticker-keyed checksum vs the re-graded dossiers + auto-revert,
behind RERANK_AUTO=1, default-OFF, --self-test; invoked in the loop by 73 stage 3c gated by RERANK_AUTO + brain-health + ≥1 L1, never from 71); data/scripts/sync_col_dm.py + tools/sheets-bridge/write_col_dm.mjs (sanctioned col-D(verdict)/col-M(conviction) sync — reconciles the carried D/M cells to the dossier oracle so a guarded re-rank passes 82's carried-cell assertion; default dry-run, COL_DM_DASHBOARD_WRITE=1 to write; 2-column assert + inverted checksum + per-row diff + backup + auto-revert; --test/--self-test); data/scripts/81_audit_dashboard_consistency.py (read-only daily
drift auditor — re-derives every col-N cell / verdict word / 📰 / rank-position vs the source of truth, WRITES NOTHING,
gates exit on class-1/2/5; --strict gates all); (read-only 📰 segment — latest
MATERIAL event from → dated factual verdict-neutral clause; never fabricates).
HEAD-WINDOW RULE: when correcting a dossier (data fix OR a re-grill finding), you MUST edit the HEAD WINDOW — the frontmatter snapshot + the one-line thesis in the first ~4,000 chars — NOT just an appended tail section. 26_build_lancedb_index.py embeds only ONE ~4,000-char head vector per dossier, so tail appends are invisible to brain retrieval. (A stale Repco-CBI "open case" flag kept surfacing until the head one-line thesis was fixed, 2026-06-18; appending a "## Re-grill" section at the tail alone did nothing.)
Always re-rank the WHOLE set (old + new) after adding — never just the new ones. (The whole-set re-rank is now
ALSO wired into the news loop: 73_refresh_cycle.sh stage 3c invokes 82_rerank_guard.py --tag headwindow to re-run the
Stage-6 publish runbook unattended behind the re-rank guard + auto-revert + maker≠checker, gated by RERANK_AUTO=1
(default-OFF, NOT in the plist, pending supervised enable) AND a healthy post-reindex brain AND ≥1 applied L1 this cycle. A
FOREVER promotion still requires the human Stage-4 gate.)
The vault is BINDING, not decoration.data/scripts/32_consult_brain.py (scoped, cited retrieval — see
CONSULTING THE BRAIN below) gates conviction, verdict and MoS at Stages 0/3/4. cites_principles may contain
ONLY slugs it actually returns (principles[].slug). No fabricated citations. If principles comes back
empty/thin → abstain + flag. (29_vault_chat.py stays available for free-form cited Q&A / ad-hoc grilling.)
Quality is a HARD GATE before price. Order of analysis: understanding → moat/owner-earnings/management
→ ONLY THEN price. A business you can't understand, or with no durable moat, cannot earn high conviction
regardless of price or optics.
Conviction = JUDGMENT, not a formula (Munger: avoid false precision / formulaic thinking). It measures
durable business quality, price-independent — see the rubric in KEY REGISTRY. Gates: no moat → 1;
chronically weak/near-zero FCF → cap 2; returns below ~12% cost of capital → cap 2. Banks/NBFCs judged on
ROE vs cost of equity (ROCE/FCF N/A); InvITs cap 2; quasi-financials (heavy FCF can offset modest ROCE).
Margin of safety is THE gate (the cornerstone, widens with uncertainty), scaled to conviction
(conv5 ≥10%, conv4 ≥15%, conv3 ≥25%, conv2 ≥40%, conv1 ≥55%), measured vs opportunity cost (the best
existing idea), NOT a bond yield. IRR HURDLE (named gate): a BUY must clear the index — expected IRR > the ~9–10% Nifty return (the default opportunity cost); a wonderful business that can't beat the index from today's price is a WATCH, not a BUY. Volatility ≠ risk — the old GBM price engine is a DEMOTED clerk
(informational only: "is an entry plausible / where's the MoS line"), never the judge or tiebreak.
Intrinsic value is a conservative RANGE (low/base/high), never a false-precise point. Buy-below =
iv_base × (1 − required_MoS). IV = business EARNING POWER, and is PRICE-INDEPENDENT — it re-estimates ONLY when
news changes earning power (a structural results delta, a capacity add, a durable order win) via a real DCF / justified-P/B
(80_estimate_iv.py takes NO price input). Price, FII/MF flows, ratings and buy-calls NEVER move IV — they move live
MoS + Upside (cols I/J/K) only. A "dynamic IV" that drifts with the quote would make the dashboard buy high and sell low.
Sell ₹ + Upside are written for every NON-FOREVER verdict — never blank them (Chairman rule 2026-06-13).
WATCH / AVOID / TOO_HARD each carry a numeric Sell ₹ = fair-value target (IV-high) AND an Upside%=(Sell−Live)/Live (honestly negative when the price is above fair value), alongside the WATCH buy-below
entry trigger. ONLY FOREVER/COMPOUND show "DON'T SELL" / "∞ hold" (lifelong hold; sell only on thesis-break,
moat erosion, a better opportunity, or a cash need). Do NOT blank a Sell/Upside cell for a WATCH/AVOID name
(that was a publish bug — the upside column must always render a number for non-FOREVER rows).
Too-hard → DISCARD from the buy-list, don't rank it (Buffett's three buckets: in / out / too-hard).
Loss-makers with no clear path, unpredictable/rapid-change businesses → TOO_HARD quarantine. Forced
inactivity is a feature.
Read the article AND its comment thread (Substack API — comments are real signal). Method-appropriate
valuation (DCF for operating cos; justified-P/B for banks; distribution-yield for InvITs; mid-cycle-EPS
multiple for commodity cyclicals). Always check for stock splits and validate the dossier's current_price
against the live yfinance close (a stale enriched-pipeline snapshot once put a price 17% wrong).
5-tier verdict exactly one per stock: FOREVER / COMPOUND / WATCH / AVOID / TOO_HARD.
add-stock.js
sheets_update_cells
multi_insert_conv.js
multi_insert_deep.js
IS_NEW RULE: in the companion order, any ticker that ALREADY exists in that companion tab (e.g. a prior-batch TOO_HARD like MAHSCOOTER, which the dashboard omits but companion tabs keep) MUST be is_new:false — else the deep/conv insert errors ("no row for new "). The dry-run catches it. So a carried-over TOO_HARD just gets its rank re-stamped, never re-built.
col-N is published for EVERY row — including AVOID / board-contradiction / needs_review names, analysed and filled exactly like any other stock. The binding Munger/Buffett CIO (vault) verdict is PRIMARY and is what col-N shows; the 56-director board panel is ADVISORY and NEVER vetoes col-N publication.
verdict==NEEDS_REVIEW
needs_review
board_contradictions
81_audit_dashboard_consistency.py
coln_news_segment.py
71_refresh_orchestrator.py
There are now TWO sanctioned single-column writers: write_col_n.mjs (col N) and write_col_l.mjs (col L, 1-yr-trend SPARKLINE, PR #30)
{6,8,10,11,13,18}
COL_N_DASHBOARD_WRITE=1
COL_L_DASHBOARD_WRITE=1
lib/dashboard-format.js
—
Lock formatting:
introspect-dashboard.js
dashboards/action-dashboard-style.json
18-col A–R
lock-dashboard-style.js
link-authors.js
reload daemon
Values: conviction = conv_v2, buy-below = buy_below_v2 (MoS-gate), verdict = verdict_v2; FOREVER/COMPOUND → Sell "DON'T SELL" (Upside "∞ hold"); WATCH/AVOID/TOO_HARD → numeric Sell = iv_high (rule 8 — NEVER blank a non-FOREVER Sell/Upside; Upside formula =IF($D="FOREVER","∞ hold",TEXT(($H-$G)/$G,"+0%;-0%")) needs a numeric Sell). NEVER hand-paint C/J/K — they auto-color via native conditional formatting (K&C green when (H−G)/G>50% or FOREVER/COMPOUND, yellow 30–50%; J yellow when within 20% of buy-below; AVOID/TOO_HARD never colored). E/F/G/H must be NUMBER-typed (₹#,##0). sheet-exec.js runs generic ops.
New dossiers → embed into RAG: .venv/bin/python data/scripts/26_build_lancedb_index.py --vault vault --db vault/.lancedb (this script auto-reloads the warm daemon; confirm /health after).
🔍 Conviction & MoS v2 (gid 1264181600): rewrite the full per-stock table (rank, ROCE/ROE, FCF, IV range,
MoS%, req MoS%, clears-bar, buy-below, verdict, conviction rationale, sell logic).
⚙️ Machinery v2 (gid 49292954): the documented process — update only if the machinery itself changes.
Buffett-Munger Deep Ranking (gid 508986127): re-stamp col A = new rank + col I = verdict for ALL, then
sortRange by rank (so dashboard "view" hyperlinks → row = rank+1 resolve). Add rows for new stocks (C&W prose).
Back up the prior engine/grade state (e.g. extracted/dengine/backup_v1/). Sync avgCost from INDmoney
(mcp__indmoney__networth_holdings IND_STOCK: avg = invested_amount/total_units) for held names.
Update memory ([[reference-paise-se-paisa-sheet]]) with the new order + FOREVER finding + whether anything cleared the MoS bar.
data/scripts/coln_news_segment.py
event_index.sqlite
Helpers in /Users/Dhiraj/dev/invest/tools/sheets-bridge/: add-stock.js (new styled row), republish.js (formula-preserving
reorder + overrides), sheet-exec.js (generic ops runner), verify-row.js, clear-row.js, lock-dashboard-style.js,
introspect-dashboard.js (capture live format → dashboards/action-dashboard-style.json), sync_dashboard_extras.js
(post-reorder col N + P/Q/R by ticker), multi_insert_dashboard.js, add_multiples_columns.js. Sanctioned single-column
writers (single-column assert + inverted checksum + auto-revert + env flag): write_col_n.mjs (col N) and write_col_l.mjs
(col L).lib/dashboard-format.js (shared row-cell builder; diagnosable — sparkline fallback).
CONVICTION RUBRIC (1-5, judgment within gates, price-independent): 5 = wide durable moat + pristine high
ROCE/ROE (≥25%) + clean multi-year FCF + long reinvestment runway + aligned mgmt (almost never). 4 = strong moat +
high returns + clean owner-earnings + good mgmt. 3 = real but narrower moat + good returns + reasonably clean FCF +
decent runway. 2 = partial moat OR lumpy/weak FCF OR returns near cost of capital OR short/unproven. 1 = no durable
moat (commodity/replicable/no pricing power). Gates: no-moat→1; weak-FCF→cap2; ROIC<~12%→cap2; bank-below-Ke→cap2;
InvIT→cap2. MoS thresholds: conv5 ≥10%, conv4 ≥15%, conv3 ≥25%, conv2 ≥40%, conv1 ≥55%.
Verdict colors (Dashboard col D, rows 4-60): FOREVER green, COMPOUND blue #c9daf8, WATCH amber, AVOID red.
E/F/G/H must be NUMBERS (₹#,##0 format) for the live GOOGLEFINANCE/Status/sparkline engine to work.