| name | check-premise |
| description | Before asserting a causal or mechanism claim about tool/system behavior, OR a factual claim about what a CURRENT artifact (spec/doc/config/rule) says, requires, or contradicts, OR changing behavior to conform to a remembered criterion, OR a casual claim about what a task/artifact IS/DOES/its status/scope — list the factual premises the claim rests on, identify the cheapest falsifier first, and check it (read the installed source / query the system's own record / re-read the live, AUTHORITATIVE artifact — not a stale local cache) before asserting or acting. Use when about to explain WHY something happened, WHAT a tool will do, WHAT a spec/doc says or requires, or WHAT a task/artifact is/does/its status is, based on an assumed or remembered claim. |
| user-invocable | true |
Check Premise
A thin agent-invoked discipline step for two related families of unverified
assertion: (1) causal/mechanism claims about tool/system behavior, and
(2) artifact-content and identity claims — what a spec/doc/config/rule
currently says or requires, or what a task/artifact currently is, does, or
its status/scope is. The pattern it fixes: the agent asserts "X happened
because Y" / "running X will do Z" / "the spec says W" / "task N is/does M"
based on an assumed or remembered premise that was never re-verified this
turn — the claim sounds like an observation but is actually a hypothesis (or,
for artifact-content, a recollection that may already be stale).
Family (1) originating incidents R1–R5 in memory 3772c77d. Structural
enforcement via .claude/hooks/causal-premise-detector.ts (mt#2216,
calibration mode). Family (2) originating incidents in memory eb4411f3
(bridge; family root de54bd12) — see
## Artifact-content and identity claims below.
When to invoke
Before any of:
- "X happened because Y" explanations where Y is a structural mechanism
(identity, permission, config, algorithm, data-shape).
- "Running X will do Y" predictions about tool behavior.
- "X is blocked/unsafe because Z" claims about system behavior.
- Any explanation that attributes causality to a mechanism that hasn't been
directly observed this turn.
- A factual claim about what a CURRENT artifact (spec / doc / config / rule
file) "says", "requires", or "contradicts".
- Changing behavior to conform to a REMEMBERED criterion, rather than the
criterion as it is currently written.
- A casual claim about what a task/artifact IS, DOES, or its STATUS or SCOPE
is — even in a low-stakes recommendation, not just a structural decision.
(The last three are the artifact-content/identity family — see
## Artifact-content and identity claims below for the falsifier specific
to that family.)
Additional trigger cues (Tier-3 residual slice — mt#2698)
Nine narrow per-surface cues, filed as cheap Tier-3 residual-slice
amendments to the "When to invoke" list above — not a new containment
strategy. Per the mt#2485 strategic partition (family record b0b294ab):
the broad-detector tier is demoted; per-surface prose-tier cues like these
are the accepted residual, with the primary containment staying Tier-1
(mt#2488, tool-boundary evidence gates) and Tier-2 (mt#2486,
code-mechanism-assertion detector). A future recurrence in this tier should
cite b0b294ab and mt#2485 rather than re-deciding the partition.
(a) Remedy for a live incident
Trigger: about to hand the user a remedy/fix-it-now instruction for a live
incident.
Falsifier: when the live repro is at hand, exercise the remedy against it (or
explicitly label the remedy unverified). A plausible mechanism story is not
evidence the remedy works — the repro at hand is cheaper and more direct than
reasoning about the mechanism.
Origin: b0b294ab R11 (mt#2688, 2026-07-08) — the agent told the user
"click Open Cockpit — it force-reloads, it'll render" for a dead-window
incident while the dead window was still open and reproducible; the remedy's
premise (reload() recovers a never-loaded document) was false, costing the
user a round-trip.
(b) Third-party platform/runtime semantics claims
Trigger: mechanism claim about third-party platform/runtime semantics
(webview, OS, library).
Falsifier: a same-turn read of FIRST-PARTY code does not verify it; read the
installed third-party source (cargo registry / node_modules) or test
empirically.
Origin: b0b294ab R11 (mt#2688, 2026-07-08) — a same-turn read of
menu.rs's reload call would have (falsely) satisfied mt#2486's
same-turn-verification suppression for cue (a)'s claim; separately,
dead-window detection was designed on WebviewWindow::url() liveness while
flagging WKWebView's failed-load URL semantics as uncertain and proceeding
anyway — the falsifier (reading wry's url_from_webview in the cargo
registry, one grep) was run only after live verification failed.
(c) A/B-observation confound
Trigger: about to encode a causal conclusion drawn from A/B observations (X
happens in context A but not context B) into a durable artifact (task spec,
memory, PR body).
Falsifier: first ENUMERATE every variable that co-varies with the A/B split,
then run ONE isolating experiment (vary the hypothesized variable while
holding the others fixed) before the conclusion lands. A confounded split's
tell is that the hypothesis variable was never varied in isolation.
Origin: b0b294ab R12 (mt#2765, 2026-07-13) — all "hangs" observations
shared port 3737 (which had live browser-tab traffic) and all "works"
observations were quiet ports; "tray-spawned vs shell-spawned" was encoded
into mt#2765's spec v1 when the real variable was concurrent request traffic.
The isolating experiments (shell daemon ON 3737; exact tray spawn shape on a
quiet port) took <5 minutes once run, and both falsified the framing.
(d) Runtime-behavior root cause
Trigger: about to assert OR refute a root cause for what a system DID at
runtime — a stall, crash, timing/liveness anomaly, "it fired / didn't fire /
hung / stopped."
Falsifier: the authoritative evidence for observed runtime behavior is the
RUNTIME RECORD — grep the service logs, read the live health/metrics endpoint
(e.g. /api/health, /api/sweeps), or inspect process state — BEFORE
concluding. Reading the SOURCE establishes only INTENDED behavior, which
cannot refute an observed-behavior hypothesis the logs could settle in one
grep. The trap is sharpest when REFUTING ("the machinery looks correct, I
found no bug, therefore it can't be that"): a static-correctness argument is
not evidence about what the code DID. Note the Tier-2 blind spot — reading the
source symbol SATISFIES mt#2486's same-turn-read suppression, but for a
runtime-behavior claim that is the "right read for the wrong question."
Origin: b0b294ab R13 (mt#3039, 2026-07-22) — the prod-state sweep-stall
investigation REFUTED the "dead interval" hypothesis from
createIntervalSweeper / meta-watchdog source ("no bug found") and concluded
the interval "kept ticking" and the meta-watchdog "never intervened." The
daemon's own logs showed the meta-watchdog firing force-restarting once a
minute for ~7.5h with staleMs growing — the interval was dead and the
force-restart ineffective (an infinite restart storm). One grep of
cockpit-daemon*.log, or a read of live /api/sweeps lastAttemptAt (frozen),
would have falsified the conclusion; the task shipped DONE on the wrong root
cause (corrected + fixed by mt#3060). See memory mem#674.
(e) Language / runtime semantics beneath first-party code
Trigger: about to assert something about evaluation order, hoisting,
scheduling, or lifecycle — "this runs before that", "these execute in
declaration order", "the body runs first", "the import completes by then".
Falsifier: reading the file establishes the TEXTUAL order of its statements; it
does NOT establish WHEN they evaluate. Evaluation order is a fact about the
language spec, not about the file. Consult the spec/docs, or run a minimal
empirical probe (a three-line module that prints the order). Note this is the
same Tier-2 blind spot as cues (b) and (d): a same-turn read of the right
file SATISFIES mt#2486's same-turn-read suppression while establishing nothing
about the layer beneath it. Extra trap: a source COMMENT asserting the ordering
("setup config FIRST before any other imports") is authorial INTENT — if the
language's semantics contradict it, the comment makes the wrong answer look
confirmed.
Origin: b0b294ab R14 (mt#3090, 2026-07-23) —
scripts/measure-eval-attribution.ts was written to "mirror src/cli.ts's
eager top-level imports IN ORDER" and replicated cli.ts's textual order, which
interleaves setupConfiguration() between imports. ESM evaluates a module's
entire import graph before its body, so in reality every static import
completes first. The harness mis-attributed ~20ms — configuration/loader
measured 0.2ms against a true marginal cost of 20.7ms, and
setupConfiguration() measured 36.0ms against 14.8ms — and those wrong numbers
reached a PR body and a task spec before the reviewer caught the ordering. See
memory mem#698.
(f) Derived-metric semantics
Trigger: about to cite a computed metric — a tier delta, a layer
decomposition, a ratio, a percentage — as evidence for the thing its label
names.
Falsifier: a derived metric's label is a CLAIM ABOUT ITS PROBE. Read what the
probe actually executes and confirm it exercises the path the label names,
before citing the number. Cross-check with a second probe on the same path; a
confounded metric's tell is that no one has stated, in one sentence, what the
probe does. This matters most for numbers that are about to enter a durable
artifact, because a metric keeps looking authoritative while every downstream
consumer silently inherits the error.
Origin: b0b294ab R14 (mt#3090, 2026-07-23) —
scripts/benchmark-cold-boot.ts defines its "bundle load + runtime/DI/config
init" layer as the tier delta version − runtime. But minsky --version
tripped needsAll in src/cli.ts, eagerly loading all ten non-shared command
groups (MCP SDK, AI tokenizer, …) — ~455ms that no narrow command pays. The
layer was overstated roughly 2× (~780ms reported; ~365ms real), and the
inflated figure hardened into three durable artifacts in sequence: mt#2968's
## Findings, the mem#675 handoff's strategic conclusion, and then mt#3090's
founding premise — a task created to attack a lever that did not exist at that
size. Timing one narrow no-DB invocation (completion → ~365ms vs --version
→ ~820ms) falsified it. See memory mem#698.
(g) A claim relayed from an intermediary
Trigger: about to state, to the principal or into a durable artifact, a
mechanism/behavior claim whose source is an intermediary rather than the
primary source — a dispatched subagent's report, a WebSearch synthesis
paragraph, a safety-monitor's verdict, or a memory's paraphrase of a doc.
Falsifier: ask "did I read the PRIMARY source THIS turn?" — the actual vendor
doc page, the issue body via API, the installed source, the config file. If
not, either read it, or state the provenance and verification status
explicitly. Per claim-confidence.mdc, a relayed claim is at most
inferred / strong-evidence, never verified-*, until
primary-source-checked.
Specific falsifiers for the two commonest intermediaries:
WebSearch's summary paragraph is not a source. It is a synthesis to
verify against the pages it links. The links are the leads; opening them
(WebFetch, or the GitHub API on the actual issue) is the work. Read the
issue BODY and its state/date, not the title — a closed-as-stale issue and
an active bug read identically in a title list.
- A subagent saying "I read the docs" is a claim, not verification. The
subagent is subject to every cue on this page; its report inherits none of
their guarantees. Treat it as evidence the claim is worth checking.
Origin: b0b294ab R15 (mt#3152, 2026-07-24, memory mem#706) — across one
session three claims were stated to the principal as fact from intermediaries
and each was corrected only after pushback: that dispatched advisors were
running on Fable (they ran on Sonnet), that a documented env var overrides the
per-call model param (relayed from a subagent report plus a search synthesis,
asserted before reading the docs — it later held up), and that the behavior
was "a known upstream bug" (it is documented-intended). mem#686 named this for
safety-monitor verdicts — "a monitor's verdict is evidence that an artifact
needs checking, never a finding about it"; this cue generalizes it to every
intermediary.
(h) Your own tooling's actual effect
Trigger: about to assert what YOUR OWN tool call actually did — the model a
dispatch ran on, the config a command actually resolved, the branch a push
actually landed on — where the assertion rests on the call having been
accepted rather than on a signal of what it did.
Falsifier: read a caller-visible signal of the ACTUAL value. "The tool
accepted the param" is not evidence the param took effect; a silently-clamped
value and an honored one produce identical tool results. Where no such signal
exists, say the claim is UNVERIFIED — do not infer it from acceptance.
Origin: same session as (g). .claude/settings.json's
CLAUDE_CODE_SUBAGENT_MODEL sits ABOVE the per-invocation model param in
Claude Code's documented resolution order, so every dispatch requesting a
tier was silently resolved to the pinned one, with no error and no
caller-visible notice; the agent read "the tool accepted model: fable" as
"it is running Fable" and attached extra epistemic weight to those advisors'
conclusions when representing them to the principal. mt#3151 tracks both the
project's own pin and the missing caller-visible signal (its SC4); until a
signal exists, this cue's honest output is "unverified," not an assumption.
(i) An open item still needing the principal's action
Trigger: about to tell the principal that an open item requires their
action — an ask awaiting their answer, a PR awaiting their review, a task
blocked on their decision.
Falsifier: re-read the item's LIVE state THIS turn — asks_get,
session_pr_get, tasks_status_get, session_pr_wait-for-review — before
asserting. Per claim-confidence.mdc, a read from an earlier turn supports
inferred, not verified; if the assertion is made without a same-turn
re-read, label it as such rather than stating it flatly. Include the
self-caused case explicitly: an action the agent itself took earlier in the
SAME turn sequence — merging the item's parent task, closing a session,
resolving a dependency — can invalidate the item's state with no external
actor involved. There is nothing to prompt a re-check in that case except
the discipline itself; the item's state can be moved by mechanisms the agent
doesn't think of as actors (sweeps, other agents, webhooks, and the agent's
own prior action alike).
Origin: b0b294ab R16 (mt#3216, 2026-07-25) — at 18:12Z the orchestrator
read ask#6024 (state: "suspended", unanswered). At 18:18Z it merged
mt#3210, the ask's parent task. At 18:21Z a background sweep auto-closed the
ask as a consequence of that merge. At 18:38Z — 26 minutes and several tool
calls later — the orchestrator told the principal "only one of them needs
you: ask#6024," from the 18:12 read, by then false. The principal attempted
to answer, was told the ask had already been responded to, and had to ask
whether the state had been checked. The claim was not careless — it rested
on a real read — but nothing in the turn required re-reading before
asserting, and the invalidating event was the agent's OWN prior action, not
an external one.
Artifact-content and identity claims (mt#2534)
A second family, distinct from causal/mechanism claims above: factual claims
about what a CURRENT artifact (spec / doc / config / rule) says, requires, or
contradicts — or a casual claim about what a task/artifact IS, DOES, its
STATUS, or its SCOPE is. Not covered by gate (m) (fires only when a spec
cites a source to justify a structural choice, at /plan-task time) or the
causal-premise detector (mt#2216, fires on tool/system mechanism claims,
not "what the spec says"). Originating incidents in memory eb4411f3
(bridge memory; family root de54bd12 — memory-snippet conflation at
artifact-write time).
Trigger
Before any of:
- Asserting what a spec/doc/config/rule "says", "requires", or "contradicts".
- Changing behavior to conform to a REMEMBERED criterion instead of the
criterion as currently written. Highest-risk when the artifact was amended
earlier in the SAME session — memory may hold a superseded version.
- A casual artifact-IDENTITY claim: what a task/artifact IS, DOES, its
STATUS, or its SCOPE — even inside a low-stakes recommendation, not only a
structural decision. (2026-06-24 R2/R3: "mt#2410 is the
/pr/:n route" —
wrong; mt#2410 is DONE and covers the ask/memory routes, deferring
/pr/:n to a task that was never filed. The claim didn't read as a
"structural choice," so it didn't feel like the trigger — it still was.)
The falsifier: re-read the LIVE, AUTHORITATIVE source — not a cache
A same-turn read is necessary but NOT sufficient. Which read counts as
authoritative depends on what the claim is about — a same-turn Read of a
stale local file can pass a naive "did-you-read" check and still be wrong:
| Claim about | Authoritative read | NOT authoritative (a cache) |
|---|
| A task spec's current content | tasks_spec_get | Memory of an earlier read this session (the spec may have been amended since) |
| A task's current status/scope | tasks_status_get / tasks_get | A PR body, a spec's ## Context section, or any other durable artifact mentioning it |
| Merged/remote file or PR content | mcp__github__get_file_contents(ref=<sha|main>) or the PR diff (pull_request_read get_files) | A local-checkout Read — local main can be many commits behind origin |
| Whether a mechanism is sanctioned | The governing decision record (RFC / ADR / memory) | A repo doc describing the mechanism approvingly — docs describe, decision records sanction |
Check the inject-git-state hook's "N behind origin" banner before trusting
a local Read for a claim about merged/remote content — it makes staleness
visible, but visibility alone doesn't stop the assert; treat "behind
origin" as a hard signal to route the claim through the GitHub API instead.
Recurrences that motivated this section
- 2026-06-22 (mt#2518 R3, originating incident): live render verification
caught a limited-id-set bug; the agent "fixed" it by fast-pathing bare
mt# and told the principal "the spec contradicts itself" — the fast-path
criterion existed only in a SUPERSEDED spec version recalled from memory.
The live spec (re-readable via tasks_spec_get) unambiguously said gated.
A wrong commit was reverted next round.
- 2026-06-26 (mt#2553): asserted a merged PR had NOT updated a consumer
skill, based on a same-turn
Read of a LOCAL file 14 commits behind
origin. The authoritative GitHub PR diff reversed the claim. A same-turn
read occurred — it just wasn't the authoritative one.
- 2026-07-13/14: a stale PR body (written weeks earlier) described a task
as "still TODO" when
tasks_status_get showed DONE; separately, a repo
doc described a heuristic-backfill mechanism approvingly without carrying
the governing RFC's later rejection of it — the doc's framing was acted on
instead of the decision record. A repo doc describing a mechanism is not
evidence the mechanism is still sanctioned; re-read the status live
(tasks_status_get) and check the decision record (RFC/ADR/memory), not
the doc's prose.
Anti-patterns specific to this family
- Asserting "the spec says/requires/contradicts X" from memory of an earlier
read in the same session, even a read from minutes ago, without checking
whether the artifact was amended since.
- Treating a PR body, a spec's
## Context section, or a repo doc's usage
instructions as evidence of a task's CURRENT status or a mechanism's
CURRENT sanction. Cross-references in durable artifacts go stale silently.
- Stating a task/artifact's identity ("task X is/does Y", "task X covers Z")
in a recommendation without re-reading, on the theory that a casual
identity claim doesn't need the same rigor as a structural decision.
Arguments
Optional: one-phrase description of the claim being made (e.g.,
/check-premise reviewer shares author identity so APPROVE is blocked).
Process
Step 1: State the claim
Write the causal claim in one sentence. Example:
"The reviewer bot is posting COMMENT instead of APPROVE because it shares
the same App identity as the PR author, and GitHub blocks self-approval."
Step 2: List the factual premises
For each distinct factual claim embedded in the explanation, list it as a
bullet. Example:
- P1: The reviewer bot (278512143) and the PR author bot (277592531) share
the same App identity.
- P2: GitHub's self-approval block fires when reviewer and author share an
App identity.
- P3: The reviewer bot's COMMENT choice is caused by the identity block, not
by the LLM's own event choice.
Step 3: Identify the cheapest falsifier
For each premise, identify the cheapest evidence that could falsify it. Order
by cost (cheapest first):
| Premise | Cheapest falsifier | Cost |
|---|
| P1: Same App identity | gh api /repos/.../pulls/N/reviews — compare reviewer vs author app_id | 1 tool call |
| P2: GitHub blocks on identity | GitHub docs / prior APPROVE from reviewer on same repo | lookup |
| P3: COMMENT caused by identity block | Read compose-review.ts:159-174 for LLM event routing | file read |
Step 4: Check the cheapest first
Execute the cheapest check. If it returns evidence that contradicts a premise,
STOP — the causal story is wrong. Update the explanation.
Example: checking P1:
gh api /repos/edobry/minsky/pulls/1456/reviews
Returns: author_association: "owner" for reviewer id 278512143, and PR
author id 277592531 — different ids. P1 is FALSE. The whole causal story
collapses. Root cause must be found elsewhere (read compose-review.ts).
Step 5: Assert only what the evidence shows
Only state causal claims that the checked evidence directly supports. For
unverified premises, say "unverified — need to check X."
Anti-patterns to avoid
- Asserting a causal mechanism based on a general model of how the system
works, without reading the actual code/data for this specific case.
- Treating a compacted session summary as verified ground truth (R5: the
drizzle high-water-mark mechanism was inherited from a summary, not read).
- Stopping at a plausible explanation without checking the cheapest falsifier.
- Citing a file/function by name without verifying its content applies to
the specific case.
Cross-references
- Memory
3772c77d — "Verify the premises of a causal explanation before
asserting it" — R1–R5 incident log.
.claude/hooks/causal-premise-detector.ts — structural enforcement hook
(mt#2216, calibration mode — logs matches to
.minsky/causal-premise-calibration.jsonl).
CLAUDE.md §Professional communication — "Verify factual claims before
agreeing or disagreeing; use 'Let me check…' before confirming facts."
feedback_confabulated_strategic_frame_to_justify_tactical_preference
(memory 88d92439) — sibling family (strategic framing vs mechanism claims).
- Memory
b0b294ab — family record for the "assertion frozen as fact without
verification" pattern (R6–R16); R11–R16 are the origin of the nine
cues above. mt#2485 — the strategic partition (Tier-1 mt#2488, Tier-2
mt#2486, Tier-3 residual = these per-surface cues). mt#2698 — cues
(a)–(c)'s task; mt#3055 — cue (d)'s task; mt#3126 — cues (e)/(f)'s task;
mt#3152 — cues (g)/(h)'s task; mt#3216 — cue (i)'s task. Cue (d)'s
incident memory: mem#674 (07cb2686); cues (e)/(f)'s: mem#698
(8f594a7e); cues (g)/(h)'s: mem#706 (a28844c1).
- Cues (b), (d), (e) and (f) share one structural property worth stating
plainly: each is a case where a same-turn read of the RIGHT first-party file
is present and still does not establish the claim, because the claim is about
a layer beneath the file (a third-party platform, the runtime record, the
language spec, or what a probe executes).
mt#2486's same-turn-read
suppression is therefore knowingly blind to this set — see mt#3113, which
strengthens that suppression for precision, making these cues the residual
coverage rather than a duplicate of it.
- Memory
eb4411f3 — bridge memory for the artifact-content/identity family
(## Artifact-content and identity claims above); originating incidents
R1–R4 (mt#2518, plus the 2026-06-24 and 2026-06-26 recurrences).
- Memory
de54bd12 — family root ("memory-snippet conflation at
artifact-write time"); the artifact-content family is a sibling surface of
the same confabulation pattern.
- mt#2534 — the task that broadened this skill to cover the
artifact-content/identity family; records the detector-tier decision
(skill-only for now; any future hook-tier mechanism routes through
ADR-024's detection-mechanism ladder / mt#2263 rather than a standalone
hook).
- mt#2263 / ADR-024 (
docs/architecture/adr-024-detection-mechanism-ladder-for-guidance-hooks.md)
— the shared detection-mechanism ladder for the guidance-hook family; the
mechanism-selection destination if this family's discipline is ever
escalated to a hook.