Add Copilot CLI V1 capture with hooks, sync, watch, and status - #73
Open
duncankmckinnon wants to merge 53 commits into
Open
Add Copilot CLI V1 capture with hooks, sync, watch, and status#73duncankmckinnon wants to merge 53 commits into
duncankmckinnon wants to merge 53 commits into
Conversation
Freeze identity validation, schema version constants, JSON round-trips, and fixture semantics for parallel V1 consumers. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep SourceBatch free of SourceSlice fields, document that child hook session IDs are agent IDs, and freeze prefix-collision detection as an archive metadata check. Co-authored-by: Cursor <cursoragent@cursor.com>
Cover parse_hook normalization, spool durability, and copilot provenance regressions so the hook observations task can be verified independently of ingestion. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Cover discovery, all three allowed tables, WAL reads, row revisions, pagination, schema diagnostics, and cli-1.0.83 usage fixture ingestion. Co-authored-by: Cursor <cursoragent@cursor.com>
Cover commit/cursor/retrieval, timestamp preservation, deduplication, lifecycle hooks, prefix-collision rejection, fault-injected crash recovery, and stale-cursor contention with synthetic SourceBatch inputs. Co-authored-by: Cursor <cursoragent@cursor.com>
Cover discovery, bounded reads, malformed lines, snapshot semantics, and cli-1.0.83 fixture ingestion. Co-authored-by: Cursor <cursoragent@cursor.com>
ISO source times are parsed rather than accepted by string shape, and read/ack skip incomplete hook records with diagnostics. Co-authored-by: Cursor <cursoragent@cursor.com>
Cover install/uninstall merge behavior, shell quoting, malformed config rejection, source-home resolution, and complete event-set verification. Co-authored-by: Cursor <cursoragent@cursor.com>
Reopen a frozen snapshot after an incomplete tail so appended newlines are ingested, hash the full consumed prefix so same-inode rewrites replay, and reject source files whose resolved paths escape the session directory. Co-authored-by: Cursor <cursoragent@cursor.com>
Discover sessions from every allowlisted table, identify rows from PRAGMA primary keys, close read-only connections, and paginate against a logical snapshot so live WAL metadata cannot starve later rows. Co-authored-by: Cursor <cursoragent@cursor.com>
…malformed hook documents. Live installation must not write a hook that cannot run, unknown non-list hook values must be left unchanged, and add/setup needs the Copilot home, restart, status, and watch guidance. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep closed sessions closed on append, checkpoint lifecycle with the journal, strip contention markers from stored cursors, and finish recovery from load/iter so a crash cannot skip source records or invent timestamps. Co-authored-by: Cursor <cursoragent@cursor.com>
Key the cursor to the database file incarnation instead of the session snapshot hash so inserts and updates cannot starve later rows. Co-authored-by: Cursor <cursoragent@cursor.com>
Cover source discovery/batch merging, capture sync idempotency, hook spooling, stale-cursor retry, and cli-1.0.83 fixture integration. Co-authored-by: Cursor <cursoragent@cursor.com>
…errors. Preserve source exhaustion so sync pages an invocation-time snapshot, keep journal recovery counts after a stale cursor retry, and surface unreadable sources instead of a silent no-op. Co-authored-by: Cursor <cursoragent@cursor.com>
Stop sync from paging a live SQLite source indefinitely by recording snapshot_end on the composed database cursor and bounding the drain loop. Co-authored-by: Cursor <cursoragent@cursor.com>
Add assertions for all source kinds, turn-slicer exclusion, hook search, and usage dashboard boundaries so generic views stay raw without V2 projections. Co-authored-by: Cursor <cursoragent@cursor.com>
Cover change detection, retry semantics, health reporting, and installation state without requiring CLI registration or hook runtime imports. Co-authored-by: Cursor <cursoragent@cursor.com>
Cover event dispatch, fail-open semantics, env tagging, lease coalescing, and bounded follow-up workers. Co-authored-by: Cursor <cursoragent@cursor.com>
…usage Make the compatibility suite fail if token dashboards ingest database snapshots, if search omits tool arguments, or if the outer versioned SourceRecord envelope is confused with payload fields. Co-authored-by: Cursor <cursoragent@cursor.com>
…eporting. Watch now treats source disappearance as a one-shot poll, not a permanent error loop, and status validates full source keys, probes real I/O, and surfaces spool diagnostics. Co-authored-by: Cursor <cursoragent@cursor.com>
Hook and follow-up workers now fail immediately on a busy archive lock instead of waiting, pass explicit event names through to parse_hook, and attach env tags to the written observation rather than the last matching payload. Co-authored-by: Cursor <cursoragent@cursor.com>
Hook-time env tags no longer walk the full session index, while still matching the observation written at the front of the batch. Co-authored-by: Cursor <cursoragent@cursor.com>
Cover copilot sync/watch/status wiring, add/remove --copilot integration, setup multiselect, console script registration, and a fixture-backed sync composition test pending the registration-and-commands implementation. Co-authored-by: Cursor <cursoragent@cursor.com>
…ach the existing capture layer. Co-authored-by: Cursor <cursoragent@cursor.com>
Cover platform flag listing, sync error propagation, status error rendering, and hook entrypoint importability. Co-authored-by: Cursor <cursoragent@cursor.com>
Status no longer prints prompt bodies, selected-ID sync treats imported diagnostics as success rather than missing, and path-resolution failures become Click errors instead of tracebacks. Co-authored-by: Cursor <cursoragent@cursor.com>
… close. Status now reads live copilot.followup.json leases, and archive lets the last top-level lifecycle hook in a composed batch win so a spooled sessionEnd can close the session. Co-authored-by: Cursor <cursoragent@cursor.com>
# Conflicts: # src/thirdeye/cli.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GitHub Copilot CLI recordings are ingested into a local schema-v1 archive of transcript, SQLite, hook, and metadata source records so later V2 projections can run without recapture.
thirdeye add --copilotandremove --copilotinstall or drop only the owned user-level hook file;thirdeye copilot sync,watch, andstatusresolve--source-home, thenCOPILOT_HOME, then~/.copilot, and never export Copilot content. Captured sessions appear in existing list/show/events/search/tail and generic UI event views as raw envelopes, not reconstructed turns or UsageStore rows.Changes
src/thirdeye/platforms/copilot/{types,constants,identity}.py: schema version 1 TypedDicts, invocation-time source-home resolution, SHA-256source_key, and stored IDscopilot-<source_key[:16]>-<native_id>with native-ID and path-traversal rejection.session-state/**/events.jsonlandworkspace.yaml(transcript.py) and allowlistedsession-store.dbtables (database.py: sessions, turns, assistant_usage_events) as bounded SourceSlices with locators, incomplete-line waiting, and read-only WAL-aware SQLite (busy timeout 100ms).archive.py,state.py) that recovers after crash, deduplicates committed source IDs, and writescopilot_transcript/copilot_database/copilot_hook/copilot_metadataevents;SessionWriter.appendaccepts a validated source timestamp;fsops.sync_directorymakes journal publish durable.hook_payload.py,spool.py); install/remove only$COPILOT_HOME/hooks/thirdeye.json(install.py); register thethirdeye-copilot-hookdispatcher.sources.py,capture.py); make hook receipt fail-open and nonblocking with a bounded follow-up worker (hooks.py,followup.py); add foreground poll-and-ingest (watch.py) and health reporting (status.py).thirdeye copilot sync|watch|status,add/remove --copilot, and Copilot as asetuptracing platform; treat Copilot camelCase hook names as native inprovenance.py.Test plan
uv run python -m pytest tests/test_copilot_*.py tests/test_add_command.py tests/test_setup_command.py tests/test_provenance.py tests/web/test_copilot_capture_views.pythirdeye add --copilotwrites$COPILOT_HOME/hooks/thirdeye.json(default~/.copilot/hooks/thirdeye.json) with a resolvablethirdeye-copilot-hookcommand;thirdeye remove --copilotremoves only owned entries and leaves captured sessions and other hooks in place--source-homeat a home populated fromtests/fixtures/copilot/cli-1.0.83and runthirdeye copilot sync: counts print, prompt bodies stay out of diagnostics, a missing--session-idexits nonzero, and empty discovery is a successful no-opthirdeye copilot statusreports resolved paths, readable capabilities, configured hooks, last observed hook, last successful import, and pending follow-up; missing hooks are informational while source errors affect exit statusthirdeye copilot watch --source-home PATH --interval 1performs an initial sync, picks up SQLite-only updates, rejects intervals below 0.1s, and exits cleanly on SIGINT with no remote exportthirdeye list/show/events/search/tailand generic UI event views ascopilot_transcript/copilot_database/copilot_hook/copilot_metadataenvelopes withschema_version=1, without turn-sliced views or UsageStore rows🤖 Generated by workbench pr_writer