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
18 changes: 18 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,22 @@ IMPORTANT: Simple, general, testable, maintainable code is better than preservin

IMPORTANT: If feedback seems non-actionable, it means you need comments explaining why the code looks that way.

**CRITICAL**: A test that pins one arm of an N-way decision reads exactly like a test that pins the decision. Derive the rows from the enumeration -- the variant list, the call-site list, the axis list -- and cover every arm, or state in the test which arms it does not cover and where they are covered instead. "It passes" and "it constrains the code" are different claims.

**CRITICAL**: A test that hand-builds its inputs proves nothing about the inputs production supplies. If a fixture constructs a dependency set, a scope, or a context by hand, either derive it through the same function production calls or justify in the test why the hand-built value is the one production produces. This has shipped a fix that could not fire: the fixture supplied a dependency set the extractor never generates, so the test passed on an input that does not occur and the defect it claimed to cover survived untouched.

## Claims About Other Tools

Vensim, Stella, and the XMILE specification are external systems. What one of them does is a **fact to be checked, not a premise to reason from** -- and the sources are cheap:

- **XMILE spec**: `docs/reference/xmile-v1.0.html`, in-repo and greppable (strip tags and search the prose; the footnotes carry the resolution rules).
- **Vensim function reference**: one page per function at vensim.com/documentation, named fn_ plus the lowercased function name with underscores.
- **Ground truth output**: real Vensim DSS runs checked into `test/` (e.g. `test/test-models/tests/vector_order/output.tab`, which is how VECTOR SORT ORDER's semantics were settled).

When code encodes a claim about another tool, cite the source next to it. When you cannot check one, write that the claim is unverified rather than asserting it -- and never let an unverified claim carry a design decision.

This is the most expensive class of error in this repo, because review does not catch it: reviewers check the code against the stated claim, not the claim against the world. A wrong premise about an external tool therefore survives every round of review that its own code passes, and the work built on top of it is wasted rather than merely wrong.

## Comment and Rustdoc Standards

- Preserve useful comments/docstrings when refactoring. Do not delete comments unless they are stale, wrong, or redundant with clearer replacement code.
Expand Down Expand Up @@ -132,6 +148,8 @@ Two things are NOT covered by "fix it", and both are explicit conversations rath
- **The fix is too large to fold in** -- it would swamp the branch's review surface, or it belongs to a different subsystem. Say so, with a cost estimate, and sequence it: its own commit, its own PR, or (if that is what the user wants) tracked for later. Do not make that call quietly.
- **The fix is not yours to make** -- it needs a product decision, or access you do not have. Surface it.

**A fix that introduces a regression is a scope signal, not a bug to try harder at.** Once the second attempt at the same discovered issue produces a new defect, stop and re-scope: the problem is larger than the branch it was found in, and each further attempt is being designed against an understanding that has already failed twice. Split it out with what was learned, rather than continuing. Discovering something mid-task tells you it exists; it does not tell you it belongs in the change you are making.

When something genuinely does need tracking, spawn the `track-issue` agent (via the Task tool with `subagent_type: "track-issue"`) with a description of the problem. It checks for duplicates in GitHub issues and [docs/tech-debt.md](/docs/tech-debt.md) and files the item, keeping your context on the main task.

## Generated/Noise Paths
Expand Down
2 changes: 1 addition & 1 deletion docs/design/ltm--loops-that-matter.md
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,7 @@ LTM machinery (the Expr0-walk-time `is_array_reducer_name`, `classify_reducer`,
the static-polarity `agg_reducer_is_monotone`) is a thin reader of it, so the
"is this a reducer" / "what kind" answers can't drift apart. AST-identical
subexpressions (keyed by canonical printed equation text, since `Expr2` is
not `Eq`) dedupe to one node.
not `Hash` and so cannot key a map directly) dedupe to one node.

**Read slice and result dims.** Each `AggNode` carries a
`read_slice: Vec<AxisRead>` -- one `AxisRead ∈ {Pinned(elem), Iterated(dim),
Expand Down
4 changes: 4 additions & 0 deletions src/libsimlin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@ impl From<engine::ErrorCode> for SimlinErrorCode {
// A macro body instantiating a module likewise collapses to the wire
// Generic code; the engine code and the message carry the detail.
engine::ErrorCode::MacroContainsModule => SimlinErrorCode::Generic,
// An unfilled equation (a variable whose equation is nothing but the
// NaN literal) likewise collapses to the wire Generic code; the
// message names the variable, which is the whole point of it.
engine::ErrorCode::UnfilledEquation => SimlinErrorCode::Generic,
}
}
}
Expand Down
Loading
Loading