Skip to content

capture: add editor and terminal S1 field extraction - #13

Open
heming-gmh wants to merge 2 commits into
Einsia:mainfrom
heming-gmh:feat/s1-editor-terminal-parsers
Open

capture: add editor and terminal S1 field extraction#13
heming-gmh wants to merge 2 commits into
Einsia:mainfrom
heming-gmh:feat/s1-editor-terminal-parsers

Conversation

@heming-gmh

Copy link
Copy Markdown

Summary

Add S1-level context extraction for editor apps (VS Code, Cursor, Windsurf) and terminal apps (Terminal.app, iTerm2, Alacritty, Warp, Kitty, Hyper).

What changes

  • capture/s1_parser.py: extract editor_file, editor_project, editor_git_branch from editor window titles, terminal_cwd from terminal window titles. New fields are injected into the capture JSON by enrich().
  • mcp/captures.py: expose new fields in read_recent_capture response so external agents can consume them.
  • timeline/aggregator.py: render new fields as compact hints in timeline block prompts for downstream reducer/classifier consumption.

How it works

Editor title parsing

Handles VS Code / Cursor / Windsurf window title patterns:

main.py — project-name - Visual Studio Code  → file=main.py, project=project-name
app.ts — website [git:feat/auth] - Cursor     → file=app.ts, project=website, branch=git:feat/auth
config.rs — my-project [WSL:Ubuntu] - VS Code → file=config.rs, project=my-project, branch=WSL:Ubuntu
main.py - Visual Studio Code                  → file=main.py, project=None

Terminal title parsing

Handles common terminal emulator window titles:

vim — ~/projects/foo — zsh    → cwd=<home>/projects/foo
user@host: /var/www/html       → cwd=/var/www/html
Terminal                        → cwd=None

Why

These fields tell downstream agents what file/project the user is editing and what directory they're working in — information that is already in the window title but was not being extracted into the structured capture dict.

Test plan

  • 8 unit tests covering editor title formats (standard, git branch, no project, WSL, bare bracket branch)
  • 4 unit tests covering terminal title formats (iTerm2, SSH, default, absolute path)
  • 2 enrichment integration tests (full enrich() path for VS Code and iTerm2)
  • 1 regression test (non-editor/non-terminal apps get None for all new fields)
  • 3 MCP-level tests verifying fields surface through read_recent_capture()
  • Full test suite passes (84/84)
  • Ruff lint clean on all changed files

Parse VS Code / Cursor / Windsurf window titles for editor_file,
editor_project, and editor_git_branch. Parse terminal window titles
(iTerm2, Terminal.app, Alacritty, Warp, etc.) for terminal_cwd.

New fields are injected into the capture JSON by s1_parser.enrich(),
exposed to MCP clients via read_recent_capture response, and rendered
in timeline block prompts for downstream reducer/classifier consumption.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces the extraction of app-specific metadata—such as file names, project names, git branches, and working directories—from the window titles of supported editors and terminals. These fields are now integrated into the capture enrichment process, MCP tool responses, and timeline aggregation. The review feedback identifies a logic error in the editor title parser where file and project parts were inverted, suggests improvements to terminal path resolution to avoid incorrect context and blocking I/O, recommends simplifying the field initialization logic, and points out a missing case for home-relative paths in SSH titles.

Comment thread src/openchronicle/capture/s1_parser.py Outdated
Comment thread src/openchronicle/capture/s1_parser.py Outdated
Comment thread src/openchronicle/capture/s1_parser.py Outdated
Comment thread src/openchronicle/capture/s1_parser.py Outdated
- Swap file/project order in ASCII-dash fallback (was inverted)
- Support ~/ home-relative paths in SSH terminal titles
- Remove ./ relative path support (meaningless outside terminal CWD)
- Replace Path.resolve() with os.path.normpath() (no disk I/O)
- Remove now-unused pathlib.Path import
- Simplify field initialisation in enrich()

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@heming-gmh

Copy link
Copy Markdown
Author

Note on relationship with #15

This PR was implemented first, as a direct extension of s1_parser.enrich(). After landing it, I felt the module was growing responsibilities too quickly — browser URL extraction, editor/terminal metadata, and future app-specific logic would all live in one function.

So I opened #15 to introduce a lightweight app parser registry with a baseline-plus-patches model. That infrastructure PR intentionally contains no editor/terminal behaviour — it only migrates the existing browser URL extraction into BrowserParser as a proof of concept.

My plan going forward:

  • If feat(capture): add S1 app parser registry with golden fixture tests #15 is accepted first, I’ll refactor this PR to register EditorParser + TerminalParser via the new registry, with fixture-driven golden tests.
  • If this PR is accepted first, the behaviour is correct as-is — it can be migrated to the registry in a follow-up without changing any output.

Happy to go either direction depending on what the maintainer prefers.

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