greprag 5.84.0 → 5.85.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,8 @@
1
1
  "use strict";
2
- /** Skill-mirror client — the Tier-3 mirror's upload half
3
- * (docs/load-system.md §Tier 3). Runs inside the Stop hook: a skill-load turn
4
- * triggers `maybeMirrorSkill`, which content-hashes the skill's markdown and
5
- * uploads ONLY on change. Follower semantics — files canonical, the mirror
6
- * shadows "last used state." Best-effort end to end: a mirror failure never
7
- * touches the turn.
8
- *
9
- * Local freshness state (`~/.greprag/state/skill-mirror.json`) remembers the
10
- * last-mirrored hash per skill so an unchanged skill costs one hash pass and
11
- * ZERO network. Markdown only, v1 — SKILL.md + docs/**\/*.md; script-bearing
12
- * assets stay file-bound (see the spec's named gaps). */
2
+ /** Skill package reader: the markdown a mirrored skill carries (SKILL.md +
3
+ * docs/**\/*.md) and its content hash. Used to verify an export and to send a
4
+ * loadout. The mirror itself is written only by git ingestion
5
+ * (skill-git-ingest.ts, adr/skill-ownership-git.md). */
13
6
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
7
  if (k2 === undefined) k2 = k;
15
8
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -44,44 +37,11 @@ var __importStar = (this && this.__importStar) || (function () {
44
37
  };
45
38
  })();
46
39
  Object.defineProperty(exports, "__esModule", { value: true });
47
- exports.skillRevisionAuthor = skillRevisionAuthor;
48
40
  exports.collectSkillFiles = collectSkillFiles;
49
41
  exports.computeMirrorHash = computeMirrorHash;
50
- exports.dryRunNativeSkillAdoption = dryRunNativeSkillAdoption;
51
- exports.syncNativeSkillAdoptions = syncNativeSkillAdoptions;
52
- exports.readMirrorState = readMirrorState;
53
- exports.writeMirrorState = writeMirrorState;
54
- exports.maybeMirrorSkill = maybeMirrorSkill;
55
42
  const fs = __importStar(require("fs"));
56
43
  const path = __importStar(require("path"));
57
- const skill_landing_1 = require("./skill-landing");
58
- const native_skill_adoption_1 = require("./native-skill-adoption");
59
- const native_skill_mirror_1 = require("./native-skill-mirror");
60
44
  const skill_mirror_files_1 = require("./skill-mirror-files");
61
- const proc_1 = require("./proc");
62
- /** Who is writing skill canon, for the revision row every write records:
63
- * the writer (`via`), the harness session, and the chip branch when the
64
- * write runs inside one. adr: adr/skill-revision-history.md */
65
- function skillRevisionAuthor(via, opts = {}) {
66
- const env = process.env;
67
- const harness = opts.harness
68
- || (env.CLAUDE_CODE_SESSION_ID || env.CLAUDECODE ? 'claude-code'
69
- : env.CODEX_THREAD_ID || env.CODEX_CI || env.CODEX_SHELL ? 'codex'
70
- : env.OPENCODE_SESSION_ID ? 'opencode' : 'cli');
71
- const sessionId = opts.sessionId || env.CLAUDE_CODE_SESSION_ID || env.CODEX_THREAD_ID
72
- || env.OPENCODE_SESSION_ID || env.GREPRAG_SESSION_ID || '';
73
- let chip = '';
74
- try {
75
- const branch = (0, proc_1.safeSpawnSync)('git', ['branch', '--show-current'], {
76
- cwd: opts.cwd || process.cwd(), encoding: 'utf8', timeout: 3000,
77
- });
78
- const name = String(branch.stdout || '').trim();
79
- if (branch.status === 0 && name.startsWith('chip/'))
80
- chip = name;
81
- }
82
- catch { /* not a git checkout */ }
83
- return { via, harness, ...(sessionId ? { sessionId } : {}), ...(chip ? { chip } : {}) };
84
- }
85
45
  /** Mirrors the server's caps (SKILL_MIRROR_* in @greprag/core — the CLI is
86
46
  * core-free, so the numbers are restated; the server re-validates anyway). */
87
47
  const MAX_FILES = 20;
@@ -141,239 +101,3 @@ function collectSkillFiles(skillDir) {
141
101
  function computeMirrorHash(files) {
142
102
  return (0, skill_mirror_files_1.computeSkillFileHash)(files);
143
103
  }
144
- function dryRunNativeSkillAdoption(params) {
145
- return (0, native_skill_adoption_1.planNativeSkillAdoption)({ ...params, collectFiles: collectSkillFiles });
146
- }
147
- function adoptedSkillId(candidate) {
148
- return candidate.scope === 'project'
149
- ? `project:${candidate.projectId}:${candidate.skillName}`
150
- : `global:${candidate.skillName}`;
151
- }
152
- async function responseJson(response) {
153
- try {
154
- return await response.json();
155
- }
156
- catch {
157
- return {};
158
- }
159
- }
160
- async function ensureNativeAdoptionOriginalSnapshot(params) {
161
- const skillId = adoptedSkillId(params.candidate);
162
- const snapshotPath = `/v1/skillmirror/${encodeURIComponent(params.candidate.skillName)}/snapshots/original`;
163
- const body = {
164
- scope: params.candidate.scope,
165
- projectId: params.candidate.projectId,
166
- skillId,
167
- source: 'disk',
168
- sourceRef: path.join(params.candidate.root, params.candidate.skillName),
169
- reason: 'captured native skill package before GrepRAG adapter adoption',
170
- };
171
- const created = await fetch(`${params.apiUrl}${snapshotPath}`, {
172
- method: 'POST',
173
- headers: { 'Authorization': `Bearer ${params.apiKey}`, 'Content-Type': 'application/json' },
174
- body: JSON.stringify(body),
175
- });
176
- if (created.ok)
177
- return true;
178
- if (created.status !== 409)
179
- return false;
180
- const query = new URLSearchParams({
181
- scope: params.candidate.scope,
182
- skillId,
183
- ...(params.candidate.projectId ? { projectId: params.candidate.projectId } : {}),
184
- });
185
- const existing = await fetch(`${params.apiUrl}${snapshotPath}?${query.toString()}`, {
186
- method: 'GET',
187
- headers: { 'Authorization': `Bearer ${params.apiKey}` },
188
- });
189
- if (!existing.ok)
190
- return false;
191
- const data = await responseJson(existing);
192
- const snapshot = data.snapshot;
193
- return snapshot?.contentHash === params.candidate.sourceHash;
194
- }
195
- async function syncNativeSkillAdoptions(params) {
196
- const plan = dryRunNativeSkillAdoption(params);
197
- const result = {
198
- plan,
199
- adopted: 0,
200
- blocked: plan.blocked.length,
201
- skipped: plan.skipped.length,
202
- };
203
- if (params.dryRun)
204
- return result;
205
- for (const candidate of plan.candidates) {
206
- const body = {
207
- files: candidate.files,
208
- contentHash: candidate.sourceHash,
209
- scope: candidate.scope,
210
- projectId: candidate.projectId,
211
- projectName: candidate.projectName,
212
- reason: `adoption of native ${params.platform} skill from ${path.join(candidate.root, candidate.skillName)}`,
213
- author: skillRevisionAuthor('adoption', { cwd: params.projectDir }),
214
- };
215
- const response = await fetch(`${params.apiUrl}/v1/skillmirror/${encodeURIComponent(candidate.skillName)}`, {
216
- method: 'POST',
217
- headers: { 'Authorization': `Bearer ${params.apiKey}`, 'Content-Type': 'application/json' },
218
- body: JSON.stringify(body),
219
- });
220
- if (!response.ok) {
221
- result.blocked++;
222
- continue;
223
- }
224
- const snapshotted = await ensureNativeAdoptionOriginalSnapshot({
225
- apiUrl: params.apiUrl,
226
- apiKey: params.apiKey,
227
- candidate,
228
- });
229
- if (!snapshotted) {
230
- result.blocked++;
231
- continue;
232
- }
233
- const installed = (0, native_skill_adoption_1.installAdoptedNativeSkill)({
234
- platform: params.platform,
235
- root: candidate.root,
236
- expectedSourceHash: candidate.sourceHash,
237
- collectFiles: collectSkillFiles,
238
- skill: {
239
- skillName: candidate.skillName,
240
- skillId: adoptedSkillId(candidate),
241
- scope: candidate.scope,
242
- projectId: candidate.projectId,
243
- projectName: candidate.projectName,
244
- files: candidate.files,
245
- },
246
- });
247
- if (installed === 'installed')
248
- result.adopted++;
249
- else if (installed === 'blocked')
250
- result.blocked++;
251
- else
252
- result.skipped++;
253
- }
254
- return result;
255
- }
256
- function materializeLocally(skillName, files, cwd) {
257
- for (const platform of native_skill_mirror_1.NATIVE_SKILL_ADAPTER_PLATFORMS) {
258
- try {
259
- (0, native_skill_mirror_1.applyNativeSkillMirror)({
260
- platform,
261
- skills: [{
262
- skillName,
263
- skillId: `global:${skillName}`,
264
- scope: 'global',
265
- contentHash: computeMirrorHash(files),
266
- files,
267
- }],
268
- projectDir: cwd,
269
- prune: false,
270
- });
271
- }
272
- catch { /* local adapter failure never breaks turn capture */ }
273
- }
274
- }
275
- function statePath() {
276
- const home = process.env.HOME || process.env.USERPROFILE || '';
277
- return path.join(home, '.greprag', 'state', 'skill-mirror.json');
278
- }
279
- function readMirrorState() {
280
- try {
281
- const parsed = JSON.parse(fs.readFileSync(statePath(), 'utf-8'));
282
- if (parsed && typeof parsed.skills === 'object' && parsed.skills) {
283
- return { skills: parsed.skills };
284
- }
285
- }
286
- catch { /* missing/unreadable → empty */ }
287
- return { skills: {} };
288
- }
289
- function writeMirrorState(state) {
290
- try {
291
- const file = statePath();
292
- fs.mkdirSync(path.dirname(file), { recursive: true });
293
- fs.writeFileSync(file, JSON.stringify(state, null, 2) + '\n');
294
- }
295
- catch { /* best-effort — worst case is one redundant upload next use */ }
296
- }
297
- async function fetchRemoteSkillHash(params) {
298
- try {
299
- const res = await fetch(`${params.apiUrl}/v1/skillmirror/${encodeURIComponent(params.skill)}?scope=global`, {
300
- headers: { 'Authorization': `Bearer ${params.apiKey}` },
301
- });
302
- if (res.status === 404)
303
- return null;
304
- if (!res.ok)
305
- return null;
306
- const data = await responseJson(res);
307
- return typeof data.contentHash === 'string' ? data.contentHash : null;
308
- }
309
- catch {
310
- return null;
311
- }
312
- }
313
- /** Mirror one skill if its content changed since the last mirror. Never throws. */
314
- async function maybeMirrorSkill(params) {
315
- try {
316
- if (!/^[A-Za-z0-9._-]{1,64}$/.test(params.skill))
317
- return 'skipped';
318
- const homeDir = process.env.HOME || process.env.USERPROFILE || '';
319
- const dir = (0, skill_landing_1.resolveSkillDir)(params.skill, params.cwd, homeDir);
320
- if (!dir)
321
- return 'skipped';
322
- const files = collectSkillFiles(dir);
323
- if (!files)
324
- return 'skipped';
325
- // The disk copy of an already-mirrored skill is the generated ADAPTER that
326
- // `materializeLocally` wrote below — a launcher whose whole body says "run
327
- // `greprag load <name>`". Uploading it makes it canon, and `greprag load`
328
- // then serves the launcher back to the agent that was told to run it: the
329
- // skill's real instructions are gone and nothing errors. That loop closed
330
- // here, one turn after every first mirror, and had already eaten the
331
- // canonical body of skills including anti-ai, chrome, gmail and root-cause.
332
- //
333
- // An adapter is never a mirror source. Canon changes through the guarded
334
- // edit path (`greprag skill edit` / `skill mirror apply`), never by
335
- // shadowing a file greprag itself generated. adr: adr/skill-adapter-never-canon.md
336
- const main = files.find(file => file.path === 'SKILL.md');
337
- if (main && (0, skill_mirror_files_1.isGeneratedSkillAdapter)(main.content))
338
- return 'skipped';
339
- const hash = computeMirrorHash(files);
340
- const state = readMirrorState();
341
- const localLease = state.skills[params.skill]?.hash;
342
- if (localLease === hash) {
343
- materializeLocally(params.skill, files, params.cwd);
344
- return 'fresh';
345
- }
346
- if (!localLease) {
347
- const remoteHash = await fetchRemoteSkillHash(params);
348
- if (remoteHash === hash) {
349
- state.skills[params.skill] = { hash, mirroredAt: new Date().toISOString() };
350
- writeMirrorState(state);
351
- materializeLocally(params.skill, files, params.cwd);
352
- return 'fresh';
353
- }
354
- if (remoteHash)
355
- return 'skipped';
356
- }
357
- const res = await fetch(`${params.apiUrl}/v1/skillmirror/${encodeURIComponent(params.skill)}`, {
358
- method: 'POST',
359
- headers: { 'Authorization': `Bearer ${params.apiKey}`, 'Content-Type': 'application/json' },
360
- body: JSON.stringify({
361
- files,
362
- contentHash: hash,
363
- scope: 'global',
364
- expectedHash: localLease,
365
- reason: params.reason || `shadow upload of local edit from ${dir}`,
366
- author: skillRevisionAuthor('shadow-upload', { cwd: params.cwd, sessionId: params.sessionId }),
367
- }),
368
- });
369
- if (!res.ok)
370
- return 'skipped';
371
- state.skills[params.skill] = { hash, mirroredAt: new Date().toISOString() };
372
- writeMirrorState(state);
373
- materializeLocally(params.skill, files, params.cwd);
374
- return 'mirrored';
375
- }
376
- catch {
377
- return 'skipped';
378
- }
379
- }
@@ -358,7 +358,7 @@ function formatSkillStaleness(report, options = {}) {
358
358
  lines.push('1. Pause trusting this skill; read the changed watched source files/diffs first.');
359
359
  lines.push('2. Classify relevance: low relevance or small delta -> use repo source as truth; no chip.');
360
360
  lines.push('3. If this task depends on the stale area and the delta is material, spawn a skill-refresh chip.');
361
- lines.push('4. The refresh chip must run `greprag load skill-change`, edit canonical GrepRAG skill source, and never edit local generated adapters.');
361
+ lines.push('4. The refresh chip edits the skill\'s git folder (~/.claude/skills/<name>/ in dotclaude, or <repo>/.claude/skills/<name>/) and commits; the mirror follows.');
362
362
  }
363
363
  if (report.projects.some(p => p.dirtyPaths.length > 0)) {
364
364
  lines.push('Baseline rule: do not stamp a new baseline while watched local edits are dirty.');
@@ -372,11 +372,8 @@ function formatSkillNoSourceBinding(skillName) {
372
372
  return [
373
373
  '[greprag skill-staleness - no source binding]',
374
374
  `/${skillName} has no source bindings.`,
375
- 'Authority: canonical mirrored payload exists in GrepRAG; local Codex/Claude/OpenCode SKILL.md files are generated adapter-only mirrors.',
376
- 'Do not edit a local native adapter as skill content.',
377
- `Agent-safe edit path: \`greprag skill mirror export ${skillName} --to <dir>\`, patch the exported Markdown files non-interactively, then \`greprag skill mirror apply <dir> --skill ${skillName} --expected-hash <exported-hash> --reason "<why>"\`.`,
378
- `Human editor shortcut: \`greprag skill edit ${skillName} --reason "<why>"\`; Codex auto-skips the editor, and agents may pass \`--no-open\` explicitly.`,
379
- `After binding a real source repo, stamp it with \`greprag skill source stamp ${skillName} --project <p> --path <rel>\`.`,
375
+ `Authority: git. Edit ~/.claude/skills/${skillName}/ (dotclaude) or <repo>/.claude/skills/${skillName}/ and commit; GrepRAG mirrors the committed files read only. Codex/OpenCode SKILL.md files are generated launchers, never content.`,
376
+ `To watch a source repo, stamp a binding into the git SKILL.md with \`greprag skill source stamp ${skillName} --project <p> --path <rel>\`, then commit.`,
380
377
  ].join('\n') + '\n';
381
378
  }
382
379
  function stampSourceBinding(params) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "greprag",
3
- "version": "5.84.0",
3
+ "version": "5.85.1",
4
4
  "description": "Private GrepRAG client for existing Claude Code, Codex, OpenCode, and Grok Build tenants.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -53,6 +53,6 @@ Each: **signature** (how it shows up in the run) · **location** (where it lives
53
53
 
54
54
  - **One friction, one edit.** If a run surfaced two defects, make two separate edits, each shown for its own accept/revert. Never batch.
55
55
  - **Apply + show diff.** Make the edit, then show the unified diff and stop for one accept/revert. (This is the operator-chosen gate; the Mechanic "always confirm" rule still holds.)
56
- - **Edit the canonical source.** Managed skills: `greprag skill edit <name> --skill-id <id> --reason "<the friction this fixes>"`; greprag-bundled skills: `packages/cli/skill/<name>/`. Never edit a generated `~/.claude/skills/<name>/SKILL.md` adapter or install artifact.
56
+ - **Edit the git source and commit.** Global skills: `~/.claude/skills/<name>/` (dotclaude repo); project skills: `<repo>/.claude/skills/<name>/`; greprag-bundled skills: `packages/cli/skill/<name>/`. The commit message names the friction this fixes. Never edit a generated Codex/OpenCode launcher or the installed copy of a bundled skill.
57
57
  - **Line budget:** a fix must not grow SKILL.md without adding a real proactive-fire rule or per-task step. Converting wallpaper → Convention B is net-neutral or smaller; mis-route adds at most one line.
58
58
  - **Out of taxonomy → spawn, don't improvise.** Anything not matching the six becomes one `greprag fix spawn --type doctrine "<unit>"` chip. `greprag fix log` is only for deliberate audit/design notes.
@@ -31,7 +31,7 @@ conversation. The registration is part of the work, not an extra:
31
31
 
32
32
  - **Docs** mirror through `greprag doc mirror sync` and can still auto-register
33
33
  pointers when edited in a live session. Search/read them through the CLI.
34
- - **Skills** auto-mirror on use (`greprag load` serves them cross-machine).
34
+ - **Skills** live in git (`~/.claude/skills/<name>/` or `<repo>/.claude/skills/<name>/`); commit them and the mirror follows (`greprag load` serves them cross-machine).
35
35
  - **Decisions** get a dated entry in the owning ADR / decision log, in the
36
36
  same commit as the code.
37
37
  - **Everything else** (state files, artifacts, conventions) gets its path
@@ -1,4 +1,4 @@
1
- # Prompt Audit — dated-model cruft in canonical instructions
1
+ # Prompt Audit — dated-model cruft in agent instructions
2
2
 
3
3
  <!-- adr: adr/prompt-audit-canon.md -->
4
4
 
@@ -14,56 +14,35 @@ local skill adapters may not override it.
14
14
 
15
15
  ## The one invariant
16
16
 
17
- **AUDIT FINDINGS LAND IN CANON, NEVER IN A FOLLOWER.** Global and repo
18
- instructions are served by `greprag load instructions`; `~/.claude/CLAUDE.md`,
19
- `~/.codex/AGENTS.md`, `<repo>/CLAUDE.md`, `<repo>/AGENTS.md` are one-way
20
- rendered followers. Editing a follower directly produces drift: the next
21
- `greprag instructions push` blocks with `local-change`, and the parity guard
22
- routes the repair back to `instructions pull`. So an accepted audit edit is
23
- applied to a **proposed revision file** in scratch and promoted with
24
- `greprag instructions pull <file> --scope <scope> --harness <harness> --push`.
25
- That single command advances canon (optimistic concurrency, `expectedRevision`)
26
- and materializes every follower for the scope. Nothing else writes a follower.
17
+ **AUDIT FINDINGS LAND IN THE GIT SOURCE, NEVER IN A RENDERED FILE.**
18
+ `~/.claude/CLAUDE.md` in the dotclaude repo is the global source; a repo's
19
+ `CLAUDE.md` and `AGENTS.md` are ordinary files in that repo.
20
+ `~/.codex/AGENTS.md` and `~/.config/opencode/AGENTS.md` are rendered from
21
+ `~/.claude/CLAUDE.md` plus `~/.claude/instructions/<codex|opencode>.md` by
22
+ `greprag instructions render` (session start runs it), so an edit there is
23
+ overwritten. GrepRAG's copy (`greprag load instructions`) is read only and
24
+ follows the last commit.
27
25
 
28
26
  ## Procedure
29
27
 
30
- 1. **Scope and target model.** `--scope global` audits the tenant-global
31
- revision; `--scope repo` audits the current repo's root revision. Target
28
+ 1. **Scope and target model.** Global audits `~/.claude/CLAUDE.md`; repo
29
+ audits the current repo's `CLAUDE.md`/`AGENTS.md`. Target
32
30
  model is the one Claude Code sessions run today (Claude Fable 5.1 as of
33
31
  2026-09). State both at the top of the report; do not ask.
34
- 2. **Render canon, not disk.**
35
- `greprag load instructions --scope global --harness claude-code > <scratch>/canon-global.md`
36
- (repo: `--scope repo`). Confirm followers are fresh first with
37
- `greprag instructions status --scope <scope>`; if any follower is
38
- `local-change`, stop and have the operator `instructions pull` it before
39
- auditing, or the audit will grade a stale canon.
40
- Overlays: `instructions` canon is `shared` + per-harness raw suffixes. When
41
- a suffix is non-empty, audit each harness render separately and land
42
- suffix edits with `instructions overlay set|derive`, never by pulling a
43
- rendered file as `shared`. When all suffixes are empty (check the document
44
- via the API or `overlay` history), the Claude render **is** `shared` and
45
- `pull` of the revised Claude render is exact.
46
- 3. **Provenance.** The Claude follower is usually Git-tracked
47
- (`~/.claude` dotclaude repo; repo files in the repo). `git log`/`git blame`
32
+ 2. **Read the source.** Global: `~/.claude/CLAUDE.md` plus any
33
+ `~/.claude/instructions/<harness>.md` addition; audit each addition
34
+ separately. Repo: that repo's `CLAUDE.md` and `AGENTS.md`. Confirm the
35
+ rendered files are current with `greprag instructions status`.
36
+ 3. **Provenance.** Every source file is in git. `git log`/`git blame`
48
37
  each emphatic or prohibitive line: which failure, on which model, did it
49
38
  prevent, and does it still reproduce on the target model?
50
39
  4. **Classify every line** with the rubric below. Produce the report and the
51
40
  proposed diff, both, always.
52
- 5. **Land.** Copy the canon render to `<scratch>/proposed-<scope>.md`, apply
53
- ONLY high-confidence hunks, then:
54
- ```text
55
- greprag instructions snapshot create --name pre-prompt-audit-<YYYY-MM-DD> --scope <scope>
56
- greprag instructions pull <scratch>/proposed-<scope>.md --scope <scope> --harness claude-code --push
57
- greprag instructions status --scope <scope> # every follower fresh
58
- ```
59
- Medium findings and flags stay in the report for the operator; they are
60
- applied by a later `pull` of an operator-approved revision, the same way.
61
- If the follower lives in a Git repo, the push dirties it; the operator
62
- commits that repo (the audit never runs git there).
63
- 6. **Write the report** to `tasks/prompt-audit-<scope>-<date>.md` in the
64
- repo you are working in (or scratch if the repo has no `tasks/`), in the
65
- shape under "Report shape". Persona (`greprag persona show`) is a separate
66
- system: note Persona findings in the report; never edit it from here.
41
+ 5. **Land.** Apply ONLY high-confidence hunks to the source file, show the
42
+ diff, and leave the commit to the operator (the audit never runs git in
43
+ their repos). After the commit, `greprag instructions render` rewrites the
44
+ AGENTS.md files and refreshes GrepRAG's copy. Medium findings and flags
45
+ stay in the report for the operator.
67
46
 
68
47
  ## Rubric (shipped copy — Anthropic prompt-audit, condensed, binding)
69
48
 
@@ -166,12 +145,12 @@ returns 400; prefill is replaced by structured outputs.
166
145
  ## Report shape
167
146
 
168
147
  Top: Assumptions (scope, target model), Inventory (what was audited and its
169
- canon revision), Summary (counts per group; two or three highest-impact
148
+ source commit), Summary (counts per group; two or three highest-impact
170
149
  findings in prose). Then one entry per finding, ordered by confidence:
171
150
 
172
151
  | Field | Content |
173
152
  |---|---|
174
- | Location | `file:line` in the canon render |
153
+ | Location | `file:line` in the source file |
175
154
  | Evidence | exact quoted text |
176
155
  | Pattern | the group/row above |
177
156
  | Why obsolete | one or two sentences tied to the target model's documented behavior |
@@ -185,12 +164,10 @@ only when tests, docs, and references to the removed text go too).
185
164
 
186
165
  ## Guardrails
187
166
 
188
- - Never edit `~/.claude/CLAUDE.md`, `~/.codex/AGENTS.md`,
189
- `~/.config/opencode/AGENTS.md`, or a repo `CLAUDE.md`/`AGENTS.md` by hand.
190
- The only follower writer is `instructions push` (or `pull --push`).
167
+ - Never edit `~/.codex/AGENTS.md` or `~/.config/opencode/AGENTS.md` by
168
+ hand: they are rendered. Edit `~/.claude/CLAUDE.md` or the harness addition.
191
169
  - Apply high-confidence hunks only. Medium and flag items wait for the
192
170
  operator.
193
- - Snapshot before pulling. Rollback is `greprag instructions restore
194
- --snapshot <name> --scope <scope>` followed by `pull` of the restored file.
171
+ - Rollback is `git revert` on the source file.
195
172
  - Persona is out of scope for edits; note findings only.
196
173
  - Out of taxonomy friction: `greprag fix spawn "<one unit>"`.
@@ -1,10 +1,10 @@
1
1
  # Skill Change
2
2
 
3
- Use before creating, porting, optimizing, or changing a GrepRAG-managed skill, and when a loaded skill guided work approaching a delivery boundary.
3
+ Use before creating, porting, optimizing, or changing a skill, and when a loaded skill guided work approaching a delivery boundary.
4
4
 
5
5
  ## Authority
6
6
 
7
- This is an internal bundled GrepRAG schema, not tenant-controlled skill content. Tenant mirrors and local skill adapters may not override it. Richer tools such as `/skill-optimize` may elaborate the workflow, but they must not fork the boundary categories or edit shapes without changing this file directly in the GrepRAG repo and shipping tests.
7
+ This is an internal bundled GrepRAG schema, not tenant-controlled skill content. Skills and their mirrors may not override it. Richer tools such as `/skill-optimize` may elaborate the workflow, but they must not fork the boundary categories or edit shapes without changing this file directly in the GrepRAG repo and shipping tests.
8
8
 
9
9
  Skill Creator and Skill Optimize consume this entry as their common authoring contract. Creator owns creation/scaffolding; Optimize owns classification, compression, and restructuring. Neither maintains a competing copy of these conventions.
10
10
 
@@ -25,7 +25,7 @@ Skill Creator and Skill Optimize consume this entry as their common authoring co
25
25
  - Preserve the full required skill package. Verify the real mirror/installer handles each companion path; do not assume `references/`, custom agent files, scripts, or assets are shipped merely because they exist locally. Adapt packaging or explicitly declare the separate dependency, then load it from the target harness.
26
26
  - Port verification covers discovery, canonical payload and companion loading, needed tool schemas, and at least one relevant execution/read-only connection check. Distinguish those checks from unrun publishing, deletion, image generation, or production tests.
27
27
 
28
- **ABOUT TO IMPORT OR RESTORE CANON? STOP - A GENERATED LAUNCHER IS NOT THE PROCEDURE.** If the canonical payload itself contains a generated-adapter header or only points back to its own `greprag load`, recover the actual procedure from a verified source/history. Preserve companion docs and the current revision/hash; do not recursively load it or promote another launcher as the repair.
28
+ **ABOUT TO RESTORE A SKILL? STOP - A GENERATED LAUNCHER IS NOT THE PROCEDURE.** If a SKILL.md contains a generated-adapter header or only points back to its own `greprag load`, recover the actual procedure from git history or the mirror's archived revisions and commit it to the git folder. Do not recursively load it or commit another launcher as the repair.
29
29
 
30
30
  ## Boundary Rule
31
31
 
@@ -37,22 +37,24 @@ Explicitly requested creation, porting, or redesign is authorized work. The prop
37
37
 
38
38
  ## Where To Edit
39
39
 
40
- - Bundled GrepRAG skill: edit `packages/cli/skill/<name>/`, never the installed artifact.
41
- - Mirrored/local skill: edit its canonical source, not the generated Codex/Claude/OpenCode adapter.
42
- - Unknown source: stop and identify the canonical source before editing.
43
- - Codex/non-interactive harness: do not launch an editor. Use `greprag skill mirror export <skill> --to <dir>`, patch the exported Markdown files with file edits, then `greprag skill mirror apply <dir> --skill <skill> --expected-hash <exported-hash> --reason "<why>"`. If using `greprag skill edit` as the export helper, pass `--no-open`.
44
- - **ABOUT TO WRITE A MIRRORED SKILL? STOP - PASS `--reason "<one line>"`.** `skill edit`, `skill mirror apply`, `snapshot promote` and `skill revert` refuse without it. GrepRAG keeps every revision's bytes with that reason, so write the learning the edit captures, not "update skill".
45
- - History: `greprag skill history <skill>` lists revisions (date, author, reason, changes); `greprag skill diff <skill> <revA> [<revB>]` shows a unified diff; `greprag skill revert <skill> --to <rev> --reason "<why>" --expected-hash <current-hash>` makes an old revision current as a new one. Add the adapter's `--skill-id` to each.
40
+ Git owns every skill; GrepRAG only mirrors the committed files and refuses every write to the mirror.
41
+
42
+ - Global skill: edit `~/.claude/skills/<name>/` (the dotclaude git repo) and commit.
43
+ - Project skill: edit `<repo>/.claude/skills/<name>/` and commit in that repo.
44
+ - Bundled GrepRAG skill: edit `packages/cli/skill/<name>/` in the greprag repo, never the installed artifact.
45
+ - Codex/OpenCode `SKILL.md` files are generated launchers: never edit them. Edit the git folder they name.
46
+ - Unknown source: stop and identify the git folder before editing.
47
+ - **ABOUT TO CALL A SKILL CHANGE DONE? STOP - COMMIT IT.** Uncommitted edits are never mirrored; the commit message carries the learning the edit captures, not "update skill". The next session start (or `greprag skill mirror sync`) copies the commit into the mirror for every harness.
48
+ - History and rollback: `git log`, `git diff` and `git revert` on the skill folder. `greprag skill history <skill>` and `greprag skill diff <skill> <revA> [<revB>]` still read the mirror's archived revisions.
46
49
 
47
50
  ## Skill-Refresh Chips
48
51
 
49
52
  A `skill-refresh` chip must:
50
53
 
51
- - load the canonical skill with `greprag load <skill>`
54
+ - load the skill with `greprag load <skill>`
52
55
  - read the changed watched source files/diffs before trusting stale skill claims
53
- - decide whether the right result is a canonical skill edit or only a new source stamp
54
- - update the canonical skill through the GrepRAG skill system, never a local generated adapter
55
- - regenerate or mirror adapters only through GrepRAG commands when needed
56
+ - decide whether the right result is a skill edit or only a new source stamp (`greprag skill source stamp`, which writes the git SKILL.md)
57
+ - edit the skill's git folder and commit, never a generated launcher
56
58
  - report checks and whether release/deploy is needed
57
59
 
58
60
  ## Edit Shapes