greprag 5.73.10 → 5.73.12

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.
Files changed (45) hide show
  1. package/dist/codex-chip-hooks.js +1 -1
  2. package/dist/codex-chip-hooks.js.map +1 -1
  3. package/dist/commands/agent-doctrine-file.d.ts +1 -1
  4. package/dist/commands/agent-doctrine-file.js +1 -1
  5. package/dist/commands/agents.d.ts +28 -2
  6. package/dist/commands/agents.js +454 -18
  7. package/dist/commands/agents.js.map +1 -1
  8. package/dist/commands/codex-chip/prompt.js +1 -1
  9. package/dist/commands/codex-chip/prompt.js.map +1 -1
  10. package/dist/commands/fix.js +6 -5
  11. package/dist/commands/fix.js.map +1 -1
  12. package/dist/commands/friction-reminder.d.ts +1 -1
  13. package/dist/commands/friction-reminder.js +4 -4
  14. package/dist/commands/friction-reminder.js.map +1 -1
  15. package/dist/commands/init.js +7 -7
  16. package/dist/commands/init.js.map +1 -1
  17. package/dist/commands/load.js +8 -7
  18. package/dist/commands/load.js.map +1 -1
  19. package/dist/commands/mechanic-spawn.d.ts +9 -9
  20. package/dist/commands/mechanic-spawn.js +29 -70
  21. package/dist/commands/mechanic-spawn.js.map +1 -1
  22. package/dist/commands/mechanic.js +4 -4
  23. package/dist/commands/os-primer-reminder.js +1 -1
  24. package/dist/commands/os-primer-reminder.js.map +1 -1
  25. package/dist/commands/parity.js +1 -1
  26. package/dist/commands/parity.js.map +1 -1
  27. package/dist/commands/ship-through-gate.d.ts +16 -0
  28. package/dist/commands/ship-through-gate.js +43 -0
  29. package/dist/commands/ship-through-gate.js.map +1 -0
  30. package/dist/commands/skill.js +59 -6
  31. package/dist/commands/skill.js.map +1 -1
  32. package/dist/index.js +10 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/native-skill-adoption.d.ts +45 -0
  35. package/dist/native-skill-adoption.js +240 -0
  36. package/dist/native-skill-adoption.js.map +1 -0
  37. package/dist/opencode-plugin.bundle.js +4 -4
  38. package/dist/skill-mirror-client.d.ts +25 -0
  39. package/dist/skill-mirror-client.js +58 -0
  40. package/dist/skill-mirror-client.js.map +1 -1
  41. package/package.json +1 -1
  42. package/skill/greprag/docs/codex-chip.md +11 -12
  43. package/skill/mechanic/SKILL.md +8 -8
  44. package/skill/templates/chip-spawn.md +1 -1
  45. package/skill/templates/codex-chip-spawn.md +130 -248
@@ -66,7 +66,7 @@ function context(input) {
66
66
  `Parent session: ${chip.parent.sessionId || 'not recorded'}`,
67
67
  `Finish by committing the durable result and reporting the commit artifact to the parent, including checks, caveats, and a Cleanup line naming archive/task, worktree, and branch actions. The optional host command is ${cli} codex chip report ${chip.id}.`,
68
68
  // adr: adr/codex-landing-doctrine.md — default parent-owned landing + the one FIX exception.
69
- 'Landing: the parent owns merge, archive, and cleanup — do not merge, push, deploy, clean up, or edit the parent checkout. ONE exception: a mission whose first line begins `FIX:` (emitted by `greprag fix spawn`) carries its own Phase 3 landing contract after peer conferral it merges its branch to main itself; cleanup stays native (`Cleanup: archive task; Codex may prune managed worktree; branch may be deleted after merge` plus `Clearance: safe to archive`), and push/release stays operator-gated for ordinary repair missions unless release/deploy was explicitly provisioned as mission completion.',
69
+ 'Landing: the parent owns merge, archive, and cleanup — do not merge, push, deploy, clean up, or edit the parent checkout. FIX exception: a mission whose first line begins `FIX:` (emitted by `greprag fix spawn`) is writable in its isolated checkout/worktree, but stops for human approval before landing or cleanup. `greprag fix spawn` only prints the mission; visible Codex task dispatch creates the isolated checkout/worktree.',
70
70
  ];
