Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/expression-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ leads with and the increment each of its blocks adds, plus counter-exemplars
for the named bans. Every issuer in them is fictional (Widgetron WDGT,
Gridcore GRDC, Fabrion FABR, ACME) and nothing is derived from a user record.

Since #834 the corpus is not the only place they live. Each conversational
surface's reference file **opens with its own copy of one of them**, so the
example is met while an answer is being written rather than only while one is
being graded. The two copies are one text, not two:
`tests/test_expression_contract.py` compares each reference block against the
scene its fence names and fails on drift.

`tests/agent/check_expression.py` derives E-7 and E-8 from that corpus (§7).
What they decide is exactly two things — that the declared answer really leads,
and that every declared block really adds a distinct increment — and the
Expand Down
1 change: 1 addition & 0 deletions docs/maintainer-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ reader-question-chain) while leaving those rows' every other ruling intact.
| Output structure & language | `docs/output-contract.md` (single authority on section order) and `docs/output-language.md` (locale contract) ↔ `card_renderer.py` ↔ `references/card-policy.md` / `card-spec.md` (subordinated: wording and in-block ranking only) |
| How the product speaks, on every surface (#823, #825) | `docs/expression-contract.md` is the single authority for expression — voice routes to `docs/output-voice.md`, disclosure relevance is D1–D6, and citation/provenance is C1–C4. Its surfaces are `docs/output-contract.md` §4 ↔ `references/trade-consequence.md` ↔ `references/freeform-answers.md` ↔ `references/decision-framing.md` ↔ `references/weekly-market-read.md`. The card may keep its footnote as local layout, but conversational surfaces have no mandatory tail block, prefix, or line cap. `tests/agent/check_expression.py` now enforces only E-5/C4 (no engine-token leaks); #825 retired E-1–E-4 because block position, marker syntax, line count, and literal deduplication did not prove relevance or clarity. `tests/test_expression_contract.py` keeps registry/routing checks and pins that D1–D6 honestly declare instruction-only verification. |
| One communication method: the answer pyramid (#832, 2026-08-21) | `docs/expression-contract.md` §3 is the **mother law** of answer shape and the only statement of it. Its readers, each of which now carries a *derivation* rather than a phrasing: `docs/output-contract.md` §2 (the card is the document incarnation — keynote = top floor, three middle blocks = the middle, the Block-1 footnote = the end block; the card's own structure is unchanged) ↔ `docs/output-voice.md` (V1 keeps its ID as the **failure class** and stops being a second statement of the rule) ↔ `skills/fomo-kernel/SKILL.md` "Shape of the answer" (the always-on projection, explicitly labelled as one) ↔ `references/trade-consequence.md` (adds exactly two parameters: lead selection and answer slots) ↔ `references/decision-framing.md` (adds two: the baseline is the top sentence with no book, the strategy-class map is a middle-floor block set) ↔ `references/weekly-market-read.md` (adds one: its optional question comes after the complete brief) ↔ `references/freeform-answers.md` (**adds nothing — an empty derivation is valid and is the default**) ↔ `tests/agent/expression-witnesses.json` ↔ `tests/agent/check_expression.py` (E-7/E-8) ↔ `tests/test_expression_contract.py` ↔ `tests/test_research_priors.py` (which pinned the no-book phrasing by literal and now pins the block order and the derivation instead). Four rules. **Derivation is additive-only**: a surface may add which blocks its middle may hold, which questions it may ask, what its end block must name, or what it may not compute — it may not restate, narrow, re-order, or contradict the shape. **The registries are frozen for shape and length**: V, D, and C take **no new ID** for "answers are too long", "lead with X", or "stop repeating Y", because five independently-worded statements of answer-first is the disease and a sixth with an ID on it is still a sixth; V10 stays unallocated (proposed in #830, demoted there, refused here). **A style fix has two lanes and only two**: amend §3 (owner ruling required, logged in §8) or add an exemplar/counter-exemplar to the witness corpus (day-to-day, no ruling). **The exemplars are the spec, and the oracle is honest about its half**: E-7 decides that a scene's declared one-sentence answer really leads, E-8 that every declared block really adds a distinct increment; the manufactured-scenario and hedging-couplet bans have **no** mechanical oracle, and the corpus asserts that by requiring their counter-exemplars to *pass* every assertion — the day one of them can be caught, that assertion is what says the boundary moved. Why the row exists at all: #830's post-merge rerun (PR #831) fixed composition and moved first-answer length by less than 5%, which is the evidence that deleting obligations without a positive shape norm only vacates space for discretionary elaboration. **Not adopted, again**: any character-count cap — #543's ceiling stayed deleted, and length is the shape's consequence, never its rule. Integrity gates (engine-owned numbers, provenance, canonical writes, execution truth, privacy) and #829 are untouched and out of scope. |
| One canonical exemplar on each surface's generation path (#834, 2026-08-22) | The exemplars stopped living only in the QC layer. Each conversational surface's reference file **opens with one canonical exemplar copied from `tests/agent/expression-witnesses.json`**: `references/trade-consequence.md` (`consider_three_way_comparison`) ↔ `references/decision-framing.md` (`no_book_single_name`) ↔ `references/freeform-answers.md` (`freeform_positions_view`) ↔ `references/weekly-market-read.md` (`weekly_read_connection`), with `docs/expression-contract.md` §3.5 and `skills/fomo-kernel/SKILL.md` "Shape of the answer" pointing at them. Four rules. **The corpus is the source and the reference file is the copy**: `tests/test_expression_contract.py::test_every_surface_reference_opens_with_its_canonical_exemplar` normalizes both sides and fails closed on drift, so editing either alone reddens — this is the hand-mirrored surface this guide forbids, made mechanical instead of forbidden, because the whole point is that the same text has to be in two places at once. **The pairing is never hand-listed**: which reference file owns a surface is read from the corpus's own `surfaces` map, and which scene a file carries is read from that file's own fence, so the sync test compares two declarations that already existed rather than adding a third to keep in step. **The marker is one line** — a fenced block whose info string is `exemplar <scene_id>` — and it is also the unit `tests/test_doc_language.py`'s `exemplar_quoted_lines` exempts from the English-only gate, since three of the four exemplars are this product speaking Traditional Chinese and quoted product output is not documentation prose (the same distinction that keeps `copy/zh-TW.json` out of `ENGLISH_IMPLEMENTATION_ASSETS`). That exemption is bounded three ways at once — by directory, by fence tag, and by the byte-identity the sync test proves — and `test_no_other_document_carries_an_exemplar_block` is what stops it spreading to a fifth file. **Placement only, per #832's stop condition**: no new registry ID, no length cap, no obligation, and the always-loaded pair stays inside #507's byte budget with SKILL.md gaining one clause, because progressive disclosure puts the exemplar in the file that is already loaded when its surface is in play. Why the row exists: #832's post-merge rerun (receipts on PR #833) bent the length curve for the first time in three of four frozen scenes and regressed the fourth — the no-book freeform one, the surface with the emptiest guidance and no engine payload anchoring the answer — which is the evidence that a norm the model never meets at generation time does not bind scale. |
| Runtime behavior | engine ↔ `SKILL.md` and routed flows/references ↔ `docs/eval-design.md` ↔ `evals/EVALS.md` |
| Demo card values | English README ↔ English demo HTML/image; Traditional Chinese README ↔ Traditional Chinese demo HTML/image. Values must match; only wording differs. |
| GTM documentation | `README.md` is the English default; `README.zh-TW.md` is the complete Traditional Chinese counterpart. Keep language links and substantive product claims synchronized. |
Expand Down
2 changes: 1 addition & 1 deletion skills/fomo-kernel/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ The engine computes portfolio consequence; it is not a company-research service.

One shape, every answer (`../../docs/expression-contract.md` §3 owns it; this is its projection, not a second wording). **A fact lives on exactly one floor, and twice is a bug.** *Top:* one sentence — the stance and the reason that decides it (proceed, resize, delay, collect evidence, choose one candidate, no trade). *Middle:* only blocks that add a new decision-relevant fact or judgment — delete one; if the decision does not change, delete it. There live the numbers that would flip the call, every `rule_effects` entry (never optional), a truth-critical denominator, unit, or pricing set beside its number, and a falsifier on any directional call — the counter-case needs no section. *Bottom:* the rest of the inventory stays in the data layer; say once you can expand it. *End:* one compact block for other material limitations; machine anchors and engine narration nowhere.

Never manufacture a scenario nobody asked for, restate a system default as insight, hedge in couplets, or make one point twice. Ask only decision-changing questions, then stop. `references/trade-consequence.md` holds the rest.
Never manufacture a scenario nobody asked for, restate a system default as insight, hedge in couplets, or make one point twice. Ask only decision-changing questions, then stop. `references/trade-consequence.md` holds the rest. Each reference opens with its exemplar; follow it.

Label judgment — thesis, valuation, timing, forecast, recommendation, ranking, selection — separate from engine facts. Give a target or forecast's material assumptions and uncertainty; never disguise it as fact or certainty. Never claim what the user did or will do.

Expand Down
20 changes: 20 additions & 0 deletions skills/fomo-kernel/references/decision-framing.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Framing a decision when there is no recorded book

## The exemplar

One whole no-book answer. Every book-derived claim is refused and the answer
still lands a stance, names the gap that decides it, and leaves the user a
falsifier they could write down themselves. Read it before writing one.

It is copied verbatim from `tests/agent/expression-witnesses.json`, scene
`no_book_single_name` — the corpus that
[expression-contract.md](../../../docs/expression-contract.md) §3.5 makes the
binding statement of this shape. Every issuer in it is invented, and
`tests/test_expression_contract.py` fails if the two copies disagree.

```exemplar no_book_single_name
WDGT 這家公司的證據支持買,但「現在進場」我不背書——缺的是估值,不是基本面。上季營收 +24%、EPS 超預期、同日上修全年(公司新聞稿,2026-07-24),這是硬的;但這些已公開三週,而我查不到現在的估值倍數,「好消息是否已在價格裡」這一半我答不了。

$5,000 試水溫,真正的洞在出場:「故事變了就賣」跟你的進場理由是同一個變數,等於沒有獨立的認錯線。可檢查的替代就用它自己簽的支票:全年營收財測或毛利率轉向,擇一寫下來,就可以進場。

(價 8/14 收盤 $188.20;你未提供持倉,部位佔比與重疊無法評)
```

`review.py consider` answers what a trade does to the user's own book, and it fails closed when there is no book to answer against. That refusal is correct — it protects the arithmetic — but it is not the end of the conversation. A user who has recorded nothing still arrives with a live decision, and refusing is not what earns their transaction history. Guidance is.

This file is the contract for decisions made without a recorded book. The user
Expand Down
21 changes: 21 additions & 0 deletions skills/fomo-kernel/references/freeform-answers.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Freeform informational answers

## The exemplar

One whole freeform answer. This route adds no parameter of its own (rule 4
below), so the exemplar is what this file has to show: the one position the
question turns on, the rest of the computed inventory behind a single offer,
and one end block. Read it before writing one.

It is copied verbatim from `tests/agent/expression-witnesses.json`, scene
`freeform_positions_view` — the corpus that
[expression-contract.md](../../../docs/expression-contract.md) §3.5 makes the
binding statement of this shape. Every issuer in it is invented, and
`tests/test_expression_contract.py` fails if the two copies disagree.

```exemplar freeform_positions_view
六檔裡只有一檔值得你現在看:GRDC 佔 31.4%,其餘五檔全在 10% 以下。

最大的那筆已經是第二大的三倍,其他五檔加起來還不到它。要完整的逐檔表(股數、成本、市值、損益、診斷標籤)跟我說一聲就給。

(帳本 8/14;價格 8/14 收盤;ETF 未拆解,成分重疊未評)
```

The user does not only meet this product through `prepare → preview →
finalize`. They ask ad hoc questions mid-conversation — "what's my portfolio
worth right now," "how much cash do I have," "what if I add to this" — and
Expand Down
22 changes: 22 additions & 0 deletions skills/fomo-kernel/references/trade-consequence.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Weighing a trade the user has not placed yet

## The exemplar

One whole `consider` answer, over a three-candidate comparison: the stance and
its deciding reason on top, the counter-side present only as the line that could
overturn the pick, and the book date, the price session and the unevaluated
valuation gap as one end block. Read it before writing one.

It is copied verbatim from `tests/agent/expression-witnesses.json`, scene
`consider_three_way_comparison` — the corpus that
[expression-contract.md](../../../docs/expression-contract.md) §3.5 makes the
binding statement of this shape. Every issuer in it is invented, and
`tests/test_expression_contract.py` fails if the two copies disagree.

```exemplar consider_three_way_comparison
三個裡我會選 GRDC 加 15 股。決定性理由:三案對組合的影響都在一個百分點內——誰都不改變你的集中度——真正有差的只有事件風險:WDGT 六天後出財報、預期已拉滿(公司財報行事曆,2026-08-14),這時把最大倉再加大,是三案裡波動最大的;FABR 18 股只佔 1.2%,公司再好這個大小也改變不了結果。GRDC 下次財報在十月底,中間乾淨,上季主業 +82%(公司財報,2026-07-30)撐著。

反面就一條:前三大會從 51.3% 升到 51.9%(GRDC 本來就是第二大)——嫌集中的話這是三案共同的問題,答案是減碼不是選誰。
會讓我改口:你本來就想賭財報超預期——那 WDGT 反而是最直接的表達,排序整個反過來。

(帳本 8/14、價格 8/14 收盤;三案動用 $4.4K/$5.1K/$4.9K;估值未評)
```

A user mid-decision asks something like *"I'm thinking of buying NVDA — what does that do to my book?"* They are not in a review and will not hand over a CSV. `consider` answers from what the product already stores: the local ledger, or transaction files if you have them in hand.

This is Layer 2 (docs/decision-fomo-kernel-shape.md §3-4): deterministic arithmetic over a hypothetical trade. The engine computes the consequence; the agent turns it and any relevant sourced evidence into an explicit recommendation. The recommendation is `agent_judgment`, never a disguised engine output or execution claim.
Expand Down
16 changes: 16 additions & 0 deletions skills/fomo-kernel/references/weekly-market-read.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Weekly Market Read prototype

## The exemplar

One whole weekly brief. The connection between the frozen reading and a
diagnosed holding leads, the bound on what that alert claims follows it, and
the next-week check closes. Read it before writing one.

It is copied verbatim from `tests/agent/expression-witnesses.json`, scene
`weekly_read_connection` — the corpus that
[expression-contract.md](../../../docs/expression-contract.md) §3.5 makes the
binding statement of this shape. Every issuer in it is invented, and
`tests/test_expression_contract.py` fails if the two copies disagree.

```exemplar weekly_read_connection
Volatility rose through the week while your heaviest name was already flagged as too large. Both readings are frozen with the review rather than refreshed today, and valuation was not checked, so this is a concentration alert rather than a claim that the holding is expensive. Watch whether the name's weight and the volatility reading remain elevated next week.
```

The #683 prototype is a read-only companion to a prepared `weekly_review`.
Run its first read only after the complete, current private-card preview and
before the existing rule choice:
Expand Down
Loading
Loading