Repository navigation
Replace finance-only hook with a generic config-driven artifact hook - #7
Merged
Merged
Conversation
The hook and REST endpoint have each needed a bug-fix PR already, with no safety net to catch regressions. This adds one and fixes the small correctness issues found during a repo review: - 50 pytest tests covering the MCP tools, REST endpoint, both auth middlewares, the dashboard, and the finance hook's parsing logic, backed by an in-memory MongoDB (mongomock-motor) so no containers are needed - GitHub Actions workflow running ruff + pytest on every push and PR - Constant-time API key comparison in the MCP/REST bearer auth, matching what the dashboard's basic auth already did - Validate REST body field types with a Pydantic model instead of inserting whatever arrives into Mongo - Clamp list_entries limit/skip (negative values raised from Mongo, and limit was unbounded) - Create indexes on created_at/source/keywords at startup, so list and dashboard queries stop collection-scanning as the store grows - Replace mutable default arguments and a dead `except (InvalidId, Exception)` clause Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
log_finance_entry.py hardcoded everything about finance-agent — the cwd
check, the artifact path shape, and every description/keyword rule — so
each new agent project would have needed its own hook script copied to
~/.claude/hooks. This splits the hook into a generic engine and
per-project config:
- hooks/log_artifact_entry.py keeps only the universal parts: the
"script prints the path of the JSON artifact it wrote" convention,
config discovery, and posting to /entries. A project opts in by
having .ai-data-store.json at its root (found by walking up from the
session cwd); everywhere else the hook stays a silent no-op, so the
global registration adds no noise. Artifacts outside the opted-in
project are refused, and relative stdout paths resolve against the
session cwd.
- The config maps artifacts to entries with regex rules over the path
and str.format templates for description/keywords. Named regex
groups ({ticker}) and dotted paths into the artifact JSON
({content.verdict.winner}) both resolve; description takes a
template list and uses the first that fully resolves, which replaces
the old hook's hand-written conditionals (price present vs not).
- hooks/configs/finance-agent.json ports all nine finance rules and
produces the same descriptions and keywords as before, verified by
the rewritten test suite (18 hook tests, 57 total).
- scripts/uninstall_hook.sh removes an installed hook's file and
settings entry, for migrating off log_finance_entry.py; the README
documents the config format and migration steps.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 of 2 tasks
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
hooks/log_artifact_entry.py— a generic PostToolUse hook replacing the finance-agent-specificlog_finance_entry.py. The engine keeps only the universal parts: the "script prints the path of the JSON artifact it wrote" convention, config discovery, and posting to/entries..ai-data-store.jsonconfig at their root (found by walking up from the session cwd) and is a silent no-op everywhere else — so it's safe registered globally, and any future agent project joins by dropping in a config file, no new hook script needed.str.formattemplates for description/keywords. Named regex groups ({ticker}) and dotted paths into the artifact JSON ({content.verdict.winner}, list indices supported) both resolve.descriptionaccepts a template list and uses the first that fully resolves — this replaces the old hook's hand-written conditionals (e.g. price present vs. absent) with graceful degradation. Keywords that fail to resolve are dropped; duplicates removed.hooks/configs/finance-agent.jsonports all nine finance rules (verdict, debate, panel, check_stock, check_crypto, history, portfolio, news_results, analysis) and produces the same descriptions/keywords as the old hook.scripts/uninstall_hook.shremoves an installed hook's file and settings entry;install_hook.shnow defaults to the new hook. README documents the config format and the migration:Test plan
ruff check .— cleanpytest— 57 passed;tests/test_hook.pyrewritten with 18 tests: template engine units, all finance artifact types end-to-end throughmain()asserting byte-identical descriptions/keywords to the old hook, and the no-op paths (no config, outside-project artifact, non-Bash, unmatched filename, missing/invalid artifact)bash -non both scripts; shipped config validated as JSON🤖 Generated with Claude Code