Fomo kernel
Turn your broker CSV into one behavioral review card
npx -y skills add atomchung/fomo-kernel --skill fomo-kernelAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 8 stars8 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Review a user's trades into one local card and an append-only thesis record, and weigh a trade they are still deciding on against their own book. Transaction history supports behavioral diagnosis; a position snapshot supports an opening structural check; a considered trade gets its engine-computed consequence — resulting weight, concentration, driver overlap, cash, and any rule of their own it would break — with the case for and against it. Use for trade reviews, transaction postmortems, brokerage-statement reviews, position reviews, and for pre-trade questions such as should I buy this, am I chasing, should I add here, or does this break my own rule, in any supported language. Not a price-target or market-forecast tool.
SKILL.md
16.1 KB, as published. Nobody here has run it
fomo-kernel
Turn transaction history into one focused behavior-review card, or a position snapshot into one narrow opening portfolio check. Both routes preserve thesis continuity and at most one user-chosen rule.
The product's value is continuity: this review reconciles against the last one, and the next one reconciles against this. That is why the boundaries below hold — a number that changes meaning between weeks makes the whole loop unreadable.
Global output voice
For every user-visible Skill surface, follow
docs/output-voice.md. It owns universal output
semantics and cross-host invariants; each selected route reference owns the
facts, slots, and order its answer requires. Load that authority for
consider and no-book decision framing.
Non-negotiable rules
- Numbers come from engine artifacts only. Never calculate, fill in, or adjust a numeric fact, ranking, weight, or identity. Determinism is what makes week-to-week reconciliation trustworthy: this week's 12% and next week's 12% have to be the same 12%.
- Invoke the engine only through the
engine/review.pyCLI (prepare,resume,preview,finalize,capture,consider,refresh,positions,render,weekly-market-read,repair-projections,set-cap,mute-rule,add-cash,resolve-market-data,doctor). Do not call anotherengine/*script or import engine modules directly — those paths bypass lifecycle validation, required-question gates, and canonical session state. - A considered trade earns a computed case, never a prose one. In a review, discuss behavior, motives, thesis evolution, and process rules; the card's prescription still never names what to buy or sell. For a trade the user is deciding on,
considerreturns what it does to their own book and which of their own rules it would break — build the case for and against from that output, mark every claim you added as your own judgment, cite an engine fact through the anchorreferences/trade-consequence.mddocuments so it can be checked against the frozen result, and state everything the response's ownchallengeblock says this answer owes — the facts, the user's exact words unreworded, the rules this trade collides with, and what nobody checked. That block is computed per call, so none of it is a list to remember. Apply the global output-voice contract to the route structure inreferences/trade-consequence.md. A case that misquotes the record, leaves an owed fact uncovered, or relabels the user's own words as an outside source is refused rather than stored. Current market context — the standing position packet and any event verification — enters only underreferences/market-lookup.md's bounded lookup contract, as sourced public facts. The decision stays theirs, and a price target or market forecast is still not something this product states. - Never invent, interpolate, or recall a market price. When a host blocks the engine's own retrieval,
review_plan.input.price_feed.requestnames what is unpriced; look those closes up from a recognized market-data source, transcribe them into the envelope inreferences/price-feed.md, and rerunprepare --prices. A price you cannot find stays missing — a missing price is never a delisting verdict or a zero return. - Trade data stays local. The source CSV, session bundles, and the ledger never enter cloud memory. The review card is private to the user: show
card-private.*by default perreferences/card-delivery.md. Local files, terminal output, and private-by-default in-client rendering are all fine; publishing, posting, or sending it to a third party is not.card-public.mdis the one share-safe artifact, and only if the user asks. - Transcribe snapshots, do not analyze them. For a position table or screenshot, copy only broker-declared facts into the JSON envelope and keep that file outside the repository, such as under
/tmp. Do not derive weights, P&L, cycle IDs, metrics, or ETF classifications, and do not use a cloud OCR service — there is no engine OCR or upload path. sessions/<session_id>/bundle.jsonis the completed result. Projections are rebuilt from it.- A freeform informational question gets a quick, direct answer. Outside the review card and its artifacts, an ad hoc question — including a
considercall — is answered briefly, in text: no chart, no rendered artifact, no multi-tool production, unless the user explicitly asks for more. A chart is never composed on the spot; it matches a name in the small pre-defined setreferences/freeform-answers.mddeclares, which bounds what the agent decides to produce on its own initiative, never what the user explicitly asks for. Brevity bounds what an answer produces, never which facts it owes: a surface with its own disclosure contract still states all of them. One exception, and only this one: recovering a price the engine could not retrieve is completing the input, not production. Whenconsiderreturns aprice_feedrecovery kit, look up the instruments it names — a search may find the publisher's page, the close is read off that page and never off a search-result snippet — transcribe them into the envelope inreferences/price-feed.md, and rerunconsider --prices. It is transcription, not analysis: at most twenty instruments, one attempt each, nothing read beyond the close. It licenses no chart, artifact, or other multi-tool work. The work is bounded and parallelizable and may be delegated to whatever faster tier the host has. Supply whatever you found, partial coverage included; when the sources genuinely publish nothing, runconsider --prices-unavailable '<the sources you checked>'and the question is refused rather than answered on cost basis — deliberately the opposite of the review-card lane, which delivers its degraded card. - A decision with no recorded book is framed, not refused.
considerfails closed for want of a book and that refusal stands, but the conversation does not end there. Followreferences/decision-framing.md: an ordinary single-trade framing asks at most three questions; its research-aware strategy framing states its baseline and strategy map, then asks at most one discriminating question last. Neither form has a portfolio number: no computed or placeholder portfolio number, nothing durable is written, and every limitation that matters is shaped as a question the user can answer rather than a gap narrated back at them. Refusing is not what earns a transaction history — naming the specific answer the next piece of evidence would buy is.
Canonical entry point
Preflight once after install. The engine fail-soft degrades — silently dropping current prices, P&L, alpha/beta, and market context — when optional runtime dependencies are missing, so verify them before first use:
cd skills/fomo-kernel
pip install -r requirements.txt # yfinance + pandas + rich
python3 engine/review.py doctor # lists what each dep unlocks; non-zero if one is missing
python3 engine/review.py prepare <CSV...> --language en
python3 engine/review.py prepare --route snapshot_review \
--snapshot-json /tmp/fomo-kernel-positions.json --language en
For transaction history, normalize broker data locally into Symbol / Action(BUY|SELL) / Quantity / Price / TradeDate / RecordType(Trade); add Market / Currency for non-US instruments. Carry Amount through whenever the source has it — it is the broker's own cash-account change for that row, already net of fees, and it makes account-level return exact instead of estimated. Do not ask the user to normalize the file themselves. Symbol and cash-anchor rules live in references/data-contract.md.
The engine prices the portfolio itself, so a normal review passes no prices. If the host blocks that, prepare still completes in a degraded mode and reports the gap in review_plan.input.price_feed.
Updating the recorded book is a different job from reviewing it, and it comes first. When the user hands over a newer holdings view and the coach root already holds a book, read flows/book-refresh.md and run refresh — whether or not they also want a review. There is nothing to guess at from their wording: when the new view holds something only the user can settle (a position that vanished, a large move on a large holding), prepare refuses and names refresh itself, and the same declaration reviews normally once the book is current. Anything smaller is adopted by the review as before. The first declaration on an empty root is still onboarding and still goes through prepare --route snapshot_review.
python3 engine/review.py refresh --snapshot-json /tmp/fomo-kernel-positions.json
prepare returns a Review Plan, not a card. Read only the flow it selects in review_plan.flow_path:
flows/first-review.mdflows/first-review-structural.md— a first review the engine tieredstructural/empty: an opening structural check, no question string, no forced commitmentflows/weekly-review.mdflows/snapshot-review.mdflows/test-drive.md
Then read the shared rules:
references/agent-boundaries.mdreferences/interaction-delivery.mdreferences/freeform-answers.mdreferences/card-delivery.mdreferences/thesis-policy.mdreferences/data-contract.md
Fixed lifecycle
prepare— run the engine, reconstruct active theses, deduplicate questions, return a Review Plan.- Agent work — resolve one host adapter, ask every required question once, create inferred theses for uncovered positions, and write a digit-free narrative.
preview— validate answers, evidence, theses, and narrative; render private and public previews.- One beat: in a single message, show the complete card inline, ask the user to choose a candidate rule, write their own, or skip, and — when
input.cash_anchor.statusisabsentorpartial— ask for the account's cash balance. Generating an artifact is not showing it. The card sits above the choices, so the user still commits to a rule only after seeing the real card. If they give the balance,add-cashrecomputes on this session's frozen prices and everything already answered carries over; then rerunpreviewon the session it returns. finalize— validate the commitment, atomically commit the canonical bundle, rebuild projections.
Step 3 is a precondition, not advice: finalize refuses to commit answers and a narrative this session's own preview never rendered, so a card the user never saw cannot become a standing rule. The commitment is the one field that may be added afterwards — that is what step 4 is for. If the refusal appears, rerun preview with the artifacts you are about to commit, show the card, and finalize; the pending session is untouched and nothing is lost.
python3 engine/review.py preview \
--session-id <ID> --answers /tmp/answers.json --narrative /tmp/narrative.json
python3 engine/review.py finalize \
--session-id <ID> --answers /tmp/answers.json --narrative /tmp/narrative.json
After an interruption, resume rather than rerunning the engine — refetching live data would silently change the facts the user already answered against:
python3 engine/review.py resume
python3 engine/review.py resume --session-id <ID>
If finalize committed the bundle but a projection failed, repair it without re-questioning the user. This is a repairable state, not a lost session:
python3 engine/review.py repair-projections
Light-tier exception. When review_plan.state_snapshot.cadence.tier == "light" (too short a span since the last review), steps 2–5 do not apply. Follow flows/light-capture.md: ask at most one light question, call capture to append the motive/emotion fact, and stop. No card, no commitment, no preview/finalize.
Agent artifact contract
The engine validates completeness, provenance, identity, and gates at preview; it will tell you what is wrong. Your side of the contract is the qualitative work it cannot check:
- Narrative (
schemas/narrative.schema.json): qualitative prose, no digits. The renderer owns every amount, percentage, date, ticker, and metric, so prose can never become a competing source of truth. Write one sentence innarrative.honestyfor each key incard_plan.required_honesty_keys, followingcard-spec.md. - Theses: add one
thesis_updatesentry per missing-thesiscycle_id, using the field vocabulary inreview_plan.authoring_contract— the unchangedcycle_idplus the qualitative fields; the engine prefills the mechanical ones and assigns all identity. State the inference source, and never present an inferred thesis as user-confirmed. - Questions:
prepareranks motive, recent-exit, matured checkpoint, and first-review entry-thesis questions by engine-owned impact and returns a route-scoped count (first review three to five, weekly one to three, snapshot none). Ask all of them; it never pads to reach a minimum.skipsemantics differ by kind: skipping an exit-reason capture is durable, while a skippeddue_revisitlegitimately returns next review. - Evidence: a confirmed evidence delta means "the user confirmed this was part of the decision," not that the claim is externally true. Do not invent
observed_at. - Instruments: use a local
--instrument-mapfor uncommon instruments; unknown instruments get no allocation exemption.
A snapshot review is an opening portfolio check, not a transaction-history diagnosis. Discuss engine-owned cost or value weights, single-position risk, driver concentration, ETF structure, and data integrity. Averaging-down counts, exit discipline, holding behavior, win rate, payoff ratio, alpha, and historical motives need transaction history — invite the user to add it later. A holdings view records the book at the time it arrives whatever it covers, so never ask whether it covers the user's whole account; ledger-derived current holdings stay canonical, and a newer holdings view reaches the recorded book through refresh rather than replacing it silently.
If a new observation could overturn the top behavioral leak, add it to observations and rerun preview rather than editing the engine artifact.
Language and sharing
--language controls user-visible questions, rules, and cards. Always pass the language the user is conversing in: a zh-TW conversation runs with --language zh-TW, zh-CN with --language zh-CN. If the user's language has no copy asset (anything other than zh-TW, zh-CN, en today) or you cannot tell, pass --language en; the engine applies the same fallback, so card surfaces come out in English either way. Keep conversing in the user's language and do not hand-translate card text. The en in the examples above is a placeholder, not a default.
Each completed session produces card-private.md and card-private.html (the complete local card) and card-public.md (a separately rendered share-safe artifact — no amounts, dates, tickers, exact weights, session IDs, or agent free text; no upload path exists).
Test drive
If the user has no data but wants to see the experience:
python3 engine/review.py prepare --test-drive --language en
Test drive follows the same lifecycle with persist:false, in an isolated root. Read review_plan.state_root from the prepare output and pass it as --root <state_root> to every later preview, finalize, and resume, or they will not find the session. It must never project into the user's coach memory, and every card and message must be visibly labeled demo data.