greprag 5.83.2 → 5.85.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/commands/agent-doctrine-file.js +5 -128
  2. package/dist/commands/agents.js +125 -846
  3. package/dist/commands/app-model.js +1 -1
  4. package/dist/commands/delivery-reminder.js +1 -1
  5. package/dist/commands/discord.js +12 -61
  6. package/dist/commands/inbox-watch.js +0 -13
  7. package/dist/commands/init.js +17 -29
  8. package/dist/commands/load.js +15 -35
  9. package/dist/commands/parity.js +1 -1
  10. package/dist/commands/reminder-registry.js +1 -8
  11. package/dist/commands/session.js +2 -2
  12. package/dist/commands/skill-mirror-reminder.js +1 -19
  13. package/dist/commands/skill.js +236 -448
  14. package/dist/hook.js +31 -54
  15. package/dist/index.js +19 -152
  16. package/dist/native-adapter-refresh.js +15 -18
  17. package/dist/native-skill-mirror.js +11 -89
  18. package/dist/opencode-plugin.bundle.js +82 -282
  19. package/dist/reminder-injector.js +1 -1
  20. package/dist/skill-activation-manifest.js +14 -37
  21. package/dist/skill-git-ingest.js +297 -0
  22. package/dist/skill-landing.js +7 -173
  23. package/dist/skill-mirror-client.js +4 -251
  24. package/dist/skill-staleness.js +3 -6
  25. package/package.json +1 -1
  26. package/skill/commander/SKILL.md +10 -12
  27. package/skill/greprag/SKILL.md +1 -1
  28. package/skill/greprag/docs/discord-handoff.md +6 -30
  29. package/skill/mechanic/docs/skill-fix-conventions.md +1 -1
  30. package/skill/templates/chip-spawn.md +6 -2
  31. package/skill/templates/delivery.md +16 -0
  32. package/skill/templates/os.md +1 -1
  33. package/skill/templates/prompt-audit.md +26 -49
  34. package/skill/templates/skill-change.md +15 -11
  35. package/dist/commands/sms.js +0 -215
@@ -24,9 +24,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
 
25
25
  // src/opencode-plugin.ts
26
26
  var crypto6 = __toESM(require("crypto"));
27
- var fs12 = __toESM(require("fs"));
28
- var os5 = __toESM(require("os"));
29
- var path13 = __toESM(require("path"));
27
+ var fs11 = __toESM(require("fs"));
28
+ var os4 = __toESM(require("os"));
29
+ var path12 = __toESM(require("path"));
30
30
 
31
31
  // src/opencode-plugin-helpers.ts
32
32
  var crypto = __toESM(require("crypto"));
@@ -2179,12 +2179,15 @@ var fs3 = __toESM(require("fs"));
2179
2179
  var path4 = __toESM(require("path"));
2180
2180
 
2181
2181
  // src/skill-landing.ts
2182
- var path3 = __toESM(require("path"));
2182
+ var path2 = __toESM(require("path"));
2183
+ var BUNDLED_SKILLS = ["greprag", "commander", "content-advisor", "mechanic"];
2184
+ var LEARNED_DIR_RELPATH = path2.join("docs", "learned");
2185
+ var LEARNINGS_RELPATH = path2.join("docs", "learnings.md");
2183
2186
 
2184
2187
  // src/skill-mirror-files.ts
2185
2188
  var crypto2 = __toESM(require("node:crypto"));
2186
2189
  var fs2 = __toESM(require("node:fs"));
