projecta-rrr 1.22.2 → 1.22.4
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 +43 -0
- package/agents/rrr-explore.md +9 -9
- package/agents/rrr-integration-checker.md +1 -1
- package/agents/rrr-project-researcher.md +1 -1
- package/agents/rrr-roadmapper.md +1 -1
- package/agents/rrr-verifier.md +1 -1
- package/bin/install.js +41 -0
- package/hooks/tool-disallow.js +57 -6
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,49 @@ 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.4] - 2026-04-19
|
|
8
|
+
|
|
9
|
+
**Patch: semantic search wired into 5 agents; rrr-explore tool names fixed.**
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- **`rrr-explore` broken tool names** — was referencing `mcp:semantic_search` / `mcp:search_sessions` (unresolvable shorthand), replaced with real tool names `mcp__rrr-search-hosted__semantic_search` and `mcp__rrr-search-hosted__search_sessions` throughout frontmatter and all body examples. Semantic search was silently falling back to grep/bash on every invocation.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- **Semantic search added to 4 agents** that previously had none:
|
|
16
|
+
- `rrr-verifier` — finds feature implementations for goal-backward verification
|
|
17
|
+
- `rrr-integration-checker` — finds cross-phase connection points
|
|
18
|
+
- `rrr-project-researcher` — adds codebase search to supplement web/Context7 research; also gets `search_sessions`
|
|
19
|
+
- `rrr-roadmapper` — useful for brownfield codebase mapping
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## [1.22.3] - 2026-04-19
|
|
24
|
+
|
|
25
|
+
**Patch: postinstall full provision + tool-disallow real-payload subagent detection + hook wiring.**
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- **`bin/install.js` postinstall now full-provisions** (was `--hud-only`). Fresh `npm install -g projecta-rrr` lands 47 commands, 13 agents, 18 hooks, plus settings.json with v1.22 hooks pre-wired (default-safe). Previously users had to run `npx projecta-rrr install` separately to get commands/agents.
|
|
29
|
+
- **v1.22 hooks now auto-wired** into `~/.claude/settings.json` on install:
|
|
30
|
+
- `PreToolUse` matcher `Task|Agent` → `hooks/model-router.js`
|
|
31
|
+
- `PreToolUse` matcher `Read|Grep|Glob` → `hooks/tool-disallow.js`
|
|
32
|
+
- `PostToolUse` matcher `Edit|MultiEdit` → `hooks/edit-batching-nudge.js`
|
|
33
|
+
- Defaults seeded: `settings.rrr.model_router: "static"` (v1.21 behavior), `settings.rrr.tok_disallow: false` (opt-in).
|
|
34
|
+
- Idempotent — re-install does not duplicate entries.
|
|
35
|
+
- Previously hook files copied but not wired (only `runHostedInstallOrchestrator()` wired them, which only runs with `--enable-hosted`).
|
|
36
|
+
- **`hooks/tool-disallow.js` subagent detection** now uses real Claude Code payload schema. Previous heuristic checked `input.agent_name` which does NOT exist in PreToolUse payloads (UAT-verified schema: `{session_id, transcript_path, cwd, permission_mode, hook_event_name, tool_name, tool_input, tool_use_id}`). New mechanism: read tail of `transcript_path` and check `isSidechain: true` to detect subagent context. Fallback: legacy `agent_name` field for forward-compat. Fail-CLOSED if transcript unreadable (over-block better than under-block when goal is token discipline).
|
|
37
|
+
|
|
38
|
+
### Operator data populated this session
|
|
39
|
+
- **`installations` table**: 5 rows (was 0) — populated from existing `repos.installation_id` data.
|
|
40
|
+
- **`repos.github_repo_id` backfill**: 24 of 59 real repos populated via `gh api /repos/PA-Ai-Team/<slug>`. Remaining 35 are inaccessible to the user PAT (likely deleted, archived, or upstream forks like OpenHands/letta — webhook routing for them is unreachable anyway, so NULL is correct).
|
|
41
|
+
|
|
42
|
+
### Verified in UAT
|
|
43
|
+
- Fresh `HOME=tmp npm install -g projecta-rrr@1.22.3 --prefix=tmp` lands 47 commands + 13 agents + 18 hooks + 3 wired hook entries with safe defaults. Re-install is idempotent (no duplicate entries).
|
|
44
|
+
- `tool-disallow`: main-thread Read with synthetic transcript (`isSidechain:false`) → BLOCK exit 2; subagent Read with `isSidechain:true` → ALLOW exit 0.
|
|
45
|
+
- 239/239 tests pass; `prepublish:check` clean.
|
|
46
|
+
|
|
47
|
+
### Known followups
|
|
48
|
+
- 35 repos with NULL `github_repo_id` (private/deleted) — operator can run via App-installation token (broader scope) if needed; for now webhook safely skips them with `{"skipped":"unindexed-repo"}`.
|
|
49
|
+
|
|
7
50
|
## [1.22.2] - 2026-04-19
|
|
8
51
|
|
|
9
52
|
**Patch: dynamic routing now actually fires in Claude Code (Opus 4.7+).**
|
package/agents/rrr-explore.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rrr-explore
|
|
3
|
-
description: Code exploration agent. Semantic-first via
|
|
3
|
+
description: Code exploration agent. Semantic-first via mcp__rrr-search-hosted__semantic_search; narrow Bash for exact identifiers only.
|
|
4
4
|
model: haiku
|
|
5
|
-
tools: Bash,
|
|
5
|
+
tools: Bash, mcp__rrr-search-hosted__semantic_search, mcp__rrr-search__semantic_search, mcp__rrr-search-hosted__search_sessions, mcp__rrr-search__search_sessions
|
|
6
6
|
disallowedTools: [Read, Grep, Glob]
|
|
7
7
|
bashAllowList:
|
|
8
8
|
- "rg"
|
|
@@ -23,7 +23,7 @@ You are a RRR code exploration agent. You explore codebases using intelligent se
|
|
|
23
23
|
|
|
24
24
|
**No narration:** Do NOT emit text between tool calls. Think, call tools, return structured findings at the end. Inter-call prose burns tokens and degrades Haiku output quality.
|
|
25
25
|
|
|
26
|
-
**Read/Grep/Glob are disabled for you.** Use `
|
|
26
|
+
**Read/Grep/Glob are disabled for you.** Use `mcp__rrr-search-hosted__semantic_search` for concepts, `mcp__rrr-search-hosted__search_sessions` for decision history, and narrow Bash (`rg`, `git log/show/blame`, `ls`, `wc` only) for exact-identifier fallback. If you genuinely need to read a whole file, return a `needs_read: <path>` hint and let the caller do it.
|
|
27
27
|
|
|
28
28
|
**Core Responsibilities:**
|
|
29
29
|
|
|
@@ -104,7 +104,7 @@ Start with questions 1 and 2. Only use question 3 when you have specific identif
|
|
|
104
104
|
|
|
105
105
|
**Invocation:**
|
|
106
106
|
```
|
|
107
|
-
|
|
107
|
+
mcp__rrr-search-hosted__semantic_search query="authentication flow" limit=10
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
### Use search_sessions (for historical context):
|
|
@@ -117,7 +117,7 @@ mcp:semantic_search query="authentication flow" limit=10
|
|
|
117
117
|
|
|
118
118
|
**Invocation:**
|
|
119
119
|
```
|
|
120
|
-
|
|
120
|
+
mcp__rrr-search-hosted__search_sessions query="why PostgreSQL over MongoDB" limit=5
|
|
121
121
|
```
|
|
122
122
|
|
|
123
123
|
### Use Bash (`rg` only) for exact identifiers:
|
|
@@ -243,12 +243,12 @@ Use search_sessions for understanding past decisions:
|
|
|
243
243
|
User: "Why did we use JWT instead of sessions?"
|
|
244
244
|
|
|
245
245
|
1. Query session history:
|
|
246
|
-
|
|
246
|
+
mcp__rrr-search-hosted__search_sessions query="JWT vs sessions authentication decision"
|
|
247
247
|
|
|
248
248
|
2. Review results for decision context
|
|
249
249
|
|
|
250
250
|
3. If needed, supplement with semantic_search for current implementation:
|
|
251
|
-
|
|
251
|
+
mcp__rrr-search-hosted__semantic_search query="JWT authentication implementation"
|
|
252
252
|
```
|
|
253
253
|
|
|
254
254
|
**Typical usage:**
|
|
@@ -271,12 +271,12 @@ Before searching, clarify:
|
|
|
271
271
|
|
|
272
272
|
**For conceptual code questions (most common):**
|
|
273
273
|
```
|
|
274
|
-
|
|
274
|
+
mcp__rrr-search-hosted__semantic_search query="how user authentication works" limit=10
|
|
275
275
|
```
|
|
276
276
|
|
|
277
277
|
**For past decisions and context:**
|
|
278
278
|
```
|
|
279
|
-
|
|
279
|
+
mcp__rrr-search-hosted__search_sessions query="why we chose JWT over sessions" limit=5
|
|
280
280
|
```
|
|
281
281
|
|
|
282
282
|
**For exact identifiers (specific lookup):**
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: rrr-integration-checker
|
|
3
3
|
description: Verifies cross-phase integration and E2E flows. Checks that phases connect properly and user workflows complete end-to-end.
|
|
4
4
|
model: haiku
|
|
5
|
-
tools: Read, Bash, Grep, Glob
|
|
5
|
+
tools: Read, Bash, Grep, Glob, mcp__rrr-search-hosted__semantic_search, mcp__rrr-search__semantic_search
|
|
6
6
|
color: blue
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: rrr-project-researcher
|
|
3
3
|
description: Researches domain ecosystem. Supports two modes - project research (.planning/research/) and milestone research (.planning/milestones/vX.Y/research/). Milestone research inherits from project research.
|
|
4
4
|
model: sonnet
|
|
5
|
-
tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__
|
|
5
|
+
tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__rrr-search-hosted__semantic_search, mcp__rrr-search__semantic_search, mcp__rrr-search-hosted__search_sessions, mcp__rrr-search__search_sessions
|
|
6
6
|
color: cyan
|
|
7
7
|
---
|
|
8
8
|
|
package/agents/rrr-roadmapper.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: rrr-roadmapper
|
|
3
3
|
description: Creates project roadmaps with phase breakdown, requirement mapping, success criteria derivation, and coverage validation. Spawned by /rrr:new-project orchestrator.
|
|
4
4
|
model: sonnet
|
|
5
|
-
tools: Read, Write, Bash, Glob, Grep
|
|
5
|
+
tools: Read, Write, Bash, Glob, Grep, mcp__rrr-search-hosted__semantic_search, mcp__rrr-search__semantic_search
|
|
6
6
|
color: purple
|
|
7
7
|
---
|
|
8
8
|
|
package/agents/rrr-verifier.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: rrr-verifier
|
|
3
3
|
description: Verifies phase goal achievement through goal-backward analysis. Checks codebase delivers what phase promised, not just that tasks completed. Creates VERIFICATION.md report.
|
|
4
4
|
model: sonnet
|
|
5
|
-
tools: Read, Bash, Grep, Glob
|
|
5
|
+
tools: Read, Bash, Grep, Glob, mcp__rrr-search-hosted__semantic_search, mcp__rrr-search__semantic_search
|
|
6
6
|
color: green
|
|
7
7
|
---
|
|
8
8
|
|
package/bin/install.js
CHANGED
|
@@ -1730,6 +1730,47 @@ function install(isGlobal) {
|
|
|
1730
1730
|
console.log(` ${green}✓${reset} Installed hooks`);
|
|
1731
1731
|
}
|
|
1732
1732
|
|
|
1733
|
+
// v1.22.3: wire Phase 83 (model-router), Phase 85 (tool-disallow + edit-batching-nudge)
|
|
1734
|
+
// PreToolUse/PostToolUse hooks. Idempotent — checks for existing entries before
|
|
1735
|
+
// adding. Defaults are SAFE (settings.rrr.tok_disallow=false; model_router=static).
|
|
1736
|
+
// Previously these were only wired when --enable-hosted ran the hosted orchestrator,
|
|
1737
|
+
// so users got the hooks on disk but no settings.json registration.
|
|
1738
|
+
if (bashStatus.available && fs.existsSync(path.join(claudeDir, 'hooks', 'model-router.js'))) {
|
|
1739
|
+
settings.hooks = settings.hooks || {};
|
|
1740
|
+
settings.hooks.PreToolUse = settings.hooks.PreToolUse || [];
|
|
1741
|
+
settings.hooks.PostToolUse = settings.hooks.PostToolUse || [];
|
|
1742
|
+
settings.rrr = settings.rrr || {};
|
|
1743
|
+
|
|
1744
|
+
const wireOnce = (chain, matcher, hookCmd, label) => {
|
|
1745
|
+
const exists = chain.some((entry) =>
|
|
1746
|
+
entry && Array.isArray(entry.hooks) && entry.hooks.some(
|
|
1747
|
+
(h) => h && typeof h.command === 'string' && h.command.includes(label)
|
|
1748
|
+
)
|
|
1749
|
+
);
|
|
1750
|
+
if (!exists) {
|
|
1751
|
+
chain.push({ matcher, hooks: [{ type: 'command', command: hookCmd }] });
|
|
1752
|
+
return true;
|
|
1753
|
+
}
|
|
1754
|
+
return false;
|
|
1755
|
+
};
|
|
1756
|
+
|
|
1757
|
+
let wiredCount = 0;
|
|
1758
|
+
if (wireOnce(settings.hooks.PreToolUse, 'Task|Agent', '$HOME/.claude/hooks/model-router.js', 'model-router.js')) wiredCount++;
|
|
1759
|
+
if (fs.existsSync(path.join(claudeDir, 'hooks', 'tool-disallow.js'))) {
|
|
1760
|
+
if (wireOnce(settings.hooks.PreToolUse, 'Read|Grep|Glob', 'node $HOME/.claude/hooks/tool-disallow.js', 'tool-disallow.js')) wiredCount++;
|
|
1761
|
+
}
|
|
1762
|
+
if (fs.existsSync(path.join(claudeDir, 'hooks', 'edit-batching-nudge.js'))) {
|
|
1763
|
+
if (wireOnce(settings.hooks.PostToolUse, 'Edit|MultiEdit', 'node $HOME/.claude/hooks/edit-batching-nudge.js', 'edit-batching-nudge.js')) wiredCount++;
|
|
1764
|
+
}
|
|
1765
|
+
if (settings.rrr.model_router === undefined) settings.rrr.model_router = 'static';
|
|
1766
|
+
if (settings.rrr.tok_disallow === undefined) settings.rrr.tok_disallow = false;
|
|
1767
|
+
if (wiredCount > 0) {
|
|
1768
|
+
console.log(` ${green}✓${reset} Wired ${wiredCount} v1.22 hook(s) (settings.rrr.model_router=static, tok_disallow=false — opt-in)`);
|
|
1769
|
+
} else {
|
|
1770
|
+
console.log(` ${dim}✓${reset} v1.22 hooks already wired`);
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1733
1774
|
const statuslineCommand = isGlobal
|
|
1734
1775
|
? '$HOME/.claude/hooks/statusline.sh'
|
|
1735
1776
|
: `${localDirName}/hooks/statusline.sh`;
|
package/hooks/tool-disallow.js
CHANGED
|
@@ -18,9 +18,16 @@
|
|
|
18
18
|
* and scripts/test-install-smoke.js).
|
|
19
19
|
* - env RRR_TOK_DISALLOW=off → kill-switch override.
|
|
20
20
|
*
|
|
21
|
-
* Subagent exemption:
|
|
22
|
-
* - PreToolUse
|
|
23
|
-
*
|
|
21
|
+
* Subagent exemption (v1.22.3 fix — UAT-verified payload schema):
|
|
22
|
+
* - Real Claude Code PreToolUse payload does NOT include `agent_name`.
|
|
23
|
+
* Schema is: {session_id, transcript_path, cwd, permission_mode,
|
|
24
|
+
* hook_event_name, tool_name, tool_input, tool_use_id}
|
|
25
|
+
* - Subagent context is detected by reading the LAST line of
|
|
26
|
+
* `transcript_path` and checking `isSidechain: true`. Sidechain entries
|
|
27
|
+
* are subagent calls; main thread is `isSidechain: false`.
|
|
28
|
+
* - Fallback: if transcript can't be read or parsed, treat as main thread
|
|
29
|
+
* (fail-CLOSED for the BLOCK case — better to over-block than under-block
|
|
30
|
+
* when the goal is token discipline).
|
|
24
31
|
*
|
|
25
32
|
* Settings location (read-only): ~/.claude/settings.json (then project
|
|
26
33
|
* .claude/settings.json — project wins). Never modified here; wiring is
|
|
@@ -66,6 +73,43 @@ function isAgentExempt(agentName, exemptList) {
|
|
|
66
73
|
return true;
|
|
67
74
|
}
|
|
68
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Detect subagent context by reading the tail of the Claude Code transcript
|
|
78
|
+
* and checking for `isSidechain: true` on recent entries.
|
|
79
|
+
*
|
|
80
|
+
* Real Claude Code PreToolUse payload includes `transcript_path` but NOT
|
|
81
|
+
* `agent_name`. The transcript JSONL has one entry per turn with isSidechain
|
|
82
|
+
* marking subagent context (UAT-verified in v1.22.3).
|
|
83
|
+
*
|
|
84
|
+
* Returns: 'subagent' | 'main' | 'unknown'
|
|
85
|
+
*/
|
|
86
|
+
function detectThreadFromTranscript(transcriptPath) {
|
|
87
|
+
if (!transcriptPath || typeof transcriptPath !== 'string') return 'unknown';
|
|
88
|
+
try {
|
|
89
|
+
if (!fs.existsSync(transcriptPath)) return 'unknown';
|
|
90
|
+
// Read last ~64KB only (transcripts can be large; we only need recent context).
|
|
91
|
+
const stat = fs.statSync(transcriptPath);
|
|
92
|
+
const fd = fs.openSync(transcriptPath, 'r');
|
|
93
|
+
const tailSize = Math.min(stat.size, 65536);
|
|
94
|
+
const buf = Buffer.alloc(tailSize);
|
|
95
|
+
fs.readSync(fd, buf, 0, tailSize, Math.max(0, stat.size - tailSize));
|
|
96
|
+
fs.closeSync(fd);
|
|
97
|
+
const lines = buf.toString('utf8').split('\n').filter(Boolean);
|
|
98
|
+
// Walk backward — the most recent non-tool-result entry is the current turn.
|
|
99
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
100
|
+
try {
|
|
101
|
+
const e = JSON.parse(lines[i]);
|
|
102
|
+
if (typeof e.isSidechain === 'boolean') {
|
|
103
|
+
return e.isSidechain ? 'subagent' : 'main';
|
|
104
|
+
}
|
|
105
|
+
} catch { /* skip malformed line */ }
|
|
106
|
+
}
|
|
107
|
+
return 'unknown';
|
|
108
|
+
} catch {
|
|
109
|
+
return 'unknown';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
69
113
|
function decideMode(settings) {
|
|
70
114
|
// Env kill-switch wins.
|
|
71
115
|
if ((process.env.RRR_TOK_DISALLOW || '').toLowerCase() === 'off') return 'off';
|
|
@@ -98,12 +142,18 @@ function main() {
|
|
|
98
142
|
// a misconfigured settings.json never breaks the installer.
|
|
99
143
|
if (process.env.RRR_INTERNAL_TOOL === '1') { process.exit(0); }
|
|
100
144
|
|
|
101
|
-
// Subagent exemption —
|
|
102
|
-
|
|
145
|
+
// Subagent exemption — v1.22.3: detect via transcript_path + isSidechain.
|
|
146
|
+
// Real Claude Code payload schema does NOT include input.agent_name.
|
|
147
|
+
// Fallback to legacy input.agent_name field for forward-compat with future
|
|
148
|
+
// Claude Code versions that may add it.
|
|
149
|
+
const legacyAgentName = input.agent_name || (input.session && input.session.agent_name) || '';
|
|
150
|
+
const thread = legacyAgentName ? 'subagent' : detectThreadFromTranscript(input.transcript_path);
|
|
103
151
|
const settings = loadSettings();
|
|
104
152
|
const exemptList = settings.tok_disallow_exempt;
|
|
105
153
|
|
|
106
|
-
|
|
154
|
+
// Subagent (sidechain) → always exempt. Unknown → treat as main (fail-CLOSED).
|
|
155
|
+
if (thread === 'subagent') { process.exit(0); }
|
|
156
|
+
if (legacyAgentName && isAgentExempt(legacyAgentName, exemptList)) { process.exit(0); }
|
|
107
157
|
|
|
108
158
|
// Explicit per-name allow (rare: when main-thread invocation of a
|
|
109
159
|
// specific named context should still be permitted).
|
|
@@ -127,5 +177,6 @@ module.exports = {
|
|
|
127
177
|
BLOCKED_TOOLS,
|
|
128
178
|
decideMode,
|
|
129
179
|
isAgentExempt,
|
|
180
|
+
detectThreadFromTranscript,
|
|
130
181
|
buildMessage,
|
|
131
182
|
};
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projecta-rrr",
|
|
3
|
-
"version": "1.22.
|
|
3
|
+
"version": "1.22.4",
|
|
4
4
|
"description": "A meta-prompting, context engineering and spec-driven development system for Claude Code by Projecta.ai",
|
|
5
5
|
"bin": {
|
|
6
6
|
"projecta-rrr": "bin/install.js",
|
|
7
7
|
"projecta-rrr-hosted-setup": "bin/hosted-setup.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"postinstall": "node bin/install.js --
|
|
10
|
+
"postinstall": "node bin/install.js --global --yes --skip-optimization && node scripts/register-mcp.js",
|
|
11
11
|
"watch": "node watcher/index.js",
|
|
12
12
|
"watch:verbose": "node watcher/index.js --verbose",
|
|
13
13
|
"watch:claude-code": "node watcher/watchers/claude-code.js --verbose",
|