references/formats.md
# Artifact formats
Schemas every `slice-and-spine-review` subagent must conform to. All dossier
artifacts are markdown files with YAML frontmatter carrying the machine
fields, plus one `session.json` index per session. Field names below are
verbatim from the approved spec's interface sketches — do not rename them.
Every dossier's frontmatter carries two common fields beyond its own schema:
- `commit`: the full commit sha the dossier was built from (staleness guard —
a session spanning edits can detect drift by diffing this against HEAD).
- `scope`: the generating scope (`slice names | seam ids | full`) passed to
the invocation that produced this artifact. Additive operational field —
not part of the spec's interface sketches; every other field name below
is verbatim from those sketches.
Dossier files land under
`.cheese/slice-and-spine/<repo>/<date>/{digests,slices,seams,verdicts}/`,
one subdirectory per artifact kind.
## FileDigest
One per file+test pair (Phase 1 fan-out unit).
| Field | Type | Notes |
| ---------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `path` | string | Repo-relative path to the source file. |
| `role` | string | One of `crust`, `internal`, `spine`, `adapter`, `port`. |
| `surface_exposed` | string[] | Identifiers this file exports for external use. |
| `surface_used` | string[] | Identifiers this file imports from elsewhere. |
| `behavior_assertions` | string[] \| UNTESTED | Behavior claims the file's tests actually assert. A file with no tests carries the literal marker `UNTESTED`, not an empty list. |
| `duplication_suspects` | string[] | Paths or symbols this file's logic appears to duplicate. |
```markdown
---
path: domains/pricing/discount.py
role: internal
surface_exposed: [calculate_discount]
surface_used: [domains.common.Money]
behavior_assertions:
- 'applies percentage discount and floors at zero'
- 'rejects negative discount rates'
duplication_suspects: []
commit: 4f2a9c1e8b7d3f0a6c5e2d1b9a8f7e6d5c4b3a2f
scope: full
---
Digest notes go here as prose, if any.
```
## SliceDossier
Rollup of a slice's FileDigests.
| Field | Type | Notes |
| ---------------- | -------- | ------------------------------------------------------------------- |
| `slice` | string | Slice name (crust role, e.g. `pricing`). |
| `crust_surface` | string[] | Union of `surface_exposed` across the slice's FileDigests. |
| `internal_files` | string[] | Paths of non-crust files in the slice. |
| `assertion_map` | object | Map of `path -> behavior_assertions` (or `UNTESTED`) for the slice. |
| `mass` | number | Slice size signal (e.g. file count or line count) used in ranking. |
```markdown
---
slice: pricing
crust_surface: [calculate_discount, price_catalog]
internal_files: [domains/pricing/discount.py, domains/pricing/catalog.py]
assertion_map:
domains/pricing/discount.py:
- 'applies percentage discount and floors at zero'
domains/pricing/catalog.py: UNTESTED
mass: 2
commit: 4f2a9c1e8b7d3f0a6c5e2d1b9a8f7e6d5c4b3a2f
scope: full
---
```
## SeamDossier
Derived from the SliceDossier(s) on slice sides plus a bare identifier and
summary for non-slice (spine, adapter/port) sides, plus co-change and
hot-path evidence.
| Field | Type | Notes |
| -------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `seam_id` | string | `"A<->B"` — the two sides joined by `<->`. |
| `edge_kind` | string | One of `slice-slice`, `spine-slice`, `adapter-port`. |
| `co_change` | number | Change-coupling score (co-change frequency across the boundary). |
| `fan_in` | number | Static fan-in count crossing the boundary. |
| `hot_paths_crossing` | string[] | Hot-path identifiers (from caller-graph code intelligence) that cross this seam. |
| `both_sides` | object | `{ a: <SliceDossier ref \| bare id + summary>, b: <SliceDossier ref \| bare id + summary> }` — a non-slice side (spine, adapter/port) carries a bare identifier plus a one-line summary string instead of a SliceDossier ref. |
| `candidates` | string[] | Files or symbols flagged as pull-up/push-down candidates at this seam. |
```markdown
---
seam_id: 'pricing<->checkout'
edge_kind: slice-slice
co_change: 0.62
fan_in: 3
hot_paths_crossing: [checkout.apply_discount]
both_sides:
a: pricing
b: checkout
candidates: [domains/checkout/pricing_helpers.py]
commit: 4f2a9c1e8b7d3f0a6c5e2d1b9a8f7e6d5c4b3a2f
scope: full
---
```
## LinkMatrix
Ordinal link-level taxonomy over slice pairs, rendered as a DSM-style matrix
in the session report.
| Field | Type | Notes |
| ------- | ----- | --------------------------------------------------------------------------- |
| `pairs` | array | List of `{ a, b, level, evidence }` entries, one per slice pair considered. |
Each `pairs` entry:
| Field | Type | Notes |
| ---------- | ------ | --------------------------------------------------------------------------- |
| `a` | string | First slice name. |
| `b` | string | Second slice name. |
| `level` | string | One of `L0`, `L1`, `L2`, `L3`, `L4` (see levels below). |
| `evidence` | object | `{ imports, co_change, hot_paths }` — the numeric evidence backing `level`. |
Levels:
- `L0` — none: no detected relationship.
- `L1` — event-linked: connected only via a typed event, no direct import.
- `L2` — crust import: one slice imports the other's public seam.
- `L3` — multi-symbol import: crust import spanning multiple symbols.
- `L4` — co-change hot: high co-change score or crossing hot paths; no
import requirement.
Every cell carries its numeric evidence — never assert a `level` without the
`evidence` object populated.
```markdown
---
pairs:
- a: pricing
b: checkout
level: L4
evidence:
imports: 3
co_change: 0.62
hot_paths: 1
- a: pricing
b: inventory
level: L1
evidence:
imports: 0
co_change: 0.05
hot_paths: 0
- a: checkout
b: inventory
level: L2
evidence:
imports: 1
co_change: 0.1
hot_paths: 0
commit: 4f2a9c1e8b7d3f0a6c5e2d1b9a8f7e6d5c4b3a2f
scope: full
---
```
## Verdict
One per seam-walk stop or spine-review stop.
| Field | Type | Notes |
| ------------- | -------- | --------------------------------------------------------------------------- |
| `seam_id` | string | The seam this verdict resolves (`"A<->B"`, or the spine stop's identifier). |
| `disposition` | string | One of `pull-up`, `push-down`, `rethink-seam`, `healthy`. |
| `rationale` | string | The human's stated reasoning for the disposition. |
| `followups` | string[] | Follow-up work items spawned by this verdict, if any. |
```markdown
---
seam_id: 'pricing<->checkout'
disposition: pull-up
rationale: >-
Discount math duplicated in checkout should live in pricing's crust; both
call sites already treat it as pricing's responsibility.
followups: ['pull discount calc into pricing.calculate_discount']
commit: 4f2a9c1e8b7d3f0a6c5e2d1b9a8f7e6d5c4b3a2f
scope: full
---
```
## Session report
Location: `.cheese/slice-and-spine/<repo>/<date>.md`.
Markdown (no required frontmatter schema beyond `commit` and `scope`)
containing:
- Stops walked, in ranked order.
- The verdict issued at each stop.
- The rendered link-level matrix (DSM-style table from `LinkMatrix.pairs`).
- Coverage: seams visited vs. total seams identified in Phase 0.
```markdown
---
commit: 4f2a9c1e8b7d3f0a6c5e2d1b9a8f7e6d5c4b3a2f
scope: full
---
# slice-and-spine-review — sliced-bread-architecture — 2026-08-17
## Stops
1. pricing<->checkout — pull-up
## Link-level matrix
| | pricing | checkout | inventory |
| --------- | ------- | -------- | --------- |
| pricing | — | L4 | L1 |
| checkout | L4 | — | L2 |
| inventory | L1 | L2 | — |
## Coverage
1 of 3 seams visited.
```
## session.json
The one JSON index for the session. Location:
`.cheese/slice-and-spine/<repo>/<date>.session.json`.
| Field | Type | Notes |
| ------------- | -------- | ------------------------------------------------------------------------- |
| `commit` | string | Commit sha the session was built from. |
| `scope` | string | Invocation scope (`slice names \| seam ids \| full`). |
| `walk_order` | string[] | Seam ids in ranked walk order. |
| `pointers` | object | Paths to the dossier files this session produced, keyed by artifact kind. |
| `seam_status` | object | Map of `seam_id -> status` (`pending \| visited \| skipped`). |
```json
{
"commit": "4f2a9c1e8b7d3f0a6c5e2d1b9a8f7e6d5c4b3a2f",
"scope": "full",
"walk_order": ["pricing<->checkout", "checkout<->inventory"],
"pointers": {
"file_digests": [
".cheese/slice-and-spine/sliced-bread-architecture/2026-08-17/digests/domains-pricing-discount.md"
],
"slice_dossiers": [
".cheese/slice-and-spine/sliced-bread-architecture/2026-08-17/slices/pricing.md"
],
"seam_dossiers": [
".cheese/slice-and-spine/sliced-bread-architecture/2026-08-17/seams/pricing-checkout.md"
],
"verdicts": [
".cheese/slice-and-spine/sliced-bread-architecture/2026-08-17/verdicts/pricing-checkout.md"
],
"session_report": ".cheese/slice-and-spine/sliced-bread-architecture/2026-08-17.md"
},
"seam_status": {
"pricing<->checkout": "visited",
"checkout<->inventory": "pending"
}
}
```
SKILL.md
---
name: slice-and-spine-review
description: >-
Run a human-in-the-loop whole-repo coherence review of a Sliced Bread
codebase: inventory slices, the spine, and seams; fan out subagents to
digest every file with its tests; walk seams in ranked order with the
human issuing a disposition per stop; review the spine for orchestration
drift. Use when the user says "review the seams", "slice and spine
review", "whole-repo coherence review", "walk the seams", or asks whether
slices still hang together after individual changes passed review. Do NOT
use for rule-compliance checking on a bounded change set
(sliced-bread-review), autonomous audit and issue filing
(sliced-bread-audit), or depth/crust-shape scoring (sliced-bread-depth) —
this skill is a guided session over the whole repo, not an automated
check.
---
# Slice and Spine Review
A human-led whole-repo coherence pass with an agentic prep sidecar. Individual
changes can each pass `sliced-bread-review`, `sliced-bread-depth`, and
`sliced-bread-audit` while the seams between slices and the spine accrete
leaky or duplicated logic no bounded-diff check ever sees. This skill
inventories the repo, fans out digests, then walks every seam with a human in
the loop.
## Invocation
```text
/slice-and-spine-review [scope: slice names | seam ids | full]
```
Default scope is `full`. A named scope (slice names or seam ids) limits
Phase 2's walk and Phase 3's spine visit to the matching seams and use cases,
but Phase 0's inventory and matrix still cover the whole repo so ranking has
full context.
## Terms
- **Slice** — a `domains/*` module in doctrine role, not necessarily a
literal directory named `domains`.
- **Crust** — a slice's public seam in the language's native form (exported
identifiers, package `__init__` surface, index module, public class
surface, or the positional root for languages with no native visibility).
Full rationale:
<https://cheeselord.dev/sliced-bread-architecture/reference/sliced-bread/>
(in-repo: [[architecture/crust-definition]]).
- **Spine** — `app/use_cases` plus the composition root (`app/bootstrap`).
- **Seam** — a crossing edge, one of exactly three kinds: slice-slice (crust
import or event), spine-slice, adapter-port binding. Distinct from a
Feathers-style test-substitution seam.
## Phase 0 — Inventory
1. Enumerate slices (crusts), the spine, and every seam crossing them,
classified into the three edge kinds above.
2. Derive **hot paths** from caller-graph code intelligence (dependency
closure / call hierarchy from entrypoints through the spine into slices).
Hot paths feed seam ranking (below), SeamDossiers (Phase 1), and spine
visit order (Phase 3).
3. Build the **slice link-level matrix**: for every slice pair, one ordinal
level with its evidence:
| Level | Meaning |
| ----- | ------------------- |
| L0 | No link |
| L1 | Event-linked |
| L2 | Crust import |
| L3 | Multi-symbol import |
| L4 | Co-change hot |
Every cell records the pinned evidence trio (`imports`, `co_change`,
`hot_paths`, per `references/formats.md`) regardless of level; a level's
meaning may cite its distinguishing detection input in prose (e.g. an
event link for L1, multiple imported symbols for L3) without that input
becoming a separate evidence field.
L4 (co-change hot) fires on a high co-change score or hot paths crossing
the pair with no import requirement — the ordinal ladder does not imply
L4 requires an import.
Pin the schema in `references/formats.md`; do not restate field shapes
here.
4. **Rank the seam walk** change-coupling-first: sort seams by `co_change`
descending (primary key); break ties with a composite of 0-1-normalized
terms (tunable):
```text
tiebreak = w_f * norm(fan_in) + w_d * depth_verdict_weight
+ w_h * norm(|hot_paths_crossing|)
norm(x) = x / max(x over all seams) # 0 when the max is 0
```
- `fan_in` — raw static fan-in count crossing the boundary; normalized to
[0,1] by the max fan_in across all seams.
- `depth_verdict_weight` — [0,1], see the verdict table below.
- `|hot_paths_crossing|` — the length of the SeamDossier's
`hot_paths_crossing` array (a string[] of hot-path identifiers),
normalized to [0,1] by the max count across all seams.
Starting weights `w_f=0.4, w_d=0.35, w_h=0.25`; adjust per repo and
record the adjustment in the session report.
`co_change` is continuous, so in practice the composite orders seams with
equal — typically zero — co-change; the weights matter most for the
never-co-changed tail.
`depth_verdict_weight` maps `sliced-bread-depth` verdicts onto [0,1] by
boundary-trouble signal strength (per that skill's own semantics); a
seam takes the max of its two sides' slice verdict weights, and a
non-slice side (spine, adapter/port) contributes 0. Verdicts come from a
`sliced-bread-depth` run or its latest report; when no depth report is
available, set `depth_verdict_weight = 0` for all seams and record the
degradation in the session report, mirroring the shallow-git-history
degradation rule below:
| Verdict | Weight |
| ------- | ------ |
| extract | 1.0 |
| narrow | 0.75 |
| watch | 0.5 |
| intent | 0.25 |
| healthy | 0 |
5. `common/` edges get a stop in the walk only when co-change flags them —
do not stop on every `common/` import by default.
6. **Shallow git history** degrades ranking to fan-in only; say so plainly in
the session output (Phase 4). Never fail the review for missing history
depth.
## Phase 1 — Fan-out
Before the human session starts, fan out one subagent per file+test pair
within the invocation's scope: the files (and their tests) of in-scope
slices, plus the spine, plus the far-side slices of every seam touching an
in-scope slice — a seam is only judgeable with both sides' dossiers — or
the whole repo when scope is `full`.
Use the Workflow tool when the harness provides it; fall back to the Agent
tool otherwise.
Each subagent produces a **FileDigest** conforming to the pinned schema in
`references/formats.md`: surface exposed, surface used, behavior assertions
extracted from its tests, and duplication suspects. A file with no tests
carries the `UNTESTED` marker in place of behavior assertions — do not infer
assertions from implementation reading.
Roll FileDigests up:
- **SliceDossier** per slice — crust surface, internal files, assertion map,
mass.
- **SeamDossier** per seam — derived from the SliceDossier(s) on slice
sides (a bare identifier + summary for a non-slice side) plus co-change
and hot-path evidence from Phase 0.
Every dossier stamps the commit it was built from (staleness guard — if the
session spans edits, a dossier older than the current HEAD at its path is
stale and must be rebuilt before its stop, not silently trusted).
All schemas live in `references/formats.md` — cite that path in dossiers and
prompts; do not duplicate the schemas here.
## Phase 2 — Seam-walk
Guided session, one stop per seam in rank order:
1. Present a **stop card**: seam id, edge kind, link level (slice-slice
seams only), both sides' summaries (SliceDossier summary for a slice
side; identifier + one-line summary for a spine or adapter/port side),
co-change and hot-path evidence, candidate findings from the dossiers.
2. The human interrogates freely — the agent answers from dossiers plus live
code intelligence (search, read, caller graph), not from memory or
speculation.
3. The human issues exactly one disposition per stop:
| Disposition | Meaning |
| ------------ | --------------------------------------------------- |
| pull-up | Duplicated/leaked logic moves up into a shared seam |
| push-down | Logic moves down out of the seam into a slice/spine |
| rethink-seam | The edge kind or direction itself is wrong |
| healthy | No action |
4. Record the verdict (rationale, follow-ups) and move to the next seam in
rank order.
The human may stop the walk at any point; coverage (seams visited vs.
total) is recorded in the session report regardless of where the walk ends.
## Phase 3 — Spine review
Visit `app/use_cases` hot-paths-first (using Phase 0's hot-path derivation
for visit order), then the composition root:
- **Orchestration-only check** — a use case that contains inline domain
logic (branching business rules, calculations, invariant checks) rather
than delegating to slices is a push-down candidate.
- **Composition-root wiring check** — `app/bootstrap` wires adapters to
ports and use cases; any domain logic or adapter-specific branching found
there is a push-down candidate into the adapter or the relevant slice.
Spine findings feed the same disposition set as Phase 2 and land in the same
session report.
## Phase 4 — Close-out
1. Write the session report to `.cheese/slice-and-spine/<repo>/<date>.md`:
stops visited, coverage, verdicts, the link-level matrix, and a note on
any ranking degradation (shallow history, adjusted weights).
2. Every **consequential** verdict (pull-up, push-down, rethink-seam — not
healthy) becomes an ADR-backed wiki page under `.hallouminate/wiki/`.
Resolve the exact namespace (`decisions/` vs `architecture/`) against the
wiki's own ADR conventions at the first close-out in a repo, and state
the resolution in the session report so later runs are consistent.
3. Render remaining follow-up work as a handoff menu (`/mold`, `/cook`) —
do not silently drop unaddressed findings.
## Non-goals
- Not rule-compliance checking on a bounded diff — use `sliced-bread-review`.
- Not autonomous audit or issue filing — use `sliced-bread-audit`.
- Not depth or crust-shape scoring — use `sliced-bread-depth`.