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.
- package/dist/codex-chip-hooks.js +1 -1
- package/dist/codex-chip-hooks.js.map +1 -1
- package/dist/commands/agent-doctrine-file.d.ts +1 -1
- package/dist/commands/agent-doctrine-file.js +1 -1
- package/dist/commands/agents.d.ts +28 -2
- package/dist/commands/agents.js +454 -18
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/codex-chip/prompt.js +1 -1
- package/dist/commands/codex-chip/prompt.js.map +1 -1
- package/dist/commands/fix.js +6 -5
- package/dist/commands/fix.js.map +1 -1
- package/dist/commands/friction-reminder.d.ts +1 -1
- package/dist/commands/friction-reminder.js +4 -4
- package/dist/commands/friction-reminder.js.map +1 -1
- package/dist/commands/init.js +7 -7
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/load.js +8 -7
- package/dist/commands/load.js.map +1 -1
- package/dist/commands/mechanic-spawn.d.ts +9 -9
- package/dist/commands/mechanic-spawn.js +29 -70
- package/dist/commands/mechanic-spawn.js.map +1 -1
- package/dist/commands/mechanic.js +4 -4
- package/dist/commands/os-primer-reminder.js +1 -1
- package/dist/commands/os-primer-reminder.js.map +1 -1
- package/dist/commands/parity.js +1 -1
- package/dist/commands/parity.js.map +1 -1
- package/dist/commands/ship-through-gate.d.ts +16 -0
- package/dist/commands/ship-through-gate.js +43 -0
- package/dist/commands/ship-through-gate.js.map +1 -0
- package/dist/commands/skill.js +59 -6
- package/dist/commands/skill.js.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/native-skill-adoption.d.ts +45 -0
- package/dist/native-skill-adoption.js +240 -0
- package/dist/native-skill-adoption.js.map +1 -0
- package/dist/opencode-plugin.bundle.js +4 -4
- package/dist/skill-mirror-client.d.ts +25 -0
- package/dist/skill-mirror-client.js +58 -0
- package/dist/skill-mirror-client.js.map +1 -1
- package/package.json +1 -1
- package/skill/greprag/docs/codex-chip.md +11 -12
- package/skill/mechanic/SKILL.md +8 -8
- package/skill/templates/chip-spawn.md +1 -1
- package/skill/templates/codex-chip-spawn.md +130 -248
package/dist/codex-chip-hooks.js
CHANGED
|
@@ -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.
|
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyJA,sDAMC;AA/JD,uCAAyB;AACzB,2CAA6B;AAE7B,uDAAoE;AACpE,uDAA4F;AAC5F,yDAAgF;AAChF,iCAA0C;AAmB1C,SAAS,WAAW,CAAC,KAAoB;IACvC,OAAO,IAAA,6BAAqB,EAAC,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,MAAM,CAAC,KAAa,EAAE,iBAAyB,EAAE,MAAe;IACvE,OAAO;QACL,kBAAkB,EAAE;YAClB,aAAa,EAAE,KAAK;YACpB,iBAAiB;YACjB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,MAAM,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,KAAoB;IACnC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,SAAS,CAAC;IAC/C,MAAM,KAAK,GAAG;QACZ,uBAAuB,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;QAC7C,SAAS,IAAA,iBAAS,EAAC,IAAI,CAAC,EAAE;QAC1B,eAAe,IAAI,CAAC,IAAI,EAAE;QAC1B,aAAa,IAAA,yBAAiB,EAAC,IAAI,CAAC,EAAE;QACtC,WAAW,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;QACjC,mBAAmB,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,cAAc,EAAE;QAC5D,0NAA0N,GAAG,sBAAsB,IAAI,CAAC,EAAE,GAAG;QAC7P,6FAA6F;QAC7F,
|
|
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
|
|
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
|
|
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
|
|
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 `
|
|
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 {};
|
package/dist/commands/agents.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/** `greprag
|
|
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
|
-
|
|
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
|
|
50
|
-
greprag
|
|
51
|
-
greprag
|
|
52
|
-
greprag
|
|
53
|
-
greprag
|
|
54
|
-
greprag
|
|
55
|
-
greprag
|
|
56
|
-
greprag
|
|
57
|
-
greprag
|
|
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
|
|
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
|
-
|
|
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 `
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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
|