Session Breakdown Skill
What it produces
A single JSON file: <session_dir>/session_breakdown.json.
- Schema:
hyperloom.session_breakdown.v6.0 (hardcoded; see SCHEMA_VERSION in breakdown/schema.py).
- Producer:
src/hyperloom/inference_optimizer/breakdown/exporter.py
- Filename:
BREAKDOWN_FILENAME (= session_breakdown.json)
Beyond the envelope (schema_version / exported_at_utc / exporter_version), the JSON
carries the sections below. This is the subset most consumers use, not the full set —
breakdown/exporter.py (the breakdown = {...} literal) and breakdown/schema.py are
authoritative.
| Section |
What it carries |
schema_version |
The wire contract. Gate features on the major version, not the exact string. |
exported_at_utc |
When this export was built. |
exporter_version |
Which exporter built it. |
metadata |
Session identity, launch configuration, component versions, Langfuse receipt, and warnings -- how the export itself went, reported once and only here. |
outcome |
Terminal status, stage reached, stop reason, the baseline and final measured results, and the validation that reconciles the stack's parts against its total. |
timeline |
The run itself: one event per stage, oldest first, each carrying its span, status, and an ext block of what that kind of stage records. Startup source events live under reports/sbd_v6/timeline/. |
close |
What the session settled at close: the steps the sequencer ran, the artifacts it published, the robustness findings it collected. |
critic |
The critic agent's own run, iteration by iteration: what it was asked about, how its rulings fell (verdict_counts), and the four artifacts each pass left behind. Per-proposal verdicts stay with the proposals, on the timeline. |
robustness |
What the robustness agent raised, turn by turn. Read outcome before counting intents: a turn that produced no envelope and a turn with nothing to raise are different findings. |
Who reads it
- A downstream stats/reporting service — primary consumer. Replaces the
MAE-synthesized
raw_report / fact_sheet. Recommended read order:
prefer session_breakdown.json if present, fall back to legacy MAE
output otherwise.
hyperloom-results-service — downstream automation may POST this
JSON when HYPERLOOM_RESULTS_SERVICE_URL is set.
- Offline / notebook analysis — single file, easy to load, no DB
needed.
When to refresh (LLM Orchestrator decision tree)
The Coordinator's cli.py finally block writes session_breakdown.json
unconditionally at end-of-session — that's the safety net. But you
should ALSO refresh it eagerly when downstream dashboards may be
watching this session live:
- Always at end-of-session (handled by
cli.py finally — you do not need to dispatch this).
- After every KEEP'd explore, specialist, framework, or kernel result
whose benchmark changed the final stack.
- After a successful sweep or conc_sweep when a live dashboard is
observing this session.
- Never mid-action — collectors expect a coherent state snapshot.
Dispatch action session_breakdown — a single 1-minute action, no inputs
required.
How to invoke
LLM-driven (Coordinator action)
# Issue an action intent like any other action
{ "action": "session_breakdown", "params": {} }
Code-driven (Python import)
from hyperloom.inference_optimizer.breakdown import build, write_breakdown_json
# Just compute the dict (no side effects)
breakdown = build("/workspace/hyperloom")
# Compute + atomically write to <sd>/session_breakdown.json
out_path = write_breakdown_json("/workspace/hyperloom")
CLI / offline (hyperloom.inference_optimizer.tools.dump_session_breakdown)
# Live session in this sandbox
python -m hyperloom.inference_optimizer.tools.dump_session_breakdown
# Historical session on a shared filesystem
python -m hyperloom.inference_optimizer.tools.dump_session_breakdown \
--session-dir /shared/hyperloom-sessions/<user>/<sid>
# Override output path (e.g. write to a staging area)
python -m hyperloom.inference_optimizer.tools.dump_session_breakdown \
--session-dir <SD> --output /tmp/breakdown.json
Bulk historical (operator)
for d in /shared/hyperloom-sessions/*/*; do
[ -d "$d" ] || continue
python -m hyperloom.inference_optimizer.tools.dump_session_breakdown \
--session-dir "$d" > /dev/null
done
Field reference (what comes from where)
The collector for each section reads only from the listed sources. All
collectors are pure functions; failure in one section never poisons
another (each becomes a warnings[] entry instead). Like the table above,
this reference is partial — breakdown/exporter.py is authoritative.
| Section |
Read from |
metadata |
manifest.json + state.json, overlaid by the recorder's own session / task_config / versions fragments |
outcome |
The recorder's close and stack fragments, plus state.{current_best, cumulative_gain_validated, optimization_stack} for the sessions that predate them |
timeline |
The event fragments in the spool, closed and assembled per event; orphans left open by a killed phase are closed on first build |
close |
The CLOSE sequencer's own close / close_step fragments |
critic |
critic-workdir/<NNN>/{request,judge_bundle,emit,review}.json, recorded as each pass returns |
robustness |
The robustness agent's per-turn envelopes, recorded as each turn returns |
What is NOT in scope
- Real-time event streaming — use
claw_session_events for that.
- LLM-based attribution — every collector is deterministic /
rule-based. Attribution is
delta_pct math, not natural language.
- Schema migration — consumers MUST check
schema_version and gate
features on it, comparing the major version (vN) rather than the
exact string: the producer emits both …v2 and …v3.0 today (see
Versioning policy) and they are wire-compatible.
- Cross-session aggregation — one file per session. Use a Jupyter
notebook or downstream analytics job for fleet views.
Failure modes
| Symptom |
Cause |
Mitigation |
warnings: ["state.json missing"] |
Session was created (manifest written) but Coordinator.save() never ran |
Sections fall back to manifest-only data. |
warnings: ["manifest.json missing"] |
Session was created without the standard cli.py path (rare) |
session.session_id falls back to state.session_id. |
optimizations.available = false |
No operations were recorded, or the projection failed |
Read unavailable_reason. The empty arrays mean unknown, not none; a warnings entry says whether state.json knew of adopted work the recorder missed. |
optimizations.validation.unclaimed_integration_count > 0 |
A change recorded as integrated has no adoption crediting it |
The adoption write was lost. unattributed_gain_pct is overstated by whatever those steps earned. |
optimizations.entries[].gain_method = local_gain_projected |
The step recorded no finishing throughput |
Its gain is projected from the executor's own percentage, not measured against the chain. |
kernel_lifecycle.detected = [] |
profile action never ran or its benchmark_report.json had no kernel_summary |
Re-run profile, or fall back to recommended from state.last_trace_analyze. |
Large warnings[] |
Multiple JSON parse failures on optimization_attempts.jsonl |
Inspect kernel-agent-workspace/.../logs/ for the corresponding kernel-agent CLI logs. |
Versioning policy
schema_version (in schema.py) carries the major contract
version; it is bumped ONLY on breaking changes (renamed/removed
fields, changed semantics).
- New exports carry
hyperloom.session_breakdown.v6.0. V6 is a breaking
cutover for the timeline: the actions record their own events as they run,
so an event's start_time is when the work began rather than when its
artefacts were written, and the KERNEL and BASELINE projections are gone.
Consumers that sorted around the old collapsed windows need to be rechecked.
- Inside v6,
enablement gained the round ledger: rounds[] and its
counters are added to the block, and the three state-sourced fields they
replace (stall_streak, inflight_task_id, dispatch_tick) are no longer
emitted. The block is runtime observability that is already {} on a
session that ran no enablement, so it carries no field a consumer can gate
a version on; the disposition of each replaced field is in
docs/reference/session-breakdown.md.
- V5 was the preceding cutover, for optimization results:
optimizations is
reshaped, and the optimization_stack, attribution, geak_invocations,
forge_invocations, and gemm_tuning projections are gone. Consumers
MUST match on the vN major prefix, never on exact-string equality, and
archived V2/V3/V4/V5 documents need a migration before a V6 reader sees them.
optimizations carries its own schema_version (currently 5),
independent of the envelope's.
- Adding optional fields is never a breaking change.
exporter_version tracks the exporter implementation independently;
consumers can ignore it.
Testing
Each collector has a unit test under src/hyperloom/inference_optimizer/tests/
that runs it against a fixture session_dir tree. An end-to-end test calls
build(...) on a fully-populated fixture and JSON-schema-validates the
result. Run:
pytest src/hyperloom/inference_optimizer/tests/ -k breakdown -v
1---2name: session-breakdown3description: Build a single self-contained `session_breakdown.json` capturing every fact a dashboard needs about one hyperloom optimization session. Use when the user mentions session-breakdown, kernel attribution, a stats/reporting service, capability summary, or wants to surface hyperloom data to an external consumer (a results/stats service, notebook, dashboard).4---56# Session Breakdown Skill78## What it produces910A single JSON file: **`<session_dir>/session_breakdown.json`**.1112- Schema: `hyperloom.session_breakdown.v6.0` (hardcoded; see `SCHEMA_VERSION` in `breakdown/schema.py`).13- Producer: `src/hyperloom/inference_optimizer/breakdown/exporter.py`14- Filename: `BREAKDOWN_FILENAME` (= `session_breakdown.json`)1516Beyond the envelope (`schema_version` / `exported_at_utc` / `exporter_version`), the JSON17carries the sections below. This is the subset most consumers use, not the full set —18`breakdown/exporter.py` (the `breakdown = {...}` literal) and `breakdown/schema.py` are19authoritative.2021| Section | What it carries |22|---------------------|----------------------------------------------------------------------------------------------------------|23| `schema_version` | The wire contract. Gate features on the **major** version, not the exact string. |24| `exported_at_utc` | When this export was built. |25| `exporter_version` | Which exporter built it. |26| `metadata` | Session identity, launch configuration, component versions, Langfuse receipt, and `warnings` -- how the export itself went, reported once and only here. |27| `outcome` | Terminal status, stage reached, stop reason, the `baseline` and `final` measured results, and the `validation` that reconciles the stack's parts against its total. |28| `timeline` | The run itself: one event per stage, oldest first, each carrying its span, status, and an `ext` block of what that kind of stage records. Startup source events live under `reports/sbd_v6/timeline/`. |29| `close` | What the session settled at close: the steps the sequencer ran, the artifacts it published, the robustness findings it collected. |30| `critic` | The critic agent's own run, iteration by iteration: what it was asked about, how its rulings fell (`verdict_counts`), and the four artifacts each pass left behind. Per-proposal verdicts stay with the proposals, on the timeline. |31| `robustness` | What the robustness agent raised, turn by turn. Read `outcome` before counting `intents`: a turn that produced no envelope and a turn with nothing to raise are different findings. |3233## Who reads it3435- **A downstream stats/reporting service** — primary consumer. Replaces the36 MAE-synthesized `raw_report` / `fact_sheet`. Recommended read order:37 prefer `session_breakdown.json` if present, fall back to legacy MAE38 output otherwise.39- **`hyperloom-results-service`** — downstream automation may POST this40 JSON when `HYPERLOOM_RESULTS_SERVICE_URL` is set.41- **Offline / notebook analysis** — single file, easy to load, no DB42 needed.4344## When to refresh (LLM Orchestrator decision tree)4546The Coordinator's `cli.py` finally block writes `session_breakdown.json`47unconditionally at end-of-session — that's the safety net. But you48should ALSO refresh it eagerly when downstream dashboards may be49watching this session live:50511. **Always** at end-of-session (handled by `cli.py finally` — you do not need to dispatch this).522. After every KEEP'd explore, specialist, framework, or kernel result53 whose benchmark changed the final stack.543. After a successful sweep or conc_sweep when a live dashboard is55 observing this session.564. **Never** mid-action — collectors expect a coherent state snapshot.5758Dispatch action `session_breakdown` — a single 1-minute action, no inputs59required.6061## How to invoke6263### LLM-driven (Coordinator action)6465```yaml66# Issue an action intent like any other action67{ "action": "session_breakdown", "params": {} }68```6970### Code-driven (Python import)7172```python73from hyperloom.inference_optimizer.breakdown import build, write_breakdown_json7475# Just compute the dict (no side effects)76breakdown = build("/workspace/hyperloom")7778# Compute + atomically write to <sd>/session_breakdown.json79out_path = write_breakdown_json("/workspace/hyperloom")80```8182### CLI / offline (`hyperloom.inference_optimizer.tools.dump_session_breakdown`)8384```bash85# Live session in this sandbox86python -m hyperloom.inference_optimizer.tools.dump_session_breakdown8788# Historical session on a shared filesystem89python -m hyperloom.inference_optimizer.tools.dump_session_breakdown \90 --session-dir /shared/hyperloom-sessions/<user>/<sid>9192# Override output path (e.g. write to a staging area)93python -m hyperloom.inference_optimizer.tools.dump_session_breakdown \94 --session-dir <SD> --output /tmp/breakdown.json95```9697### Bulk historical (operator)9899```bash100for d in /shared/hyperloom-sessions/*/*; do101 [ -d "$d" ] || continue102 python -m hyperloom.inference_optimizer.tools.dump_session_breakdown \103 --session-dir "$d" > /dev/null104done105```106107## Field reference (what comes from where)108109The collector for each section reads only from the listed sources. All110collectors are pure functions; failure in one section never poisons111another (each becomes a `warnings[]` entry instead). Like the table above,112this reference is partial — `breakdown/exporter.py` is authoritative.113114| Section | Read from |115|-------------|-----------------------------------------------------------------------------------------------------------------|116| `metadata` | `manifest.json` + `state.json`, overlaid by the recorder's own `session` / `task_config` / `versions` fragments |117| `outcome` | The recorder's `close` and stack fragments, plus `state.{current_best, cumulative_gain_validated, optimization_stack}` for the sessions that predate them |118| `timeline` | The event fragments in the spool, closed and assembled per event; orphans left open by a killed phase are closed on first build |119| `close` | The CLOSE sequencer's own `close` / `close_step` fragments |120| `critic` | `critic-workdir/<NNN>/{request,judge_bundle,emit,review}.json`, recorded as each pass returns |121| `robustness`| The robustness agent's per-turn envelopes, recorded as each turn returns |122123## What is NOT in scope124125- **Real-time event streaming** — use `claw_session_events` for that.126- **LLM-based attribution** — every collector is deterministic /127 rule-based. Attribution is `delta_pct` math, not natural language.128- **Schema migration** — consumers MUST check `schema_version` and gate129 features on it, comparing the **major** version (`vN`) rather than the130 exact string: the producer emits both `…v2` and `…v3.0` today (see131 Versioning policy) and they are wire-compatible.132- **Cross-session aggregation** — one file per session. Use a Jupyter133 notebook or downstream analytics job for fleet views.134135## Failure modes136137| Symptom | Cause | Mitigation |138|----------------------------------------------------|--------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|139| `warnings: ["state.json missing"]` | Session was created (manifest written) but `Coordinator.save()` never ran | Sections fall back to manifest-only data. |140| `warnings: ["manifest.json missing"]` | Session was created without the standard cli.py path (rare) | `session.session_id` falls back to `state.session_id`. |141| `optimizations.available = false` | No operations were recorded, or the projection failed | Read `unavailable_reason`. The empty arrays mean unknown, not none; a `warnings` entry says whether `state.json` knew of adopted work the recorder missed. |142| `optimizations.validation.unclaimed_integration_count > 0` | A change recorded as integrated has no adoption crediting it | The adoption write was lost. `unattributed_gain_pct` is overstated by whatever those steps earned. |143| `optimizations.entries[].gain_method = local_gain_projected` | The step recorded no finishing throughput | Its gain is projected from the executor's own percentage, not measured against the chain. |144| `kernel_lifecycle.detected = []` | `profile` action never ran or its `benchmark_report.json` had no `kernel_summary` | Re-run profile, or fall back to `recommended` from `state.last_trace_analyze`. |145| Large `warnings[]` | Multiple JSON parse failures on `optimization_attempts.jsonl` | Inspect `kernel-agent-workspace/.../logs/` for the corresponding kernel-agent CLI logs. |146147## Versioning policy148149- `schema_version` (in `schema.py`) carries the **major** contract150 version; it is bumped ONLY on breaking changes (renamed/removed151 fields, changed semantics).152- New exports carry `hyperloom.session_breakdown.v6.0`. V6 is a breaking153 cutover for the timeline: the actions record their own events as they run,154 so an event's `start_time` is when the work began rather than when its155 artefacts were written, and the KERNEL and BASELINE projections are gone.156 Consumers that sorted around the old collapsed windows need to be rechecked.157- Inside v6, `enablement` gained the round ledger: `rounds[]` and its158 counters are added to the block, and the three state-sourced fields they159 replace (`stall_streak`, `inflight_task_id`, `dispatch_tick`) are no longer160 emitted. The block is runtime observability that is already `{}` on a161 session that ran no enablement, so it carries no field a consumer can gate162 a version on; the disposition of each replaced field is in163 `docs/reference/session-breakdown.md`.164- V5 was the preceding cutover, for optimization results: `optimizations` is165 reshaped, and the `optimization_stack`, `attribution`, `geak_invocations`,166 `forge_invocations`, and `gemm_tuning` projections are gone. Consumers167 MUST match on the `vN` major prefix, never on exact-string equality, and168 archived V2/V3/V4/V5 documents need a migration before a V6 reader sees them.169- `optimizations` carries its own `schema_version` (currently `5`),170 independent of the envelope's.171- Adding optional fields is **never** a breaking change.172- `exporter_version` tracks the exporter implementation independently;173 consumers can ignore it.174175## Testing176177Each collector has a unit test under `src/hyperloom/inference_optimizer/tests/`178that runs it against a fixture session_dir tree. An end-to-end test calls179`build(...)` on a fully-populated fixture and JSON-schema-validates the180result. Run:181182```bash183pytest src/hyperloom/inference_optimizer/tests/ -k breakdown -v184```