projecta-rrr 1.21.3 → 1.21.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 +44 -0
- package/bin/hosted-setup.js +275 -0
- package/bin/install.js +32 -0
- package/commands/rrr/discuss-phase.md +1 -0
- package/commands/rrr/execute-phase.md +1 -0
- package/commands/rrr/plan-phase.md +1 -0
- package/commands/rrr/progress.md +1 -0
- package/commands/rrr/verify-work.md +1 -0
- package/package.json +3 -2
- package/rrr/references/semantic-search-preference.md +42 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,50 @@ 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.21.4] - 2026-04-18
|
|
8
|
+
|
|
9
|
+
**One-command adoption + slash-command integration.**
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **`projecta-rrr hosted-setup`** — interactive wizard for any repo to adopt
|
|
14
|
+
hosted semantic search in ~1 minute. Steps: prerequisite check → bearer
|
|
15
|
+
paste → team/repo/root_sha detection → `.rrr-search.json` generation →
|
|
16
|
+
`claude mcp add` → GitHub App install link → first-index hint.
|
|
17
|
+
Idempotent; safe to re-run. Also callable as:
|
|
18
|
+
- `projecta-rrr-hosted-setup` (standalone bin)
|
|
19
|
+
- `npx projecta-rrr hosted-setup`
|
|
20
|
+
|
|
21
|
+
- **`rrr/references/semantic-search-preference.md`** — shared reference
|
|
22
|
+
included in 5 slash commands via `@rrr/references/...` import:
|
|
23
|
+
- `/rrr:progress`
|
|
24
|
+
- `/rrr:plan-phase`
|
|
25
|
+
- `/rrr:execute-phase`
|
|
26
|
+
- `/rrr:discuss-phase`
|
|
27
|
+
- `/rrr:verify-work`
|
|
28
|
+
|
|
29
|
+
Instructs the command workflow to prefer `mcp__rrr-search-hosted__semantic_search`
|
|
30
|
+
(or local stdio fallback) over Grep/Read for concept-level exploration.
|
|
31
|
+
Grep remains the right tool for exact-identifier lookups.
|
|
32
|
+
|
|
33
|
+
- **Postinstall nudge** — after `npm install projecta-rrr`, if the current
|
|
34
|
+
dir is a git repo without `.rrr-search.json`, prints a 3-line invitation
|
|
35
|
+
to run `projecta-rrr hosted-setup`. Non-blocking; skipped gracefully on
|
|
36
|
+
any error.
|
|
37
|
+
|
|
38
|
+
### Why this release
|
|
39
|
+
|
|
40
|
+
Before v1.21.4 the hosted infrastructure was live but disconnected from
|
|
41
|
+
daily RRR workflow: slash commands used Grep/Read directly, only the
|
|
42
|
+
`rrr-explore` agent was wired to semantic_search, and the local-stdio
|
|
43
|
+
`rrr-search` was preferred over the hosted path. This release makes the
|
|
44
|
+
hosted path the default for conceptual code exploration across all RRR
|
|
45
|
+
slash commands, while preserving grep for the cases it's best at.
|
|
46
|
+
|
|
47
|
+
Other repos adopting RRR get `hosted-setup` as a one-step wizard instead
|
|
48
|
+
of the manual `claude mcp add` + `.rrr-search.json` + GitHub App dance
|
|
49
|
+
documented in `docs/ONBOARDING.md`.
|
|
50
|
+
|
|
7
51
|
## [1.21.3] - 2026-04-18
|
|
8
52
|
|
|
9
53
|
**Phase 78 D.5 dogfood — real measurements + onboarding for other repos.**
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* bin/hosted-setup.js — one-command wizard for hosted-search onboarding.
|
|
4
|
+
*
|
|
5
|
+
* Walks a user through:
|
|
6
|
+
* 1. Prerequisite check (claude CLI, git repo, Node 18+)
|
|
7
|
+
* 2. Bearer token capture (paste OR link to admin)
|
|
8
|
+
* 3. Team + repo identity (team_id prompt, slug from dir name, root_sha from git)
|
|
9
|
+
* 4. .rrr-search.json creation (if missing)
|
|
10
|
+
* 5. `claude mcp add` for rrr-search-hosted
|
|
11
|
+
* 6. GitHub App install link (open in browser)
|
|
12
|
+
* 7. Optional: trigger first index via MCP tool (prints curl command)
|
|
13
|
+
*
|
|
14
|
+
* Re-entrant: skips completed steps. Idempotent.
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* npx projecta-rrr hosted-setup
|
|
18
|
+
* OR: rrr-hosted-setup (if globally installed)
|
|
19
|
+
*
|
|
20
|
+
* No-interactive mode (for CI):
|
|
21
|
+
* projecta-rrr hosted-setup --team my-team --bearer rrr_... --repo-slug my-repo --yes
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const fs = require('fs');
|
|
25
|
+
const path = require('path');
|
|
26
|
+
const readline = require('readline');
|
|
27
|
+
const { execSync, spawnSync } = require('child_process');
|
|
28
|
+
|
|
29
|
+
const HOSTED_URL = 'https://rrr-search-hosted.fly.dev/mcp';
|
|
30
|
+
const GH_APP_INSTALL_URL = 'https://github.com/apps/rrr-search/installations/new';
|
|
31
|
+
const MCP_NAME = 'rrr-search-hosted';
|
|
32
|
+
|
|
33
|
+
// ──────────────────────────────── UI ──────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
const COLOR = process.stdout.isTTY;
|
|
36
|
+
const c = {
|
|
37
|
+
dim: s => COLOR ? `\x1b[2m${s}\x1b[0m` : s,
|
|
38
|
+
bold: s => COLOR ? `\x1b[1m${s}\x1b[0m` : s,
|
|
39
|
+
green: s => COLOR ? `\x1b[32m${s}\x1b[0m` : s,
|
|
40
|
+
yellow: s => COLOR ? `\x1b[33m${s}\x1b[0m` : s,
|
|
41
|
+
red: s => COLOR ? `\x1b[31m${s}\x1b[0m` : s,
|
|
42
|
+
cyan: s => COLOR ? `\x1b[36m${s}\x1b[0m` : s
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function banner (text) {
|
|
46
|
+
const bar = '━'.repeat(65);
|
|
47
|
+
console.log(c.cyan(bar));
|
|
48
|
+
console.log(c.bold(c.cyan(` ${text}`)));
|
|
49
|
+
console.log(c.cyan(bar));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function step (n, total, title) {
|
|
53
|
+
console.log();
|
|
54
|
+
console.log(c.bold(`Step ${n}/${total}: ${title}`));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function ok (msg) { console.log(` ${c.green('✓')} ${msg}`); }
|
|
58
|
+
function warn (msg) { console.log(` ${c.yellow('⚠')} ${msg}`); }
|
|
59
|
+
function err (msg) { console.log(` ${c.red('✗')} ${msg}`); }
|
|
60
|
+
function info (msg) { console.log(` ${c.dim(msg)}`); }
|
|
61
|
+
|
|
62
|
+
async function prompt (rl, question) {
|
|
63
|
+
return new Promise(resolve => rl.question(` ${c.bold('?')} ${question} `, resolve));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ──────────────────────────────── args ────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
function parseArgs (argv) {
|
|
69
|
+
const out = { team: null, bearer: null, repoSlug: null, yes: false, skipIndex: false };
|
|
70
|
+
for (let i = 0; i < argv.length; i++) {
|
|
71
|
+
const a = argv[i];
|
|
72
|
+
if (a === '--team') out.team = argv[++i];
|
|
73
|
+
else if (a === '--bearer') out.bearer = argv[++i];
|
|
74
|
+
else if (a === '--repo-slug') out.repoSlug = argv[++i];
|
|
75
|
+
else if (a === '--yes' || a === '-y') out.yes = true;
|
|
76
|
+
else if (a === '--skip-index') out.skipIndex = true;
|
|
77
|
+
else if (a === '-h' || a === '--help') {
|
|
78
|
+
console.log(`Usage: projecta-rrr hosted-setup [--team X] [--bearer rrr_...] [--repo-slug X] [--yes] [--skip-index]`);
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ──────────────────────────────── checks ──────────────────────────────────
|
|
86
|
+
|
|
87
|
+
function which (cmd) {
|
|
88
|
+
try {
|
|
89
|
+
execSync(`command -v ${cmd}`, { stdio: 'pipe' });
|
|
90
|
+
return true;
|
|
91
|
+
} catch { return false; }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function gitRootSha (cwd) {
|
|
95
|
+
try {
|
|
96
|
+
const out = execSync('git rev-list --max-parents=0 HEAD', { cwd, stdio: 'pipe' }).toString().trim().split('\n')[0];
|
|
97
|
+
if (!/^[a-f0-9]{40}$/.test(out)) return null;
|
|
98
|
+
return out;
|
|
99
|
+
} catch { return null; }
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function gitRemoteOwnerRepo (cwd) {
|
|
103
|
+
try {
|
|
104
|
+
const url = execSync('git config --get remote.origin.url', { cwd, stdio: 'pipe' }).toString().trim();
|
|
105
|
+
const m = url.match(/[:/]([^/:]+)\/([^/:.]+?)(?:\.git)?$/);
|
|
106
|
+
if (!m) return null;
|
|
107
|
+
return { owner: m[1], repo: m[2] };
|
|
108
|
+
} catch { return null; }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function mcpAlreadyRegistered (name) {
|
|
112
|
+
try {
|
|
113
|
+
const out = execSync('claude mcp list', { stdio: 'pipe' }).toString();
|
|
114
|
+
return out.includes(name + ':');
|
|
115
|
+
} catch { return false; }
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ──────────────────────────────── flow ────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
async function main () {
|
|
121
|
+
const args = parseArgs(process.argv.slice(2));
|
|
122
|
+
const cwd = process.cwd();
|
|
123
|
+
const TOTAL_STEPS = 6;
|
|
124
|
+
|
|
125
|
+
banner(` rrr-search-hosted setup — ${path.basename(cwd)}`);
|
|
126
|
+
|
|
127
|
+
// ---------- Step 1: prerequisites ----------
|
|
128
|
+
step(1, TOTAL_STEPS, 'Prerequisites');
|
|
129
|
+
let ready = true;
|
|
130
|
+
|
|
131
|
+
if (which('claude')) ok('Claude Code CLI installed');
|
|
132
|
+
else { err('Claude Code CLI (`claude`) not found on PATH'); ready = false; }
|
|
133
|
+
|
|
134
|
+
if (fs.existsSync(path.join(cwd, '.git'))) ok('In a git repo');
|
|
135
|
+
else { err('Not in a git repo — `cd` into your project root first'); ready = false; }
|
|
136
|
+
|
|
137
|
+
const nodeMaj = Number(process.versions.node.split('.')[0]);
|
|
138
|
+
if (nodeMaj >= 18) ok(`Node ${process.versions.node}`);
|
|
139
|
+
else { err(`Node ${process.versions.node} (need ≥18)`); ready = false; }
|
|
140
|
+
|
|
141
|
+
if (mcpAlreadyRegistered(MCP_NAME)) {
|
|
142
|
+
warn(`${MCP_NAME} already registered in Claude Code — will re-validate`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!ready) { console.log(); err('Fix above and re-run.'); process.exit(1); }
|
|
146
|
+
|
|
147
|
+
// ---------- Step 2: bearer token ----------
|
|
148
|
+
step(2, TOTAL_STEPS, 'Team bearer token');
|
|
149
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
150
|
+
|
|
151
|
+
let bearer = args.bearer || process.env.RRR_HOSTED_MCP_TOKEN || null;
|
|
152
|
+
if (!bearer && !args.yes) {
|
|
153
|
+
info('You need a bearer token of the form: rrr_<prefix>_<32chars>');
|
|
154
|
+
info('New team? Ask your rrr-search admin to run:');
|
|
155
|
+
info(' node rrr/hosted-mcp/scripts/issue-team-token.mjs <team-id>');
|
|
156
|
+
console.log();
|
|
157
|
+
bearer = (await prompt(rl, 'Paste bearer (or blank to skip MCP registration):')).trim() || null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (bearer) {
|
|
161
|
+
if (!/^rrr_[a-z0-9]{1,16}_[A-Za-z0-9]{32}$/.test(bearer)) {
|
|
162
|
+
rl.close();
|
|
163
|
+
err('Bearer format invalid. Expected rrr_<prefix>_<32chars>.');
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
ok(`Bearer captured (team prefix: ${bearer.split('_')[1]})`);
|
|
167
|
+
} else {
|
|
168
|
+
warn('No bearer — skipping MCP registration. You can run this wizard again after getting one.');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ---------- Step 3: team + repo identity ----------
|
|
172
|
+
step(3, TOTAL_STEPS, 'Team + repo identity');
|
|
173
|
+
|
|
174
|
+
const rootSha = gitRootSha(cwd);
|
|
175
|
+
if (!rootSha) { rl.close(); err('Could not read git root commit'); process.exit(1); }
|
|
176
|
+
const rootSha12 = rootSha.slice(0, 12);
|
|
177
|
+
ok(`root_sha (first 12): ${rootSha12}`);
|
|
178
|
+
|
|
179
|
+
const remote = gitRemoteOwnerRepo(cwd);
|
|
180
|
+
if (remote) info(`Remote: ${remote.owner}/${remote.repo}`);
|
|
181
|
+
|
|
182
|
+
let teamId = args.team;
|
|
183
|
+
if (!teamId) {
|
|
184
|
+
const default_ = remote?.owner?.toLowerCase()?.replace(/[^a-z0-9-]/g, '-') || 'my-team';
|
|
185
|
+
if (!args.yes) {
|
|
186
|
+
teamId = (await prompt(rl, `team_id [${default_}]:`)).trim() || default_;
|
|
187
|
+
} else teamId = default_;
|
|
188
|
+
}
|
|
189
|
+
ok(`team_id: ${teamId}`);
|
|
190
|
+
|
|
191
|
+
let repoSlug = args.repoSlug || remote?.repo || path.basename(cwd);
|
|
192
|
+
if (!args.yes) {
|
|
193
|
+
const ans = (await prompt(rl, `slug [${repoSlug}]:`)).trim();
|
|
194
|
+
if (ans) repoSlug = ans;
|
|
195
|
+
}
|
|
196
|
+
ok(`slug: ${repoSlug}`);
|
|
197
|
+
|
|
198
|
+
const repoId = `${teamId}:${repoSlug}:${rootSha12}`;
|
|
199
|
+
info(`repo_id: ${repoId}`);
|
|
200
|
+
|
|
201
|
+
// ---------- Step 4: .rrr-search.json ----------
|
|
202
|
+
step(4, TOTAL_STEPS, '.rrr-search.json');
|
|
203
|
+
|
|
204
|
+
const cfgPath = path.join(cwd, '.rrr-search.json');
|
|
205
|
+
if (fs.existsSync(cfgPath)) {
|
|
206
|
+
ok(`.rrr-search.json exists — leaving as-is`);
|
|
207
|
+
} else {
|
|
208
|
+
const cfg = {
|
|
209
|
+
team_id: teamId,
|
|
210
|
+
slug: repoSlug,
|
|
211
|
+
root_sha: rootSha,
|
|
212
|
+
budget_tokens: 10_000_000,
|
|
213
|
+
deny_extra: []
|
|
214
|
+
};
|
|
215
|
+
fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + '\n');
|
|
216
|
+
ok(`Wrote .rrr-search.json (budget 10M tokens, no extra deny globs)`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ---------- Step 5: register MCP ----------
|
|
220
|
+
step(5, TOTAL_STEPS, 'Register MCP in Claude Code');
|
|
221
|
+
|
|
222
|
+
if (!bearer) {
|
|
223
|
+
warn('Skipping (no bearer).');
|
|
224
|
+
} else {
|
|
225
|
+
if (mcpAlreadyRegistered(MCP_NAME)) {
|
|
226
|
+
info('Removing existing registration to re-register with current bearer');
|
|
227
|
+
try { execSync(`claude mcp remove ${MCP_NAME}`, { stdio: 'pipe' }); } catch { /* ignore */ }
|
|
228
|
+
}
|
|
229
|
+
const res = spawnSync('claude', [
|
|
230
|
+
'mcp', 'add', '--transport', 'http', MCP_NAME, HOSTED_URL,
|
|
231
|
+
'--header', `Authorization: Bearer ${bearer}`
|
|
232
|
+
], { stdio: 'pipe' });
|
|
233
|
+
if (res.status === 0) ok(`Registered ${MCP_NAME}`);
|
|
234
|
+
else {
|
|
235
|
+
err(`claude mcp add failed (exit ${res.status})`);
|
|
236
|
+
console.log(res.stderr?.toString() || res.stdout?.toString() || '');
|
|
237
|
+
rl.close();
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
// Verify connection
|
|
241
|
+
try {
|
|
242
|
+
const list = execSync('claude mcp list', { stdio: 'pipe' }).toString();
|
|
243
|
+
if (list.includes(`${MCP_NAME}:`) && /Connected|✓/.test(list)) {
|
|
244
|
+
ok('MCP connection verified');
|
|
245
|
+
} else {
|
|
246
|
+
warn(`Registered but health check inconclusive — run: claude mcp list`);
|
|
247
|
+
}
|
|
248
|
+
} catch { warn('Health check skipped'); }
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// ---------- Step 6: GitHub App + first index ----------
|
|
252
|
+
step(6, TOTAL_STEPS, 'GitHub App + first index');
|
|
253
|
+
console.log();
|
|
254
|
+
console.log(c.bold(' Install GitHub App (required for ingest):'));
|
|
255
|
+
console.log(c.cyan(` ${GH_APP_INSTALL_URL}`));
|
|
256
|
+
console.log();
|
|
257
|
+
info('After installing, note the installation_id (URL: .../installations/<ID>)');
|
|
258
|
+
info(`Then queue first index via MCP tool (with bearer):`);
|
|
259
|
+
console.log(c.dim(` mcp__${MCP_NAME}__index_repo({`));
|
|
260
|
+
console.log(c.dim(` git_url: "https://github.com/${remote?.owner || '<OWNER>'}/${remote?.repo || '<REPO>'}.git",`));
|
|
261
|
+
console.log(c.dim(` team_id: "${teamId}",`));
|
|
262
|
+
console.log(c.dim(` slug: "${repoSlug}",`));
|
|
263
|
+
console.log(c.dim(` installation_id: <ID>`));
|
|
264
|
+
console.log(c.dim(` })`));
|
|
265
|
+
|
|
266
|
+
rl.close();
|
|
267
|
+
console.log();
|
|
268
|
+
banner(' Done.');
|
|
269
|
+
console.log(` ${c.green('→')} Restart Claude Code session (/clear) so MCP tools reload.`);
|
|
270
|
+
console.log(` ${c.green('→')} In a new session, agents can call ${c.bold('mcp__rrr-search-hosted__semantic_search')}.`);
|
|
271
|
+
console.log(` ${c.dim('Docs: docs/ONBOARDING.md · Troubleshooting: docs/hosted-search-setup.md')}`);
|
|
272
|
+
console.log();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
main().catch(e => { console.error(c.red('Fatal:'), e.message); process.exit(1); });
|
package/bin/install.js
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// Subcommand dispatch — v1.21.4+. Routes `projecta-rrr <sub> ...` to
|
|
4
|
+
// dedicated scripts. Empty / --hud-only / --global fall through to the
|
|
5
|
+
// default install flow below for back-compat.
|
|
6
|
+
(function dispatch () {
|
|
7
|
+
const sub = process.argv[2];
|
|
8
|
+
if (sub === 'hosted-setup') {
|
|
9
|
+
require('./hosted-setup.js');
|
|
10
|
+
return; // the required script runs main() immediately
|
|
11
|
+
}
|
|
12
|
+
// Fall through — default RRR install.
|
|
13
|
+
})();
|
|
14
|
+
|
|
15
|
+
// If the subcommand already took over (e.g. hosted-setup ended the process),
|
|
16
|
+
// the lines below never execute. If we're on the default install path,
|
|
17
|
+
// continue as before.
|
|
18
|
+
if (process.argv[2] === 'hosted-setup') return;
|
|
19
|
+
|
|
3
20
|
const fs = require('fs');
|
|
4
21
|
const path = require('path');
|
|
5
22
|
const os = require('os');
|
|
@@ -2465,6 +2482,21 @@ ${optimizationNote}
|
|
|
2465
2482
|
|
|
2466
2483
|
Run ${cyan}/rrr:help${reset} anytime to see all commands.
|
|
2467
2484
|
`);
|
|
2485
|
+
|
|
2486
|
+
// v1.21.4+: nudge for hosted semantic search if not yet set up in cwd.
|
|
2487
|
+
try {
|
|
2488
|
+
const cwd = process.cwd();
|
|
2489
|
+
const inGit = fs.existsSync(path.join(cwd, '.git'));
|
|
2490
|
+
const hasRrrConfig = fs.existsSync(path.join(cwd, '.rrr-search.json'));
|
|
2491
|
+
if (inGit && !hasRrrConfig) {
|
|
2492
|
+
console.log(` ${cyan}━━━ v1.21 Hosted Semantic Search available ━━━${reset}
|
|
2493
|
+
${dim}99% token savings vs grep on exploration queries.${reset}
|
|
2494
|
+
${dim}One-minute wizard walks you through setup:${reset}
|
|
2495
|
+
${green}projecta-rrr hosted-setup${reset}
|
|
2496
|
+
${dim}Or read docs/ONBOARDING.md for the manual path.${reset}
|
|
2497
|
+
`);
|
|
2498
|
+
}
|
|
2499
|
+
} catch { /* never block install on nudge */ }
|
|
2468
2500
|
}
|
|
2469
2501
|
|
|
2470
2502
|
/**
|
|
@@ -21,6 +21,7 @@ Extract implementation decisions that downstream agents need — researcher and
|
|
|
21
21
|
@~/.claude/rrr/references/principles.md
|
|
22
22
|
@~/.claude/rrr/workflows/discuss-phase.md
|
|
23
23
|
@~/.claude/rrr/templates/context.md
|
|
24
|
+
@rrr/references/semantic-search-preference.md
|
|
24
25
|
</execution_context>
|
|
25
26
|
|
|
26
27
|
<context>
|
|
@@ -29,6 +29,7 @@ When `--auto` flag is passed, chains discuss-plan-execute automatically for the
|
|
|
29
29
|
@~/.claude/rrr/references/ui-brand.md
|
|
30
30
|
@~/.claude/rrr/workflows/execute-phase.md
|
|
31
31
|
@rrr/lib/phase-paths.md
|
|
32
|
+
@rrr/references/semantic-search-preference.md
|
|
32
33
|
</execution_context>
|
|
33
34
|
|
|
34
35
|
<context>
|
package/commands/rrr/progress.md
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projecta-rrr",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.4",
|
|
4
4
|
"description": "A meta-prompting, context engineering and spec-driven development system for Claude Code by Projecta.ai",
|
|
5
5
|
"bin": {
|
|
6
|
-
"projecta-rrr": "bin/install.js"
|
|
6
|
+
"projecta-rrr": "bin/install.js",
|
|
7
|
+
"projecta-rrr-hosted-setup": "bin/hosted-setup.js"
|
|
7
8
|
},
|
|
8
9
|
"scripts": {
|
|
9
10
|
"postinstall": "node bin/install.js --hud-only --global && node scripts/register-mcp.js",
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Semantic Search Preference (v1.21+)
|
|
2
|
+
|
|
3
|
+
**Include this via `@rrr/references/semantic-search-preference.md` in slash-command execution contexts.**
|
|
4
|
+
|
|
5
|
+
## Rule
|
|
6
|
+
|
|
7
|
+
When exploring the codebase to answer "what does X do?", "where is Y configured?", or "how does Z work?":
|
|
8
|
+
|
|
9
|
+
1. **If `mcp__rrr-search-hosted__semantic_search` is available** (check via tool list): use it FIRST.
|
|
10
|
+
- Pass `repo_id` for this repo (format: `{team_id}:{slug}:{root_sha12}`; see `.rrr-search.json`).
|
|
11
|
+
- Set `k=5` for broad queries, `k=10` for deep dives.
|
|
12
|
+
- Follow-up with `Read` on the returned file paths if you need full context.
|
|
13
|
+
|
|
14
|
+
2. **If `mcp__rrr-search__semantic_search` is available** (local stdio fallback): use it second.
|
|
15
|
+
|
|
16
|
+
3. **Grep/ripgrep** only for **exact identifier lookups** (e.g., `grep "^function foo"`, `rg '\bFOO_CONSTANT\b'`) — NOT for concept exploration.
|
|
17
|
+
|
|
18
|
+
4. **Read full files** only after semantic search has narrowed the target.
|
|
19
|
+
|
|
20
|
+
## Why
|
|
21
|
+
|
|
22
|
+
- **Token cost:** semantic_search returns 3-10 ranked chunks (~500 tokens). Grep returns hundreds of lines (~10K tokens). Read on a 500-line file burns ~10K tokens.
|
|
23
|
+
- **Relevance:** semantic_search ranks by cosine similarity + RRF fusion with ripgrep; grep returns alphabetically.
|
|
24
|
+
- **Cross-file synthesis:** top-K often spans multiple files — one call answers "how X works" that would otherwise need 3-5 greps.
|
|
25
|
+
|
|
26
|
+
## Discovery
|
|
27
|
+
|
|
28
|
+
Check availability once at workflow start:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
claude mcp list 2>&1 | grep -E "rrr-search-hosted|rrr-search:" | head -2
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or via tool list in the current session (tools prefixed with `mcp__rrr-search-hosted__` or `mcp__rrr-search__` are signals).
|
|
35
|
+
|
|
36
|
+
## Fallback
|
|
37
|
+
|
|
38
|
+
If neither is registered: proceed with Grep/Read as before. The v1.21 hosted path is additive — it doesn't break local-only workflows.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
*Referenced by: /rrr:progress, /rrr:plan-phase, /rrr:execute-phase, /rrr:discuss-phase, /rrr:verify-work (v1.21.4+).*
|