The shape check¶
Run this before drafting in Sketch mode, and any time the discussion in any mode hinges on "what does this touch" or "what depends on this". The check is read-only โ culture and mold both run it; only the artifact stage differs.
What it answers¶
- Signatures: what does the touched function/type look like today? What sibling signatures already exist in the same module so a new one fits convention?
- Callers (upstream): who calls the touched symbol, and from which modules?
- Callees (downstream): what does the touched symbol call into? Surfaced by the same symbol query โ
kind: "symbol"returns aโโ calls โโfooter with one-hop callees. No extra call. - Imports / blast radius: which files import this module? Which does this module import?
These four answers together describe the shape of the change and bound its blast radius โ both upstream (who breaks if I change this) and downstream (what could I drag into the change). The downstream half is what InlineCoder-style bidirectional inlining is empirically worth on repo-level edits; ignoring it leaves a known gap.
Procedure¶
Run all three. Cheap when the answers are small; the cost of skipping is silent misrouting later.
| Question | Tool | Call |
|---|---|---|
Current signature? Sibling signatures? Downstream callees (โโ calls โโ footer)? |
cheez-search |
tilth_search(query: "<symbol>", kind: "symbol", expand: 2, scope: "<module>") |
| Who calls this? (upstream) | cheez-search |
tilth_search(query: "<symbol>", kind: "callers", scope: ".") |
| What's the import / blast radius? | cheez-search |
tilth_deps(path: "<file>") |
The first call does double duty โ its โโ calls โโ footer is the cheap callee read; do not issue a separate query for it.
For multi-symbol changes, batch up to five symbols in a single cheez-search call (query: "a, b, c"). Re-run only when a new symbol enters scope.
Output expected before exit¶
A summary at the top of the Sketch turn (or culture's blast-radius step):
Shape check on <symbol(s)>:
signature(s): <one line per touched seam>
callers: <count> sites in <N> non-test files (paths)
callees: <count> one-hop calls (names) โ omit line if empty
blast radius: imported by <count> files; imports <count> modules
verdict: low | medium | high
The callees line is optional โ print it only when the symbol query's โโ calls โโ footer is non-empty. A leaf function with no callees should drop the line, not print 0.
A high verdict (multi-module callers or more than five importers) makes the Grill gate mandatory in mold (see handshake.md) and forces culture to label the option [high blast radius] before continuing trade-off talk.
When tilth / cheez-search is unavailable¶
Shape-check should not block the dialogue when its preferred tools are missing. Substitute where a sanctioned alternative exists; for shape-check specifically, do not substitute textual search โ grep / rg over a symbol name produces a count of string occurrences, not callers or importers, and a guessed blast-radius verdict is worse than an honest unknown. (This is a shape-check rule, not a global cheez-* ban: outside cheez-* skills, mold and other workflow skills may use host tools where they are the right answer โ see the README's "host tools are still the right call outside code work" line.)
- Callers / callees: fall back to LSP
textDocument/references/textDocument/prepareCallHierarchywhen a language server is reachable. Note the substitution out loud. - Imports / blast radius: no LSP equivalent. Skip the count, mark the line
unknown, and lean on the verdict downgrade below. - Verdict: cap at
[?]instead oflow | medium | highโ a guessed verdict is worse than an honest unknown. Sketch and culture should treat[?]likehighfor gating purposes (Grill gate engages, option labelled[high blast radius]) until the user accepts the gap.
If both tilth and LSP are unavailable, say so once and proceed with [?]. Do not silently substitute a textual search for the shape-check itself.
When to skip¶
- The touched symbol has zero callers (greenfield) โ say so out loud.
- The change is contained to one private function inside a single file with no exports โ sibling signature lookup still applies; deps and callers can be skipped.
- The user explicitly said
skip the shape check.
Why¶
Trade-offs and seams discussed without a shape check rely on the agent's guess at impact. The check converts that guess into numbers โ caller count, callee count, importer count โ the user can argue with.
The directionality matters: upstream (callers) tells you who breaks if the seam changes; downstream (callees) tells you what the change might drag in. Bidirectional structural context is empirically worth a measurable accuracy lift on repo-level edits, and the downstream half rides for free on the existing symbol query.