projecta-rrr 1.22.1 → 1.22.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/hooks/model-router.js +5 -2
- package/package.json +1 -1
- package/rrr/lib/install-hooks-wiring.js +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,40 @@ All notable changes to RRR will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
6
|
|
|
7
|
+
## [1.22.2] - 2026-04-19
|
|
8
|
+
|
|
9
|
+
**Patch: dynamic routing now actually fires in Claude Code (Opus 4.7+).**
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- **Phase 83 model-router matcher**: Claude Code (Opus 4.7+) emits subagent dispatches as `tool_name: "Agent"`, not `"Task"`. v1.22.0/.1 hardcoded `"Task"` in both:
|
|
13
|
+
1. `hooks/model-router.js` internal gate (`if (toolName !== "Task") return emitAllow()`)
|
|
14
|
+
2. `rrr/lib/install-hooks-wiring.js` matcher (`{ matcher: "Task", ... }`)
|
|
15
|
+
Result: hook never fired for any Agent dispatch in Opus 4.7+ sessions, so dynamic routing was a no-op even with `settings.rrr.model_router: "dynamic"`.
|
|
16
|
+
|
|
17
|
+
v1.22.2 accepts both `Task` and `Agent`. Live UAT verified end-to-end:
|
|
18
|
+
```
|
|
19
|
+
{"ts":"2026-04-19T05:46:21Z","event":"dispatch","tool_name":"Agent",
|
|
20
|
+
"agent_name":"rrr-explore","tier":"haiku","reason":"dispatch"}
|
|
21
|
+
```
|
|
22
|
+
Token usage on rrr-explore call: ~10.4k (haiku) vs ~13.2k baseline (general-purpose, sonnet/inherit) — ~21% reduction from tier downgrade alone, on a single dispatch.
|
|
23
|
+
|
|
24
|
+
### Verified in UAT (v1.21 hosted webhook + Phase 80 App-level)
|
|
25
|
+
- **Hosted Fly app redeployed** with v1.22 code (was running pre-Phase-80 image — `/webhooks/github-app` returned 404 until `fly deploy`).
|
|
26
|
+
- **Phase 80 webhook end-to-end**:
|
|
27
|
+
- Ping: 200 OK
|
|
28
|
+
- Valid HMAC push (with `installation_id` lookup): 202 + `{queued:true, job_id}`
|
|
29
|
+
- Replay (same delivery_id): 200 + `{duplicate:true}` ✓ dedup
|
|
30
|
+
- Bad signature: 401 `signature_invalid`
|
|
31
|
+
- Non-default branch: 200 `{skipped:"non-default-branch"}`
|
|
32
|
+
- Unindexed repo (NULL `github_repo_id`): 200 `{skipped:"unindexed-repo"}`
|
|
33
|
+
- **Neon migration 014 applied**: `installations` table populated with 5 rows from existing `repos.installation_id` data.
|
|
34
|
+
- **`installations` table**: 5 rows under `team_id=pa-ai-team`. Largest installation: 125117864 (29 repos).
|
|
35
|
+
|
|
36
|
+
### Known followups
|
|
37
|
+
- **Backfill `repos.github_repo_id`** for all 62 repos via `gh api /repos/<full_name>`. Without this, App-level webhook deliveries hit "unindexed-repo" skip path. Operator-actionable.
|
|
38
|
+
- **Postinstall `--hud-only`** still requires separate `npx projecta-rrr install` for full provision. v1.22.x followup.
|
|
39
|
+
- **`tool-disallow` subagent exemption heuristic** uses `input.agent_name` — this field is NOT present in real Claude Code PreToolUse payload (UAT-verified payload schema has `tool_name`, `tool_input`, `session_id`, `transcript_path`, `cwd`, `permission_mode`, `tool_use_id`). Subagent context detection needs different mechanism.
|
|
40
|
+
|
|
7
41
|
## [1.22.1] - 2026-04-19
|
|
8
42
|
|
|
9
43
|
**Patch: fixes v1.22.0 fresh install regression.**
|
package/hooks/model-router.js
CHANGED
|
@@ -85,9 +85,12 @@ function main() {
|
|
|
85
85
|
try { input = JSON.parse(raw); }
|
|
86
86
|
catch (_e) { return emitAllow('router: stdin not JSON'); }
|
|
87
87
|
|
|
88
|
-
// Only act on the
|
|
88
|
+
// Only act on the subagent-dispatch tool — every other tool is pass-through.
|
|
89
|
+
// Claude Code uses either "Task" (Anthropic API name, most builds) or "Agent"
|
|
90
|
+
// (Opus 4.7+ builds) for subagent dispatch. Accept both — confirmed via
|
|
91
|
+
// v1.22.2 UAT live-session capture (/tmp/uat-hook-log.jsonl).
|
|
89
92
|
const toolName = input.tool_name;
|
|
90
|
-
if (toolName !== 'Task') return emitAllow();
|
|
93
|
+
if (toolName !== 'Task' && toolName !== 'Agent') return emitAllow();
|
|
91
94
|
|
|
92
95
|
const toolInput = (input.tool_input && typeof input.tool_input === 'object') ? input.tool_input : {};
|
|
93
96
|
|
package/package.json
CHANGED
|
@@ -210,7 +210,10 @@ function wireToolRedirect({ repoHooksDir, userHooksDir, userSettingsPath, dryRun
|
|
|
210
210
|
*/
|
|
211
211
|
function buildModelRouterEntry(hookAbsPath) {
|
|
212
212
|
return {
|
|
213
|
-
|
|
213
|
+
// Claude Code uses either "Task" (most builds) or "Agent" (Opus 4.7+) as
|
|
214
|
+
// the subagent dispatch tool name. Match both via regex alternation —
|
|
215
|
+
// confirmed via v1.22.2 UAT live-session capture.
|
|
216
|
+
matcher: 'Task|Agent',
|
|
214
217
|
hooks: [
|
|
215
218
|
{ type: 'command', command: `node ${hookAbsPath}` },
|
|
216
219
|
],
|