71
71
  if ((0, model_1.chipMissionKind)(chip) === 'fix') {
72
72
  lines.push('Harness: Codex. Mission: visible native FIX chip with ordinary writable authority, not an internal subagent.', 'Scope: repair GrepRAG-owned harness surfaces in this checkout: load entries, skill templates, docs, hook context, CLI messages, and tests. Codex owns native task creation, worktrees, permissions, Git, and task lifecycle.', 'Own diagnosis, implementation, tests, commit, and parent report. Inspect Codex behavior only far enough to correct GrepRAG guidance or report a precise external blocker.', 'FIX peer handoff: if a peer offers to coordinate, integrate, rework, or take over a harness repair, hand off branch/commit, dirty files, checks, blockers, and caveats. Do not defend patch ownership; peers may take ownership within their assigned GrepRAG harness scope.', 'Visible delegation route: load `codex-chip-spawn` and create the child with `codex_app__create_thread` using the current project worktree target; load `chip-leader` for multi-chip seams. Never use `multi_agent_v1__spawn_agent` for a visible chip.');
@@ -1 +1 @@
1
- {"version":3,"file":"codex-chip-hooks.js","sourceRoot":"","sources":["../src/codex-chip-hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codex-chip-hooks.js","sourceRoot":"","sources":["../src/codex-chip-hooks.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- /** Pure full-file follower helpers for canonical agent doctrine.
1
+ /** Pure full-file follower helpers for canonical GrepRAG Instructions.
2
2
  *
3
3
  * Follower files must stay byte-faithful instruction files. Ownership state
4
4
  * lives outside the markdown in the GrepRAG parity manifest.
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- /** Pure full-file follower helpers for canonical agent doctrine.
2
+ /** Pure full-file follower helpers for canonical GrepRAG Instructions.
3
3
  *
4
4
  * Follower files must stay byte-faithful instruction files. Ownership state
5
5
  * lives outside the markdown in the GrepRAG parity manifest.
@@ -1,6 +1,31 @@
1
- /** `greprag agents` — canonical agent-doctrine adoption and materialization. */
1
+ /** `greprag instructions` — canonical GrepRAG Instructions adoption/materialization.
2
+ *
3
+ * `greprag agents` remains as a compatibility alias. */
2
4
  type Harness = 'claude-code' | 'codex' | 'opencode';
3
5
  type Scope = 'global' | 'repo';
6
+ interface OriginalInstructionSnapshot {
7
+ snapshotName?: string;
8
+ harness: Harness;
9
+ path: string;
10
+ scope: Scope;
11
+ projectId: string | null;
12
+ directory: string;
13
+ status: 'present' | 'missing';
14
+ content: string;
15
+ contentHash: string;
16
+ capturedAt: string;
17
+ source: 'git-history' | 'disk' | 'missing';
18
+ sourceRef?: string | null;
19
+ reason?: string | null;
20
+ }
21
+ export interface FollowerTarget {
22
+ harness: Harness;
23
+ actualPath: string;
24
+ manifestPath: string;
25
+ note?: string;
26
+ combinedAgents?: boolean;
27
+ }
28
+ export declare function collectOriginalSnapshots(targets: FollowerTarget[], scope: Scope, projectId: string | null, directory: string): OriginalInstructionSnapshot[];
4
29
  export interface AgentDoctrineBootstrapResult {
5
30
  canonicalScopes: Scope[];
6
31
  currentFollowers: number;
@@ -9,7 +34,8 @@ export interface AgentDoctrineBootstrapResult {
9
34
  }
10
35
  /** Init-time seed for the active harness. No canon is a clean no-op; only a
11
36
  * missing/empty follower is written. Every existing nonmatching file requires
12
- * an explicit `agents push` or `agents pull`. */
37
+ * an explicit `instructions push` or `instructions pull`. */
13
38
  export declare function bootstrapAgentDoctrine(apiKey: string, harness: Harness): Promise<AgentDoctrineBootstrapResult>;
39
+ export declare function runInstructions(args: string[]): Promise<void>;
14
40
  export declare function runAgents(args: string[]): Promise<void>;
15
41
  export {};
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
- /** `greprag agents` — canonical agent-doctrine adoption and materialization. */
2
+ /** `greprag instructions` — canonical GrepRAG Instructions adoption/materialization.
3
+ *
4
+ * `greprag agents` remains as a compatibility alias. */
3
5
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
6
  if (k2 === undefined) k2 = k;
5
7
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -34,7 +36,9 @@ var __importStar = (this && this.__importStar) || (function () {
34
36
  };
35
37
  })();
36
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.collectOriginalSnapshots = collectOriginalSnapshots;
37
40
  exports.bootstrapAgentDoctrine = bootstrapAgentDoctrine;
41
+ exports.runInstructions = runInstructions;
38
42
  exports.runAgents = runAgents;
39
43
  const crypto = __importStar(require("node:crypto"));
40
44
  const fs = __importStar(require("node:fs"));
@@ -43,24 +47,35 @@ const path = __importStar(require("node:path"));
43
47
  const project_anchor_1 = require("../project-anchor");
44
48
  const proc_1 = require("../proc");
45
49
  const agent_doctrine_file_1 = require("./agent-doctrine-file");
46
- const HELP = `greprag agents — canonical CLAUDE.md / AGENTS.md doctrine
50
+ function help(commandName) {
51
+ const aliasNote = commandName === 'agents'
52
+ ? '\n\nNOTE\n `greprag agents` is a deprecated alias. Use `greprag instructions`.'
53
+ : '';
54
+ return `greprag ${commandName} — canonical GrepRAG Instructions for CLAUDE.md / AGENTS.md
47
55
 
48
56
  USAGE
49
- greprag agents pull <file> [--scope global|repo] [--harness <name>] [--push]
50
- greprag agents push [--scope global|repo|all] [--check] [--force]
51
- greprag agents adopt <file> [--scope global|repo] [--harness <name>] [--no-sync]
52
- greprag agents revise <file> [--scope global|repo] [--harness <name>] [--no-sync]
53
- greprag agents overlay set <harness> <file> [--scope global|repo] [--no-sync]
54
- greprag agents overlay derive <harness> <shared-file> <rendered-file> [--scope global|repo] [--no-sync]
55
- greprag agents overlay clear <harness> [--scope global|repo] [--no-sync]
56
- greprag agents sync [--scope global|repo|all] [--check] [--force]
57
- greprag agents status [--scope global|repo|all]
57
+ greprag ${commandName} pull <file> [--scope global|repo] [--harness <name>] [--push]
58
+ greprag ${commandName} push [--scope global|repo|all] [--check] [--force]
59
+ greprag ${commandName} adopt <file> [--scope global|repo] [--harness <name>] [--no-sync]
60
+ greprag ${commandName} revise <file> [--scope global|repo] [--harness <name>] [--no-sync]
61
+ greprag ${commandName} overlay set <harness> <file> [--scope global|repo] [--no-sync]
62
+ greprag ${commandName} overlay derive <harness> <shared-file> <rendered-file> [--scope global|repo] [--no-sync]
63
+ greprag ${commandName} overlay clear <harness> [--scope global|repo] [--no-sync]
64
+ greprag ${commandName} snapshot create --name <name> [--scope global|repo|all] [--harness <name>] [--from-ref <git-ref>] [--force]
65
+ greprag ${commandName} snapshot list [--scope global|repo|all]
66
+ greprag ${commandName} snapshot show <name> [--scope global|repo|all]
67
+ greprag ${commandName} restore --snapshot <name> [--scope global|repo|all] [--harness <name>] [--check] [--force]
68
+ greprag ${commandName} sync [--scope global|repo|all] [--check] [--force]
69
+ greprag ${commandName} status [--scope global|repo|all]
58
70
 
59
71
  MODEL
60
- Adopt and revise copy source bytes exactly; no model rewrites doctrine.
72
+ Adopt and revise copy source bytes exactly; no model rewrites instructions.
73
+ The first adoption stores Original Snapshots for every managed follower.
61
74
  Harness translations are raw additive suffixes. Pull writes disk to canon.
62
75
  Push writes canon to disk only when the external sync baseline is clean.
63
- Status/check never writes.`;
76
+ Snapshots are named exact-byte rollback points and do not change canon.
77
+ Status/check never writes.${aliasNote}`;
78
+ }
64
79
  function config(apiKeyOverride) {
65
80
  return {
66
81
  apiUrl: process.env.GREPRAG_API_URL || 'https://api.greprag.com',
@@ -81,6 +96,51 @@ function repoRoot(cwd = process.cwd()) {
81
96
  return path.resolve(cwd);
82
97
  }
83
98
  }
99
+ function fileGitRoot(filePath) {
100
+ try {
101
+ return String((0, proc_1.safeExecFileSync)('git', ['-C', path.dirname(filePath), 'rev-parse', '--show-toplevel'], {
102
+ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
103
+ })).trim();
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ }
109
+ function gitFileAt(root, ref, relativePath) {
110
+ try {
111
+ return String((0, proc_1.safeExecFileSync)('git', ['-C', root, 'show', `${ref}:${relativePath}`], {
112
+ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
113
+ maxBuffer: 1024 * 1024,
114
+ }));
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ }
120
+ function firstInstructionTouch(root, relativePath) {
121
+ try {
122
+ const out = String((0, proc_1.safeExecFileSync)('git', [
123
+ '-C', root,
124
+ 'log',
125
+ '--reverse',
126
+ '--format=%H',
127
+ '--all',
128
+ '-G', 'Agent Doctrine|Doctrine Mirror|agent doctrine|greprag agents|greprag instructions|GrepRAG Instructions',
129
+ '--',
130
+ relativePath,
131
+ ], {
132
+ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
133
+ maxBuffer: 1024 * 1024,
134
+ })).trim();
135
+ return out.split(/\r?\n/).find(Boolean) || null;
136
+ }
137
+ catch {
138
+ return null;
139
+ }
140
+ }
141
+ function looksManagedOrRenamed(content) {
142
+ return /Agent Doctrine|Doctrine Mirror|agent doctrine|greprag agents|greprag instructions|GrepRAG Instructions/i.test(content);
143
+ }
84
144
  function relativeDirectory(root, requested) {
85
145
  const absolute = requested
86
146
  ? path.resolve(root, requested)
@@ -138,6 +198,146 @@ function parityUnitName(scope, projectId, directory) {
138
198
  : crypto.createHash('sha256').update(directory).digest('hex').slice(0, 8);
139
199
  return `agent-doctrine-${projectId.slice(0, 8)}-${suffix}`;
140
200
  }
201
+ function snapshotContentHash(value) {
202
+ return crypto.createHash('sha256').update(value).digest('hex');
203
+ }
204
+ function normalizeSnapshotName(value) {
205
+ const name = (value || '').trim();
206
+ if (!/^[a-z0-9][a-z0-9._-]{0,79}$/i.test(name)) {
207
+ throw new Error('snapshot name must be 1-80 chars: letters, numbers, dot, underscore, or dash');
208
+ }
209
+ return name;
210
+ }
211
+ function snapshotNameOf(snapshot) {
212
+ return snapshot.snapshotName || 'original';
213
+ }
214
+ function originalSnapshotForTarget(target, scope, projectId, directory, capturedAt) {
215
+ const base = {
216
+ snapshotName: 'original',
217
+ harness: target.harness,
218
+ path: target.manifestPath,
219
+ scope,
220
+ projectId,
221
+ directory,
222
+ capturedAt,
223
+ };
224
+ if (!fs.existsSync(target.actualPath)) {
225
+ return {
226
+ ...base,
227
+ status: 'missing',
228
+ content: '',
229
+ contentHash: snapshotContentHash(''),
230
+ source: 'missing',
231
+ sourceRef: null,
232
+ reason: 'follower file did not exist at adoption time',
233
+ };
234
+ }
235
+ const diskContent = fs.readFileSync(target.actualPath, 'utf8');
236
+ if (looksManagedOrRenamed(diskContent)) {
237
+ const gitRoot = fileGitRoot(target.actualPath);
238
+ if (gitRoot) {
239
+ const rel = path.relative(gitRoot, target.actualPath).replace(/\\/g, '/');
240
+ const firstTouch = firstInstructionTouch(gitRoot, rel);
241
+ if (firstTouch) {
242
+ const historical = gitFileAt(gitRoot, `${firstTouch}^`, rel);
243
+ if (historical !== null) {
244
+ return {
245
+ ...base,
246
+ status: 'present',
247
+ content: historical,
248
+ contentHash: snapshotContentHash(historical),
249
+ source: 'git-history',
250
+ sourceRef: `${firstTouch}^`,
251
+ reason: `pre-GrepRAG-Instructions snapshot from parent of ${firstTouch.slice(0, 12)}`,
252
+ };
253
+ }
254
+ }
255
+ }
256
+ }
257
+ return {
258
+ ...base,
259
+ status: 'present',
260
+ content: diskContent,
261
+ contentHash: snapshotContentHash(diskContent),
262
+ source: 'disk',
263
+ sourceRef: null,
264
+ reason: looksManagedOrRenamed(diskContent)
265
+ ? 'historical pre-instructions file was not recoverable; captured disk bytes'
266
+ : 'captured disk bytes before first GrepRAG Instructions adoption',
267
+ };
268
+ }
269
+ function diskSnapshotForTarget(target, scope, projectId, directory, snapshotName, capturedAt) {
270
+ const base = {
271
+ snapshotName,
272
+ harness: target.harness,
273
+ path: target.manifestPath,
274
+ scope,
275
+ projectId,
276
+ directory,
277
+ capturedAt,
278
+ };
279
+ if (!fs.existsSync(target.actualPath)) {
280
+ return {
281
+ ...base,
282
+ status: 'missing',
283
+ content: '',
284
+ contentHash: snapshotContentHash(''),
285
+ source: 'missing',
286
+ sourceRef: null,
287
+ reason: `snapshot ${snapshotName}: follower file did not exist`,
288
+ };
289
+ }
290
+ const content = fs.readFileSync(target.actualPath, 'utf8');
291
+ return {
292
+ ...base,
293
+ status: 'present',
294
+ content,
295
+ contentHash: snapshotContentHash(content),
296
+ source: 'disk',
297
+ sourceRef: null,
298
+ reason: `snapshot ${snapshotName}: captured disk bytes`,
299
+ };
300
+ }
301
+ function gitRefSnapshotForTarget(target, scope, projectId, directory, snapshotName, capturedAt, ref) {
302
+ const base = {
303
+ snapshotName,
304
+ harness: target.harness,
305
+ path: target.manifestPath,
306
+ scope,
307
+ projectId,
308
+ directory,
309
+ capturedAt,
310
+ };
311
+ const gitRoot = fileGitRoot(target.actualPath);
312
+ if (gitRoot) {
313
+ const rel = path.relative(gitRoot, target.actualPath).replace(/\\/g, '/');
314
+ const content = gitFileAt(gitRoot, ref, rel);
315
+ if (content !== null) {
316
+ return {
317
+ ...base,
318
+ status: 'present',
319
+ content,
320
+ contentHash: snapshotContentHash(content),
321
+ source: 'git-history',
322
+ sourceRef: ref,
323
+ reason: `snapshot ${snapshotName}: captured ${rel} from ${ref}`,
324
+ };
325
+ }
326
+ }
327
+ return {
328
+ ...base,
329
+ status: 'missing',
330
+ content: '',
331
+ contentHash: snapshotContentHash(''),
332
+ source: 'missing',
333
+ sourceRef: ref,
334
+ reason: `snapshot ${snapshotName}: no file at ${ref}`,
335
+ };
336
+ }
337
+ function collectOriginalSnapshots(targets, scope, projectId, directory) {
338
+ const capturedAt = new Date().toISOString();
339
+ return targets.map((target) => originalSnapshotForTarget(target, scope, projectId, directory, capturedAt));
340
+ }
141
341
  function uniqueNonempty(values) {
142
342
  const seen = new Set();
143
343
  const out = [];
@@ -228,6 +428,13 @@ function inferHarness(file, explicit) {
228
428
  return explicit;
229
429
  return file && path.basename(file).toUpperCase() === 'CLAUDE.MD' ? 'claude-code' : 'codex';
230
430
  }
431
+ function parseOptionalHarness(explicit) {
432
+ if (!explicit)
433
+ return undefined;
434
+ if (explicit === 'claude-code' || explicit === 'codex' || explicit === 'opencode')
435
+ return explicit;
436
+ throw new Error('--harness must be claude-code, codex, or opencode');
437
+ }
231
438
  function inferScope(file, explicit) {
232
439
  if (explicit === 'global' || explicit === 'repo')
233
440
  return explicit;
@@ -334,6 +541,9 @@ async function exactSourceCommand(args, mode) {
334
541
  sourcePath,
335
542
  content,
336
543
  expectedRevision: endpointMode === 'revise' ? current?.revision ?? null : null,
544
+ originalSnapshots: endpointMode === 'adopt'
545
+ ? collectOriginalSnapshots(ctx.targets, scope, ctx.projectId, ctx.directory)
546
+ : undefined,
337
547
  followers: ctx.targets.map((target) => ({
338
548
  harness: target.harness,
339
549
  path: target.manifestPath,
@@ -343,6 +553,10 @@ async function exactSourceCommand(args, mode) {
343
553
  });
344
554
  const verb = mode === 'pull' ? 'Pulled' : mode === 'adopt' ? 'Adopted' : 'Revised';
345
555
  console.log(`${verb} ${body.document.scopeKey} revision ${body.document.revision}.`);
556
+ if (endpointMode === 'adopt' && body.document.originalSnapshots?.length) {
557
+ const historical = body.document.originalSnapshots.filter((s) => s.source === 'git-history').length;
558
+ console.log(`Original Snapshots stored: ${body.document.originalSnapshots.length} (${historical} from git history).`);
559
+ }
346
560
  const shouldPush = mode === 'pull'
347
561
  ? args.includes('--push')
348
562
  : !args.includes('--no-sync');
@@ -422,6 +636,218 @@ async function overlayCommand(args) {
422
636
  await syncOne({ scope, args, check: false, force: args.includes('--force') });
423
637
  }
424
638
  }
639
+ function originalSnapshotForRenderTarget(doc, target, scope, projectId, directory, snapshotName) {
640
+ const snapshots = doc.originalSnapshots || [];
641
+ return snapshots.find((snapshot) => snapshot.harness === target.harness
642
+ && snapshotNameOf(snapshot) === snapshotName
643
+ && snapshot.path === target.manifestPath
644
+ && snapshot.scope === scope
645
+ && (scope === 'global' || snapshot.projectId === projectId)
646
+ && snapshot.directory === directory) || null;
647
+ }
648
+ async function restoreOne(params) {
649
+ const ctx = context(params.scope, params.args);
650
+ const doc = await fetchDocument(params.scope, ctx.projectId, ctx.directory);
651
+ if (!doc) {
652
+ console.log(`${params.scope}: no canonical doctrine`);
653
+ return { canonical: false, current: 0, changed: 0, blocked: 0 };
654
+ }
655
+ const stats = { canonical: true, current: 0, changed: 0, blocked: 0 };
656
+ for (const target of ctx.targets.filter(t => targetMatchesHarness(t, params.harness))) {
657
+ const snapshot = originalSnapshotForRenderTarget(doc, target, params.scope, ctx.projectId, ctx.directory, params.snapshotName);
658
+ if (!snapshot) {
659
+ console.log(` blocked ${target.actualPath} — no snapshot '${params.snapshotName}' stored for this follower`);
660
+ stats.blocked++;
661
+ continue;
662
+ }
663
+ const exists = fs.existsSync(target.actualPath);
664
+ const source = exists ? fs.readFileSync(target.actualPath, 'utf8') : '';
665
+ const alreadyOriginal = snapshot.status === 'missing'
666
+ ? !exists
667
+ : exists && source === snapshot.content;
668
+ if (alreadyOriginal) {
669
+ console.log(` current ${target.actualPath}`);
670
+ stats.current++;
671
+ continue;
672
+ }
673
+ const currentRender = renderForTarget(doc, target);
674
+ const cleanManagedFollower = !exists || source === currentRender;
675
+ if (!cleanManagedFollower && !params.force) {
676
+ console.log(` blocked ${target.actualPath} — local edits differ from the current GrepRAG render; rerun with --force only after saving them`);
677
+ stats.blocked++;
678
+ continue;
679
+ }
680
+ const action = snapshot.status === 'missing' ? 'remove' : 'restore';
681
+ const sourceNote = snapshot.source === 'git-history' && snapshot.sourceRef
682
+ ? `${snapshot.source}:${snapshot.sourceRef}`
683
+ : snapshot.source;
684
+ console.log(` ${params.check ? `would-${action}` : action} ${target.actualPath} — snapshot '${params.snapshotName}' from ${sourceNote}`);
685
+ stats.changed++;
686
+ if (params.check)
687
+ continue;
688
+ if (snapshot.status === 'missing') {
689
+ if (exists)
690
+ fs.rmSync(target.actualPath);
691
+ }
692
+ else {
693
+ fs.mkdirSync(path.dirname(target.actualPath), { recursive: true });
694
+ fs.writeFileSync(target.actualPath, snapshot.content, 'utf8');
695
+ }
696
+ }
697
+ return stats;
698
+ }
699
+ async function restoreCommand(args) {
700
+ const snapshotName = normalizeSnapshotName(flag(args, '--snapshot'));
701
+ const requested = flag(args, '--scope') || 'all';
702
+ if (!['global', 'repo', 'all'].includes(requested)) {
703
+ throw new Error('--scope must be global|repo|all');
704
+ }
705
+ const harness = parseOptionalHarness(flag(args, '--harness'));
706
+ const scopes = requested === 'all' ? ['global', 'repo'] : [requested];
707
+ const check = args.includes('--check');
708
+ let changed = 0;
709
+ let blocked = 0;
710
+ for (const scope of scopes) {
711
+ console.log(`${scope}:`);
712
+ const stats = await restoreOne({
713
+ scope,
714
+ args,
715
+ check,
716
+ force: args.includes('--force'),
717
+ snapshotName,
718
+ harness,
719
+ });
720
+ changed += stats.changed;
721
+ blocked += stats.blocked;
722
+ }
723
+ if (changed > 0 && !check) {
724
+ console.log('Restored snapshot bytes. Canon is unchanged; run `greprag instructions pull <file>` to promote restored bytes back into canon.');
725
+ }
726
+ if (check && changed > 0) {
727
+ console.error(`${changed} follower(s) would be restored.`);
728
+ process.exitCode = 1;
729
+ }
730
+ if (blocked > 0)
731
+ process.exitCode = 1;
732
+ }
733
+ function snapshotSummary(doc) {
734
+ const out = new Map();
735
+ for (const snapshot of doc.originalSnapshots || []) {
736
+ const name = snapshotNameOf(snapshot);
737
+ const rows = out.get(name) || [];
738
+ rows.push(snapshot);
739
+ out.set(name, rows);
740
+ }
741
+ return out;
742
+ }
743
+ async function snapshotCreateOne(params) {
744
+ const ctx = context(params.scope, params.args);
745
+ const doc = await fetchDocument(params.scope, ctx.projectId, ctx.directory);
746
+ if (!doc) {
747
+ console.log(`${params.scope}: no canonical doctrine`);
748
+ return 0;
749
+ }
750
+ const targets = ctx.targets.filter(t => targetMatchesHarness(t, params.harness));
751
+ const capturedAt = new Date().toISOString();
752
+ const snapshots = targets.map((target) => params.fromRef
753
+ ? gitRefSnapshotForTarget(target, params.scope, ctx.projectId, ctx.directory, params.snapshotName, capturedAt, params.fromRef)
754
+ : diskSnapshotForTarget(target, params.scope, ctx.projectId, ctx.directory, params.snapshotName, capturedAt));
755
+ const body = await apiJson('/v1/agents/snapshot', {
756
+ method: 'POST',
757
+ body: JSON.stringify({
758
+ scope: params.scope,
759
+ projectId: ctx.projectId,
760
+ directory: ctx.directory,
761
+ snapshotName: params.snapshotName,
762
+ snapshots,
763
+ replace: params.force,
764
+ expectedRevision: doc.revision,
765
+ }),
766
+ });
767
+ const present = snapshots.filter((snapshot) => snapshot.status === 'present').length;
768
+ console.log(`${params.scope}: stored snapshot '${params.snapshotName}' for ${snapshots.length} follower(s) (${present} present) at revision ${body.document.revision}.`);
769
+ return snapshots.length;
770
+ }
771
+ async function snapshotListOne(scope, args) {
772
+ const ctx = context(scope, args);
773
+ const doc = await fetchDocument(scope, ctx.projectId, ctx.directory);
774
+ if (!doc) {
775
+ console.log(`${scope}: no canonical doctrine`);
776
+ return;
777
+ }
778
+ console.log(`${scope}: ${doc.scopeKey} revision ${doc.revision}`);
779
+ const groups = snapshotSummary(doc);
780
+ if (groups.size === 0) {
781
+ console.log(' no snapshots');
782
+ return;
783
+ }
784
+ for (const [name, rows] of [...groups.entries()].sort(([a], [b]) => a.localeCompare(b))) {
785
+ const present = rows.filter((row) => row.status === 'present').length;
786
+ const capturedAt = rows.map((row) => row.capturedAt).sort()[0] || '(unknown)';
787
+ console.log(` ${name}: ${rows.length} follower(s), ${present} present, first captured ${capturedAt}`);
788
+ }
789
+ }
790
+ async function snapshotShowOne(scope, args, snapshotName) {
791
+ const ctx = context(scope, args);
792
+ const doc = await fetchDocument(scope, ctx.projectId, ctx.directory);
793
+ if (!doc) {
794
+ console.log(`${scope}: no canonical doctrine`);
795
+ return;
796
+ }
797
+ const rows = (doc.originalSnapshots || [])
798
+ .filter((snapshot) => snapshotNameOf(snapshot) === snapshotName);
799
+ console.log(`${scope}: ${doc.scopeKey} revision ${doc.revision}`);
800
+ if (rows.length === 0) {
801
+ console.log(` snapshot '${snapshotName}' not found`);
802
+ return;
803
+ }
804
+ for (const row of rows) {
805
+ const ref = row.sourceRef ? ` ${row.sourceRef}` : '';
806
+ console.log(` ${row.harness} ${row.path}`);
807
+ console.log(` ${row.status} ${row.source}${ref} ${row.contentHash}`);
808
+ if (row.reason)
809
+ console.log(` ${row.reason}`);
810
+ }
811
+ }
812
+ async function snapshotCommand(args) {
813
+ const action = args[0];
814
+ const requested = flag(args, '--scope') || 'all';
815
+ if (!['global', 'repo', 'all'].includes(requested)) {
816
+ throw new Error('--scope must be global|repo|all');
817
+ }
818
+ const scopes = requested === 'all' ? ['global', 'repo'] : [requested];
819
+ if (action === 'create') {
820
+ const snapshotName = normalizeSnapshotName(flag(args, '--name'));
821
+ const harness = parseOptionalHarness(flag(args, '--harness'));
822
+ const fromRef = flag(args, '--from-ref');
823
+ let count = 0;
824
+ for (const scope of scopes) {
825
+ count += await snapshotCreateOne({
826
+ scope,
827
+ args,
828
+ snapshotName,
829
+ fromRef,
830
+ force: args.includes('--force'),
831
+ harness,
832
+ });
833
+ }
834
+ if (count > 0)
835
+ console.log('Snapshot storage only changed rollback metadata; canon render bytes are unchanged.');
836
+ return;
837
+ }
838
+ if (action === 'list') {
839
+ for (const scope of scopes)
840
+ await snapshotListOne(scope, args);
841
+ return;
842
+ }
843
+ if (action === 'show') {
844
+ const snapshotName = normalizeSnapshotName(args[1] && !args[1].startsWith('-') ? args[1] : flag(args, '--name'));
845
+ for (const scope of scopes)
846
+ await snapshotShowOne(scope, args, snapshotName);
847
+ return;
848
+ }
849
+ throw new Error('snapshot requires create, list, or show');
850
+ }
425
851
  async function syncCommand(args, checkOverride = false) {
426
852
  const requested = flag(args, '--scope') || 'all';
427
853
  if (!['global', 'repo', 'all'].includes(requested)) {
@@ -445,7 +871,7 @@ async function syncCommand(args, checkOverride = false) {
445
871
  }
446
872
  /** Init-time seed for the active harness. No canon is a clean no-op; only a
447
873
  * missing/empty follower is written. Every existing nonmatching file requires
448
- * an explicit `agents push` or `agents pull`. */
874
+ * an explicit `instructions push` or `instructions pull`. */
449
875
  async function bootstrapAgentDoctrine(apiKey, harness) {
450
876
  const result = {
451
877
  canonicalScopes: [], currentFollowers: 0, changedFollowers: 0, blockedFollowers: 0,
@@ -462,10 +888,10 @@ async function bootstrapAgentDoctrine(apiKey, harness) {
462
888
  }
463
889
  return result;
464
890
  }
465
- async function runAgents(args) {
891
+ async function runInstructionsCommand(args, commandName) {
466
892
  const sub = args[0];
467
893
  if (!sub || sub === 'help' || sub === '--help' || sub === '-h') {
468
- console.log(HELP);
894
+ console.log(help(commandName));
469
895
  return;
470
896
  }
471
897
  if (sub === 'pull')
@@ -478,13 +904,23 @@ async function runAgents(args) {
478
904
  return exactSourceCommand(args.slice(1), 'revise');
479
905
  if (sub === 'overlay')
480
906
  return overlayCommand(args.slice(1));
907
+ if (sub === 'snapshot')
908
+ return snapshotCommand(args.slice(1));
909
+ if (sub === 'restore')
910
+ return restoreCommand(args.slice(1));
481
911
  if (sub === 'optimize') {
482
- throw new Error('agents optimize was removed: use lossless agents pull or explicit agents overlay');
912
+ throw new Error(`${commandName} optimize was removed: use lossless ${commandName} pull or explicit ${commandName} overlay`);
483
913
  }
484
914
  if (sub === 'sync')
485
915
  return syncCommand(args.slice(1));
486
916
  if (sub === 'status')
487
917
  return syncCommand(args.slice(1), true);
488
- throw new Error(`unknown agents command: ${sub}`);
918
+ throw new Error(`unknown ${commandName} command: ${sub}`);
919
+ }
920
+ async function runInstructions(args) {
921
+ return runInstructionsCommand(args, 'instructions');
922
+ }
923
+ async function runAgents(args) {
924
+ return runInstructionsCommand(args, 'agents');
489
925
  }
490
926
  //# sourceMappingURL=agents.js.map