Extract common hook protocol + experimental memory extraction#54
Merged
Conversation
Folds prior unsigned WIP commits into a single signed commit. abstract hook protocol (issue #50): Storage and analyzers operate on a single canonical AbstractHookEvent; each harness owns its wire format via an adapter (ClaudeCodeAdapter, OpenCodeAdapter). EventType values are snake_case canonical (Migration015 translates legacy PascalCase). multi-harness memory extraction (issue #46): find_memories discovers and parses both Claude Code and OpenCode sessions. OpenCode's message/<sid>/<message_id>.json + part/<mid>/<part_id>.json tree is walked in chronological order and emitted in the same USER:/ASSISTANT:/[TOOL: ...] format as the Claude parser, so downstream LLM extraction is harness-agnostic. processed_memory_sessions.source column (Migration017) prevents cross-harness key collisions. freshness validator (4-action LLM judge): All open-ended judgment is deferred to the LLM. The dedupe threshold is data-driven per project: p75 of the existing memory bank's pairwise similarity distribution, clamped to [0.45, 0.95]. The judge picks one of keep_both / merge / supersede / dedupe. supersede links existing to new via MemoryEntry.superseded_by (Migration016) instead of flipping retained; merge rewrites the candidate; dedupe skips save. preflight: find_memories validates both the chat LLM and embedding endpoint via GET /v1/models before processing any session; aborts with click.ClickException listing all failures. No partial batch completion. --dry-run skips the check. Truncation defaults (tool_input=120, tool_output=120, tool_result=200) preserved as Pydantic-fielded defaults on TranscriptTruncationConfig so callers can override without hardcoding changes. Verified: 976 tests pass; end-to-end on /mnt/terradump/code/microagi/moelite with MicroAGI MiniMax-M3 endpoint from opencode.json (8 memories saved, freshness ran KEEP_BOTH at sim=0.59, project p75=0.57 -> derived threshold 0.57). Signed with 34A5902CFFFC0171037ABFE2F810974410C09E22 (Alex Korolev (HOT) <lxk@droidcraft.org>).
📊 Slopometry QPE ReportQPE Score: 0.2476
Code Smell Breakdown
|
📈 Slopometry Impact ReportImpact: SIGNIFICANT IMPROVEMENT (score: 1.234)
Smell Advantage Breakdown
|
…tion
User-facing # Installation no longer smuggles dev-only advice ('After
making code changes, reinstall to update the global tool') that
confused the flow for first-time installers.
Promoted ### Development Installation (git clone + uv sync + uv run
pytest) from a buried sub-section under # Configuration to its own
top-level # Development section. The dev reinstall command now lives
there next to the clone instructions.
Also wrapped the shell-source lines in a bash fence (the snippet
was rendering as raw markdown lines before the next heading).
3421b57 to
a828b8f
Compare
…edback
After ACTION REQUIRED lists the swallowed_exception / acknowledged_silent_except
files, append a concrete example showing the exact comment format
('\# slopometry: allow-silent - <short reason>') so a human reviewer can
copy-paste it to acknowledge the handler after review and stop it from
blocking next time.
The hint appears only when a swallow-related smell is blocking (so it
doesn't clutter feedback for unrelated smells), and is symmetric:
both the swallowed (initial review) and acknowledged (mass-suppression
review) branches point at the same comment format and the inverse
operation (remove the marker to revert).
Also expanded the SmellDefinition.guidance text and the SmellCounts
Field descriptions for swallowed_exception, acknowledged_silent_except,
and test_skip to document the marker comment format + how to revert,
so the schema/docs stay in sync with the runtime hint.
3 new tests (swallow_hint_shown_when_swallowed_blocking,
swallow_hint_shown_when_acknowledged_increased,
swallow_hint_absent_when_no_swallow_smell) verify the hint is emitted
exactly when expected.
…cleanup - Add stdin_timeout_seconds to Settings; remove 5.0s magic number from dispatch.py - Remove migrations 016-018: tables are new in this branch, _create_tables has final schema - Add include_superseded param to get_memories (filters superseded_by IS NULL by default) - Remove redundant mark_session_processed from save_memories (caller owns that) - Make source param required on mark_session_processed/is_session_processed - Add FreshnessAction StrEnum with .color property - Add FreshnessVerdict + LLMMemoryCandidate pydantic models for structured LLM JSON parsing - Create llm_text.py with strip_llm_wrappers() + parse_llm_json() shared helpers - Convert MemoryFreshnessValidator class to validate_freshness() function - Make freshness thresholds configurable via Settings (floor/ceiling) - Remove api_key='dummy' defaults from MemoryExtractor/MemoryFreshnessValidator - Extract platform path helpers to settings.py (get_claude_projects_dirs, get_opencode_storage_root) - Simplify EmbeddingService: move openai import inside try block - Use FreshnessAction enum comparisons instead of string literals in commands.py and tests - Move inline imports to module top-level (Counter/defaultdict, parse_llm_json, settings) - Add return type annotations to _capture_git_state/_capture_project in dispatch.py - Rename all tests to test_<fn>__<behavior_when_context> convention - Add tests: superseded filtering, save_memories not marking session, preflight unreachable endpoint - ruff: 0 errors; pyright: 0 errors; pytest: 979 passed, 5 skipped, 3 pre-existing failures
…wledge silent exception - Remove map_tool_name from ClaudeCodeAdapter and OpenCodeAdapter (dead code, never called) - Remove orphan section comments (# Memory types, # Memory) from models/__init__.py - Add allow-silent marker to emit_event_from_stdin dispatch except block (hook subprocess must not crash the harness session)
- Add retired_reason column (migration 016) separate from superseded_by - audit_staleness(): LLM checks existing memories against transcript for retirement (fixed bugs, completed work, outdated state) - prune-memories CLI command for on-demand staleness sweeps - Fix DEDUPE: skip saving deduped candidates instead of metadata tagging - Fix MERGE: mark old memory superseded_by new merged entry - Fix staleness audit: exclude freshly-saved memories from audit scope - Action priority resolution: SUPERSEDE > MERGE > DEDUPE > KEEP_BOTH (only winning action's side effects apply per candidate group) - Extract _call_llm_json helper to DRY reconciliation + staleness LLM calls - Promote magic numbers to settings (memory_query_limit, transcript truncation, prune transcript window, reconciliation/staleness max_tokens) - Hoist openai import to top-level in memory_freshness - README: mark LLM-dependent features, add offline_mode config section, document concurrent sessions limitation - CLAUDE.md: update core components, CLI commands, model paths - Tests: 114 new tests across freshness, service, models, migrations, reconciliation priority, prune-memories CLI integration
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.
implements #50 and experimental memory extractor from project-related transcripts