Skip to content

feat: wire file_edits/session_agent_policies/display_name to real surfaces - #3442

Merged
Sinity merged 8 commits into
masterfrom
feature/wire-captured-unread-data
Jul 31, 2026
Merged

feat: wire file_edits/session_agent_policies/display_name to real surfaces#3442
Sinity merged 8 commits into
masterfrom
feature/wire-captured-unread-data

Conversation

@Sinity

@Sinity Sinity commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Summary

Three beads about polylogue evidence that is already captured and persisted, but unreachable from any CLI/MCP/API surface. This PR wires the genuine remainders: file_edits, session_agent_policies, and sessions.display_name (the Claude Code "slug" wire field).

Problem

  • polylogue-nua7: file_edits (76,272 live rows), session_agent_policies (402,879 rows), and session_refs (19,024 rows) each had a complete, tested read chain that terminated at repository/archive/sessions.py with nothing above it. session_refs was already wired by prior PRs fix(insights): prefer typed PR/session evidence over regex correlation #3425/fix(insights): finish typed session-PR evidence + wire root: filter #3431 (read --view correlation); file_edits and session_agent_policies remained unreachable from any CLI/MCP/API surface. Four helpers (get_file_edit, sync_get_file_edits_for_session, sync_get_session_refs, sync_session_agent_policies_batch) had zero references anywhere outside their own def/__all__ entry.
  • polylogue-cgfy: the Claude Code slug wire field (1,500 sampled occurrences) is captured into ParsedSession.display_name and persisted into sessions.display_name, but neither Session nor SessionSummary carried a display_name field at all — the value was dropped on every read path. This is the fix for subagent rows rendering as <uuid-prefix>:agent-<suffix> instead of a human name.
  • polylogue-pbuh: AC6 asked for a live before/after census of UUID-titled sessions and PR-link counts. Measured read-only against /realm/db/polylogue/index.db.

Solution

  1. polylogue/api/archive.py: added Polylogue.get_file_edits() / get_agent_policies(), mirroring the existing get_session_events() reader pattern (returns None for an unknown session, an empty list for a session with no matching rows).
  2. MCP (polylogue/mcp/server_cutover.py): wired both into the existing get(ref, projection=...) dispatcher as two new projection values ("file-edits", "agent-policies") alongside the existing "events" projection. No new tool or tool contract needed — same six-tool get operation.
  3. CLI: added read --view file-edits / read --view agent-policies, following the existing events/hooks view pattern — new handler module polylogue/cli/read_views/file_edits.py, registered in read_view_handlers.py, read_view_registry.py, and the profile metadata in archive/viewport/profiles.py. Also required adding entries to polylogue/surfaces/projection_spec.py's EvidenceFamily/READ_VIEW_PROJECTION_FAMILIES maps — a separate registry from the CLI handler registry that raises "unknown projection view" if a view is missing there.
  4. Dead code: deleted the four zero-reference helpers named in nua7's audit, plus their now-dangling sqlite3 imports where nothing else used them.
  5. display_name reachability (polylogue-cgfy), two independent hydration paths:
    • Async repository path (storage/hydrators.py): added display_name to Session/SessionSummary (archive/session/domain_models.py) and their runtime mixins' display_title property — now falls back user_title > title > display_name > id[:8].
    • Sync ArchiveStore summary path that backs find/MCP get(ref) default projection (storage/sqlite/archive_tiers/archive.py): added display_name to ArchiveSessionSummary, selected it in read_summary's and list_summaries' SQL, and made it a title fallback tier above the existing structural-label fallback (polylogue-cijx.4 decision 3) when no provider title exists — display_name is real origin evidence (title_source="origin"), stronger than a derived structural label. Wired through api/archive.py::_archive_summary_to_domain.
  6. pbuh AC6 live census (read-only against /realm/db/polylogue/index.db, no code change — measurement only):
    • 16,420 Claude Code sessions total; 14,717 carry title_source='unknown' (raw-id/structural-label fallback before this PR).
    • 7,088 of those 16,420 sessions have a captured display_name; 6,585 of the 14,717 title_source='unknown' sessions (44.7%) now surface a real slug-derived title instead of a raw id or structural label — this PR's concrete, measured improvement.
    • session_events with event_type='claude_pr_link': 19,140 rows (unchanged by this PR — pr-link reader wiring was already resolved by the earlier fix(insights): prefer typed PR/session evidence over regex correlation #3425/fix(insights): finish typed session-PR evidence + wire root: filter #3431 pass; see pbuh's own notes).
    • file_edits: 76,272 rows; session_agent_policies: 402,879 rows; session_refs: 19,024 rows (167 distinct sessions) — all now reachable per point 1-3 above.

AC disposition

polylogue-nua7: file_edits/session_agent_policies now have real CLI (read --view file-edits/agent-policies) and MCP (get(projection=...)) consumers; session_refs already had one (prior PRs, verified unchanged). All four zero-reference helpers deleted. Satisfied.

polylogue-cgfy: AC1 (per-key classification recorded in OriginSpec) and AC4 (re-runnable committed enumeration) were already addressed by prior passes per the bead's own notes — not re-verified in this pass, out of this PR's declared surface. AC2's structuredPatch/originalFile/oldString persistence was already done (index v46); this PR adds the missing read side (file_edits reachability, point 1-3 above) — the specific "cijx grading rises from observed to checkpointed" wiring is a separate insights-model change (insights/session_commit.py-adjacent, in this PR's avoid list) and remains open, noted here as a genuine remainder. AC3 (slug reaches read surfaces) is satisfied — see point 5 above, proven with a measured live census (point 6) and end-to-end tests. AC5 (bytes/row counts per key acquired) is partially covered by the live counts in point 6 but not a full per-key report.

