Skip to content

[design·P1] A rule is the user's own standing expectation, not a review output — the loop, and what currently forces it through one door #650

Description

@atomchung

Status

Design discussion, owner-ruled 2026-07-31. Recorded so it is not re-derived. Blocks nothing; it reframes several open issues and should be read before spending on any of them.

The ruling, in the owner's own terms

Four points, given directly:

  1. It is a loop. A rule is both a product of a review and the yardstick the next review measures against. Not either/or — the agent's first framing of it as one or the other was wrong. And a rule's inputs are many; the review card is only one of them. It is fundamentally a memory-shaped concept, not a card feature.
  2. Discipline is supposed to accumulate.
  3. You should be able to state a rule without running a review. At bottom it is the same question already on the table: do I have a preferred trading style, and what are my choices?
  4. Research it, record it here, do not act yet.

Why this is #446's layer 2, not a new concept

#446's three-layer model puts "who this person is — cross-period behavior patterns, accumulated motives, trading personality" at layer 2, and #619 documents profile.md as that layer's first guess (2026-07-13, PR #183): a free-text file holding "trading goals + 3 personal principles, the reconciliation baseline for reviews."

Point 3 above is that layer stated in the owner's words. A rule is the most concrete instance of it the product already ships — and the only one that has ever had a persistence mechanism. So this is not a fourth memory concept; it is evidence about what layer 2 is actually for, arriving from a direction #446 did not come from.

What the product does today, measured on main@878c333

There is no way to state a rule without finishing a review. The CLI surface is prepare, resume, preview, finalize, capture, consider, refresh, positions, render, repair-projections, set-cap, mute-rule, add-cash, resolve-market-data, doctor. There is no add-rule. set-cap sets one specific numeric override and mute-rule silences an existing line; neither states a new expectation. A rule can only be born at a review's exit, one per review.

The rule store is not two competing sources. rules.jsonl is a rebuildable projection (references/data-contract.md), derived from the finalized session's commitment. consider reads the projection through problems.load_rules_reportconsequence.rule_collision; the review lane reads the previous session's commitment directly. One canonical fact, two readers. That part is sound.

Only the most recent commitment is reconciled. Switch rules and the previous one's track record ends there — nothing accumulates about whether any rule worked, which is point 2 failing in practice.

The pre-commitment preview card exists because the rule is an output. Measured across three personas, the preview and the finalized card differ by 5 lines out of 53–63, and every one of those lines is the rule sentence (it appears twice on the card) plus its grounding sub-line. The product renders a whole second card to hold the place of one sentence. It has to, because the rule is produced by the flow it must appear in.

The "no rule change this period" nudge is never computed. card_renderer's no-commitment branch prints the continuity sentence unconditionally on every returning user's preview; nothing checks whether the engine actually proposes a change. Its own docstring describes the intended behaviour ("when the engine proposes no change it restates the standing rule") and the implementation never tests the condition.

What follows if a rule is a standing expectation

Stated as consequences to be evaluated, not as a plan:

  • The preview card's reason to exist dissolves. Its job is to show the user a card before they supply the one thing the card is missing. If the rule is already standing, there is nothing missing, and the review simply reports against it. (The delivery-receipt job [feat·gate] Nothing stops finalize from committing a card the user never saw — the preview guarantee is instruction-only #628 established is separate and still needs an answer — but a receipt does not require a second full render.)
  • fix(card): the standing-rule line names this period's prescription, not the rule the user actually committed to #645 changes subject. "The standing rule remains" is currently a false placeholder for a choice not yet made. Against a standing object it becomes a true statement. That issue may be repairing something that should not exist; do not implement it before this is settled.
  • One rule per review stops being a natural limit. It is a property of the exit that creates them, not of what a person can hold themselves to.
  • The review's purpose sharpens — from "here is your analysis, now pick a rule" to "here is how your stated expectations held up."
  • consider is one reader, not the rule's home. Review, a single-trade look, and a pre-trade question are three occasions to consult the same standing expectation.

What is not decided here

Evidence this changes something real

The 2026-07-29 diagnosis of "a review carries no payoff" concluded the cause was that nothing consumes the history. A rule is the one mechanism that does — and today it is reborn each review, reconciled only against its immediate predecessor, and cannot be stated at all except by completing a full review. That is the same finding, reached from the rule's side.

A real card from the shipped fixtures, for the record: a user committed to a 20% single-position cap, and the next review reads 當時 33%,這次 100%. The product states it in one sentence and moves on. Next period it will state it again. Whatever else this is, it is not yet discipline.

Related

#446 (the distillation layer this belongs to), #619 (profile.md, that layer's first guess), #645 (preview copy — hold), #628 (the delivery receipt the preview currently carries), #610 (the owner walk that can observe whether the engine's top-ranked candidate is the one a real user would pick), #429 (a question nobody reads is a defect).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions