feat(plugins): capture harness events as producer envelopes (#997)#998
feat(plugins): capture harness events as producer envelopes (#997)#998sourrris wants to merge 1 commit into
Conversation
…velopes (basicmachines-co#997) Signed-off-by: sourrrish <officialsourish0@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 72c08126f5
ℹ️ 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".
| if _hook_dir: | ||
| _shared_dir = os.path.join(_hook_dir, "..", "..", "shared") | ||
| sys.path.insert(0, os.path.normpath(_shared_dir)) |
There was a problem hiding this comment.
Bundle the shared envelope helper with plugin packages
When the hooks run from the installed plugin package (for example the documented Claude sparse install includes .claude-plugin plugins/claude-code, and the Codex manifest points at plugins/codex), there is no sibling plugins/shared directory in that package. This lookup therefore points outside the packaged plugin, the ImportError is swallowed, and _HAS_ENVELOPE stays false, so installed users never get envelope frontmatter/provenance or captureEvents logging. Vendor the helper inside each plugin or include plugins/shared in the packaged/installable source.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Implements an opt-in “harness WAL” for Claude Code and Codex by normalizing selected harness hook events into a shared producer-envelope shape, stamping checkpoints with provenance/idempotency metadata, and optionally logging raw envelopes locally for later coalescing.
Changes:
- Added a stdlib-only
HarnessEnvelopemodule with idempotency + redaction helpers and a local JSONL event log writer. - Integrated envelope creation into Claude Code and Codex SessionStart / PreCompact hooks (provenance stamping + optional WAL logging).
- Added forward-compat
ToolLedgerpicoschemas and documented/configured the feature in Claude Code.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| plugins/shared/harness_envelope.py | New shared envelope + redaction + idempotency + JSONL WAL append/rotation helper. |
| plugins/codex/hooks/session-start.py | Logs session_started envelopes locally when enabled. |
| plugins/codex/hooks/pre-compact.py | Stamps Codex checkpoints with provenance/idempotency and optionally logs envelopes. |
| plugins/codex/schemas/tool-ledger.md | Adds ToolLedger schema for future PostToolUse support. |
| plugins/claude-code/hooks/session-start.sh | Passes hook dir into heredoc Python and logs session_started envelopes locally when enabled. |
| plugins/claude-code/hooks/pre-compact.sh | Passes hook dir into heredoc Python, stamps checkpoints with envelope metadata, optionally logs envelopes. |
| plugins/claude-code/schemas/tool-ledger.md | Adds ToolLedger schema for future PostToolUse support. |
| plugins/claude-code/settings.example.json | Documents new captureEvents/redaction/retention settings. |
| plugins/claude-code/DESIGN.md | Documents Harness WAL design, envelope shape, config, and behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if isinstance(value, str): | ||
| # Check for environment-secret-like values | ||
| if SECRET_VALUE_RE.match(value): | ||
| result[key] = "[REDACTED]" | ||
| continue | ||
|
|
||
| # Check for denied paths |
| line = envelope_to_json(envelope) + "\n" | ||
| with open(log_path, "a") as fh: | ||
| fh.write(line) | ||
|
|
||
| # --- Rotation check --- | ||
| # Trigger: log exceeds the cap. Why: unbounded growth would fill disk | ||
| # on long-running projects. Outcome: keep the newest half. | ||
| try: | ||
| with open(log_path) as fh: | ||
| lines = fh.readlines() | ||
| if len(lines) > cap: | ||
| keep = lines[len(lines) // 2 :] | ||
| with open(log_path, "w") as fh: | ||
| fh.writelines(keep) |
| # --- Log the event locally for coalescing --- | ||
| # Trigger: captureEvents is enabled. Why: the local event log feeds future | ||
| # memory routines (SPEC-61) without requiring the note to carry every detail. | ||
| if _HAS_ENVELOPE and envelope and capture_events: | ||
| append_to_event_log(envelope, str(cwd)) |
| cwd=str(cwd), | ||
| project_hint=primary_project, | ||
| hook_name="SessionStart", | ||
| ) | ||
| append_to_event_log(envelope, str(cwd)) |
| if _HAS_ENVELOPE and envelope and capture_events: | ||
| append_to_event_log(envelope, cwd) |
| cwd=cwd, | ||
| project_hint=primary_project, | ||
| hook_name="SessionStart", | ||
| ) | ||
| append_to_event_log(envelope, cwd) |
| - Is append-only (no reads during hook execution) | ||
| - Is capped at 1000 lines (configurable via `eventRetention`); oldest half rotates out |
Summary
This PR implements issue #997 by introducing a shared, opt-in "harness WAL" path for the Claude Code and Codex plugins. It normalizes supported hook events (
session_started,compaction_imminent) into Basic Memory producer envelopes and stamps checkpoints with provenance and idempotency metadata.Proposed Changes
New Files
HarnessEnvelopedataclass, factory, idempotency logic, redaction utils, and event logging logic.Modified Files
plugins/claude-code/hooks/pre-compact.sh&session-start.sh:BM_HOOK_DIRenvironment variable passing to resolve the real hook directory inside Python inline heredocs (__file__resolves to<stdin>otherwise).harness_envelopeto create envelopes, stamp provenance observations, add idempotency metadata to frontmatter, and log events locally ifcaptureEventsis enabled.plugins/codex/hooks/pre-compact.py&session-start.py:harness_envelopein the Python-native hooks.plugins/claude-code/settings.example.json:captureEvents(defaults tofalse),redactKeys,redactPaths, andeventRetention.plugins/claude-code/DESIGN.md:Verification Plan
just package-check(Passed successfully)just package-check-claude-code(Passed successfully, verified Claude Code manifest schema)Closes #997