greprag 5.84.0 → 5.85.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/agent-doctrine-file.js +5 -128
- package/dist/commands/agents.js +125 -846
- package/dist/commands/init.js +17 -29
- package/dist/commands/load.js +14 -36
- package/dist/commands/parity.js +1 -1
- package/dist/commands/skill-mirror-reminder.js +1 -18
- package/dist/commands/skill.js +137 -566
- package/dist/hook.js +30 -54
- package/dist/index.js +571 -573
- package/dist/native-adapter-refresh.js +15 -18
- package/dist/native-skill-mirror.js +11 -92
- package/dist/opencode-plugin.bundle.js +81 -283
- package/dist/skill-activation-manifest.js +14 -37
- package/dist/skill-git-ingest.js +300 -0
- package/dist/skill-landing.js +7 -173
- package/dist/skill-mirror-client.js +4 -280
- package/dist/skill-staleness.js +3 -6
- package/package.json +1 -1
- package/skill/mechanic/docs/skill-fix-conventions.md +1 -1
- package/skill/templates/os.md +1 -1
- package/skill/templates/prompt-audit.md +26 -49
- package/skill/templates/skill-change.md +15 -13
package/dist/commands/init.js
CHANGED
|
@@ -74,29 +74,20 @@ async function trySyncNativeSkillMirror(apiKey, platform, cwd = process.cwd()) {
|
|
|
74
74
|
return `Native skill mirror unavailable; existing skills preserved (${message})`;
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
|
|
77
|
+
/** Render the Codex/OpenCode AGENTS.md files from ~/.claude/CLAUDE.md (the git
|
|
78
|
+
* source) and say what happened. adr: adr/skill-ownership-git.md */
|
|
79
|
+
function renderInstructionsSummary() {
|
|
78
80
|
try {
|
|
79
|
-
|
|
81
|
+
const results = (0, agents_1.renderGlobalInstructions)();
|
|
82
|
+
if (results.every(r => r.status === 'no-source'))
|
|
83
|
+
return 'AGENTS.md render: no ~/.claude/CLAUDE.md yet';
|
|
84
|
+
const written = results.filter(r => r.status === 'written').length;
|
|
85
|
+
return written ? `AGENTS.md render: ${written} file(s) rewritten from ~/.claude/CLAUDE.md` : 'AGENTS.md render: current';
|
|
80
86
|
}
|
|
81
87
|
catch (error) {
|
|
82
|
-
|
|
83
|
-
console.warn(` GrepRAG Instructions materialization skipped: ${message}`);
|
|
84
|
-
return null;
|
|
88
|
+
return `AGENTS.md render skipped: ${error instanceof Error ? error.message : String(error)}`;
|
|
85
89
|
}
|
|
86
90
|
}
|
|
87
|
-
function doctrineBootstrapSummary(result) {
|
|
88
|
-
if (!result)
|
|
89
|
-
return 'GrepRAG Instructions: materialization unavailable; existing files preserved';
|
|
90
|
-
if (result.canonicalScopes.length === 0)
|
|
91
|
-
return 'GrepRAG Instructions: no canonical scopes adopted yet';
|
|
92
|
-
const state = result.changedFollowers > 0
|
|
93
|
-
? `${result.changedFollowers} follower(s) materialized`
|
|
94
|
-
: `${result.currentFollowers} follower(s) already current`;
|
|
95
|
-
const blocked = result.blockedFollowers > 0
|
|
96
|
-
? `; ${result.blockedFollowers} existing follower(s) preserved (run greprag instructions push explicitly)`
|
|
97
|
-
: '';
|
|
98
|
-
return `GrepRAG Instructions (${result.canonicalScopes.join(' + ')}): ${state}${blocked}`;
|
|
99
|
-
}
|
|
100
91
|
function hasEnvPrefix(prefix) {
|
|
101
92
|
return Object.keys(process.env).some(k => k.startsWith(prefix));
|
|
102
93
|
}
|
|
@@ -344,13 +335,11 @@ async function runInit(opts) {
|
|
|
344
335
|
// chip-spawn POINTER announce names the trigger + the command). One less
|
|
345
336
|
// install-time file write, and it works in every project, not just where the
|
|
346
337
|
// file happened to be installed.
|
|
347
|
-
// Step 7:
|
|
348
|
-
//
|
|
349
|
-
//
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
changes.push(doctrineBootstrapSummary(doctrine));
|
|
353
|
-
if (!doctrine?.canonicalScopes.includes('global')) {
|
|
338
|
+
// Step 7: ~/.claude/CLAUDE.md. A file committed in git is its owner's to
|
|
339
|
+
// edit, so init leaves it alone; an untracked one gets the greprag CLI
|
|
340
|
+
// section as before. adr: adr/skill-ownership-git.md
|
|
341
|
+
changes.push(renderInstructionsSummary());
|
|
342
|
+
if ((0, agents_1.committedInstructionSource)() === null) {
|
|
354
343
|
const claudeMdPatched = patchGlobalClaudeMd();
|
|
355
344
|
changes.push(claudeMdPatched
|
|
356
345
|
? 'Patched ~/.claude/CLAUDE.md greprag CLI section'
|
|
@@ -525,13 +514,13 @@ async function runOpenCodeInit(opts) {
|
|
|
525
514
|
console.warn(' Plugin bundle not found (build issue) — run `npm run build` in packages/cli and retry');
|
|
526
515
|
}
|
|
527
516
|
envChanges.push(await trySyncNativeSkillMirror(apiKey, 'opencode'));
|
|
528
|
-
const
|
|
517
|
+
const instructionsSummary = renderInstructionsSummary();
|
|
529
518
|
// Summary
|
|
530
519
|
console.log('\n Setup complete!\n');
|
|
531
520
|
for (const c of envChanges)
|
|
532
521
|
console.log(` - ${c}`);
|
|
533
522
|
console.log(` - Project anchor: ${anchor.anchorPath} (source: ${anchor.source})`);
|
|
534
|
-
console.log(` - ${
|
|
523
|
+
console.log(` - ${instructionsSummary}`);
|
|
535
524
|
if (pluginInstalled)
|
|
536
525
|
console.log(` - Plugin: ${pluginMain}`);
|
|
537
526
|
console.log(` - Shared env: ${getGrepragEnvPath()}`);
|
|
@@ -583,8 +572,7 @@ async function runCodexInit(opts) {
|
|
|
583
572
|
if (codexSkill)
|
|
584
573
|
changes.push(`Skill: installed → ${codexSkill}`);
|
|
585
574
|
changes.push(await trySyncNativeSkillMirror(apiKey, 'codex'));
|
|
586
|
-
|
|
587
|
-
changes.push(doctrineBootstrapSummary(doctrine));
|
|
575
|
+
changes.push(renderInstructionsSummary());
|
|
588
576
|
try {
|
|
589
577
|
const res = await fetch(`${API_URL}/v1/inbox/projects/register`, {
|
|
590
578
|
method: 'POST',
|
package/dist/commands/load.js
CHANGED
|
@@ -60,7 +60,6 @@ const os = __importStar(require("os"));
|
|
|
60
60
|
const harness_1 = require("../harness");
|
|
61
61
|
const skill_activation_manifest_1 = require("../skill-activation-manifest");
|
|
62
62
|
const project_anchor_1 = require("../project-anchor");
|
|
63
|
-
const skill_landing_1 = require("../skill-landing");
|
|
64
63
|
const skill_mirror_files_1 = require("../skill-mirror-files");
|
|
65
64
|
const proc_1 = require("../proc");
|
|
66
65
|
const skill_staleness_1 = require("../skill-staleness");
|
|
@@ -91,7 +90,7 @@ const LIBRARY = {
|
|
|
91
90
|
},
|
|
92
91
|
'skill-change': {
|
|
93
92
|
files: ['skill/templates/skill-change.md'],
|
|
94
|
-
purpose: '
|
|
93
|
+
purpose: 'How to change a skill after a run: edit its git folder and commit (GrepRAG only mirrors it), Convention A/B shapes, and when to propose instead.',
|
|
95
94
|
},
|
|
96
95
|
mechanic: {
|
|
97
96
|
files: ['skill/mechanic/SKILL.md', 'skill/mechanic/docs/skill-fix-conventions.md'],
|
|
@@ -109,10 +108,10 @@ const LIBRARY = {
|
|
|
109
108
|
files: ['skill/templates/chip-leader-opencode.md'],
|
|
110
109
|
purpose: 'Plan a MULTI-CHIP mission for opencode (integration branch, seams, merge order). Loaded from chip-bootloader when ≥2 chips are needed.',
|
|
111
110
|
},
|
|
112
|
-
// adr: adr/prompt-audit-canon.md — the audit lands
|
|
111
|
+
// adr: adr/prompt-audit-canon.md — the audit lands as an edit to ~/.claude/CLAUDE.md in git, never to a rendered AGENTS.md.
|
|
113
112
|
'prompt-audit': {
|
|
114
113
|
files: ['skill/templates/prompt-audit.md'],
|
|
115
|
-
purpose: 'Audit
|
|
114
|
+
purpose: 'Audit CLAUDE.md instructions for dated-model cruft (shipped rubric) and land accepted edits in ~/.claude/CLAUDE.md (git); the AGENTS.md files are rendered from it.',
|
|
116
115
|
},
|
|
117
116
|
};
|
|
118
117
|
/** Absolute path to a payload shipped in the package. */
|
|
@@ -189,7 +188,7 @@ async function printCatalog() {
|
|
|
189
188
|
for (const name of names) {
|
|
190
189
|
console.log(` ${name.padEnd(width)} ${LIBRARY[name].purpose}`);
|
|
191
190
|
}
|
|
192
|
-
console.log(` ${'instructions'.padEnd(width)}
|
|
191
|
+
console.log(` ${'instructions'.padEnd(width)} Read-only copy of ~/.claude/CLAUDE.md (git is the source; AGENTS.md files are rendered from it).`);
|
|
193
192
|
console.log(` ${'agents'.padEnd(width)} Deprecated alias for instructions.`);
|
|
194
193
|
// Tier-3 section: the operator's own skills, auto-mirrored from use.
|
|
195
194
|
const data = await mirrorGet('/v1/skillmirror');
|
|
@@ -201,20 +200,18 @@ async function printCatalog() {
|
|
|
201
200
|
// A mirrored skill with no native adapter on this harness never reaches the
|
|
202
201
|
// harness's own skill list — the agent can only reach it through this
|
|
203
202
|
// catalog. Mark the gap here and name the command that closes it.
|
|
204
|
-
// A hand-kept copy does reach that list, but the harness runs the copy and
|
|
205
|
-
// never sees canon move on, so it is marked too (with `~`).
|
|
206
203
|
const platform = (0, harness_1.inferCurrentHarness)() || '';
|
|
207
204
|
const native = platform
|
|
208
205
|
? (0, skill_activation_manifest_1.readNativeSkillNames)({ platform, cwd: process.cwd(), homeDir: os.homedir() })
|
|
209
206
|
: new Map();
|
|
210
|
-
const { missing
|
|
207
|
+
const { missing } = (0, skill_activation_manifest_1.nativeAdapterGap)(platform, skills, native);
|
|
211
208
|
const w = Math.max(...skills.map((s) => (s.skillName || '').length), 8);
|
|
212
|
-
console.log('\nYour mirrored skills (
|
|
209
|
+
console.log('\nYour mirrored skills (copied from git commits — work on any machine/harness):\n');
|
|
213
210
|
for (const s of skills) {
|
|
214
211
|
if (!s.skillName)
|
|
215
212
|
continue;
|
|
216
213
|
const scope = s.scope === 'project' && s.projectId ? ` [project:${s.projectId.slice(0, 8)}]` : '';
|
|
217
|
-
const gap = missing.includes(s.skillName) ? ' *' :
|
|
214
|
+
const gap = missing.includes(s.skillName) ? ' *' : '';
|
|
218
215
|
console.log(` ${(s.skillName + scope + gap).padEnd(w + 20)} ${(s.description || '').slice(0, 110)}`);
|
|
219
216
|
}
|
|
220
217
|
const installCommand = (0, skill_activation_manifest_1.nativeAdapterInstallCommand)(platform, missing);
|
|
@@ -223,13 +220,6 @@ async function printCatalog() {
|
|
|
223
220
|
console.log(' in this harness\'s own skill list. Install the adapters with:\n');
|
|
224
221
|
console.log(` ${installCommand}\n`);
|
|
225
222
|
}
|
|
226
|
-
const cutoverCommand = (0, skill_activation_manifest_1.localCopyCutoverCommand)(platform, localCopies);
|
|
227
|
-
if (cutoverCommand) {
|
|
228
|
-
console.log(`\n ~ ${localCopies.length} skill(s) run from a hand-kept copy in ${platform}, not an adapter — the harness`);
|
|
229
|
-
console.log(' keeps running that copy when the mirrored skill changes. Replacing a copy is a per-skill');
|
|
230
|
-
console.log(' call; its SKILL.md is backed up first:\n');
|
|
231
|
-
console.log(` ${cutoverCommand}\n`);
|
|
232
|
-
}
|
|
233
223
|
}
|
|
234
224
|
console.log('\n greprag load <name> print the full entry / mirrored skill');
|
|
235
225
|
console.log(' greprag load /<name> print a user-named slash skill');
|
|
@@ -451,13 +441,13 @@ async function printMirroredSkill(name, args) {
|
|
|
451
441
|
// adr: adr/skill-adapter-never-canon.md
|
|
452
442
|
if ((0, skill_mirror_files_1.isGeneratedSkillAdapter)(file.content)) {
|
|
453
443
|
const identityArg = args.skillId ? ` --skill-id ${args.skillId}` : '';
|
|
454
|
-
console.error(`Mirrored skill "${name}" has no
|
|
455
|
-
`Refusing to serve it: the
|
|
456
|
-
`
|
|
444
|
+
console.error(`Mirrored skill "${name}" has no body — the mirror is holding a generated launcher.\n` +
|
|
445
|
+
`Refusing to serve it: the launcher is what sent you here, not the skill.\n\n` +
|
|
446
|
+
`The skill lives in git. Restore SKILL.md in its folder (~/.claude/skills/${name}/ in the dotclaude repo, ` +
|
|
447
|
+
`or <repo>/.claude/skills/${name}/), commit, then run \`greprag skill mirror sync\`. Earlier mirrored ` +
|
|
448
|
+
`bytes stay readable:\n` +
|
|
457
449
|
` greprag skill history ${name}${identityArg}\n` +
|
|
458
|
-
` greprag skill
|
|
459
|
-
` greprag skill mirror snapshot list ${name}${identityArg}\n` +
|
|
460
|
-
` greprag skill mirror snapshot promote ${name} --name <snapshot>${identityArg} --expected-hash <current-hash> --reason "<why>"\n`);
|
|
450
|
+
` greprag skill mirror snapshot restore ${name} --name <snapshot>${identityArg} --to <dir>\n`);
|
|
461
451
|
process.exitCode = 1;
|
|
462
452
|
return true;
|
|
463
453
|
}
|
|
@@ -473,18 +463,6 @@ async function printMirroredSkill(name, args) {
|
|
|
473
463
|
}
|
|
474
464
|
process.stdout.write(file.content.endsWith('\n') ? file.content : file.content + '\n');
|
|
475
465
|
if (!args.docPath) {
|
|
476
|
-
// A mirror-managed skill's SKILL.md is a generated adapter, so the Skill
|
|
477
|
-
// Learning Loop cannot land a fuse there without fighting the mirror for
|
|
478
|
-
// the file. Its pending gains ride the load payload instead — this is the
|
|
479
|
-
// moment the agent reads the skill. adr: adr/skill-fuse-delivery.md
|
|
480
|
-
try {
|
|
481
|
-
const pending = await mirrorGet('/v1/skillgain/pending');
|
|
482
|
-
const gains = pending?.gains || [];
|
|
483
|
-
const block = (0, skill_landing_1.buildLoadFuseBlock)(name, gains);
|
|
484
|
-
if (block)
|
|
485
|
-
process.stdout.write(block);
|
|
486
|
-
}
|
|
487
|
-
catch { /* a gain that fails to surface must never break the skill load */ }
|
|
488
466
|
await printStateDocHints(name, file.content);
|
|
489
467
|
const companions = files.map((f) => f.path).filter((p) => p !== 'SKILL.md');
|
|
490
468
|
if (companions.length > 0) {
|
|
@@ -506,7 +484,7 @@ async function runLoad(args) {
|
|
|
506
484
|
if (name === 'instructions' || name === 'agents') {
|
|
507
485
|
if (await printGrepRagInstructions(args.slice(1)))
|
|
508
486
|
return;
|
|
509
|
-
console.error('No
|
|
487
|
+
console.error('No mirrored instructions yet. `greprag instructions render` mirrors the committed ~/.claude/CLAUDE.md.');
|
|
510
488
|
process.exit(1);
|
|
511
489
|
}
|
|
512
490
|
// An explicit --skill-id names one mirrored skill, so it outranks a bundled
|
package/dist/commands/parity.js
CHANGED
|
@@ -254,7 +254,7 @@ async function tableCmd(args) {
|
|
|
254
254
|
console.log(` reconciled: ${u.lastReconcile ? u.lastReconcile.slice(0, 10) : 'never'}`);
|
|
255
255
|
console.log('');
|
|
256
256
|
}
|
|
257
|
-
console.log('
|
|
257
|
+
console.log('Instruction files reconcile with `greprag instructions render`; other units use a parity fix chip.');
|
|
258
258
|
}
|
|
259
259
|
// ---------- Dispatch ------------------------------------------------------------
|
|
260
260
|
async function runParity(args) {
|
|
@@ -18,28 +18,12 @@ function renderEntry(skill) {
|
|
|
18
18
|
function buildSkillMirrorAnnounce(m, platform) {
|
|
19
19
|
if (!m || m.count <= 0)
|
|
20
20
|
return null;
|
|
21
|
-
// A hand-kept copy is in the native skill list, so it is not in the trigger
|
|
22
|
-
// list below, but the harness runs that copy and never sees canon move on.
|
|
23
|
-
// Name each one; replacing a live copy is the user's call, skill by skill.
|
|
24
|
-
const cutoverCommand = (0, skill_activation_manifest_1.localCopyCutoverCommand)(platform || '', m.localCopies);
|
|
25
|
-
const copies = m.localCopies.length === 1 ? 'one mirrored skill' : `${m.localCopies.length} mirrored skills`;
|
|
26
|
-
const copySection = cutoverCommand ? [
|
|
27
|
-
'### Hand-Kept Copies',
|
|
28
|
-
`This harness lists ${copies} from a hand-kept copy instead of an adapter, `
|
|
29
|
-
+ `so it keeps running that copy when the mirrored skill changes: ${m.localCopies.join(', ')}. `
|
|
30
|
-
+ 'Replacing a copy with its adapter is the user\'s call, one skill at a time (the old SKILL.md is backed up first):',
|
|
31
|
-
'',
|
|
32
|
-
` ${cutoverCommand}`,
|
|
33
|
-
'',
|
|
34
|
-
'Offer that command when the user asks why a skill behaves out of date, or when you needed one of them this session.',
|
|
35
|
-
'',
|
|
36
|
-
] : [];
|
|
37
21
|
if (m.skills.length === 0) {
|
|
38
22
|
const line = '[greprag skills: slash skills are available. '
|
|
39
23
|
+ 'When discussing skills with the user, say use/create/update/refresh `/skill`; '
|
|
40
24
|
+ 'keep storage mechanics internal unless diagnosing a failure or the user asks how it works. '
|
|
41
25
|
+ 'Use `greprag load <skill>` to read skill instructions.]';
|
|
42
|
-
return
|
|
26
|
+
return line;
|
|
43
27
|
}
|
|
44
28
|
// Mirrored skills with no native package never reach the native skill list.
|
|
45
29
|
// Name the gap and the one command that closes it, or it stays invisible
|
|
@@ -64,7 +48,6 @@ function buildSkillMirrorAnnounce(m, platform) {
|
|
|
64
48
|
'When discussing skills with the user, say use/create/update/refresh `/skill`; keep storage mechanics internal unless diagnosing a failure or the user asks how it works.',
|
|
65
49
|
'',
|
|
66
50
|
...gapSection,
|
|
67
|
-
...copySection,
|
|
68
51
|
'### Trigger Rules',
|
|
69
52
|
'If the user names a skill (with or without `/`) OR the request clearly matches a skill\'s description below, '
|
|
70
53
|
+ 'you MUST activate that skill for the current turn. Match meaning, not exact keywords.',
|