Skip to content

v0.23.0: the trace chip, and a second line that holds its edge - #9

Open
lroolle wants to merge 3 commits into
feat/agent-surfacefrom
feat/trace-chip
Open

v0.23.0: the trace chip, and a second line that holds its edge#9
lroolle wants to merge 3 commits into
feat/agent-surfacefrom
feat/trace-chip

Conversation

@lroolle

@lroolle lroolle commented Jul 29, 2026

Copy link
Copy Markdown
Member

Two taste fixes for the two-line render, stacked on #8.

The trace chip

A session whose wire is being captured by cctrace (deva --trace, or cctrace directly) now says so:

deva-chore (main) [cctrace:9317]        +11/-10 6m $7.53 fabl5[1m][█░░░░░21%] [MAX|@feast] 5h[81%@04:00] 7d[61%]
  • Left, with path and branch — being recorded is session identity, so it lives in the structure lane, dim. Red stays reserved for pressure.
  • The port is the live trace UI on localhost — the one actionable fact.
  • Detection, strongest signal first: CCTRACE_SERVER_PORT (cctrace exports trace identity into its child env — feat: trace identity in the traced child's env (proxy modes) cctrace#75 closes the mitm-mode gap), the capture's CA plumbing (NODE_EXTRA_CA_CERTS under a cctrace dir), or deva's DEVA_TRACE=1.
  • Plumbing-only captures (older cctrace) resolve the port through the live-instance registry (<data-dir>/instances/*.json, a documented contract): session id first, then project path, then only-live-capture. Tombstones never lend their port; two live captures with no match stay honest with a bare [cctrace]. Live testing against this repo's own traced dev session surfaced two registry realities: cctrace REDACTS stored session ids past the first 8 hex, so the match runs on the sid8 prefix (cctrace's own join key); and crashed captures leave non-tombstoned "live" entries behind, so the path/only-live fallbacks trust heartbeat-fresh files only — the sid8 match keeps trusting any non-tombstone entry, since a dead capture means a dead session anyway.

The advisor's true edge

The advisor row anchored on term_width - 5, but under a pipe tput cols answers a flat 80 no matter how wide the terminal is — line 1 overflowed the phantom edge while the advice dangled mid-line beneath it:

  deva-chore                     fabl5[1m] fb[86%]+1 5h[81%@04:00] 7d[61%]~ [MAX|@feast]
  + 7d resets @09:00, 39% unused — ~21% expires even at full burn

The row now anchors on line 1's actual rendered width (line1_cols, recorded by format_output), so the second line's right edge meets the first's whatever the width guess was:

  deva-chore                     fabl5[1m] fb[86%]+1 5h[81%@04:00] 7d[61%]~ [MAX|@feast]
                + 7d resets @09:00, 39% unused — ~21% expires even at full burn

Width detection itself got honest too: the controlling tty (stty size </dev/tty) and an inherited COLUMNS both beat tput's flat default.

Tests

348 pass (336 statusline + 12 installer). 14 new: 8 chip units (env, registry match, tombstone, marker-derived registry, fallbacks, ambiguity honesty), 2 chip integrations, 2 edge-alignment integrations (true width + phantom-40 overflow). t/helpers.bash now scrubs the trace env the way it scrubs account identity — this repo's own dev loop runs under deva --trace, which is exactly how the leak would happen (the chip found this session's real live capture during testing).

🤖 Generated with Claude Code

lroolle and others added 2 commits July 29, 2026 04:10
Two taste fixes for the two-line render.

A session traced by cctrace (deva --trace, or cctrace directly) now
wears a dim [cctrace:PORT] chip on the LEFT, next to path and branch:
being recorded is session identity, so it lives in the structure lane —
red stays reserved for pressure. Detection takes the strongest signal
available: the trace env cctrace exports into its child
(CCTRACE_SERVER_PORT), the capture's CA plumbing (NODE_EXTRA_CA_CERTS
under a cctrace dir), or deva's DEVA_TRACE=1. Plumbing-only captures
(older cctrace) resolve the port through the live-instance registry —
session id first, then project path, then only-live-capture; tombstones
never lend their port. No resolvable port still shows a bare [cctrace].

The advisor row anchored on term_width - 5, but under a pipe `tput
cols` answers a flat 80 whatever the terminal is — line 1 overflowed
the phantom edge while the advice dangled mid-line beneath it. The row
now anchors on line 1's ACTUAL rendered width (line1_cols, recorded by
format_output), so the second line's right edge meets the first's even
when the width guess is wrong. Width detection itself got honest too:
the controlling tty (stty size </dev/tty) and an inherited COLUMNS both
beat tput's default.

Tests: 12 new (8 chip units, 2 chip integrations, 2 edge-alignment
integrations); helpers now scrub the trace env the way they scrub
account identity — this repo's own dev loop runs under deva --trace,
which is exactly how the leak would happen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lroolle added a commit to thevibeworks/cctrace that referenced this pull request Jul 29, 2026
The mitm and base-url modes injected only plumbing into the spawned
client — HTTPS_PROXY and the CA bundle vars. A subprocess of a traced
session (a statusline, a hook, a nested agent) that wanted to KNOW it
was being captured had to sniff that plumbing and scan the instance
registry for the live UI port: heuristics for a fact the spawning
process holds in hand.

Say it outright instead (traceIdentityEnv in src/capture.ts, merged at
the one spawn site): CCTRACE_TRACE_FILE always, CCTRACE_SERVER_PORT +
CCTRACE_INSTANCE_ID when a live server exists. Node mode has exported
these names since day one; the proxy modes agree now. First consumer:
claude-code-statusline's [cctrace:PORT] chip
(thevibeworks/claude-code-statusline#9), which keeps the registry scan
only as its fallback for older captures.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Live testing against this repo's own traced dev session caught two
registry realities the first cut missed. cctrace REDACTS session ids
before they land on disk ("c3a6e0f3-****-…"), so an exact-id match
never fires against a real registry — match on the sid8 prefix, the
same join key cctrace's own UI uses. And crashed captures leave
non-tombstoned "live" entries behind for up to a day, so the project-
path and only-live fallbacks now trust heartbeat-fresh files only
(<2min against a 30s heartbeat); the sid8 match keeps trusting any
non-tombstone entry — if OUR capture died, this session's proxy died
with it.

Tests 346 -> 348: the sid test now stores a redacted id, plus
stale-entry coverage both ways (sid8 claims its own stale entry;
fallbacks refuse a stranger's).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant