feat(sources): admit ~/.claude/todos plan snapshots with a session read model - #3543
Conversation
|
Warning Review limit reached
Next review available in: 20 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (17)
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. Comment |
35ccc2f to
a9cd32a
Compare
…ad model Problem: Claude Code writes several artifacts beyond the session JSONL transcript that the archive never captured. ~/.claude/todos/*.json holds the agent's live TODO/plan state per session (task lists with status), overwritten wholesale on every TodoWrite call and pruned by the harness on its own schedule -- unread state is eventually lost, not merely delayed (polylogue-t0p). Solution: - New todo_snapshot OriginArtifactRule (polylogue/sources/origin_specs.py) admits ~/.claude/todos/<session-id>[-agent-<agent-id>].json as a fact-tier Claude Code artifact, following the same admission shape as the existing workflow_run_snapshot/agent_sidecar_meta rules, with an explicit fidelity note (preserved: content/status/priority/id and list order; lost: intermediate transitions between two watcher-observed snapshots, no in-file timestamp). - polylogue/sources/parsers/claude/todos.py parses the bare JSON array, recovering session_id/agent_id from the filename. - ~/.claude/todos is a new configured/watched source root (polylogue/config.py, polylogue/paths/_roots.py, polylogue/sources/live/watcher.py), aliased to the claude-code provider (polylogue/core/provider_identity.py) so the existing _admit_non_session_origin_artifacts admission path and OriginSpec classification pick it up with no bespoke wiring. - polylogue/insights/claude_todo_projection.py is a storage-free, session-linked read model (mirrors insights/run_projection.py's own precedent) over every retained todo_snapshot raw revision: per-session plan state, latest completion rate, and per-item status-transition history across observed snapshots. - plan_completion_rate registered in insights/measurement/registered_metrics.py's DEFAULT_METRIC_REGISTRY (rxdo.9.1 identity layer), the same bounded slice session_cost_usd already uses -- reachable via MCP get(ref="metric:plan_completion_rate"). polylogue-9l5.7's full statistics/composition registry remains unstarted; this does not invent a second identity mechanism. Deferred (see PR body for file-history follow-up scope and what this session learned about its on-disk shape): ~/.claude/file-history/ content acquisition, and the lower-priority history.jsonl/debug/mcp-logs/ide/jobs artifacts the bead also names. Verification: - devtools test tests/unit/sources/test_origin_specs.py tests/unit/sources/test_parsers_claude_todos.py tests/unit/insights/test_claude_todo_projection.py tests/unit/core/test_config.py tests/unit/sources/test_live_watcher.py -> 219 passed (1 pre-existing failure, test_live_batch_processor_records_durable_attempt, reproduces identically on master with this diff stashed -- unrelated to this change). - mypy polylogue -> Success: no issues found in 1113 source files. - ruff check / ruff format --check -> clean. - devtools render all --check -> OK (topology projection regenerated for the two new modules). - devtools lab policy classifier-fingerprints reports one pre-existing drift (ai_parser.py:looks_like_ai) reproduced identically with this diff stashed -- not introduced by this change. Ref polylogue-t0p Co-Authored-By: Claude <noreply@anthropic.com>
a9cd32a to
f4c2598
Compare
Summary
Ingests Claude Code's live plan-snapshot directory (
~/.claude/todos/*.json) into the archive end-to-end: raw admission with provenance, a session-linked read model over every retained revision, and a registered plan-completion metric.~/.claude/file-history/is deferred as a scoped follow-up (see below).Problem
polylogue-t0p: Claude Code writes several artifacts beyond the session JSONL transcript that answer questions the transcript alone cannot, and the harness prunes some of them on its own schedule -- unread state is eventually lost, not merely delayed.
~/.claude/todos/<session-id>[-agent-<agent-id>].jsonholds the agent's current TODO/plan list (task content/status/priority/id), overwritten wholesale on everyTodoWritecall. Nothing in the archive captured this before.Solution
todo_snapshotOriginArtifactRuleinpolylogue/sources/origin_specs.pyclassifiestodos/*.jsonas a fact-tier Claude Code artifact, the same admission shape already used forworkflow_run_snapshot/agent_sidecar_meta(PR feat(sources): report per-type sidecar coverage for Claude Code parse #3419/fix(sources): reconcile sidecar coverage with attachment evidence events #3437/fix(sources): stop claude-code tool-result sidecars over-counting debt #3448 sidecar-join precedent this bead pointed at). Fidelity is declared explicitly: preserved -- every item's content/status/priority/id and the agent's own list order; lost -- intermediate status transitions between two watcher-observed snapshots (each write is a full overwrite, no in-file timestamp), and anything pruned before observation.polylogue/sources/parsers/claude/todos.pyparses the bare JSON array and recoverssession_id/agent_idfrom the filename (<uuid>[-agent-<uuid>].json, verified against the real on-disk shape under~/.claude/todos/).~/.claude/todosis a new configured/watched source (polylogue/config.py,polylogue/paths/_roots.py,polylogue/sources/live/watcher.py-- a secondWatchSourcesibling toclaude-code, same pattern as the existingcodex-stateroot), aliased to theclaude-codeprovider (polylogue/core/provider_identity.py) so the existing_admit_non_session_origin_artifactsadmission path andclassify_artifact_pathpick it up with zero bespoke wiring -- confirmed by tracing that gate'sProvider.from_string(source.name) is Provider.CLAUDE_CODEfilter.polylogue/insights/claude_todo_projection.pyis a storage-free, session-linked projection (same justification asinsights/run_projection.py) over every retainedtodo_snapshotraw revision inraw_sessions(not just the current-pointerraw_artifactsrow, which would collapse history to the latest snapshot) -- per-session plan state, latest completion rate, and per-item status-transition history across observed snapshots.plan_completion_rateregistered ininsights/measurement/registered_metrics.py'sDEFAULT_METRIC_REGISTRY(rxdo.9.1 identity layer), the same bounded slicesession_cost_usdalready uses -- reachable via MCPget(ref="metric:plan_completion_rate"). polylogue-9l5.7's full statistics/composition registry (checked: still open,MeasureSpecunimplemented) is not duplicated here; this registers identity only, same limitationsession_cost_usdalready documents.Deferred:
~/.claude/file-history/Investigated the real on-disk shape to save the follow-up lane research time:
~/.claude/file-history/<session-id>/<hash>@v<N>holding raw pre-edit file bytes with no wrapper (no path, no timestamp inside the file itself).<hash>@v<N>back to a real file path lives inside the session's own JSONL transcript, in atype: "file-history-snapshot"record'ssnapshot.trackedFileBackups: {<path>: {backupFileName, version, backupTime}}map (plustype: "file-history-delta"records for incremental updates).code_parser.py's_sidecar_evidence_payloadforfile-history-snapshot/file-history-delta,#2qx.4) -- it records the file list and backup pointers, but never acquires the actual snapshot bytes at~/.claude/file-history/.trackedFileBackupspointers to the sibling~/.claude/file-history/<session-id>/directory, content-address-acquire each snapshot as a blob keyed to (session, path, version), and apply the same privacy/redaction discipline_acquire_attachment_blobuses for attachments (these are literal pre-edit file contents from real projects). This is a distinct acquisition shape fromtodo_snapshot(cross-referencing two directories, not a single self-contained file) and was intentionally left out of this PR per the bead's own note that if full scope is too large for one PR, todos should land alone.Lower-priority artifacts the bead also names (
history.jsonl,history-summaries/,debug/,mcp-logs/,ide/locks,jobs/,ccusage/stats caches) were not investigated this session; still open.Verification
devtools test tests/unit/sources/test_origin_specs.py tests/unit/sources/test_parsers_claude_todos.py tests/unit/insights/test_claude_todo_projection.py tests/unit/core/test_config.py tests/unit/sources/test_live_watcher.py-> 219 passed. (One pre-existing failure,test_live_batch_processor_records_durable_attempt, reproduces identically with this diff stashed on this same checkout -- unrelated codex-path assertion, not touched by this change.)mypy polylogue->Success: no issues found in 1113 source files.ruff check/ruff format --check-> clean.devtools render all --check-> OK (topology projection regenerated for the two new modules,devtools render topology-projection).devtools verify --quick-> exit 0 (includes a cherry-picked, already-vetted-elsewhere ack commit for an unrelated pre-existingclassifier-fingerprintsgate failure from PR feat(sources): add per-file acquisition logging and tighten claude-ai detection #3537, tracked separately at issue classifier-fingerprint: looks_like_ai drift from PR #3537 not acknowledged #3540 -- confirmed viagit stashthat this failure predates and is independent of this branch's changes).Anti-vacuity: removing the
todo_snapshotOriginArtifactRule(or narrowing its path pattern) makesartifact_rule_for_path/classify_artifact_pathreturnNonefor a real todos path, whichtest_origin_spec_admits_todos_directory_artifact_as_fact_tierand the end-to-endtest_todos_admitted_and_materialized_into_session_linked_plan_states(viaparse_sources_archive) both catch. Removing theclaude-code-todos->claude-codeprovider alias makes_admit_non_session_origin_artifacts'sProvider.from_string(source.name) is Provider.CLAUDE_CODEgate skip the source entirely, caught bytest_todos_source_name_resolves_to_claude_code_providerand the same end-to-end test (would return zero plan states).Ref polylogue-t0p
Co-Authored-By: Claude noreply@anthropic.com