greprag 5.6.2 → 5.8.1
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/dist/commands/lore.d.ts +28 -0
- package/dist/commands/lore.js +357 -0
- package/dist/commands/lore.js.map +1 -0
- package/dist/hook.d.ts +17 -1
- package/dist/hook.js +151 -17
- package/dist/hook.js.map +1 -1
- package/dist/index.js +19 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skill/greprag/SKILL.md +19 -19
- package/skill/lore-advisor/SKILL.md +183 -0
- package/skill/templates/chip-spawn.md +16 -8
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** greprag lore — per-project LEARNINGS substrate.
|
|
2
|
+
*
|
|
3
|
+
* Lore = what was learned (Old English `lār`). Project-specific emergent
|
|
4
|
+
* knowledge — discovered constraints, gotchas, tribal knowledge that drifts
|
|
5
|
+
* as the codebase evolves. Reviewed via /lore-advisor. Distinct from static
|
|
6
|
+
* project knowledge (which lives in CLAUDE.md / docs / code structure).
|
|
7
|
+
*
|
|
8
|
+
* Pull-based: agents seed lore they wish a future spawned chip had known;
|
|
9
|
+
* future chips query the relevant scope at spawn time and skip the
|
|
10
|
+
* discovery they would otherwise repeat. All server work delegates to
|
|
11
|
+
* FactsService in @greprag/core via /v1/facts/:projectId — the CLI is a
|
|
12
|
+
* thin HTTP printer + project resolver.
|
|
13
|
+
*
|
|
14
|
+
* Note: the server-side route + DB column stay named `facts` (internal —
|
|
15
|
+
* surface-only rename in v5.7.0). The CLI maps `lore` commands to `facts` URLs.
|
|
16
|
+
*
|
|
17
|
+
* Subcommands:
|
|
18
|
+
* add "<text>" --scope <S> [--project <name>] [--source-session <id>]
|
|
19
|
+
* query [--scope <S>] [--query "<intent>"] [--project <name>]
|
|
20
|
+
* [--limit <N=10>] [--format markdown|json]
|
|
21
|
+
* list [--project <name>] [--format markdown|json]
|
|
22
|
+
* delete <nodeId> [--project <name>]
|
|
23
|
+
* scopes [--project <name>]
|
|
24
|
+
*
|
|
25
|
+
* Project resolution: without --project, uses the current cwd's project
|
|
26
|
+
* anchor (readAnchor). With --project <name>, hits /v1/projects to
|
|
27
|
+
* resolve name → projectId (case-insensitive). */
|
|
28
|
+
export declare function runLore(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// adr: adr/lore-rename.md
|
|
3
|
+
/** greprag lore — per-project LEARNINGS substrate.
|
|
4
|
+
*
|
|
5
|
+
* Lore = what was learned (Old English `lār`). Project-specific emergent
|
|
6
|
+
* knowledge — discovered constraints, gotchas, tribal knowledge that drifts
|
|
7
|
+
* as the codebase evolves. Reviewed via /lore-advisor. Distinct from static
|
|
8
|
+
* project knowledge (which lives in CLAUDE.md / docs / code structure).
|
|
9
|
+
*
|
|
10
|
+
* Pull-based: agents seed lore they wish a future spawned chip had known;
|
|
11
|
+
* future chips query the relevant scope at spawn time and skip the
|
|
12
|
+
* discovery they would otherwise repeat. All server work delegates to
|
|
13
|
+
* FactsService in @greprag/core via /v1/facts/:projectId — the CLI is a
|
|
14
|
+
* thin HTTP printer + project resolver.
|
|
15
|
+
*
|
|
16
|
+
* Note: the server-side route + DB column stay named `facts` (internal —
|
|
17
|
+
* surface-only rename in v5.7.0). The CLI maps `lore` commands to `facts` URLs.
|
|
18
|
+
*
|
|
19
|
+
* Subcommands:
|
|
20
|
+
* add "<text>" --scope <S> [--project <name>] [--source-session <id>]
|
|
21
|
+
* query [--scope <S>] [--query "<intent>"] [--project <name>]
|
|
22
|
+
* [--limit <N=10>] [--format markdown|json]
|
|
23
|
+
* list [--project <name>] [--format markdown|json]
|
|
24
|
+
* delete <nodeId> [--project <name>]
|
|
25
|
+
* scopes [--project <name>]
|
|
26
|
+
*
|
|
27
|
+
* Project resolution: without --project, uses the current cwd's project
|
|
28
|
+
* anchor (readAnchor). With --project <name>, hits /v1/projects to
|
|
29
|
+
* resolve name → projectId (case-insensitive). */
|
|
30
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
31
|
+
if (k2 === undefined) k2 = k;
|
|
32
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
33
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
34
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
35
|
+
}
|
|
36
|
+
Object.defineProperty(o, k2, desc);
|
|
37
|
+
}) : (function(o, m, k, k2) {
|
|
38
|
+
if (k2 === undefined) k2 = k;
|
|
39
|
+
o[k2] = m[k];
|
|
40
|
+
}));
|
|
41
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
42
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
43
|
+
}) : function(o, v) {
|
|
44
|
+
o["default"] = v;
|
|
45
|
+
});
|
|
46
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
47
|
+
var ownKeys = function(o) {
|
|
48
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
49
|
+
var ar = [];
|
|
50
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
51
|
+
return ar;
|
|
52
|
+
};
|
|
53
|
+
return ownKeys(o);
|
|
54
|
+
};
|
|
55
|
+
return function (mod) {
|
|
56
|
+
if (mod && mod.__esModule) return mod;
|
|
57
|
+
var result = {};
|
|
58
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
59
|
+
__setModuleDefault(result, mod);
|
|
60
|
+
return result;
|
|
61
|
+
};
|
|
62
|
+
})();
|
|
63
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
64
|
+
exports.runLore = runLore;
|
|
65
|
+
const fs = __importStar(require("fs"));
|
|
66
|
+
const path = __importStar(require("path"));
|
|
67
|
+
const project_anchor_1 = require("../project-anchor");
|
|
68
|
+
const API_URL_DEFAULT = 'https://api.greprag.com';
|
|
69
|
+
// ---------- Config / env (mirrors corpus.ts) ------------------------------
|
|
70
|
+
function loadEnvFile(filePath) {
|
|
71
|
+
try {
|
|
72
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
73
|
+
for (const line of content.split('\n')) {
|
|
74
|
+
const trimmed = line.trim();
|
|
75
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
76
|
+
continue;
|
|
77
|
+
const eqIdx = trimmed.indexOf('=');
|
|
78
|
+
if (eqIdx < 1)
|
|
79
|
+
continue;
|
|
80
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
81
|
+
let value = trimmed.slice(eqIdx + 1).trim();
|
|
82
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
83
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
84
|
+
value = value.slice(1, -1);
|
|
85
|
+
}
|
|
86
|
+
if (!process.env[key])
|
|
87
|
+
process.env[key] = value;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch { /* file missing — fine */ }
|
|
91
|
+
}
|
|
92
|
+
function getConfig() {
|
|
93
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
94
|
+
if (homeDir)
|
|
95
|
+
loadEnvFile(path.join(homeDir, '.greprag', '.env'));
|
|
96
|
+
if (!process.env.GREPRAG_API_KEY)
|
|
97
|
+
loadEnvFile(path.join(process.cwd(), '.env'));
|
|
98
|
+
return {
|
|
99
|
+
apiUrl: process.env.GREPRAG_API_URL || API_URL_DEFAULT,
|
|
100
|
+
apiKey: process.env.GREPRAG_API_KEY || '',
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
async function apiCall(url, apiKey, body) {
|
|
104
|
+
const res = await fetch(url, {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
|
|
107
|
+
body: JSON.stringify(body),
|
|
108
|
+
});
|
|
109
|
+
if (!res.ok)
|
|
110
|
+
throw new Error(`API ${res.status}: ${await res.text()}`);
|
|
111
|
+
return res.json();
|
|
112
|
+
}
|
|
113
|
+
async function apiGet(url, apiKey) {
|
|
114
|
+
const res = await fetch(url, { headers: { 'Authorization': `Bearer ${apiKey}` } });
|
|
115
|
+
if (!res.ok)
|
|
116
|
+
throw new Error(`API ${res.status}: ${await res.text()}`);
|
|
117
|
+
return res.json();
|
|
118
|
+
}
|
|
119
|
+
async function apiDelete(url, apiKey) {
|
|
120
|
+
const res = await fetch(url, {
|
|
121
|
+
method: 'DELETE',
|
|
122
|
+
headers: { 'Authorization': `Bearer ${apiKey}` },
|
|
123
|
+
});
|
|
124
|
+
if (!res.ok)
|
|
125
|
+
throw new Error(`API ${res.status}: ${await res.text()}`);
|
|
126
|
+
return res.json();
|
|
127
|
+
}
|
|
128
|
+
// ---------- Helpers --------------------------------------------------------
|
|
129
|
+
function getFlag(args, flag) {
|
|
130
|
+
const idx = args.indexOf(flag);
|
|
131
|
+
if (idx === -1 || idx + 1 >= args.length)
|
|
132
|
+
return undefined;
|
|
133
|
+
return args[idx + 1];
|
|
134
|
+
}
|
|
135
|
+
function abortNotConfigured() {
|
|
136
|
+
console.error('Not configured. Run: greprag init');
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
/** Resolve which project a lore command operates on. --project <name> wins
|
|
140
|
+
* via the tenant's projects registry; otherwise the cwd's anchor decides. */
|
|
141
|
+
async function resolveProject(args, apiUrl, apiKey) {
|
|
142
|
+
const projectArg = getFlag(args, '--project');
|
|
143
|
+
if (!projectArg) {
|
|
144
|
+
const anchor = (0, project_anchor_1.readAnchor)(process.cwd());
|
|
145
|
+
return { projectId: anchor.projectId, projectName: anchor.projectName };
|
|
146
|
+
}
|
|
147
|
+
const r = await apiGet(`${apiUrl}/v1/projects`, apiKey);
|
|
148
|
+
const needle = projectArg.trim().toLowerCase();
|
|
149
|
+
const match = (r.projects || []).find(p => p.project_name.toLowerCase() === needle);
|
|
150
|
+
if (!match) {
|
|
151
|
+
throw new Error(`project "${projectArg}" not found under this tenant. ` +
|
|
152
|
+
`Register it via 'greprag init' in that directory, then retry.`);
|
|
153
|
+
}
|
|
154
|
+
return { projectId: match.project_id, projectName: match.project_name };
|
|
155
|
+
}
|
|
156
|
+
/** Try to read the current session's UUID from the harness env (Claude Code
|
|
157
|
+
* exposes it as CLAUDE_SESSION_ID on hook invocations). Falls back to
|
|
158
|
+
* undefined — callers should pass --source-session explicitly when they
|
|
159
|
+
* know it. */
|
|
160
|
+
function readSessionEnv() {
|
|
161
|
+
return process.env.CLAUDE_SESSION_ID || process.env.GREPRAG_SESSION_ID || null;
|
|
162
|
+
}
|
|
163
|
+
// ---------- add -----------------------------------------------------------
|
|
164
|
+
async function addCmd(args) {
|
|
165
|
+
const cfg = getConfig();
|
|
166
|
+
if (!cfg.apiKey)
|
|
167
|
+
abortNotConfigured();
|
|
168
|
+
const text = args[0];
|
|
169
|
+
if (!text || text.startsWith('--')) {
|
|
170
|
+
console.error('Usage: greprag lore add "<text>" --scope <scope> [--project <name>] [--source-session <id>]');
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
const scope = getFlag(args, '--scope');
|
|
174
|
+
if (!scope) {
|
|
175
|
+
console.error('Usage: greprag lore add "<text>" --scope <scope> [--project <name>]');
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
const sourceSession = getFlag(args, '--source-session') || readSessionEnv();
|
|
179
|
+
const { projectId, projectName } = await resolveProject(args, cfg.apiUrl, cfg.apiKey);
|
|
180
|
+
const result = await apiCall(`${cfg.apiUrl}/v1/facts/${projectId}`, cfg.apiKey, {
|
|
181
|
+
text, scope,
|
|
182
|
+
sourceSessionId: sourceSession,
|
|
183
|
+
projectName,
|
|
184
|
+
});
|
|
185
|
+
if (!result.ok || !result.nodeId)
|
|
186
|
+
throw new Error(result.error || 'add failed');
|
|
187
|
+
console.log(`Added lore [${result.nodeId}] scope=${scope} project=${projectName}`);
|
|
188
|
+
}
|
|
189
|
+
// ---------- query ---------------------------------------------------------
|
|
190
|
+
async function queryCmd(args) {
|
|
191
|
+
const cfg = getConfig();
|
|
192
|
+
if (!cfg.apiKey)
|
|
193
|
+
abortNotConfigured();
|
|
194
|
+
const scope = getFlag(args, '--scope');
|
|
195
|
+
const queryStr = getFlag(args, '--query');
|
|
196
|
+
const limit = parseInt(getFlag(args, '--limit') || '10', 10);
|
|
197
|
+
const format = (getFlag(args, '--format') || 'markdown').toLowerCase();
|
|
198
|
+
if (format !== 'markdown' && format !== 'json') {
|
|
199
|
+
console.error('--format must be markdown or json');
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
const { projectId, projectName } = await resolveProject(args, cfg.apiUrl, cfg.apiKey);
|
|
203
|
+
const params = new URLSearchParams();
|
|
204
|
+
if (scope)
|
|
205
|
+
params.set('scope', scope);
|
|
206
|
+
if (queryStr)
|
|
207
|
+
params.set('query', queryStr);
|
|
208
|
+
params.set('limit', String(limit));
|
|
209
|
+
const result = await apiGet(`${cfg.apiUrl}/v1/facts/${projectId}?${params.toString()}`, cfg.apiKey);
|
|
210
|
+
if (!result.ok || !result.facts)
|
|
211
|
+
throw new Error(result.error || 'query failed');
|
|
212
|
+
if (format === 'json') {
|
|
213
|
+
console.log(JSON.stringify({
|
|
214
|
+
project: projectName,
|
|
215
|
+
scope: scope ?? null,
|
|
216
|
+
query: queryStr ?? null,
|
|
217
|
+
lore: result.facts,
|
|
218
|
+
}, null, 2));
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (result.facts.length === 0) {
|
|
222
|
+
const scopeNote = scope ? ` (scope=${scope})` : '';
|
|
223
|
+
const queryNote = queryStr ? ` matching "${queryStr}"` : '';
|
|
224
|
+
console.log(`No lore in ${projectName}${scopeNote}${queryNote}.`);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
for (let i = 0; i < result.facts.length; i++) {
|
|
228
|
+
console.log(`${i + 1}. ${result.facts[i].text}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// ---------- list ----------------------------------------------------------
|
|
232
|
+
async function listCmd(args) {
|
|
233
|
+
const cfg = getConfig();
|
|
234
|
+
if (!cfg.apiKey)
|
|
235
|
+
abortNotConfigured();
|
|
236
|
+
const format = (getFlag(args, '--format') || 'text').toLowerCase();
|
|
237
|
+
if (format !== 'text' && format !== 'json' && format !== 'markdown') {
|
|
238
|
+
console.error('--format must be text, markdown, or json');
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
const { projectId, projectName } = await resolveProject(args, cfg.apiUrl, cfg.apiKey);
|
|
242
|
+
const result = await apiGet(`${cfg.apiUrl}/v1/facts/${projectId}/list`, cfg.apiKey);
|
|
243
|
+
if (!result.ok || !result.facts)
|
|
244
|
+
throw new Error(result.error || 'list failed');
|
|
245
|
+
if (format === 'json') {
|
|
246
|
+
console.log(JSON.stringify({
|
|
247
|
+
project: projectName,
|
|
248
|
+
lore: result.facts,
|
|
249
|
+
}, null, 2));
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (result.facts.length === 0) {
|
|
253
|
+
console.log(`No lore seeded in ${projectName} yet.`);
|
|
254
|
+
console.log('Add some: greprag lore add "<text>" --scope <scope>');
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
// Group by scope (server already orders scope ASC, createdAt DESC).
|
|
258
|
+
const grouped = new Map();
|
|
259
|
+
for (const f of result.facts) {
|
|
260
|
+
const scope = f.scope || '(no scope)';
|
|
261
|
+
if (!grouped.has(scope))
|
|
262
|
+
grouped.set(scope, []);
|
|
263
|
+
grouped.get(scope).push(f);
|
|
264
|
+
}
|
|
265
|
+
console.log(`\n${result.facts.length} lore entr${result.facts.length === 1 ? 'y' : 'ies'} in ${projectName}:\n`);
|
|
266
|
+
for (const [scope, rows] of grouped) {
|
|
267
|
+
console.log(`## ${scope} (${rows.length})`);
|
|
268
|
+
for (const f of rows) {
|
|
269
|
+
const date = f.createdAt ? f.createdAt.slice(0, 10) : '';
|
|
270
|
+
console.log(` [${f.nodeId}] ${date} ${f.text}`);
|
|
271
|
+
}
|
|
272
|
+
console.log('');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// ---------- delete --------------------------------------------------------
|
|
276
|
+
async function deleteCmd(args) {
|
|
277
|
+
const cfg = getConfig();
|
|
278
|
+
if (!cfg.apiKey)
|
|
279
|
+
abortNotConfigured();
|
|
280
|
+
const nodeId = args[0];
|
|
281
|
+
if (!nodeId || nodeId.startsWith('--')) {
|
|
282
|
+
console.error('Usage: greprag lore delete <nodeId> [--project <name>]');
|
|
283
|
+
process.exit(1);
|
|
284
|
+
}
|
|
285
|
+
if (!/^[0-9a-f]{8}$/i.test(nodeId)) {
|
|
286
|
+
console.error('nodeId must be 8 hex chars (printed in `greprag lore list`).');
|
|
287
|
+
process.exit(1);
|
|
288
|
+
}
|
|
289
|
+
const { projectId, projectName } = await resolveProject(args, cfg.apiUrl, cfg.apiKey);
|
|
290
|
+
const result = await apiDelete(`${cfg.apiUrl}/v1/facts/${projectId}/${nodeId}`, cfg.apiKey);
|
|
291
|
+
if (!result.ok)
|
|
292
|
+
throw new Error(result.error || 'delete failed');
|
|
293
|
+
console.log(`Deleted lore [${nodeId}] from ${projectName}`);
|
|
294
|
+
}
|
|
295
|
+
// ---------- scopes --------------------------------------------------------
|
|
296
|
+
async function scopesCmd(args) {
|
|
297
|
+
const cfg = getConfig();
|
|
298
|
+
if (!cfg.apiKey)
|
|
299
|
+
abortNotConfigured();
|
|
300
|
+
const { projectId, projectName } = await resolveProject(args, cfg.apiUrl, cfg.apiKey);
|
|
301
|
+
const result = await apiGet(`${cfg.apiUrl}/v1/facts/${projectId}/scopes`, cfg.apiKey);
|
|
302
|
+
if (!result.ok || !result.scopes)
|
|
303
|
+
throw new Error(result.error || 'scopes failed');
|
|
304
|
+
if (result.scopes.length === 0) {
|
|
305
|
+
console.log(`No scopes in ${projectName} yet.`);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
for (const s of result.scopes)
|
|
309
|
+
console.log(s);
|
|
310
|
+
}
|
|
311
|
+
// ---------- Dispatch ------------------------------------------------------
|
|
312
|
+
const SUB_HELP = `
|
|
313
|
+
greprag lore — per-project LEARNINGS substrate.
|
|
314
|
+
|
|
315
|
+
Subcommands:
|
|
316
|
+
add "<text>" --scope <S> [--project <name>] [--source-session <id>]
|
|
317
|
+
Append a new lore entry under the given scope.
|
|
318
|
+
query [--scope <S>] [--query "<intent>"] [--project <name>]
|
|
319
|
+
[--limit N=10] [--format markdown|json]
|
|
320
|
+
Read lore. With --query, lexical-rank by
|
|
321
|
+
relevance. Without, most recent first.
|
|
322
|
+
list [--project <name>] [--format markdown|json]
|
|
323
|
+
Every lore entry grouped by scope (for review).
|
|
324
|
+
delete <nodeId> [--project <name>]
|
|
325
|
+
Drop one lore entry by its 8-char nodeId.
|
|
326
|
+
scopes [--project <name>] Distinct scope labels present in this project.
|
|
327
|
+
|
|
328
|
+
Examples:
|
|
329
|
+
greprag lore add "Migrations live at repo root, not packages/api/migrations." --scope chip-startup
|
|
330
|
+
greprag lore query --scope chip-startup --limit 10 --format markdown
|
|
331
|
+
greprag lore query --query "where do migrations live" --limit 5
|
|
332
|
+
greprag lore list
|
|
333
|
+
greprag lore delete a3f2c1d4
|
|
334
|
+
greprag lore scopes
|
|
335
|
+
`.trim();
|
|
336
|
+
async function runLore(args) {
|
|
337
|
+
const sub = args[0];
|
|
338
|
+
const rest = args.slice(1);
|
|
339
|
+
switch (sub) {
|
|
340
|
+
case 'add': return addCmd(rest);
|
|
341
|
+
case 'query': return queryCmd(rest);
|
|
342
|
+
case 'list': return listCmd(rest);
|
|
343
|
+
case 'delete': return deleteCmd(rest);
|
|
344
|
+
case 'scopes': return scopesCmd(rest);
|
|
345
|
+
case undefined:
|
|
346
|
+
case 'help':
|
|
347
|
+
case '--help':
|
|
348
|
+
case '-h':
|
|
349
|
+
console.log(SUB_HELP);
|
|
350
|
+
return;
|
|
351
|
+
default:
|
|
352
|
+
console.error(`Unknown subcommand: ${sub}\n`);
|
|
353
|
+
console.log(SUB_HELP);
|
|
354
|
+
process.exit(1);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
//# sourceMappingURL=lore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lore.js","sourceRoot":"","sources":["../../src/commands/lore.ts"],"names":[],"mappings":"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"}
|
package/dist/hook.d.ts
CHANGED
|
@@ -5,4 +5,20 @@
|
|
|
5
5
|
* /v1/memory/turn. No LLM, no enrichment — the API just inserts the row.
|
|
6
6
|
* See C:/greprag/docs/episodic-memory.md.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
/** Derive a chip slug from the title. Strip the `Chip: ` prefix, lowercase,
|
|
9
|
+
* replace non-alphanumeric runs with `-`, trim leading/trailing dashes.
|
|
10
|
+
* `Chip: Fix synthesis loop` → `fix-synthesis-loop`. */
|
|
11
|
+
export declare function deriveSlugFromTitle(title: string): string;
|
|
12
|
+
/** Returns true when the prompt is "new-style" — neither Block 1 nor Block 2
|
|
13
|
+
* evidence is present, so the hook should auto-inject both. Old-style
|
|
14
|
+
* prompts (anything containing `git worktree add` or `greprag send`) pass
|
|
15
|
+
* through unchanged for back-compat. */
|
|
16
|
+
export declare function isNewStylePrompt(prompt: string): boolean;
|
|
17
|
+
/** Augment a new-style prompt: prepend Block 1, append Block 2.
|
|
18
|
+
* Returns the same prompt when slug derivation produces an empty string
|
|
19
|
+
* (e.g. title is just `Chip: ` with no verb phrase) — validation then
|
|
20
|
+
* rejects with a clean "missing worktree" message. */
|
|
21
|
+
export declare function augmentPrompt(title: string, prompt: string): string;
|
|
22
|
+
/** Substitute Tier 1 placeholders in the prompt. Best-effort: missing
|
|
23
|
+
* values leave the placeholder in for loud chip-runtime failure. */
|
|
24
|
+
export declare function substitutePlaceholders(prompt: string, sessionId: string | undefined, alias: string | null): string;
|
package/dist/hook.js
CHANGED
|
@@ -40,6 +40,10 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
40
40
|
};
|
|
41
41
|
})();
|
|
42
42
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.deriveSlugFromTitle = deriveSlugFromTitle;
|
|
44
|
+
exports.isNewStylePrompt = isNewStylePrompt;
|
|
45
|
+
exports.augmentPrompt = augmentPrompt;
|
|
46
|
+
exports.substitutePlaceholders = substitutePlaceholders;
|
|
43
47
|
const path = __importStar(require("path"));
|
|
44
48
|
const fs = __importStar(require("fs"));
|
|
45
49
|
const crypto = __importStar(require("crypto"));
|
|
@@ -1010,11 +1014,104 @@ async function notify(_input) {
|
|
|
1010
1014
|
// Intentional no-op. See docstring above.
|
|
1011
1015
|
return;
|
|
1012
1016
|
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1017
|
+
/** Derive a chip slug from the title. Strip the `Chip: ` prefix, lowercase,
|
|
1018
|
+
* replace non-alphanumeric runs with `-`, trim leading/trailing dashes.
|
|
1019
|
+
* `Chip: Fix synthesis loop` → `fix-synthesis-loop`. */
|
|
1020
|
+
function deriveSlugFromTitle(title) {
|
|
1021
|
+
return title
|
|
1022
|
+
.replace(/^Chip:\s*/, '')
|
|
1023
|
+
.toLowerCase()
|
|
1024
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
1025
|
+
.replace(/^-+|-+$/g, '');
|
|
1026
|
+
}
|
|
1027
|
+
/** Read the cached identity handle. Returns the alias part (before `@`) so
|
|
1028
|
+
* it can be substituted in `<handle>@greprag.com/<id>` templates without
|
|
1029
|
+
* doubling the domain. Returns null on any read/parse error — caller leaves
|
|
1030
|
+
* the placeholder in for loud runtime failure. */
|
|
1031
|
+
function readIdentityAlias() {
|
|
1032
|
+
try {
|
|
1033
|
+
const home = process.env.HOME || process.env.USERPROFILE || '';
|
|
1034
|
+
if (!home)
|
|
1035
|
+
return null;
|
|
1036
|
+
const cachePath = path.join(home, '.greprag', 'identity.json');
|
|
1037
|
+
const raw = fs.readFileSync(cachePath, 'utf-8');
|
|
1038
|
+
const data = JSON.parse(raw);
|
|
1039
|
+
if (typeof data?.handle !== 'string' || !data.handle)
|
|
1040
|
+
return null;
|
|
1041
|
+
const at = data.handle.indexOf('@');
|
|
1042
|
+
return at > 0 ? data.handle.slice(0, at) : data.handle;
|
|
1043
|
+
}
|
|
1044
|
+
catch {
|
|
1045
|
+
return null;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
/** Build Block 1 (escape-to-root + worktree-add + parent-session-id ref).
|
|
1049
|
+
* Uses literal `<parent-session-id>` so Tier 1 substitution can replace it
|
|
1050
|
+
* later in a single uniform pass. */
|
|
1051
|
+
function buildBlock1(slug) {
|
|
1052
|
+
return ('**Setup — do this FIRST:**\n' +
|
|
1053
|
+
'\n' +
|
|
1054
|
+
'```bash\n' +
|
|
1055
|
+
'main_root=$(git rev-parse --git-common-dir | xargs dirname)\n' +
|
|
1056
|
+
'cd "$main_root"\n' +
|
|
1057
|
+
`git worktree add .claude/worktrees/${slug} -b chip/${slug}\n` +
|
|
1058
|
+
`cd .claude/worktrees/${slug}\n` +
|
|
1059
|
+
'```\n' +
|
|
1060
|
+
'\n' +
|
|
1061
|
+
'Your parent\'s session id is `<parent-session-id>`.\n' +
|
|
1062
|
+
'\n' +
|
|
1063
|
+
'---\n');
|
|
1064
|
+
}
|
|
1065
|
+
/** Build Block 2 (greprag send report-back + cleanup discipline).
|
|
1066
|
+
* Uses literal `<handle>` and `<parent-session-id>` for Tier 1 substitution. */
|
|
1067
|
+
function buildBlock2(slug) {
|
|
1068
|
+
return ('---\n' +
|
|
1069
|
+
'\n' +
|
|
1070
|
+
'**Block 2 — Report back via greprag inbox:**\n' +
|
|
1071
|
+
'\n' +
|
|
1072
|
+
'```bash\n' +
|
|
1073
|
+
`greprag send "<status>: <commit hash> on chip/${slug} — <one-line>" \\\n` +
|
|
1074
|
+
' --to <handle>@greprag.com/<parent-session-id> \\\n' +
|
|
1075
|
+
' --from-session <own-session-id> \\\n' +
|
|
1076
|
+
' --artifact commit:<hash>\n' +
|
|
1077
|
+
'```\n' +
|
|
1078
|
+
'\n' +
|
|
1079
|
+
'Substitute `<own-session-id>` from your SessionStart hook output.\n' +
|
|
1080
|
+
'\n' +
|
|
1081
|
+
'**Cleanup discipline (HARD RULE):** chip prompts forbid `git clean`, ' +
|
|
1082
|
+
'`git reset --hard`, `git worktree remove`, `git checkout <other>`, ' +
|
|
1083
|
+
'raw `rm -rf` outside the worktree\'s tracked files.\n');
|
|
1084
|
+
}
|
|
1085
|
+
/** Returns true when the prompt is "new-style" — neither Block 1 nor Block 2
|
|
1086
|
+
* evidence is present, so the hook should auto-inject both. Old-style
|
|
1087
|
+
* prompts (anything containing `git worktree add` or `greprag send`) pass
|
|
1088
|
+
* through unchanged for back-compat. */
|
|
1089
|
+
function isNewStylePrompt(prompt) {
|
|
1090
|
+
return !/\bgit\s+worktree\s+add\b/.test(prompt) &&
|
|
1091
|
+
!/\bgreprag\s+send\b/.test(prompt);
|
|
1092
|
+
}
|
|
1093
|
+
/** Augment a new-style prompt: prepend Block 1, append Block 2.
|
|
1094
|
+
* Returns the same prompt when slug derivation produces an empty string
|
|
1095
|
+
* (e.g. title is just `Chip: ` with no verb phrase) — validation then
|
|
1096
|
+
* rejects with a clean "missing worktree" message. */
|
|
1097
|
+
function augmentPrompt(title, prompt) {
|
|
1098
|
+
const slug = deriveSlugFromTitle(title);
|
|
1099
|
+
if (!slug)
|
|
1100
|
+
return prompt;
|
|
1101
|
+
return buildBlock1(slug) + '\n' + prompt + '\n\n' + buildBlock2(slug);
|
|
1102
|
+
}
|
|
1103
|
+
/** Substitute Tier 1 placeholders in the prompt. Best-effort: missing
|
|
1104
|
+
* values leave the placeholder in for loud chip-runtime failure. */
|
|
1105
|
+
function substitutePlaceholders(prompt, sessionId, alias) {
|
|
1106
|
+
let out = prompt;
|
|
1107
|
+
const short = (0, session_id_1.truncateSessionId)(sessionId);
|
|
1108
|
+
if (short)
|
|
1109
|
+
out = out.split('<parent-session-id>').join(short);
|
|
1110
|
+
if (alias)
|
|
1111
|
+
out = out.split('<handle>').join(alias);
|
|
1112
|
+
return out;
|
|
1113
|
+
}
|
|
1114
|
+
function validateChip(title, prompt) {
|
|
1018
1115
|
const violations = [];
|
|
1019
1116
|
if (!title.startsWith('Chip: ')) {
|
|
1020
1117
|
violations.push(`title "${title}" missing required "Chip: " prefix. ` +
|
|
@@ -1032,19 +1129,56 @@ function handlePreSpawnCheck(input) {
|
|
|
1032
1129
|
`\`greprag send "<status>: <commit> on chip/<slug>" --to <handle>@greprag.com/<parent-session-id> ` +
|
|
1033
1130
|
`--from-session <own-session-id> --artifact commit:<hash>\`.`);
|
|
1034
1131
|
}
|
|
1035
|
-
|
|
1132
|
+
return violations;
|
|
1133
|
+
}
|
|
1134
|
+
function handlePreSpawnCheck(input) {
|
|
1135
|
+
if (input.tool_name !== 'mcp__ccd_session__spawn_task')
|
|
1036
1136
|
return;
|
|
1037
|
-
const
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1137
|
+
const title = input.tool_input?.title ?? '';
|
|
1138
|
+
const originalPrompt = input.tool_input?.prompt ?? '';
|
|
1139
|
+
// Tier 2 — augment new-style minimal prompts.
|
|
1140
|
+
let prompt = isNewStylePrompt(originalPrompt)
|
|
1141
|
+
? augmentPrompt(title, originalPrompt)
|
|
1142
|
+
: originalPrompt;
|
|
1143
|
+
// Tier 1 — substitute placeholders (applies to augmented body AND any
|
|
1144
|
+
// placeholders the agent included in an old-style prompt).
|
|
1145
|
+
const alias = readIdentityAlias();
|
|
1146
|
+
prompt = substitutePlaceholders(prompt, input.session_id, alias);
|
|
1147
|
+
// Validate the final prompt. Augmented prompts should pass; old-style
|
|
1148
|
+
// prompts missing Block 1/2 still get a clean deny.
|
|
1149
|
+
const violations = validateChip(title, prompt);
|
|
1150
|
+
if (violations.length > 0) {
|
|
1151
|
+
const reason = `Chip prompt rejected by greprag PreToolUse validator. Fix the following and re-call spawn_task:\n - ` +
|
|
1152
|
+
violations.join('\n - ') +
|
|
1153
|
+
`\n\nFull conventions: ~/.claude/docs/chip-spawn.md.`;
|
|
1154
|
+
process.stdout.write(JSON.stringify({
|
|
1155
|
+
hookSpecificOutput: {
|
|
1156
|
+
hookEventName: 'PreToolUse',
|
|
1157
|
+
permissionDecision: 'deny',
|
|
1158
|
+
permissionDecisionReason: reason,
|
|
1159
|
+
},
|
|
1160
|
+
}) + '\n');
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
// Augmented or substituted — emit modifiedInput so the harness picks up
|
|
1164
|
+
// the rewritten prompt. Otherwise stay silent.
|
|
1165
|
+
if (prompt !== originalPrompt) {
|
|
1166
|
+
const modifiedInput = {
|
|
1167
|
+
title,
|
|
1168
|
+
prompt,
|
|
1169
|
+
};
|
|
1170
|
+
if (input.tool_input?.tldr !== undefined)
|
|
1171
|
+
modifiedInput.tldr = input.tool_input.tldr;
|
|
1172
|
+
if (input.tool_input?.cwd !== undefined)
|
|
1173
|
+
modifiedInput.cwd = input.tool_input.cwd;
|
|
1174
|
+
process.stdout.write(JSON.stringify({
|
|
1175
|
+
hookSpecificOutput: {
|
|
1176
|
+
hookEventName: 'PreToolUse',
|
|
1177
|
+
permissionDecision: 'allow',
|
|
1178
|
+
modifiedInput,
|
|
1179
|
+
},
|
|
1180
|
+
}) + '\n');
|
|
1181
|
+
}
|
|
1048
1182
|
}
|
|
1049
1183
|
async function main() {
|
|
1050
1184
|
const subcommand = process.argv[2];
|