2187
- var path2 = __toESM(require("node:path"));
2190
+ var path3 = __toESM(require("node:path"));
2188
2191
  function computeSkillFileHash(files) {
2189
2192
  const hash = crypto2.createHash("sha256");
2190
2193
  for (const file of [...files].sort((a, b) => a.path.localeCompare(b.path))) {
@@ -2208,13 +2211,13 @@ function isLinkedSkillFolder(dir) {
2208
2211
  function isSkillFolderOwnedElsewhere(dir) {
2209
2212
  if (isLinkedSkillFolder(dir))
2210
2213
  return true;
2211
- const root = path2.dirname(path2.resolve(dir));
2212
- const harnessDir = path2.basename(path2.dirname(root));
2213
- if (path2.basename(root) !== "skills" || !INSTALLED_SKILL_HARNESS_DIRS.includes(harnessDir))
2214
+ const root = path3.dirname(path3.resolve(dir));
2215
+ const harnessDir = path3.basename(path3.dirname(root));
2216
+ if (path3.basename(root) !== "skills" || !INSTALLED_SKILL_HARNESS_DIRS.includes(harnessDir))
2214
2217
  return false;
2215
2218
  let skillMd = "";
2216
2219
  try {
2217
- skillMd = fs2.readFileSync(path2.join(dir, "SKILL.md"), "utf8");
2220
+ skillMd = fs2.readFileSync(path3.join(dir, "SKILL.md"), "utf8");
2218
2221
  } catch {
2219
2222
  }
2220
2223
  if (isGeneratedSkillAdapter(skillMd))
@@ -2225,8 +2228,8 @@ function isSkillFolderOwnedElsewhere(dir) {
2225
2228
  if (harnessDir !== ".claude" && harnessDir !== ".agents")
2226
2229
  return false;
2227
2230
  try {
2228
- const lock = JSON.parse(fs2.readFileSync(path2.join(path2.dirname(path2.dirname(root)), ".agents", ".skill-lock.json"), "utf8"));
2229
- return Boolean(lock?.skills && Object.prototype.hasOwnProperty.call(lock.skills, path2.basename(dir)));
2231
+ const lock = JSON.parse(fs2.readFileSync(path3.join(path3.dirname(path3.dirname(root)), ".agents", ".skill-lock.json"), "utf8"));
2232
+ return Boolean(lock?.skills && Object.prototype.hasOwnProperty.call(lock.skills, path3.basename(dir)));
2230
2233
  } catch {
2231
2234
  return false;
2232
2235
  }
@@ -2237,11 +2240,6 @@ function isSafeMirroredSkillFile(file) {
2237
2240
  return /^docs\/(?!.*(?:^|\/)\.\.(?:\/|$))[A-Za-z0-9._\/-]+\.md$/.test(file.path);
2238
2241
  }
2239
2242
 
2240
- // src/skill-landing.ts
2241
- var BUNDLED_SKILLS = ["greprag", "commander", "content-advisor", "mechanic"];
2242
- var LEARNED_DIR_RELPATH = path3.join("docs", "learned");
2243
- var LEARNINGS_RELPATH = path3.join("docs", "learnings.md");
2244
-
2245
2243
  // src/skill-activation-manifest.ts
2246
2244
  var MAX_NATIVE_SKILL_FILES = 1500;
2247
2245
  var MAX_SCAN_DEPTH = 7;
@@ -2348,19 +2346,15 @@ function readNativeSkillNames(params) {
2348
2346
  }
2349
2347
  function nativeAdapterGap(platform, mirrored, native) {
2350
2348
  const missing = [];
2351
- const localCopies = [];
2352
- if (!platform)
2353
- return { missing, localCopies };
2354
- for (const { skillName, scope } of mirrored) {
2349
+ if (platform !== "codex" && platform !== "opencode")
2350
+ return { missing };
2351
+ for (const { skillName } of mirrored) {
2355
2352
  if (!skillName || BUNDLED_SKILLS.includes(skillName))
2356
2353
  continue;
2357
- const kind = native.get(skillName.toLowerCase());
2358
- if (!kind)
2354
+ if (!native.get(skillName.toLowerCase()))
2359
2355
  missing.push(skillName);
2360
- else if (kind === "local" && platform === "claude-code" && scope !== "project")
2361
- localCopies.push(skillName);
2362
2356
  }
2363
- return { missing, localCopies };
2357
+ return { missing };
2364
2358
  }
2365
2359
  function buildMirroredSkillActivation(entries, native, platform) {
2366
2360
  const valid = entries.filter((entry) => entry.skillName && entry.triggerDescription);
@@ -2377,16 +2371,7 @@ function buildMirroredSkillActivation(entries, native, platform) {
2377
2371
  function nativeAdapterInstallCommand(platform, missingNames) {
2378
2372
  if (missingNames.length === 0)
2379
2373
  return null;
2380
- if (platform === "claude-code") {
2381
- return `greprag skill mirror sync claude-code --only ${[...missingNames].sort().join(",")}`;
2382
- }
2383
- if (platform === "codex" || platform === "opencode") {
2384
- return `greprag skill mirror sync ${platform}`;
2385
- }
2386
- return null;
2387
- }
2388
- function localCopyCutoverCommand(platform, localCopies) {
2389
- return localCopies.length > 0 ? nativeAdapterInstallCommand(platform, ["<name>"]) : null;
2374
+ return platform === "codex" || platform === "opencode" ? `greprag skill mirror sync ${platform}` : null;
2390
2375
  }
2391
2376
  function activationFromApiRows(params) {
2392
2377
  const entries = params.rows.filter((row) => typeof row.skillName === "string" && !!row.skillName && typeof row.triggerDescription === "string" && !!row.triggerDescription).map((row) => ({
@@ -2409,20 +2394,9 @@ function renderEntry(skill) {
2409
2394
  function buildSkillMirrorAnnounce(m, platform) {
2410
2395
  if (!m || m.count <= 0)
2411
2396
  return null;
2412
- const cutoverCommand = localCopyCutoverCommand(platform || "", m.localCopies);
2413
- const copies = m.localCopies.length === 1 ? "one mirrored skill" : `${m.localCopies.length} mirrored skills`;
2414
- const copySection = cutoverCommand ? [
2415
- "### Hand-Kept Copies",
2416
- `This harness lists ${copies} from a hand-kept copy instead of an adapter, so it keeps running that copy when the mirrored skill changes: ${m.localCopies.join(", ")}. Replacing a copy with its adapter is the user's call, one skill at a time (the old SKILL.md is backed up first):`,
2417
- "",
2418
- ` ${cutoverCommand}`,
2419
- "",
2420
- "Offer that command when the user asks why a skill behaves out of date, or when you needed one of them this session.",
2421
- ""
2422
- ] : [];
2423
2397
  if (m.skills.length === 0) {
2424
2398
  const line = "[greprag skills: slash skills are available. When discussing skills with the user, say use/create/update/refresh `/skill`; keep storage mechanics internal unless diagnosing a failure or the user asks how it works. Use `greprag load <skill>` to read skill instructions.]";
2425
- return [line, "", ...copySection].join("\n").trimEnd();
2399
+ return line;
2426
2400
  }
2427
2401
  const installCommand = nativeAdapterInstallCommand(platform || "", m.missing);
2428
2402
  const gapSection = installCommand ? [
@@ -2440,7 +2414,6 @@ function buildSkillMirrorAnnounce(m, platform) {
2440
2414
  "When discussing skills with the user, say use/create/update/refresh `/skill`; keep storage mechanics internal unless diagnosing a failure or the user asks how it works.",
2441
2415
  "",
2442
2416
  ...gapSection,
2443
- ...copySection,
2444
2417
  "### Trigger Rules",
2445
2418
  "If the user names a skill (with or without `/`) OR the request clearly matches a skill's description below, you MUST activate that skill for the current turn. Match meaning, not exact keywords.",
2446
2419
  "",
@@ -2466,7 +2439,6 @@ function buildSkillMirrorAnnounce(m, platform) {
2466
2439
  }
2467
2440
  var skillMirrorAnnounceModule = {
2468
2441
  id: "skill-mirror-announce",
2469
- source: "prompt",
2470
2442
  dependsOn: ["load-primer"],
2471
2443
  // references `greprag load` — the primer establishes it
2472
2444
  detect: (_env) => ({ tier: "silent" }),
@@ -2549,7 +2521,7 @@ function buildDeliveryAnnounce(env) {
2549
2521
  `[DELIVERY \u2014 ${project}]`,
2550
2522
  "Commit useful, passing work. Only committed state delivers; ignore uncommitted and untracked work in every checkout.",
2551
2523
  coordinationLine(env.platform),
2552
- "Land every ready same-repo commit: update the default branch, rebase your worktree onto its tip, retest there, take greprag merge-lock in the canonical checkout, recheck the tip, merge --ff-only, release --landed. Tip moved? Free the lock and prepare again. Never rebase a shared default branch.",
2524
+ "Land every ready same-repo commit: update the default branch, rebase your worktree onto its tip, retest there, take greprag merge-lock in the canonical checkout, recheck the tip, merge --ff-only, release --landed. Tip moved? Free the lock and prepare again. A chip's branch arrives rebased by the chip: only fast-forward it; refused, free the lock and send it back. Never rebase in another session's worktree or a shared default branch.",
2553
2525
  "Deploy through this repo's delivery profile, from its canonical primary checkout unless the profile says otherwise. Worktrees build; they do not deploy. Then verify production serves the commit you shipped.",
2554
2526
  "THE GOAL ALREADY AUTHORIZES ALL OF THIS. Do not stop to ask permission to commit, merge, or deploy. Separate approval is for effects outside code delivery: destructive data, secrets, money, customer-facing messages.",
2555
2527
  "Why each rule, and the details: `greprag load delivery`."
@@ -4177,11 +4149,6 @@ function recodeMessagesToPng(messages, opts) {
4177
4149
  return stats;
4178
4150
  }
4179
4151
 
4180
- // src/claude-lifecycle-cutover.ts
4181
- var fs11 = __toESM(require("fs"));
4182
- var os4 = __toESM(require("os"));
4183
- var path12 = __toESM(require("path"));
4184
-
4185
4152
  // src/native-skill-mirror.ts
4186
4153
  var fs10 = __toESM(require("node:fs"));
4187
4154
  var os3 = __toESM(require("node:os"));
@@ -4423,123 +4390,44 @@ function canonicalContentHash(skill) {
4423
4390
  function canonicalLookupArgs(skill) {
4424
4391
  return `--skill-id ${canonicalSkillId(skill)}`;
4425
4392
  }
4426
- function canonicalWriteArgs(skill) {
4427
- if (skill.scope !== "project" || !skill.projectId)
4428
- return "";
4429
- const replaces = (skill.replaces || []).map((id) => ` --replaces ${id}`).join("");
4430
- return `--scope project --project-id ${skill.projectId}${replaces}`;
4431
- }
4432
- function canonicalEditArgs(skill) {
4433
- return [canonicalLookupArgs(skill), canonicalWriteArgs(skill)].filter(Boolean).join(" ");
4434
- }
4435
- function nativeCreationLocations(platform) {
4436
- if (platform === "codex") {
4437
- return "`~/.codex/skills/<new-name>/SKILL.md` (global) or `<repo>/.agents/skills/<new-name>/SKILL.md` (project)";
4438
- }
4439
- if (platform === "opencode") {
4440
- return "`~/.config/opencode/skills/<new-name>/SKILL.md` (global) or `<repo>/.opencode/skills/<new-name>/SKILL.md` (project)";
4441
- }
4442
- return "`~/.claude/skills/<new-name>/SKILL.md` (global) or `<repo>/.claude/skills/<new-name>/SKILL.md` (project)";
4443
- }
4444
- function renderChangeSkillLine(params) {
4445
- const exportCommand = `greprag skill mirror export ${params.skillName} ${params.identityArg} --to <dir>`;
4446
- const applyCommand = `greprag skill mirror apply <dir> --skill ${params.skillName} ${params.editArgs} --expected-hash <exported-hash>`;
4447
- if (params.platform === "codex") {
4448
- return `- **Change this skill:** run \`greprag load skill-change\`, then \`${exportCommand}\`; patch the exported Markdown files non-interactively; run \`${applyCommand}\`; then \`${params.syncCommand}\`; then verify with \`${params.loadCommand}\`.`;
4449
- }
4450
- return `- **Change this skill:** run \`greprag load skill-change\`, then \`greprag skill edit ${params.skillName} ${params.editArgs}\`, then \`${params.syncCommand}\`, then verify with \`${params.loadCommand}\`.`;
4451
- }
4452
- function renderEditingSection(platform, params) {
4453
- const exportCommand = `greprag skill mirror export ${params.skillName} ${params.identityArg} --to <dir>`;
4454
- const applyCommand = `greprag skill mirror apply <dir> --skill ${params.skillName} ${params.editArgs} --expected-hash <exported-hash>`;
4455
- if (platform === "codex") {
4456
- return `## Editing
4457
-
4458
- Codex agents must use the non-interactive mirror path:
4459
-
4460
- \`\`\`bash
4461
- ${exportCommand}
4462
- # patch the exported Markdown files with normal file edits
4463
- ${applyCommand}
4464
- \`\`\`
4465
-
4466
- Do not launch an interactive editor from Codex. If using \`greprag skill edit\` as an export helper, include \`--no-open\` and run the printed apply command after patching.
4467
- `;
4468
- }
4469
- return `## Editing
4470
-
4471
- To edit this skill, run the guarded editor flow:
4472
-
4473
- \`\`\`bash
4474
- greprag skill edit ${params.skillName} ${params.editArgs}
4475
- \`\`\`
4476
-
4477
- Manual path:
4478
-
4479
- \`\`\`bash
4480
- ${exportCommand}
4481
- ${applyCommand}
4482
- \`\`\`
4483
- `;
4393
+ function gitSkillFolder(skill) {
4394
+ return skill.scope === "project" ? `\`<repo>/.claude/skills/${skill.skillName}/\`${skill.projectName ? ` in the ${skill.projectName} repo` : ""}` : `\`~/.claude/skills/${skill.skillName}/\` in the dotclaude repo`;
4484
4395
  }
4485
4396
  function renderAdapterBody(platform, skill) {
4486
4397
  const skillName = skill.skillName;
4487
4398
  const skillId = canonicalSkillId(skill);
4488
4399
  const identityArg = canonicalLookupArgs(skill);
4489
- const editArgs = canonicalEditArgs(skill);
4490
- const creationLocations = nativeCreationLocations(platform);
4491
4400
  const syncCommand = nativeAdapterInstallCommand(platform, [skillName]);
4492
- const creationLine = platform === "claude-code" ? "- **Create another skill:** use the normal native creation path and leave it unmanaged until a separate Claude cutover is approved." : `- **Create another skill:** create a normal native skill at ${creationLocations}; run \`${syncCommand} --dry-run\` and confirm it says \`adopt\`; then run \`${syncCommand}\`. GrepRAG adopts it as canon and replaces the native package with an adapter.`;
4493
4401
  const companions = skill.files.map((file) => file.path).filter((relative) => relative !== "SKILL.md").sort();
4494
4402
  const harnessArg = `--harness ${platform}`;
4495
4403
  const loadCommand = `greprag load ${skillName} ${identityArg} ${harnessArg}`;
4496
- const changeSkillLine = renderChangeSkillLine({
4497
- platform,
4498
- skillName,
4499
- editArgs,
4500
- identityArg,
4501
- syncCommand,
4502
- loadCommand
4503
- });
4504
- const editingSection = renderEditingSection(platform, { skillName, editArgs, identityArg });
4505
- const companionLines = companions.length ? companions.map((relative) => `- \`greprag load ${skillName} ${relative} ${identityArg} ${harnessArg}\``).join("\n") : "- No companion docs are mirrored into this native adapter.";
4404
+ const companionLines = companions.length ? companions.map((relative) => `- \`greprag load ${skillName} ${relative} ${identityArg} ${harnessArg}\``).join("\n") : "- No companion docs are mirrored into this launcher.";
4506
4405
  return `# ${skillName}
4507
4406
 
4508
4407
  ## GENERATED ADAPTER \u2014 NEVER EDIT
4509
4408
 
4510
- This is a disposable GrepRAG launcher for ${platform}, not canonical skill content. Never edit or copy this adapter, and never use \`greprag skill install\` to create or change a mirrored skill.
4511
-
4512
- Do not add or maintain project-state/doc pointers here. Current project state belongs in repo docs and the GrepRAG doc mirror; \`greprag load ${skillName} ${identityArg} ${harnessArg}\` discovers relevant state docs dynamically.
4409
+ This is a disposable GrepRAG launcher for ${platform}, not skill content. The skill lives in git at ${gitSkillFolder(skill)}; GrepRAG mirrors the committed files read-only and this launcher loads them.
4513
4410
 
4514
4411
  Required action chains:
4515
4412
 
4516
4413
  - **Use this skill:** run \`${loadCommand}\` before acting.
4517
- ${changeSkillLine}
4518
- ${creationLine}
4414
+ - **Change this skill:** edit ${gitSkillFolder(skill)} with normal file edits, commit, then run \`${syncCommand}\` (session start does it too) and verify with \`${loadCommand}\`. Uncommitted edits are never served. History and rollback are git log / git revert on that folder.
4415
+ - **Create another skill:** create \`~/.claude/skills/<new-name>/SKILL.md\` (dotclaude repo, global) or \`<repo>/.claude/skills/<new-name>/SKILL.md\` (project), commit, then run \`${syncCommand}\`.
4519
4416
 
4520
4417
  Authority: ${skillId}
4521
4418
  Source binding: ${sourceBindingState(skill)}
4522
4419
  Canonical content hash: ${canonicalContentHash(skill)}
4523
4420
  ${typeof skill.revision === "number" ? `Mirror revision: ${skill.revision}` : "Mirror revision: unknown"}
4524
4421
 
4525
- ${editingSection}
4526
-
4527
- Snapshot rollback:
4528
-
4529
- \`\`\`bash
4530
- greprag skill mirror snapshot list ${skillName} ${identityArg}
4531
- greprag skill mirror snapshot promote ${skillName} --name <snapshot> ${editArgs} --expected-hash <current-hash>
4532
- \`\`\`
4533
-
4534
4422
  ## Mandatory Invocation
4535
4423
 
4536
4424
  When this skill activates, run:
4537
4425
 
4538
4426
  \`\`\`bash
4539
- greprag load ${skillName} ${identityArg} ${harnessArg}
4427
+ ${loadCommand}
4540
4428
  \`\`\`
4541
4429
 
4542
- Read and follow that canonical payload before responding or taking action.
4430
+ Read and follow that payload before responding or taking action.
4543
4431
 
4544
4432
  ## Companion Docs
4545
4433
 
@@ -4803,94 +4691,6 @@ async function fetchNativeMirroredSkill(apiUrl, apiKey, row) {
4803
4691
  } : null;
4804
4692
  }
4805
4693
 
4806
- // src/claude-lifecycle-cutover.ts
4807
- var CLAUDE_LIFECYCLE_SKILLS = ["commit", "deploy", "release"];
4808
- function adapterFor(skill) {
4809
- const files = buildNativeSkillAdapter("claude-code", skill, { allowClaudeCode: true });
4810
- if (!files || files.length !== 1 || files[0].path !== "SKILL.md") {
4811
- throw new Error(`Claude lifecycle adapter is invalid for ${skill.skillName}.`);
4812
- }
4813
- return files;
4814
- }
4815
- function safeTimestamp(now) {
4816
- return now.toISOString().replace(/[:.]/g, "-");
4817
- }
4818
- function requiredSkills(skills, names) {
4819
- const byName = new Map(skills.filter((skill) => skill.scope !== "project").map((skill) => [skill.skillName, skill]));
4820
- return names.map((name) => {
4821
- const skill = byName.get(name);
4822
- if (!skill)
4823
- throw new Error(`Canonical Claude lifecycle skill missing: ${name}.`);
4824
- return skill;
4825
- });
4826
- }
4827
- function applyClaudeLifecycleCutover(params) {
4828
- const homeDir = params.homeDir || os4.homedir();
4829
- const root = nativeSkillRoot("claude-code", homeDir);
4830
- const state = readState(root);
4831
- const names = params.names?.length ? params.names : CLAUDE_LIFECYCLE_SKILLS;
4832
- const prepared = requiredSkills(params.skills, names).map((skill) => {
4833
- const target = path12.join(root, skill.skillName);
4834
- if (isSkillFolderOwnedElsewhere(target)) {
4835
- throw new Error(`Claude skill folder is owned elsewhere (a link or another installer's package): ${skill.skillName}; not written.`);
4836
- }
4837
- const skillMd = path12.join(target, "SKILL.md");
4838
- const adapterFiles = adapterFor(skill);
4839
- const nextHash = computeSkillFileHash(adapterFiles);
4840
- const managed = state.skills[skill.skillName];
4841
- let currentContent;
4842
- if (fs11.existsSync(skillMd))
4843
- currentContent = fs11.readFileSync(skillMd, "utf8");
4844
- if (managed) {
4845
- const currentFiles = currentContent === void 0 ? null : [{ path: "SKILL.md", content: currentContent }];
4846
- if (!currentFiles || computeSkillFileHash(currentFiles) !== managed.hash) {
4847
- throw new Error(`Claude lifecycle adapter diverged: ${skill.skillName}.`);
4848
- }
4849
- } else if (fs11.existsSync(target) && currentContent === void 0) {
4850
- throw new Error(`Claude lifecycle package has no SKILL.md: ${skill.skillName}.`);
4851
- }
4852
- return { skill, target, skillMd, adapterFiles, nextHash, managed, currentContent };
4853
- });
4854
- const replacements = prepared.filter((item) => !item.managed && item.currentContent !== void 0);
4855
- let backupDir;
4856
- if (replacements.length > 0) {
4857
- backupDir = path12.join(
4858
- homeDir,
4859
- ".greprag",
4860
- "backups",
4861
- "claude-lifecycle-cutover",
4862
- safeTimestamp(params.now || /* @__PURE__ */ new Date())
4863
- );
4864
- for (const item of replacements) {
4865
- const destination = path12.join(backupDir, item.skill.skillName, "SKILL.md");
4866
- fs11.mkdirSync(path12.dirname(destination), { recursive: true });
4867
- fs11.writeFileSync(destination, item.currentContent, "utf8");
4868
- }
4869
- }
4870
- const result = {
4871
- installed: 0,
4872
- updated: 0,
4873
- current: 0,
4874
- blocked: 0,
4875
- backupDir
4876
- };
4877
- for (const item of prepared) {
4878
- if (item.managed && item.managed.hash === item.nextHash) {
4879
- result.current++;
4880
- continue;
4881
- }
4882
- fs11.mkdirSync(item.target, { recursive: true });
4883
- fs11.writeFileSync(item.skillMd, item.adapterFiles[0].content, "utf8");
4884
- state.skills[item.skill.skillName] = { hash: item.nextHash, files: ["SKILL.md"] };
4885
- if (item.managed)
4886
- result.updated++;
4887
- else
4888
- result.installed++;
4889
- }
4890
- writeState(root, state);
4891
- return result;
4892
- }
4893
-
4894
4694
  // src/native-adapter-refresh.ts
4895
4695
  function readAdapterStamps(content) {
4896
4696
  const frontmatter = /^---\n([\s\S]*?)\n---/.exec(content.replace(/\r\n?/g, "\n"))?.[1] || "";
@@ -4906,7 +4706,7 @@ function readAdapterStamps(content) {
4906
4706
  function staleNativeAdapters(params) {
4907
4707
  const globalRoot = nativeSkillRoot(params.platform, params.homeDir);
4908
4708
  const roots = [globalRoot];
4909
- const projectRoot = params.projectDir && params.platform !== "claude-code" ? writerOwnedProjectSkillRoot(params.platform, params.projectDir, params.homeDir) : null;
4709
+ const projectRoot = params.projectDir ? writerOwnedProjectSkillRoot(params.platform, params.projectDir, params.homeDir) : null;
4910
4710
  if (projectRoot)
4911
4711
  roots.push(projectRoot);
4912
4712
  const byId = /* @__PURE__ */ new Map();
@@ -4940,7 +4740,7 @@ function staleNativeAdapters(params) {
4940
4740
  }
4941
4741
  async function refreshNativeAdapters(params) {
4942
4742
  const platform = params.platform;
4943
- if (platform !== "claude-code" && platform !== "codex" && platform !== "opencode") {
4743
+ if (platform !== "codex" && platform !== "opencode") {
4944
4744
  return { refreshed: 0, blocked: 0 };
4945
4745
  }
4946
4746
  const stale = staleNativeAdapters({ ...params, platform });
@@ -4951,7 +4751,7 @@ async function refreshNativeAdapters(params) {
4951
4751
  if (!skill)
4952
4752
  continue;
4953
4753
  try {
4954
- const result = platform === "claude-code" ? applyClaudeLifecycleCutover({ skills: [skill], names: [skill.skillName], homeDir: params.homeDir }) : applyNativeSkillMirror({
4754
+ const result = applyNativeSkillMirror({
4955
4755
  platform,
4956
4756
  skills: [skill],
4957
4757
  homeDir: params.homeDir,
@@ -4968,14 +4768,14 @@ async function refreshNativeAdapters(params) {
4968
4768
  }
4969
4769
 
4970
4770
  // src/opencode-plugin.ts
4971
- var DEBUG_LOG_PATH = path13.join(os5.homedir(), ".greprag", "opencode-plugin-debug.log");
4771
+ var DEBUG_LOG_PATH = path12.join(os4.homedir(), ".greprag", "opencode-plugin-debug.log");
4972
4772
  var _debugLogReady = false;
4973
4773
  function dlogInit() {
4974
4774
  if (_debugLogReady)
4975
4775
  return;
4976
4776
  _debugLogReady = true;
4977
4777
  try {
4978
- fs12.writeFileSync(DEBUG_LOG_PATH, "");
4778
+ fs11.writeFileSync(DEBUG_LOG_PATH, "");
4979
4779
  } catch {
4980
4780
  }
4981
4781
  }
@@ -4984,7 +4784,7 @@ function dlog(msg) {
4984
4784
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [greprag-memory] ${msg}
4985
4785
  `;
4986
4786
  try {
4987
- fs12.appendFileSync(DEBUG_LOG_PATH, line);
4787
+ fs11.appendFileSync(DEBUG_LOG_PATH, line);
4988
4788
  } catch {
4989
4789
  }
4990
4790
  }
@@ -4992,9 +4792,9 @@ dlog(`module top reached: pid=${process.pid} argv0=${process.argv[0]} distPath=$
4992
4792
  var API_URL = "https://api.greprag.com";
4993
4793
  function loadEnvFile(filePath2) {
4994
4794
  try {
4995
- if (!fs12.existsSync(filePath2))
4795
+ if (!fs11.existsSync(filePath2))
4996
4796
  return;
4997
- const raw = fs12.readFileSync(filePath2, "utf-8");
4797
+ const raw = fs11.readFileSync(filePath2, "utf-8");
4998
4798
  for (const line of raw.split(/\r?\n/)) {
4999
4799
  const trimmed = line.trim();
5000
4800
  if (!trimmed || trimmed.startsWith("#"))
@@ -5014,12 +4814,12 @@ function loadEnvFile(filePath2) {
5014
4814
  }
5015
4815
  }
5016
4816
  function loadGrepragEnv() {
5017
- loadEnvFile(path13.join(HOME, ".greprag", ".env"));
4817
+ loadEnvFile(path12.join(HOME, ".greprag", ".env"));
5018
4818
  try {
5019
- const p = path13.join(HOME, ".claude", "settings.json");
5020
- if (!fs12.existsSync(p))
4819
+ const p = path12.join(HOME, ".claude", "settings.json");
4820
+ if (!fs11.existsSync(p))
5021
4821
  return;
5022
- const data = JSON.parse(fs12.readFileSync(p, "utf-8"));
4822
+ const data = JSON.parse(fs11.readFileSync(p, "utf-8"));
5023
4823
  if (data && data.env && typeof data.env === "object") {
5024
4824
  for (const [key, val] of Object.entries(data.env)) {
5025
4825
  if (!process.env[key] && typeof val === "string") {
@@ -5032,11 +4832,11 @@ function loadGrepragEnv() {
5032
4832
  }
5033
4833
  loadGrepragEnv();
5034
4834
  dlog(`env loaded: MEMORY_HOOK_ENABLED=${process.env.MEMORY_HOOK_ENABLED || "<unset>"} GREPRAG_API_KEY=${process.env.GREPRAG_API_KEY ? "set" : "<unset>"} GREPRAG_OPENCODE_CAPTURE=${process.env.GREPRAG_OPENCODE_CAPTURE || "<unset>"}`);
5035
- var WATCHER_LOCK = path13.join(HOME || os5.homedir(), ".greprag", "opencode-watch.lock");
4835
+ var WATCHER_LOCK = path12.join(HOME || os4.homedir(), ".greprag", "opencode-watch.lock");
5036
4836
  var WATCHER_STALE_MS = 3e4;
5037
4837
  function findGrepragBinary() {
5038
4838
  const override = process.env.GREPRAG_BIN;
5039
- if (override && fs12.existsSync(override))
4839
+ if (override && fs11.existsSync(override))
5040
4840
  return override;
5041
4841
  const binaryName = process.platform === "win32" ? "greprag.cmd" : "greprag";
5042
4842
  try {
@@ -5045,14 +4845,14 @@ function findGrepragBinary() {
5045
4845
  const candidate = line.trim();
5046
4846
  if (!candidate)
5047
4847
  continue;
5048
- if (!fs12.existsSync(candidate))
4848
+ if (!fs11.existsSync(candidate))
5049
4849
  continue;
5050
4850
  if (process.platform === "win32") {
5051
- const ext = path13.extname(candidate).toLowerCase();
4851
+ const ext = path12.extname(candidate).toLowerCase();
5052
4852
  if (ext === ".cmd" || ext === ".exe" || ext === ".bat")
5053
4853
  return candidate;
5054
4854
  const cmdSibling = candidate + ".cmd";
5055
- if (fs12.existsSync(cmdSibling))
4855
+ if (fs11.existsSync(cmdSibling))
5056
4856
  return cmdSibling;
5057
4857
  continue;
5058
4858
  }
@@ -5061,19 +4861,19 @@ function findGrepragBinary() {
5061
4861
  } catch {
5062
4862
  }
5063
4863
  const candidates = process.platform === "win32" ? [
5064
- path13.join(HOME, "AppData", "Roaming", "npm", "greprag.cmd"),
5065
- path13.join(HOME, "AppData", "Roaming", "npm", "greprag"),
5066
- path13.join(HOME, "AppData", "Local", "Yarn", "bin", "greprag.cmd"),
5067
- path13.join(HOME, "AppData", "Local", "pnpm", "bin", "greprag.cmd")
4864
+ path12.join(HOME, "AppData", "Roaming", "npm", "greprag.cmd"),
4865
+ path12.join(HOME, "AppData", "Roaming", "npm", "greprag"),
4866
+ path12.join(HOME, "AppData", "Local", "Yarn", "bin", "greprag.cmd"),
4867
+ path12.join(HOME, "AppData", "Local", "pnpm", "bin", "greprag.cmd")
5068
4868
  ] : [
5069
4869
  "/usr/local/bin/greprag",
5070
4870
  "/opt/homebrew/bin/greprag",
5071
- path13.join(HOME || "", ".local", "bin", "greprag"),
5072
- path13.join(HOME || "", ".yarn", "bin", "greprag")
4871
+ path12.join(HOME || "", ".local", "bin", "greprag"),
4872
+ path12.join(HOME || "", ".yarn", "bin", "greprag")
5073
4873
  ];
5074
4874
  for (const c of candidates) {
5075
4875
  try {
5076
- if (c && fs12.existsSync(c))
4876
+ if (c && fs11.existsSync(c))
5077
4877
  return c;
5078
4878
  } catch {
5079
4879
  }
@@ -5082,18 +4882,18 @@ function findGrepragBinary() {
5082
4882
  }
5083
4883
  function tryClaimWatcherLock() {
5084
4884
  try {
5085
- const fd = fs12.openSync(WATCHER_LOCK, "wx");
4885
+ const fd = fs11.openSync(WATCHER_LOCK, "wx");
5086
4886
  return { ok: true, fd };
5087
4887
  } catch (err) {
5088
4888
  if (err.code !== "EEXIST") {
5089
4889
  return { ok: false, reason: "lock-create-failed" };
5090
4890
  }
5091
4891
  try {
5092
- const stat = fs12.statSync(WATCHER_LOCK);
4892
+ const stat = fs11.statSync(WATCHER_LOCK);
5093
4893
  const ageMs = Date.now() - stat.mtimeMs;
5094
4894
  let pidAlive = false;
5095
4895
  try {
5096
- const pid = parseInt(fs12.readFileSync(WATCHER_LOCK, "utf-8").trim(), 10);
4896
+ const pid = parseInt(fs11.readFileSync(WATCHER_LOCK, "utf-8").trim(), 10);
5097
4897
  pidAlive = pid > 0 && isPidAlive(pid);
5098
4898
  } catch {
5099
4899
  }
@@ -5101,10 +4901,10 @@ function tryClaimWatcherLock() {
5101
4901
  return { ok: false, reason: "busy" };
5102
4902
  }
5103
4903
  try {
5104
- fs12.unlinkSync(WATCHER_LOCK);
4904
+ fs11.unlinkSync(WATCHER_LOCK);
5105
4905
  } catch {
5106
4906
  }
5107
- const fd = fs12.openSync(WATCHER_LOCK, "wx");
4907
+ const fd = fs11.openSync(WATCHER_LOCK, "wx");
5108
4908
  return { ok: true, fd };
5109
4909
  } catch (err2) {
5110
4910
  return { ok: false, reason: "lock-stale-replace-failed" };
@@ -5145,11 +4945,11 @@ function startCaptureWatcher() {
5145
4945
  return;
5146
4946
  }
5147
4947
  try {
5148
- fs12.writeSync(claim.fd, String(process.pid));
5149
- fs12.closeSync(claim.fd);
4948
+ fs11.writeSync(claim.fd, String(process.pid));
4949
+ fs11.closeSync(claim.fd);
5150
4950
  } catch {
5151
4951
  try {
5152
- fs12.unlinkSync(WATCHER_LOCK);
4952
+ fs11.unlinkSync(WATCHER_LOCK);
5153
4953
  } catch {
5154
4954
  }
5155
4955
  return;
@@ -5165,11 +4965,11 @@ function startCaptureWatcher() {
5165
4965
  const claim2 = tryClaimWatcherLock();
5166
4966
  if (claim2.ok) {
5167
4967
  try {
5168
- fs12.writeSync(claim2.fd, String(process.pid));
5169
- fs12.closeSync(claim2.fd);
4968
+ fs11.writeSync(claim2.fd, String(process.pid));
4969
+ fs11.closeSync(claim2.fd);
5170
4970
  } catch {
5171
4971
  try {
5172
- fs12.unlinkSync(WATCHER_LOCK);
4972
+ fs11.unlinkSync(WATCHER_LOCK);
5173
4973
  } catch {
5174
4974
  }
5175
4975
  return false;
@@ -5212,7 +5012,7 @@ function startCaptureWatcher() {
5212
5012
  childStartTime = Date.now();
5213
5013
  dlog(`startCaptureWatcher: spawned 'greprag opencode watch' pid=${child.pid ?? "<none>"}`);
5214
5014
  try {
5215
- fs12.writeFileSync(WATCHER_LOCK, String(child.pid));
5015
+ fs11.writeFileSync(WATCHER_LOCK, String(child.pid));
5216
5016
  } catch {
5217
5017
  }
5218
5018
  child.stderr?.on("data", (chunk2) => {
@@ -5224,9 +5024,9 @@ function startCaptureWatcher() {
5224
5024
  child.on("exit", (code, signal) => {
5225
5025
  dlog(`startCaptureWatcher: child pid=${child.pid ?? "<none>"} exited code=${code} signal=${signal || "none"}`);
5226
5026
  try {
5227
- const current = fs12.readFileSync(WATCHER_LOCK, "utf-8").trim();
5027
+ const current = fs11.readFileSync(WATCHER_LOCK, "utf-8").trim();
5228
5028
  if (current === String(child.pid))
5229
- fs12.unlinkSync(WATCHER_LOCK);
5029
+ fs11.unlinkSync(WATCHER_LOCK);
5230
5030
  } catch {
5231
5031
  }
5232
5032
  currentChild = null;
@@ -5255,7 +5055,7 @@ function startCaptureWatcher() {
5255
5055
  `
5256
5056
  );
5257
5057
  try {
5258
- fs12.unlinkSync(WATCHER_LOCK);
5058
+ fs11.unlinkSync(WATCHER_LOCK);
5259
5059
  } catch {
5260
5060
  }
5261
5061
  return;
@@ -5287,7 +5087,7 @@ function startCaptureWatcher() {
5287
5087
  }, 2e3).unref();
5288
5088
  }
5289
5089
  try {
5290
- fs12.unlinkSync(WATCHER_LOCK);
5090
+ fs11.unlinkSync(WATCHER_LOCK);
5291
5091
  } catch {
5292
5092
  }
5293
5093
  };
@@ -5357,7 +5157,7 @@ async function fetchSkillActivation(apiKey, cwd) {
5357
5157
  rows,
5358
5158
  apiUrl: API_URL,
5359
5159
  apiKey,
5360
- homeDir: os5.homedir(),
5160
+ homeDir: os4.homedir(),
5361
5161
  projectDir: cwd
5362
5162
  }).catch(() => void 0);
5363
5163
  return activationFromApiRows({
@@ -5432,11 +5232,11 @@ function startSessionRelay(sessionId, serverUrl) {
5432
5232
  return;
5433
5233
  }
5434
5234
  try {
5435
- fs12.writeSync(claim.fd, String(process.pid));
5436
- fs12.closeSync(claim.fd);
5235
+ fs11.writeSync(claim.fd, String(process.pid));
5236
+ fs11.closeSync(claim.fd);
5437
5237
  } catch {
5438
5238
  try {
5439
- fs12.unlinkSync(lockPath);
5239
+ fs11.unlinkSync(lockPath);
5440
5240
  } catch {
5441
5241
  }
5442
5242
  return;
@@ -5451,11 +5251,11 @@ function startSessionRelay(sessionId, serverUrl) {
5451
5251
  const claim2 = tryClaimRelayLock(lockPath);
5452
5252
  if (claim2.ok) {
5453
5253
  try {
5454
- fs12.writeSync(claim2.fd, String(process.pid));
5455
- fs12.closeSync(claim2.fd);
5254
+ fs11.writeSync(claim2.fd, String(process.pid));
5255
+ fs11.closeSync(claim2.fd);
5456
5256
  } catch {
5457
5257
  try {
5458
- fs12.unlinkSync(lockPath);
5258
+ fs11.unlinkSync(lockPath);
5459
5259
  } catch {
5460
5260
  }
5461
5261
  return false;
@@ -5491,7 +5291,7 @@ function startSessionRelay(sessionId, serverUrl) {
5491
5291
  childStartTime = Date.now();
5492
5292
  dlog(`startSessionRelay: spawned 'greprag opencode relay' pid=${child.pid ?? "<none>"}`);
5493
5293
  try {
5494
- fs12.writeFileSync(lockPath, String(child.pid));
5294
+ fs11.writeFileSync(lockPath, String(child.pid));
5495
5295
  } catch {
5496
5296
  }
5497
5297
  child.stderr?.on("data", (chunk2) => {
@@ -5502,9 +5302,9 @@ function startSessionRelay(sessionId, serverUrl) {
5502
5302
  });
5503
5303
  child.on("exit", (code, signal) => {
5504
5304
  try {
5505
- const current = fs12.readFileSync(lockPath, "utf-8").trim();
5305
+ const current = fs11.readFileSync(lockPath, "utf-8").trim();
5506
5306
  if (current === String(child.pid))
5507
- fs12.unlinkSync(lockPath);
5307
+ fs11.unlinkSync(lockPath);
5508
5308
  } catch {
5509
5309
  }
5510
5310
  currentChild = null;
@@ -5531,7 +5331,7 @@ function startSessionRelay(sessionId, serverUrl) {
5531
5331
  `
5532
5332
  );
5533
5333
  try {
5534
- fs12.unlinkSync(lockPath);
5334
+ fs11.unlinkSync(lockPath);
5535
5335
  } catch {
5536
5336
  }
5537
5337
  return;
@@ -5563,7 +5363,7 @@ function startSessionRelay(sessionId, serverUrl) {
5563
5363
  }, 2e3).unref();
5564
5364
  }
5565
5365
  try {
5566
- fs12.unlinkSync(lockPath);
5366
+ fs11.unlinkSync(lockPath);
5567
5367
  } catch {
5568
5368
  }
5569
5369
  };