You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(ingest): single-transcript Claude hook fast-path + global --quiet (#420)
* feat(ingest): single-transcript Claude hook fast-path + global --quiet
Restores 1.x parity gaps called out in #375:
- `relayburn-sdk`: new `ingest_claude_transcript_path` verb that parses
just the one JSONL the caller hands it and persists an EOF cursor so a
follow-up `ingest_all` skips it. `ingest_claude_session` now delegates
through it.
- `relayburn-cli`: `burn ingest --hook claude` drives the new fast-path
on the payload's `transcript_path`, bounding per-hook cost to one
parse. Falls back to a full sweep if the payload omits the path.
- `relayburn-cli`: `--quiet` is no longer hook-only — accepted in
default (one-shot) and `--watch` modes too. One-shot mode still
writes its final summary on stdout so pipelines stay capturable.
- `relayburn-cli`: documents the intentional non-port of 1.x's
`--opencode-stream` / `--opencode-url` / `--opencode-global` flags
(the file-based OpenCode adapter + FS-event watch is the supported
2.x path; the SDK still ships `OpencodeStreamIngestor` for embedders
who want to consume the SSE feed themselves).
Tests:
- SDK: `ingest_claude_transcript_path_*` covers the EOF cursor
contract and the missing-file no-op policy.
- CLI smoke: one-shot stdout summary, `--quiet` keeps stdout summary,
hook fast-path no-op on missing transcript, hook payload validation,
`--quiet` suppresses the hook payload warning, watch+hook mutex.
Closes#375.
https://claude.ai/code/session_011ubB69Zxijqb1BsYVYL9iQ
* fix(ingest): wire hook payload fallback for missing transcript_path
The previous guard returned 0 whenever transcript_path was absent,
making the documented ingest_all fallback unreachable. Older Claude
Code hook payloads carry session_id without transcript_path; they now
fall through to a full sweep instead of being ignored.
Add a smoke test pinning the new contract: a payload with session_id
but no transcript_path runs under --quiet without stderr noise.
Caught by Codex review on #420.
https://claude.ai/code/session_011ubB69Zxijqb1BsYVYL9iQ
* fix(ingest): honor --quiet in watch mode + propagate metadata errors
Three reviewer-flagged fixes:
- `relayburn-cli`: `run_watch` now gates the TaskProgress spinner and
all subsequent set_task / suspend / finish_and_clear calls behind
Option<TaskProgress>, matching the run_once / run_hook pattern. With
`--watch --quiet` the spinner is no longer created at all.
- `relayburn-sdk`: `ingest_claude_transcript_path` only suppresses
NotFound when stat-ing the transcript; permission / IO errors now
propagate to the caller instead of being silently dropped as an
empty report.
- `crates/relayburn-cli/tests/smoke.rs`: pin the one-shot quiet
contract harder — stderr must be empty, not just "stdout still has
the summary".
- `CHANGELOG.md`: drop the trailing "Closes#375" per the
impact-first style guide.
https://claude.ai/code/session_011ubB69Zxijqb1BsYVYL9iQ
* fix(ingest): resolve pending stamps + silence missing transcript in fast-path
Two reviewer-flagged gaps in ingest_claude_transcript_path:
- The fast-path was saving the EOF cursor without calling
resolve_pending_stamps_for_session_in, so pending stamps for the
session went unapplied and IngestReport.applied_pending_stamps was
always 0. Mirror the per-harness sweep's candidate construction
(using session_id + project from result.turns[0]) and delegate to
resolve_pending_stamps_for_report before persisting the cursor.
- The NotFound arm wrote a "[burn] no session file found at ..." line
to stderr, contradicting the documented hook policy of staying
silent so the caller decides whether to surface the rotation. Drop
the eprintln; keep the empty-report return.
https://claude.ai/code/session_011ubB69Zxijqb1BsYVYL9iQ
---------
Co-authored-by: Claude <noreply@anthropic.com>
-`burn summary`: new `subagents: X paired, Y orphan` line (and matching `subagents` key in `--json`) populated by a lazy walk over `~/.claude/projects/`. Skipped entirely when no sidecars exist anywhere reachable so pre-#435 outputs stay byte-identical. Honors `BURN_CLAUDE_PROJECTS_DIR` for test sandboxing. (#435)
28
41
- Ledger schema bumped to v4 — new nullable `turns.subagent_id TEXT` column denormalizes `TurnRecord.subagent.agent_id` so subagent rows are queryable without re-deserializing `record_json`. Migrated in place by `ALTER TABLE … ADD COLUMN`; pre-v4 rows stay `NULL` and are backfilled by `burn state rebuild`. (#435)
29
42
-`relayburn-sdk`: Claude slash-command triads (`/review`, `/init`, custom skills) now collapse into one synthetic `Skill` activity instead of inflating the activity count three rows at a time. Detection pins on the caveat → invocation → stdout parent-UUID chain shape with `<command-name>` / `<local-command-stdout>` purpose checks, so real user prompts that happen to look structurally similar are not misdetected. Token attribution stays on the underlying assistant rows — `Skill` is a view, not a billing reattribution. New `ActivityCategory::Skill` variant and `detect_slash_triads` helper. (#438)
30
-
31
-
### Changed
32
-
33
43
-`relayburn-sdk`: Claude Code parser now skips harness-injected
34
44
`<task-notification>` rows when emitting `UserTurnRecord`s. The detector
35
45
matches shape AND purpose across three envelope variants
0 commit comments