51 lines
2.8 KiB
Markdown
51 lines
2.8 KiB
Markdown
# Spec: Hook Python Port
|
|
|
|
## Purpose
|
|
|
|
Defines the requirements for porting the memory plugin's bash hooks to Python, including shared module structure, error handling conventions, and correctness verification via golden fixtures.
|
|
|
|
## Requirements
|
|
|
|
### Requirement: Single config loader
|
|
A `config.py` module SHALL expose `load_config() -> Config` (frozen dataclass) that parses `config.yaml`, expands paths, applies defaults, and handles missing file — replacing all duplicated inline YAML parsers.
|
|
|
|
#### Scenario: Config loaded once per hook invocation
|
|
- **WHEN** any hook script runs
|
|
- **THEN** it calls `load_config()` exactly once and accesses all config values through the returned `Config` dataclass
|
|
|
|
### Requirement: Uniform stdin parser
|
|
A `hook_io.py` module SHALL expose `read_input() -> HookInput` (dataclass with fields: session_id, cwd, file_path, reason) that parses hook stdin JSON, replacing all inline stdin parsers and eliminating the `python3`-vs-`jq` inconsistency.
|
|
|
|
#### Scenario: stdin parsed uniformly across all hooks
|
|
- **WHEN** any of the five hook entry points (session_start, session_context, post_tool_use_write, session_end, memsearch_sync) runs
|
|
- **THEN** stdin is parsed via `read_input()`, not inline shell commands or ad-hoc python
|
|
|
|
### Requirement: Named session-state contract
|
|
A `session_state.py` module SHALL expose `record_touch(session_id, path)` and `read_touches(session_id) -> list[str]`, encapsulating the `/tmp/claude-vault-touched-$SESSION_ID` temp-file handoff between post-tool-use-write and session-end hooks.
|
|
|
|
#### Scenario: Touch handoff uses named functions
|
|
- **WHEN** post_tool_use_write records a vault touch
|
|
- **THEN** it calls `record_touch(session_id, path)` rather than writing the temp file directly
|
|
|
|
#### Scenario: Session-end reads touches via named function
|
|
- **WHEN** session_end reads which vault files were touched
|
|
- **THEN** it calls `read_touches(session_id)` rather than reading the temp file directly
|
|
|
|
### Requirement: Fail-open hook mains
|
|
Every hook `main()` function MUST wrap execution in try/except; uncaught exceptions MUST log the error and exit with code 0.
|
|
|
|
#### Scenario: Exception does not disrupt session
|
|
- **WHEN** a hook raises an uncaught exception
|
|
- **THEN** the hook logs the exception to stderr and exits 0 (session continues normally)
|
|
|
|
### Requirement: Behavior-faithful port with golden fixtures
|
|
The Python port MUST demonstrate identical output to the bash hooks against golden fixtures before any cleanup or refactoring.
|
|
|
|
#### Scenario: Golden fixtures captured before port
|
|
- **WHEN** the port task begins
|
|
- **THEN** golden fixture files exist for each of the 4 bash hooks (known stdin → snapshot of side effects)
|
|
|
|
#### Scenario: Python output matches bash output
|
|
- **WHEN** Python hooks are run against golden fixtures
|
|
- **THEN** output matches the bash hook snapshots exactly before any refactor proceeds
|