polylogue-pbuh: AC6 (before/after census) satisfied as a live measurement (point 6) — this is the "after" state; no "before" baseline exists since the parser fix landed in an earlier PR and no un-fixed archive is available to compare against. AC1-AC5 were already resolved in prior passes per the bead's own extensive notes; not re-verified here, out of this PR's declared surface (parsers/claude, assembly_claude_code.py, providers/claude_code*.py were avoided per the task's own instructions).

Verification

  • devtools test tests/unit/mcp/test_server_surfaces.py — 11 passed, including 3 new tests exercising get(projection="file-edits"), get(projection="agent-policies"), and the default get(ref) display_name fallback through the real MCP tool_manager entrypoint against a real ArchiveStore-written session.
  • devtools test tests/unit/cli/test_file_edits_and_agent_policies_views.py — 2 passed, full CliRunner invocation of read --view file-edits/agent-policies against a real ArchiveStore-written session.
  • devtools test tests/unit/storage/test_session_display_name_reaches_repository.py — 2 passed, proving both Session and SessionSummary carry display_name/display_title correctly through the real writer → async repository chain, and that a real title still wins over the slug.
  • devtools test tests/unit/storage/test_unread_wire_batch_v46.py tests/unit/storage/test_repository_agent_policies.py — 13 passed (no regression from dead-helper removal).
  • devtools test tests/unit/storage/test_title_source_queryable.py tests/unit/storage/test_archive_tiers_write.py tests/unit/storage/test_archive_tiers_archive.py tests/unit/cli/test_query_exec_laws.py — 243 passed (no regressions to existing title/summary logic).
  • devtools test tests/unit/api/test_facade_contracts.py -k "no_undiscovered or file_edits or agent_polic" — 3 passed.
  • Broader affected-area sweep: 28 test files that directly import the touched domain modules (tests/unit/{api,archive,cli,core,insights,sources,storage,surfaces}/...) — 863 passed, 2 pre-existing unrelated failures (test_archive_tiers_api_raw_artifacts_read_source_tier, 4 parametrized cases of test_filters_props.py::TestFilterDateParsing) confirmed to reproduce identically with this branch's changes reverted — stale hardcoded date assertions / a clock-hygiene issue in archive/filter/filters.py, untouched by this PR.
  • mypy --strict on every touched file — no issues.
  • devtools verify --quick — exit 0.
  • devtools render all --check — all surfaces sync OK (regenerated docs/cli-reference.md, docs/plans/topology-target.yaml for the new polylogue/cli/read_views/file_edits.py module).

Not run: full devtools verify --all / whole-directory tests/unit sweep (anti-pattern per repo convention — testmon wasn't seeded in this worktree; relying on the targeted + affected-area sweeps above plus CI's post-merge heavy test suite).

Ref polylogue-nua7, polylogue-cgfy, polylogue-pbuh

Sinity added 6 commits July 31, 2026 12:44
Problem: polylogue-nua7 found session_agent_policies (402,879 rows),
file_edits (76,105), and session_refs (18,949) each have a complete,
correct, tested read chain that terminates at
repository/archive/sessions.py with nothing above it -- zero references
outside polylogue/storage/ except their own tests. session_refs was
already wired by #3425/#3431 (correlation_view.py); file_edits and
session_agent_policies remained unreachable from any CLI/MCP/API surface.

Solution: add Polylogue.get_file_edits()/get_agent_policies() to
polylogue/api/archive.py (mirroring the existing get_session_events()
reader pattern), and wire them into the MCP get(ref, projection=...)
dispatcher as two new projections ("file-edits", "agent-policies")
alongside the existing "events" projection. No new MCP tool or tool
contract needed -- same six-tool "get" operation, new projection values
documented in its docstring.

Verification: devtools test tests/unit/mcp/test_server_surfaces.py
(9 passed, including 2 new tests exercising get(projection="file-edits")
and get(projection="agent-policies") through the real MCP tool_manager
entrypoint against a real ArchiveStore-written session, not the storage
function directly).

Ref polylogue-nua7
Problem: polylogue-nua7 found file_edits (76,105 live rows) and
session_agent_policies each have a complete, tested read chain that
terminates at the repository layer with nothing above it -- reachable
only from the MCP get(projection=...) surface added in the prior commit,
not from the CLI.

Solution: register two new read views following the existing "events"/
"hooks" pattern -- polylogue/cli/messages.py::run_session_file_edits /
run_session_agent_policies call the new Polylogue.get_file_edits() /
get_agent_policies() API methods; polylogue/cli/read_views/file_edits.py
wires them into the read-view invocation/delivery machinery; registered
in read_view_handlers.py, read_view_registry.py, and the profile
metadata in archive/viewport/profiles.py. Also required updating
polylogue/surfaces/projection_spec.py's EvidenceFamily/
READ_VIEW_PROJECTION_FAMILIES maps (a separate registry from the CLI
handler registry) -- missing entries there raised "unknown projection
view" at runtime.

Regenerated docs/cli-reference.md and docs/plans/topology-target.yaml
(new polylogue/cli/read_views/file_edits.py module) via devtools render.

Verification: devtools test tests/unit/cli/test_file_edits_and_agent_policies_views.py
(2 passed, full CliRunner invocation of `read --view file-edits` /
`read --view agent-policies` against a real ArchiveStore-written
session -- not the storage function or API method in isolation);
devtools test tests/unit/cli/test_click_app.py tests/unit/cli/test_completion_matrix.py -k view
(14 passed, no registry drift); devtools verify --quick (exit 0);
devtools render all --check (all surfaces sync OK).

Ref polylogue-nua7
…s/agent_policies helpers

Problem: polylogue-nua7 named four helpers with zero references anywhere
in the repo outside their own def + __all__ entry (not even a test):
queries/file_edits.py get_file_edit / sync_get_file_edits_for_session,
queries/session_refs.py sync_get_session_refs,
queries/session_agent_policies.py sync_session_agent_policies_batch.
Re-verified with rg against the current tree: still zero references
after the async get_file_edits/get_agent_policies methods landed on
the real MCP/CLI surfaces in the prior two commits -- these sync/
single-row variants were never the read path anything used.

Solution: delete all four, plus their now-dangling sqlite3 imports
where nothing else in the module used them (file_edits.py,
session_refs.py; session_agent_policies.py keeps sqlite3 for
_row_to_agent_policy's Row type hint).

Verification: devtools test tests/unit/storage/test_unread_wire_batch_v46.py
tests/unit/storage/test_repository_agent_policies.py (13 passed);
rg for each deleted name across polylogue/ and tests/ (zero hits);
mypy --strict on the three touched files (no issues); ruff format/check
clean.

Ref polylogue-nua7
Problem: polylogue-cgfy AC3 asks that the Claude Code "slug" wire field
(1,500 sampled occurrences, e.g. "greedy-squishing-hamming") reach read
surfaces so subagent rows carry names instead of
"<uuid-prefix>:agent-<suffix>". The parser already captures it into
ParsedSession.display_name (polylogue-2qx.4) and the writer persists it
into the sessions.display_name column, but neither the Session nor
SessionSummary domain model had a display_name field at all -- the value
landed durably and was dropped on every read path.

Solution, two independent hydration paths both wired:

1. Async repository path (storage/hydrators.py): added display_name to
   Session/SessionSummary (archive/session/domain_models.py) and their
   runtime mixins' display_title property (domain_runtime.py,
   summary_runtime.py) -- display_title now falls back user_title >
   title > display_name > id[:8], one tier above the raw id truncation.

2. Sync ArchiveStore summary path that backs `find`/MCP get(ref) default
   projection (storage/sqlite/archive_tiers/archive.py): added
   display_name to ArchiveSessionSummary, selected it in read_summary's
   and list_summaries' SQL, and in _summary_from_row made it a title
   fallback tier ABOVE the existing structural-label fallback
   (polylogue-cijx.4 decision 3) when no provider title exists --
   display_name is real origin evidence (title_source="origin"), stronger
   than a derived structural label. Wired through
   api/archive.py::_archive_summary_to_domain so MCP/CLI/API session
   summaries carry it.

Verification: devtools test tests/unit/mcp/test_server_surfaces.py
tests/unit/storage/test_session_display_name_reaches_repository.py
(12 passed, including a new MCP get(ref) test proving a title-absent
session now surfaces its slug through the real ArchiveStore-backed
summary path, and a repository-level test proving both Session and
SessionSummary carry display_name/display_title correctly, with a
second test proving a real title still wins over the slug);
devtools test tests/unit/storage/test_title_source_queryable.py
tests/unit/storage/test_archive_tiers_write.py tests/unit/storage/test_archive_tiers_archive.py
tests/unit/cli/test_query_exec_laws.py (243 passed, no regressions to
existing title/summary logic); mypy --strict on all touched files;
devtools verify --quick (exit 0); devtools render all --check (sync OK).

Ref polylogue-cgfy
…tract suite

Problem: devtools test tests/unit/api/test_facade_contracts.py failed
test_no_undiscovered_async_methods after this branch's earlier commit
added Polylogue.get_file_edits()/get_agent_policies() -- the contract
suite enumerates every public async method on Polylogue and fails until
each is explicitly categorized.

Solution: add both to READ_BY_ID_NONE_METHODS (same category as the
get_session_events sibling they were modeled on -- returns None for an
unknown session id rather than an empty container).

Verification: devtools test tests/unit/api/test_facade_contracts.py -k
"no_undiscovered or (method_has_typed_signature and (get_file_edits or
get_agent_policies))" (3 passed).

Ref polylogue-nua7
Rebasing onto origin/master (which gained 5 new commits during this
branch's development, including new modules) left docs/plans/topology-target.yaml
stale relative to the rebased tree. Regenerated via
devtools render topology-projection.
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@Sinity, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 57 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 460aaabf-34ce-4b9f-8bc4-88e0e982ff0a

📥 Commits

Reviewing files that changed from the base of the PR and between a8f7410 and 89da761.

📒 Files selected for processing (22)
  • docs/cli-reference.md
  • docs/plans/topology-target.yaml
  • polylogue/api/archive.py
  • polylogue/archive/session/domain_models.py
  • polylogue/archive/session/domain_runtime.py
  • polylogue/archive/session/summary_runtime.py
  • polylogue/archive/viewport/profiles.py
  • polylogue/cli/messages.py
  • polylogue/cli/read_view_handlers.py
  • polylogue/cli/read_view_registry.py
  • polylogue/cli/read_views/file_edits.py
  • polylogue/mcp/server_cutover.py
  • polylogue/storage/hydrators.py
  • polylogue/storage/sqlite/archive_tiers/archive.py
  • polylogue/storage/sqlite/queries/file_edits.py
  • polylogue/storage/sqlite/queries/session_agent_policies.py
  • polylogue/storage/sqlite/queries/session_refs.py
  • polylogue/surfaces/projection_spec.py
  • tests/unit/api/test_facade_contracts.py
  • tests/unit/cli/test_file_edits_and_agent_policies_views.py
  • tests/unit/mcp/test_server_surfaces.py
  • tests/unit/storage/test_session_display_name_reaches_repository.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Ref polylogue-nua7, polylogue-cgfy, polylogue-pbuh

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c7a7462e9e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +81 to +82
if self.display_name:
return self.display_name

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor title provenance before choosing the stored title

For existing sessions whose nonblank title is a synthetic native ID with title_source='unknown' or 'path'—the live-data case this change is intended to fix—display_title returns that value before it can reach the new display_name branch. Consequently, repository-hydrated Session objects and the twin SessionSummary implementation still display the UUID instead of the slug; apply the same title-source-aware distinction already used by _summary_from_row.

AGENTS.md reference: AGENTS.md:L354-L356

Useful? React with 👍 / 👎.

Comment thread polylogue/api/archive.py
git_branch=summary.git_branch,
git_repository_url=summary.git_repository_url,
provider_project_ref=summary.provider_project_ref,
display_name=summary.display_name,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Hydrate display names on full archive reads

This wires display_name only through the summary conversion. The public Polylogue.get_session() path uses _archive_session_to_session(archive.read_session(...)), but ArchiveSessionEnvelope neither selects nor carries sessions.display_name, so full session reads still produce Session.display_name=None and fall back to the raw ID when no title exists. Add the column to both archive-envelope read variants and pass it through the full-session converter.

AGENTS.md reference: AGENTS.md:L351-L353

Useful? React with 👍 / 👎.

Comment thread polylogue/api/archive.py
"""
resolved = await self.repository.resolve_id(session_id)
resolved_id = str(resolved) if resolved is not None else session_id
session = await self.repository.get(resolved_id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid loading full transcripts to check session existence

For a large session, each new evidence reader first calls repository.get, which fetches and hydrates every message, attachment, session event, and tag before issuing the small targeted file_edits or session_agent_policies query. Thus even an empty agent-policy projection can consume memory and latency proportional to the entire transcript, making the new CLI/MCP views impractical for the multi-GiB sessions the archive supports; use a lightweight session-record/summary existence check instead. The same issue is repeated in get_agent_policies.

Useful? React with 👍 / 👎.

# Conflicts:
#	.beads/issues.jsonl
#	docs/plans/topology-target.yaml
@Sinity
Sinity merged commit 4a17f74 into master Jul 31, 2026
1 of 3 checks passed
@Sinity
Sinity deleted the feature/wire-captured-unread-data branch July 31, 2026 11:15
Sinity added a commit that referenced this pull request Jul 31, 2026
…#3465)

## Summary

Closes out the remainder of polylogue-cgfy's disposition work now that
PR #3442 landed the flagship consumption gap
(structuredPatch/originalFile/oldString -> file_edits, reachable via API
+ MCP + CLI `read --view file-edits`). Adds the two remaining
genuinely-unread, real-value wire keys (`requestId`,
`thinkingMetadata.maxThinkingTokens`) and records the full disposition
(read / measured-negative / deliberately-dropped-duplicate) for the rest
of the bead's "other unread keys of substance" list in the Claude Code
OriginSpec's `fidelity_notes`, satisfying AC1.

## Problem

polylogue-cgfy's 2026-07-29 corpus enumeration found 34 of the 70 most
common Claude Code wire keys with zero references in
`polylogue/sources/`. The structuredPatch/originalFile/oldString cluster
(105K/92K/86K rows) and most of the "other keys of substance" list
(`stop_reason`, `stop_sequence`, `cache_creation`, `ttftMs`, `todos`,
`toolUseResult.sandbox`/`filenames`/`numFiles`, `slug`) were captured by
prior sessions on this bead and PR #3442, but two items remained
genuinely unread with no recorded disposition either way: `requestId`
(1,171 sampled occurrences -- the Anthropic API's per-call request id)
and `thinkingMetadata.maxThinkingTokens` (34 occurrences -- the
extended-thinking token budget). The bead's remaining lower-value items
(`userType`, `sourceToolAssistantUUID`, `hookCount`/`hookInfos`,
`toolUseID`) also had no recorded disposition, so AC1 ("every key...
classified... recorded in the Claude Code OriginSpec fidelity
declaration") was incomplete.

Verified each of those lower-value items directly against a real
~/.claude/projects corpus before classifying:
- `userType` is the literal string `"external"` on every sampled record
(measured negative, same class as the bead's own `usage.service_tier`
finding).
- `sourceToolAssistantUUID` equals that same record's own `parentUuid`,
already captured as `ParsedMessage.parent_message_provider_id` -- a
duplicate spelling, not new evidence.
- `hookCount`/`hookInfos` describe hook firings already tracked durably
(with outcome, which `hookInfos` lacks) in `source.db`'s
`raw_hook_events`.
- `toolUseID` is already consumed for its real signal (the
`progress`/`agent_progress` delegation-edge disposition documented in
`code_parser.py`'s module docstring).

Also discovered en route: `master` HEAD (5798b3d) failed to import at
all (`ImportError: cannot import name 'literal_check'`) -- #3458 deleted
it as a supposed zero-call-site dead shim, but #3451 had wired real call
sites into it earlier the same day. Fixed and merged separately as #3464
so this branch could even run tests; this branch is rebased on top of
that fix.

## Solution

- `polylogue/sources/parsers/claude/code_parser.py`:
`_message_usage_event_payload` gains a `record` parameter (the top-level
record `item`, since `requestId`/`thinkingMetadata` live there, not
inside `message`); the sole call site now passes `record=item`. Both new
keys ride the existing `message_usage` session-event payload as
`request_id`/`max_thinking_tokens`.
- **Production callers exercising the new fields**:
`Session.session_events` -> CLI `read --view events`
(`polylogue/cli/read_views/events.py` -> `run_session_events`,
`polylogue/cli/messages.py`) and MCP `get(ref, projection="events")`
(`polylogue/mcp/server_cutover.py:905`) already render every
`session_events` row generically regardless of `event_type` -- no new
consumer code needed, verified by reading both call chains before
writing this PR (the generic `events` projection was wired by prior
work, not this PR).
- `polylogue/sources/origin_specs.py`: new `fidelity_notes` entry on the
Claude Code `OriginSpec` recording the full disposition table above.

## Verification

- `devtools test
tests/unit/sources/test_claude_code_unread_wire_fields.py
tests/unit/sources/test_parsers_claude_code_artifacts.py
tests/unit/sources/test_origin_specs.py` -> 57 passed
- `devtools verify --quick` -> exit 0 (format, lint, mypy, render all
--check, schema-versioning policy)
- Anti-vacuity: each new field has a paired "field absent" test
asserting the key is omitted from the payload, not fabricated

Ref polylogue-cgfy

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Enhancements**
- Claude Code usage events now capture available request identifiers and
maximum thinking-token settings.
- Missing metadata continues to be omitted, keeping usage records clean
and accurate.

- **Quality Improvements**
- Added coverage to verify that these Claude Code fields are preserved
and handled consistently.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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