greprag 5.83.2 → 5.85.0
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/app-model.js +1 -1
- package/dist/commands/delivery-reminder.js +1 -1
- package/dist/commands/discord.js +12 -61
- package/dist/commands/inbox-watch.js +0 -13
- package/dist/commands/init.js +17 -29
- package/dist/commands/load.js +15 -35
- package/dist/commands/parity.js +1 -1
- package/dist/commands/reminder-registry.js +1 -8
- package/dist/commands/session.js +2 -2
- package/dist/commands/skill-mirror-reminder.js +1 -19
- package/dist/commands/skill.js +236 -448
- package/dist/hook.js +31 -54
- package/dist/index.js +19 -152
- package/dist/native-adapter-refresh.js +15 -18
- package/dist/native-skill-mirror.js +11 -89
- package/dist/opencode-plugin.bundle.js +82 -282
- package/dist/reminder-injector.js +1 -1
- package/dist/skill-activation-manifest.js +14 -37
- package/dist/skill-git-ingest.js +297 -0
- package/dist/skill-landing.js +7 -173
- package/dist/skill-mirror-client.js +4 -251
- package/dist/skill-staleness.js +3 -6
- package/package.json +1 -1
- package/skill/commander/SKILL.md +10 -12
- package/skill/greprag/SKILL.md +1 -1
- package/skill/greprag/docs/discord-handoff.md +6 -30
- package/skill/mechanic/docs/skill-fix-conventions.md +1 -1
- package/skill/templates/chip-spawn.md +6 -2
- package/skill/templates/delivery.md +16 -0
- package/skill/templates/os.md +1 -1
- package/skill/templates/prompt-audit.md +26 -49
- package/skill/templates/skill-change.md +15 -11
- package/dist/commands/sms.js +0 -215
|
@@ -292,7 +292,7 @@ async function buildAppModel(cwd, requestedProjectId, homeDir = os.homedir()) {
|
|
|
292
292
|
group: 'Other',
|
|
293
293
|
}),
|
|
294
294
|
enabled: !disabled.has(module.id),
|
|
295
|
-
surface:
|
|
295
|
+
surface: 'Agent guidance',
|
|
296
296
|
harnesses: module.harnesses || ['claude-code', 'codex', 'opencode', 'grok'],
|
|
297
297
|
})),
|
|
298
298
|
},
|
|
@@ -50,7 +50,7 @@ function buildDeliveryAnnounce(env) {
|
|
|
50
50
|
`[DELIVERY — ${project}]`,
|
|
51
51
|
'Commit useful, passing work. Only committed state delivers; ignore uncommitted and untracked work in every checkout.',
|
|
52
52
|
coordinationLine(env.platform),
|
|
53
|
-
'Land every ready same-repo commit: update the default branch, rebase your worktree onto its tip, retest there, take greprag merge-lock in the canonical checkout, recheck the tip, merge --ff-only, release --landed. Tip moved? Free the lock and prepare again. Never rebase a shared default branch.',
|
|
53
|
+
'Land every ready same-repo commit: update the default branch, rebase your worktree onto its tip, retest there, take greprag merge-lock in the canonical checkout, recheck the tip, merge --ff-only, release --landed. Tip moved? Free the lock and prepare again. A chip\'s branch arrives rebased by the chip: only fast-forward it; refused, free the lock and send it back. Never rebase in another session\'s worktree or a shared default branch.',
|
|
54
54
|
'Deploy through this repo\'s delivery profile, from its canonical primary checkout unless the profile says otherwise. Worktrees build; they do not deploy. Then verify production serves the commit you shipped.',
|
|
55
55
|
'THE GOAL ALREADY AUTHORIZES ALL OF THIS. Do not stop to ask permission to commit, merge, or deploy. Separate approval is for effects outside code delivery: destructive data, secrets, money, customer-facing messages.',
|
|
56
56
|
'Why each rule, and the details: `greprag load delivery`.',
|
package/dist/commands/discord.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/** greprag discord <pair|unpair|me|
|
|
2
|
+
/** greprag discord <pair|unpair|me|typing> — Discord bot CLI.
|
|
3
3
|
*
|
|
4
4
|
* pair POSTs /v1/discord/pair with the current project anchor; prints
|
|
5
5
|
* the 6-char code + DM-the-bot instructions.
|
|
6
6
|
* unpair DELETEs /v1/discord/pair.
|
|
7
|
-
* me GETs /v1/discord/me — pairing
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* me GETs /v1/discord/me — pairing state.
|
|
8
|
+
* typing POSTs /v1/discord/typing — refreshes the typing indicator.
|
|
9
|
+
*
|
|
10
|
+
* Sessions DM the operator with `greprag send --to discord:<snowflake>`.
|
|
11
|
+
* Nothing reads DMs sent to the bot: the Front Desk and the handoff pin were
|
|
12
|
+
* retired 2026-10-06, so the bot answers each one with a fixed line.
|
|
11
13
|
*/
|
|
12
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
15
|
exports.DISCORD_HELP = void 0;
|
|
14
16
|
exports.callDiscordPair = callDiscordPair;
|
|
15
17
|
exports.callDiscordUnpair = callDiscordUnpair;
|
|
16
18
|
exports.callDiscordMe = callDiscordMe;
|
|
17
|
-
exports.callDiscordHandoff = callDiscordHandoff;
|
|
18
|
-
exports.callDiscordUnhandoff = callDiscordUnhandoff;
|
|
19
19
|
exports.callDiscordTyping = callDiscordTyping;
|
|
20
20
|
async function callDiscordPair(deps, projectId) {
|
|
21
21
|
const f = deps.fetchImpl ?? fetch;
|
|
@@ -45,30 +45,6 @@ async function callDiscordMe(deps) {
|
|
|
45
45
|
});
|
|
46
46
|
return (await res.json());
|
|
47
47
|
}
|
|
48
|
-
async function callDiscordHandoff(deps, args) {
|
|
49
|
-
const f = deps.fetchImpl ?? fetch;
|
|
50
|
-
const res = await f(`${deps.apiUrl}/v1/discord/handoff`, {
|
|
51
|
-
method: 'POST',
|
|
52
|
-
headers: {
|
|
53
|
-
'Authorization': `Bearer ${deps.apiKey}`,
|
|
54
|
-
'Content-Type': 'application/json',
|
|
55
|
-
},
|
|
56
|
-
body: JSON.stringify({
|
|
57
|
-
project_id: args.projectId,
|
|
58
|
-
session_id: args.sessionId,
|
|
59
|
-
ttl_minutes: args.ttlMinutes,
|
|
60
|
-
}),
|
|
61
|
-
});
|
|
62
|
-
return (await res.json());
|
|
63
|
-
}
|
|
64
|
-
async function callDiscordUnhandoff(deps) {
|
|
65
|
-
const f = deps.fetchImpl ?? fetch;
|
|
66
|
-
const res = await f(`${deps.apiUrl}/v1/discord/handoff`, {
|
|
67
|
-
method: 'DELETE',
|
|
68
|
-
headers: { 'Authorization': `Bearer ${deps.apiKey}` },
|
|
69
|
-
});
|
|
70
|
-
return (await res.json());
|
|
71
|
-
}
|
|
72
48
|
async function callDiscordTyping(deps) {
|
|
73
49
|
const f = deps.fetchImpl ?? fetch;
|
|
74
50
|
const res = await f(`${deps.apiUrl}/v1/discord/typing`, {
|
|
@@ -78,44 +54,19 @@ async function callDiscordTyping(deps) {
|
|
|
78
54
|
return (await res.json());
|
|
79
55
|
}
|
|
80
56
|
exports.DISCORD_HELP = `
|
|
81
|
-
greprag discord —
|
|
57
|
+
greprag discord — let your sessions DM you on Discord.
|
|
82
58
|
|
|
83
|
-
Pair once
|
|
84
|
-
|
|
85
|
-
away from the desk and want to keep the same thread alive on your phone).
|
|
59
|
+
Pair once; then any session can message you (see Outbound below). The bot does
|
|
60
|
+
not read DMs you send it: the Front Desk was retired 2026-10-06.
|
|
86
61
|
|
|
87
62
|
Subcommands:
|
|
88
63
|
greprag discord pair Generate a 15-min code; DM @greprag-bot
|
|
89
64
|
/pair <code> to link this Discord account
|
|
90
65
|
to the current project.
|
|
91
66
|
greprag discord unpair Remove the pairing.
|
|
92
|
-
greprag discord me Show current pairing
|
|
93
|
-
greprag discord handoff [--ttl N] Pin DMs to (current project, current
|
|
94
|
-
session) for N minutes (default 60,
|
|
95
|
-
max 1440). Bot DMs you a confirmation,
|
|
96
|
-
then this command BLOCKS and streams
|
|
97
|
-
inbound DMs to stdout (one per line)
|
|
98
|
-
until killed. Run it under Claude's
|
|
99
|
-
Monitor tool: each line = one
|
|
100
|
-
notification right back into the
|
|
101
|
-
agent's turn. Sliding TTL: each
|
|
102
|
-
inbound DM extends the pin by >=30 min.
|
|
103
|
-
[--session <8-hex>] Override session id (default: CLAUDE_SESSION_ID).
|
|
104
|
-
[--project <name>] Override project (default: cwd anchor).
|
|
105
|
-
[--orchestrator] Tenant-wide watcher — sees inbox traffic
|
|
106
|
-
from any project under this tenant. The
|
|
107
|
-
DM pin still routes here, but the agent
|
|
108
|
-
has portfolio-wide eyes. Use when this
|
|
109
|
-
session is the user's orchestrator
|
|
110
|
-
(/business-advisor loaded, etc.).
|
|
111
|
-
[--json] Emit raw JSON per line (for Monitor).
|
|
112
|
-
[--no-watch] Pin and exit — skip the inline watcher.
|
|
113
|
-
For scripted use; loses the live DM stream.
|
|
114
|
-
greprag discord unhandoff Clear the active handoff — DMs revert
|
|
115
|
-
to default project.
|
|
67
|
+
greprag discord me Show current pairing state.
|
|
116
68
|
greprag discord typing Refresh the "typing..." indicator on
|
|
117
|
-
Discord for ~10s.
|
|
118
|
-
inbound DM; call manually during long
|
|
69
|
+
Discord for ~10s. Call it during long
|
|
119
70
|
agent turns so the user sees activity
|
|
120
71
|
instead of silence.
|
|
121
72
|
|
|
@@ -251,19 +251,6 @@ function printMessage(msg) {
|
|
|
251
251
|
function emitDmReplyDirective(msg, session) {
|
|
252
252
|
if (!session)
|
|
253
253
|
return;
|
|
254
|
-
// Front Desk Switchboard relay: the operator reached THIS session through the
|
|
255
|
-
// receptionist and `references.reply_to` is the rail to answer on. Fires for
|
|
256
|
-
// ANY message_type (the relay uses plain 'message'), and takes precedence over
|
|
257
|
-
// the legacy Discord-DM path. Without this the session falls back to the bare
|
|
258
|
-
// sender handle (travis@greprag.com) — the reply lands in MAIN, never reaching
|
|
259
|
-
// the operator on Discord/SMS. Live failure 2026-06-08. spec:
|
|
260
|
-
// docs/front-desk-switchboard.md §4 (return leg).
|
|
261
|
-
const replyTo = msg.references?.reply_to;
|
|
262
|
-
if (replyTo) {
|
|
263
|
-
console.log(`[greprag] Operator via front desk — answer now, even mid-task: greprag send --to ${replyTo} "…" ` +
|
|
264
|
-
`(exact addr; bare handle is lost). If they reply inline here, don't echo to Discord/SMS.`);
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
254
|
if (msg.message_type !== 'discord_dm')
|
|
268
255
|
return;
|
|
269
256
|
const snowflake = msg.references?.discord?.snowflake ?? '<snowflake>';
|
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,11 +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
|
-
`Restore
|
|
457
|
-
`
|
|
458
|
-
`
|
|
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` +
|
|
449
|
+
` greprag skill history ${name}${identityArg}\n` +
|
|
450
|
+
` greprag skill mirror snapshot restore ${name} --name <snapshot>${identityArg} --to <dir>\n`);
|
|
459
451
|
process.exitCode = 1;
|
|
460
452
|
return true;
|
|
461
453
|
}
|
|
@@ -471,18 +463,6 @@ async function printMirroredSkill(name, args) {
|
|
|
471
463
|
}
|
|
472
464
|
process.stdout.write(file.content.endsWith('\n') ? file.content : file.content + '\n');
|
|
473
465
|
if (!args.docPath) {
|
|
474
|
-
// A mirror-managed skill's SKILL.md is a generated adapter, so the Skill
|
|
475
|
-
// Learning Loop cannot land a fuse there without fighting the mirror for
|
|
476
|
-
// the file. Its pending gains ride the load payload instead — this is the
|
|
477
|
-
// moment the agent reads the skill. adr: adr/skill-fuse-delivery.md
|
|
478
|
-
try {
|
|
479
|
-
const pending = await mirrorGet('/v1/skillgain/pending');
|
|
480
|
-
const gains = pending?.gains || [];
|
|
481
|
-
const block = (0, skill_landing_1.buildLoadFuseBlock)(name, gains);
|
|
482
|
-
if (block)
|
|
483
|
-
process.stdout.write(block);
|
|
484
|
-
}
|
|
485
|
-
catch { /* a gain that fails to surface must never break the skill load */ }
|
|
486
466
|
await printStateDocHints(name, file.content);
|
|
487
467
|
const companions = files.map((f) => f.path).filter((p) => p !== 'SKILL.md');
|
|
488
468
|
if (companions.length > 0) {
|
|
@@ -504,7 +484,7 @@ async function runLoad(args) {
|
|
|
504
484
|
if (name === 'instructions' || name === 'agents') {
|
|
505
485
|
if (await printGrepRagInstructions(args.slice(1)))
|
|
506
486
|
return;
|
|
507
|
-
console.error('No
|
|
487
|
+
console.error('No mirrored instructions yet. `greprag instructions render` mirrors the committed ~/.claude/CLAUDE.md.');
|
|
508
488
|
process.exit(1);
|
|
509
489
|
}
|
|
510
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) {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* PURE over ReminderEnv — the hook assembles env (i/o) and emits the returned lines;
|
|
6
6
|
* a broken module never blocks a turn (fail-open per module). */
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.ANNOUNCE_POINTER_RESERVE = exports.ANNOUNCE_HARNESS_CAP = exports.ANNOUNCE_INLINE_BUDGET = exports.compactReannounceModules = exports.
|
|
8
|
+
exports.ANNOUNCE_POINTER_RESERVE = exports.ANNOUNCE_HARNESS_CAP = exports.ANNOUNCE_INLINE_BUDGET = exports.compactReannounceModules = exports.harnessModules = exports.REGISTRY = void 0;
|
|
9
9
|
exports.collectReminders = collectReminders;
|
|
10
10
|
exports.bootOrder = bootOrder;
|
|
11
11
|
exports.collectAnnounces = collectAnnounces;
|
|
@@ -66,13 +66,6 @@ exports.REGISTRY = [
|
|
|
66
66
|
* update a parallel id list. (Root-cause repair, chip/opencode-fix-chip-system-parity.) */
|
|
67
67
|
const harnessModules = (harness, registry = exports.REGISTRY) => registry.filter((m) => !m.harnesses || m.harnesses.includes(harness));
|
|
68
68
|
exports.harnessModules = harnessModules;
|
|
69
|
-
/** Split the registry by READ surface (docs/reminder-interrupt.md). UserPromptSubmit
|
|
70
|
-
* evaluates `prompt`-source modules (the default); PreToolUse evaluates `command`-source
|
|
71
|
-
* modules (they read env.toolCommand). Announces are always prompt-side (SessionStart). */
|
|
72
|
-
const promptModules = (registry = exports.REGISTRY) => registry.filter((m) => (m.source ?? 'prompt') === 'prompt');
|
|
73
|
-
exports.promptModules = promptModules;
|
|
74
|
-
const commandModules = (registry = exports.REGISTRY) => registry.filter((m) => m.source === 'command');
|
|
75
|
-
exports.commandModules = commandModules;
|
|
76
69
|
/** PostCompact re-announce set (docs/reminder-interrupt.md). A compaction wipes the
|
|
77
70
|
* SessionStart announces from context, so the announce modules re-present afterward —
|
|
78
71
|
* by DEFAULT all of them; a module opts out with `reannounceOnCompact: false`. The
|
package/dist/commands/session.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* retitle <session-8hex> "<title>" — force-set a session's registry title,
|
|
5
5
|
* overriding the gpt-5.4-nano auto-title. Used by the multi-chip /chip-leader
|
|
6
6
|
* convention: a chip stamps its own label-aligned title ("Chip A — …") in
|
|
7
|
-
* Block 1 so the FleetView watcher list
|
|
8
|
-
*
|
|
7
|
+
* Block 1 so the FleetView watcher list lines up with the leader's chip
|
|
8
|
+
* labels. Thin HTTP client over POST /v1/memory/title. */
|
|
9
9
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
10
|
if (k2 === undefined) k2 = k;
|
|
11
11
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -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.',
|
|
@@ -90,7 +73,6 @@ function buildSkillMirrorAnnounce(m, platform) {
|
|
|
90
73
|
}
|
|
91
74
|
exports.skillMirrorAnnounceModule = {
|
|
92
75
|
id: 'skill-mirror-announce',
|
|
93
|
-
source: 'prompt',
|
|
94
76
|
dependsOn: ['load-primer'], // references `greprag load` — the primer establishes it
|
|
95
77
|
detect: (_env) => ({ tier: 'silent' }), // announce-only
|
|
96
78
|
announce: (env) => buildSkillMirrorAnnounce(env.mirroredSkills, env.platform),
|