Capability-set targeting + Claude Code headless provider + resilience fixes

Capability targeting (new feature):
- loop --capability <SET|ALL> scopes which capability library the loop reasons
  against. data/capability_sets/<name>.json (same schema as capabilities.json)
  holds one-off targeted products; drop a file in and pass its name, no code
  changes. First set: agentminder (Broadcom AgentMinder, agentic-AI identity).
- capabilities.set_active_set() swaps the active library; keyword pre-filter is
  bypassed for small targeted sets so every signal is evaluated. New
  'capability-sets' command lists them; run banner shows the active set.

LLM provider — the '429' was a disguised policy block:
- Anthropic rejects Claude Code OAuth tokens on /v1/messages for non-Claude-Code
  traffic with a fake rate_limit_error (no anthropic-ratelimit-* headers). New
  'claude-cli' provider runs inference through the sanctioned headless path
  (claude -p --append-system-prompt --model), now the default provider.
- OAuth keychain token auto-refresh via headless claude when expired.

Resilience:
- STATE_DIR is overridable (macOS endpoint-security locked output/state via
  com.apple.macl); load_memory tolerates PermissionError; exa usage counter
  tolerates malformed files; run.py handles Ctrl-C cleanly (no traceback).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 09:00:02 -04:00
parent c2854ba163
commit fefda7481f
9 changed files with 234 additions and 26 deletions

View File

@@ -25,6 +25,7 @@ python3 run.py loop --no-domain-filter # Exa: broad-web news (default)
| `--tier T` | Only `strategic` / `enterprise` / `growth` accounts |
| `--rep NAME` | Only accounts assigned to a rep (case-insensitive name or `rep_id` substring) |
| `--limit N` | Process at most N accounts. Order: **strategic tier first, then least-recently-scanned** (never-scanned first). The run cursor (`output/state/run_cursor.json`) persists, so successive `--limit` runs walk the whole territory — e.g. a nightly `loop --limit 30` covers 342 accounts in ~12 days. |
| `--capability SET` | Capability set to reason against: `ALL` (full 40-capability portfolio, default) or a named set from `data/capability_sets/` (e.g. `agentminder`). In a targeted set the keyword pre-filter is bypassed so EVERY signal is evaluated against the chosen product. List sets: `python3 run.py capability-sets`. **Add a new one-off product**: drop `data/capability_sets/<name>.json` (same schema as `capabilities.json`) and pass `--capability <name>` — no code changes. |
| `--domain-filter` | Scope Exa news to the account's own domain (newsroom/PR only) |
| `--no-domain-filter` | Broad-web news about the account (default) |