Skip to content

Add serve-origin marker + parent-task attribution to usage records - #80

Merged
Jason-Vaughan merged 2 commits into
mainfrom
feat/serve-origin-parent-task
Jul 4, 2026
Merged

Add serve-origin marker + parent-task attribution to usage records#80
Jason-Vaughan merged 2 commits into
mainfrom
feat/serve-origin-parent-task

Conversation

@Jason-Vaughan

Copy link
Copy Markdown
Owner

What

Fixes #74 — the two measurement gaps deferred from the #70 plan:

  • Origin marker: usage records carry an optional origin field (cli | gui | serve), threaded from each entry surface through run_once/run_once_stream (all five recording sites, including mid-stream/abandoned finalization). tanglebrain --stats and the knob panel show the per-origin split; records predating the field roll up as untagged, never guessed at. Delegate records are structurally exempt (they roll up separately, as before).
  • Parent-task attribution: the serve endpoint reads an optional X-TangleBrain-Parent-Task header — trimmed, non-printables dropped (folded-header \r\n, ANSI escapes), capped at 128 chars — and records it as parent_task_id on the task record for cross-system attribution. Never routed on. Reverse linkage already existed (chatcmpl-<task_id>).

Both are additive, written-only-when-present record fields; old records and readers are unaffected. No routing changes.

Why

TangleClaw's integration against the endpoint (TC#455) is imminent; records written without the origin marker can never be retroactively attributed, so this ships before serve traffic starts accruing. The header gives OpenAI-compat callers the same parent-task linkage the MCP delegate tree gets via TANGLEBRAIN_TASK_ID.

Test plan

  • 494 tests green (make test), 12 new/updated: record field write/omit semantics, task-record parent linkage, rollup by_origin bucketing with the untagged sentinel + delegate exemption, --stats line shown only when tagged, origin/parent threading through every run_once/run_once_stream recording site (pin-streamed, pin-emulated, router-emulated), serve handler threading (plain + stream), dispatch-level header sanitization, control-char/length-cap sanitizer cases, GUI origin tag, and a real-socket proof that the header reaches routing.
  • Independent Critic review: SHIP-WITH-FIXES → all 3 findings addressed (panel origin tile, non-printable stripping, router-path attribution test).

Fixes #74.

🤖 Generated with Claude Code

Records gain an optional origin field (cli|gui|serve) threaded from each
entry surface through run_once/run_once_stream; --stats shows the per-origin
split, with pre-existing records rolling up as "untagged" rather than being
guessed at. The serve endpoint additionally reads an optional
X-TangleBrain-Parent-Task header — trimmed, capped at 128 chars — and records
it as parent_task_id for cross-system attribution. Both are additive,
written-only-when-present record fields; old records and readers unaffected.
No routing changes.
- Panel now shows the per-origin split (the issue names the panel as a
  contract surface), hidden while all history is untagged — same stance
  as the CLI's format_rollup.
- sanitize_parent_task drops non-printable characters (folded-header \r\n,
  ANSI escapes) so no control bytes ever reach usage records; tested.
- Router-path recording site in run_once_stream now has the same
  attribution assertion as the other two sites.
@cursor

cursor Bot commented Jul 4, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@Jason-Vaughan
Jason-Vaughan merged commit ebe7e1d into main Jul 4, 2026
3 checks passed
@Jason-Vaughan
Jason-Vaughan deleted the feat/serve-origin-parent-task branch July 4, 2026 07:29
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.

[feature] serve: parent-task linkage + serve-origin marker in usage records

1 participant