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.
@@ -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
  "",
@@ -4176,11 +4149,6 @@ function recodeMessagesToPng(messages, opts) {
4176
4149
  return stats;
4177
4150
  }
4178
4151
 
4179
- // src/claude-lifecycle-cutover.ts
4180
- var fs11 = __toESM(require("fs"));
4181
- var os4 = __toESM(require("os"));
4182
- var path12 = __toESM(require("path"));
4183
-
4184
4152
  // src/native-skill-mirror.ts
4185
4153
  var fs10 = __toESM(require("node:fs"));
4186
4154
  var os3 = __toESM(require("node:os"));
@@ -4422,126 +4390,44 @@ function canonicalContentHash(skill) {
4422
4390
  function canonicalLookupArgs(skill) {
4423
4391
  return `--skill-id ${canonicalSkillId(skill)}`;
4424
4392
  }
4425
- function canonicalWriteArgs(skill) {
4426
- if (skill.scope !== "project" || !skill.projectId)
4427
- return "";
4428
- const replaces = (skill.replaces || []).map((id) => ` --replaces ${id}`).join("");
4429
- return `--scope project --project-id ${skill.projectId}${replaces}`;
4430
- }
4431
- function canonicalEditArgs(skill) {
4432
- return [canonicalLookupArgs(skill), canonicalWriteArgs(skill)].filter(Boolean).join(" ");
4433
- }
4434
- function nativeCreationLocations(platform) {
4435
- if (platform === "codex") {
4436
- return "`~/.codex/skills/<new-name>/SKILL.md` (global) or `<repo>/.agents/skills/<new-name>/SKILL.md` (project)";
4437
- }
4438
- if (platform === "opencode") {
4439
- return "`~/.config/opencode/skills/<new-name>/SKILL.md` (global) or `<repo>/.opencode/skills/<new-name>/SKILL.md` (project)";
4440
- }
4441
- return "`~/.claude/skills/<new-name>/SKILL.md` (global) or `<repo>/.claude/skills/<new-name>/SKILL.md` (project)";
4442
- }
4443
- function renderChangeSkillLine(params) {
4444
- const exportCommand = `greprag skill mirror export ${params.skillName} ${params.identityArg} --to <dir>`;
4445
- const applyCommand = `greprag skill mirror apply <dir> --skill ${params.skillName} ${params.editArgs} --expected-hash <exported-hash> --reason "<why>"`;
4446
- if (params.platform === "codex") {
4447
- 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}\`.`;
4448
- }
4449
- return `- **Change this skill:** run \`greprag load skill-change\`, then \`greprag skill edit ${params.skillName} ${params.editArgs} --reason "<why>"\`, then \`${params.syncCommand}\`, then verify with \`${params.loadCommand}\`.`;
4450
- }
4451
- function renderEditingSection(platform, params) {
4452
- const exportCommand = `greprag skill mirror export ${params.skillName} ${params.identityArg} --to <dir>`;
4453
- const applyCommand = `greprag skill mirror apply <dir> --skill ${params.skillName} ${params.editArgs} --expected-hash <exported-hash> --reason "<why>"`;
4454
- if (platform === "codex") {
4455
- return `## Editing
4456
-
4457
- Codex agents must use the non-interactive mirror path:
4458
-
4459
- \`\`\`bash
4460
- ${exportCommand}
4461
- # patch the exported Markdown files with normal file edits
4462
- ${applyCommand}
4463
- \`\`\`
4464
-
4465
- 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.
4466
- `;
4467
- }
4468
- return `## Editing
4469
-
4470
- To edit this skill, run the guarded editor flow:
4471
-
4472
- \`\`\`bash
4473
- greprag skill edit ${params.skillName} ${params.editArgs} --reason "<why>"
4474
- \`\`\`
4475
-
4476
- Manual path:
4477
-
4478
- \`\`\`bash
4479
- ${exportCommand}
4480
- ${applyCommand}
4481
- \`\`\`
4482
- `;
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`;
4483
4395
  }
4484
4396
  function renderAdapterBody(platform, skill) {
4485
4397
  const skillName = skill.skillName;
4486
4398
  const skillId = canonicalSkillId(skill);
4487
4399
  const identityArg = canonicalLookupArgs(skill);
4488
- const editArgs = canonicalEditArgs(skill);
4489
- const creationLocations = nativeCreationLocations(platform);
4490
4400
  const syncCommand = nativeAdapterInstallCommand(platform, [skillName]);
4491
- 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.`;
4492
4401
  const companions = skill.files.map((file) => file.path).filter((relative) => relative !== "SKILL.md").sort();
4493
4402
  const harnessArg = `--harness ${platform}`;
4494
4403
  const loadCommand = `greprag load ${skillName} ${identityArg} ${harnessArg}`;
4495
- const changeSkillLine = renderChangeSkillLine({
4496
- platform,
4497
- skillName,
4498
- editArgs,
4499
- identityArg,
4500
- syncCommand,
4501
- loadCommand
4502
- });
4503
- const editingSection = renderEditingSection(platform, { skillName, editArgs, identityArg });
4504
- 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.";
4505
4405
  return `# ${skillName}
4506
4406
 
4507
4407
  ## GENERATED ADAPTER \u2014 NEVER EDIT
4508
4408
 
4509
- 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.
4510
-
4511
- 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.
4512
4410
 
4513
4411
  Required action chains:
4514
4412
 
4515
4413
  - **Use this skill:** run \`${loadCommand}\` before acting.
4516
- ${changeSkillLine}
4517
- ${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}\`.
4518
4416
 
4519
4417
  Authority: ${skillId}
4520
4418
  Source binding: ${sourceBindingState(skill)}
4521
4419
  Canonical content hash: ${canonicalContentHash(skill)}
4522
4420
  ${typeof skill.revision === "number" ? `Mirror revision: ${skill.revision}` : "Mirror revision: unknown"}
4523
4421
 
4524
- ${editingSection}
4525
-
4526
- History and rollback (every canon write keeps its bytes and reason):
4527
-
4528
- \`\`\`bash
4529
- greprag skill history ${skillName} ${identityArg}
4530
- greprag skill diff ${skillName} <revA> [<revB>] ${identityArg}
4531
- greprag skill revert ${skillName} --to <rev> ${identityArg} --reason "<why>" --expected-hash <current-hash>
4532
- greprag skill mirror snapshot list ${skillName} ${identityArg}
4533
- greprag skill mirror snapshot promote ${skillName} --name <snapshot> ${editArgs} --expected-hash <current-hash> --reason "<why>"
4534
- \`\`\`
4535
-
4536
4422
  ## Mandatory Invocation
4537
4423
 
4538
4424
  When this skill activates, run:
4539
4425
 
4540
4426
  \`\`\`bash
4541
- greprag load ${skillName} ${identityArg} ${harnessArg}
4427
+ ${loadCommand}
4542
4428
  \`\`\`
4543
4429
 
4544
- Read and follow that canonical payload before responding or taking action.
4430
+ Read and follow that payload before responding or taking action.
4545
4431
 
4546
4432
  ## Companion Docs
4547
4433
 
@@ -4805,94 +4691,6 @@ async function fetchNativeMirroredSkill(apiUrl, apiKey, row) {
4805
4691
  } : null;
4806
4692
  }
4807
4693
 
4808
- // src/claude-lifecycle-cutover.ts
4809
- var CLAUDE_LIFECYCLE_SKILLS = ["commit", "deploy", "release"];
4810
- function adapterFor(skill) {
4811
- const files = buildNativeSkillAdapter("claude-code", skill, { allowClaudeCode: true });
4812
- if (!files || files.length !== 1 || files[0].path !== "SKILL.md") {
4813
- throw new Error(`Claude lifecycle adapter is invalid for ${skill.skillName}.`);
4814
- }
4815
- return files;
4816
- }
4817
- function safeTimestamp(now) {
4818
- return now.toISOString().replace(/[:.]/g, "-");
4819
- }
4820
- function requiredSkills(skills, names) {
4821
- const byName = new Map(skills.filter((skill) => skill.scope !== "project").map((skill) => [skill.skillName, skill]));
4822
- return names.map((name) => {
4823
- const skill = byName.get(name);
4824
- if (!skill)
4825
- throw new Error(`Canonical Claude lifecycle skill missing: ${name}.`);
4826
- return skill;
4827
- });
4828
- }
4829
- function applyClaudeLifecycleCutover(params) {
4830
- const homeDir = params.homeDir || os4.homedir();
4831
- const root = nativeSkillRoot("claude-code", homeDir);
4832
- const state = readState(root);
4833
- const names = params.names?.length ? params.names : CLAUDE_LIFECYCLE_SKILLS;
4834
- const prepared = requiredSkills(params.skills, names).map((skill) => {
4835
- const target = path12.join(root, skill.skillName);
4836
- if (isSkillFolderOwnedElsewhere(target)) {
4837
- throw new Error(`Claude skill folder is owned elsewhere (a link or another installer's package): ${skill.skillName}; not written.`);
4838
- }
4839
- const skillMd = path12.join(target, "SKILL.md");
4840
- const adapterFiles = adapterFor(skill);
4841
- const nextHash = computeSkillFileHash(adapterFiles);
4842
- const managed = state.skills[skill.skillName];
4843
- let currentContent;
4844
- if (fs11.existsSync(skillMd))
4845
- currentContent = fs11.readFileSync(skillMd, "utf8");
4846
- if (managed) {
4847
- const currentFiles = currentContent === void 0 ? null : [{ path: "SKILL.md", content: currentContent }];
4848
- if (!currentFiles || computeSkillFileHash(currentFiles) !== managed.hash) {
4849
- throw new Error(`Claude lifecycle adapter diverged: ${skill.skillName}.`);
4850
- }
4851
- } else if (fs11.existsSync(target) && currentContent === void 0) {
4852
- throw new Error(`Claude lifecycle package has no SKILL.md: ${skill.skillName}.`);
4853
- }
4854
- return { skill, target, skillMd, adapterFiles, nextHash, managed, currentContent };
4855
- });
4856
- const replacements = prepared.filter((item) => !item.managed && item.currentContent !== void 0);
4857
- let backupDir;
4858
- if (replacements.length > 0) {
4859
- backupDir = path12.join(
4860
- homeDir,
4861
- ".greprag",
4862
- "backups",
4863
- "claude-lifecycle-cutover",
4864
- safeTimestamp(params.now || /* @__PURE__ */ new Date())
4865
- );
4866
- for (const item of replacements) {
4867
- const destination = path12.join(backupDir, item.skill.skillName, "SKILL.md");
4868
- fs11.mkdirSync(path12.dirname(destination), { recursive: true });
4869
- fs11.writeFileSync(destination, item.currentContent, "utf8");
4870
- }
4871
- }
4872
- const result = {
4873
- installed: 0,
4874
- updated: 0,
4875
- current: 0,
4876
- blocked: 0,
4877
- backupDir
4878
- };
4879
- for (const item of prepared) {
4880
- if (item.managed && item.managed.hash === item.nextHash) {
4881
- result.current++;
4882
- continue;
4883
- }
4884
- fs11.mkdirSync(item.target, { recursive: true });
4885
- fs11.writeFileSync(item.skillMd, item.adapterFiles[0].content, "utf8");
4886
- state.skills[item.skill.skillName] = { hash: item.nextHash, files: ["SKILL.md"] };
4887
- if (item.managed)
4888
- result.updated++;
4889
- else
4890
- result.installed++;
4891
- }
4892
- writeState(root, state);
4893
- return result;
4894
- }
4895
-
4896
4694
  // src/native-adapter-refresh.ts
4897
4695
  function readAdapterStamps(content) {
4898
4696
  const frontmatter = /^---\n([\s\S]*?)\n---/.exec(content.replace(/\r\n?/g, "\n"))?.[1] || "";
@@ -4908,7 +4706,7 @@ function readAdapterStamps(content) {
4908
4706
  function staleNativeAdapters(params) {
4909
4707
  const globalRoot = nativeSkillRoot(params.platform, params.homeDir);
4910
4708
  const roots = [globalRoot];
4911
- 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;
4912
4710
  if (projectRoot)
4913
4711
  roots.push(projectRoot);
4914
4712
  const byId = /* @__PURE__ */ new Map();
@@ -4942,7 +4740,7 @@ function staleNativeAdapters(params) {
4942
4740
  }
4943
4741
  async function refreshNativeAdapters(params) {
4944
4742
  const platform = params.platform;
4945
- if (platform !== "claude-code" && platform !== "codex" && platform !== "opencode") {
4743
+ if (platform !== "codex" && platform !== "opencode") {
4946
4744
  return { refreshed: 0, blocked: 0 };
4947
4745
  }
4948
4746
  const stale = staleNativeAdapters({ ...params, platform });
@@ -4953,7 +4751,7 @@ async function refreshNativeAdapters(params) {
4953
4751
  if (!skill)
4954
4752
  continue;
4955
4753
  try {
4956
- const result = platform === "claude-code" ? applyClaudeLifecycleCutover({ skills: [skill], names: [skill.skillName], homeDir: params.homeDir }) : applyNativeSkillMirror({
4754
+ const result = applyNativeSkillMirror({
4957
4755
  platform,
4958
4756
  skills: [skill],
4959
4757
  homeDir: params.homeDir,
@@ -4970,14 +4768,14 @@ async function refreshNativeAdapters(params) {
4970
4768
  }
4971
4769
 
4972
4770
  // src/opencode-plugin.ts
4973
- 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");
4974
4772
  var _debugLogReady = false;
4975
4773
  function dlogInit() {
4976
4774
  if (_debugLogReady)
4977
4775
  return;
4978
4776
  _debugLogReady = true;
4979
4777
  try {
4980
- fs12.writeFileSync(DEBUG_LOG_PATH, "");
4778
+ fs11.writeFileSync(DEBUG_LOG_PATH, "");
4981
4779
  } catch {
4982
4780
  }
4983
4781
  }
@@ -4986,7 +4784,7 @@ function dlog(msg) {
4986
4784
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [greprag-memory] ${msg}
4987
4785
  `;
4988
4786
  try {
4989
- fs12.appendFileSync(DEBUG_LOG_PATH, line);
4787
+ fs11.appendFileSync(DEBUG_LOG_PATH, line);
4990
4788
  } catch {
4991
4789
  }
4992
4790
  }
@@ -4994,9 +4792,9 @@ dlog(`module top reached: pid=${process.pid} argv0=${process.argv[0]} distPath=$
4994
4792
  var API_URL = "https://api.greprag.com";
4995
4793
  function loadEnvFile(filePath2) {
4996
4794
  try {
4997
- if (!fs12.existsSync(filePath2))
4795
+ if (!fs11.existsSync(filePath2))
4998
4796
  return;
4999
- const raw = fs12.readFileSync(filePath2, "utf-8");
4797
+ const raw = fs11.readFileSync(filePath2, "utf-8");
5000
4798
  for (const line of raw.split(/\r?\n/)) {
5001
4799
  const trimmed = line.trim();
5002
4800
  if (!trimmed || trimmed.startsWith("#"))
@@ -5016,12 +4814,12 @@ function loadEnvFile(filePath2) {
5016
4814
  }
5017
4815
  }
5018
4816
  function loadGrepragEnv() {
5019
- loadEnvFile(path13.join(HOME, ".greprag", ".env"));
4817
+ loadEnvFile(path12.join(HOME, ".greprag", ".env"));
5020
4818
  try {
5021
- const p = path13.join(HOME, ".claude", "settings.json");
5022
- if (!fs12.existsSync(p))
4819
+ const p = path12.join(HOME, ".claude", "settings.json");
4820
+ if (!fs11.existsSync(p))
5023
4821
  return;
5024
- const data = JSON.parse(fs12.readFileSync(p, "utf-8"));
4822
+ const data = JSON.parse(fs11.readFileSync(p, "utf-8"));
5025
4823
  if (data && data.env && typeof data.env === "object") {
5026
4824
  for (const [key, val] of Object.entries(data.env)) {
5027
4825
  if (!process.env[key] && typeof val === "string") {
@@ -5034,11 +4832,11 @@ function loadGrepragEnv() {
5034
4832
  }
5035
4833
  loadGrepragEnv();
5036
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>"}`);
5037
- 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");
5038
4836
  var WATCHER_STALE_MS = 3e4;
5039
4837
  function findGrepragBinary() {
5040
4838
  const override = process.env.GREPRAG_BIN;
5041
- if (override && fs12.existsSync(override))
4839
+ if (override && fs11.existsSync(override))
5042
4840
  return override;
5043
4841
  const binaryName = process.platform === "win32" ? "greprag.cmd" : "greprag";
5044
4842
  try {
@@ -5047,14 +4845,14 @@ function findGrepragBinary() {
5047
4845
  const candidate = line.trim();
5048
4846
  if (!candidate)
5049
4847
  continue;
5050
- if (!fs12.existsSync(candidate))
4848
+ if (!fs11.existsSync(candidate))
5051
4849
  continue;
5052
4850
  if (process.platform === "win32") {
5053
- const ext = path13.extname(candidate).toLowerCase();
4851
+ const ext = path12.extname(candidate).toLowerCase();
5054
4852
  if (ext === ".cmd" || ext === ".exe" || ext === ".bat")
5055
4853
  return candidate;
5056
4854
  const cmdSibling = candidate + ".cmd";
5057
- if (fs12.existsSync(cmdSibling))
4855
+ if (fs11.existsSync(cmdSibling))
5058
4856
  return cmdSibling;
5059
4857
  continue;
5060
4858
  }
@@ -5063,19 +4861,19 @@ function findGrepragBinary() {
5063
4861
  } catch {
5064
4862
  }
5065
4863
  const candidates = process.platform === "win32" ? [
5066
- path13.join(HOME, "AppData", "Roaming", "npm", "greprag.cmd"),
5067
- path13.join(HOME, "AppData", "Roaming", "npm", "greprag"),
5068
- path13.join(HOME, "AppData", "Local", "Yarn", "bin", "greprag.cmd"),
5069
- 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")
5070
4868
  ] : [
5071
4869
  "/usr/local/bin/greprag",
5072
4870
  "/opt/homebrew/bin/greprag",
5073
- path13.join(HOME || "", ".local", "bin", "greprag"),
5074
- path13.join(HOME || "", ".yarn", "bin", "greprag")
4871
+ path12.join(HOME || "", ".local", "bin", "greprag"),
4872
+ path12.join(HOME || "", ".yarn", "bin", "greprag")
5075
4873
  ];
5076
4874
  for (const c of candidates) {
5077
4875
  try {
5078
- if (c && fs12.existsSync(c))
4876
+ if (c && fs11.existsSync(c))
5079
4877
  return c;
5080
4878
  } catch {
5081
4879
  }
@@ -5084,18 +4882,18 @@ function findGrepragBinary() {
5084
4882
  }
5085
4883
  function tryClaimWatcherLock() {
5086
4884
  try {
5087
- const fd = fs12.openSync(WATCHER_LOCK, "wx");
4885
+ const fd = fs11.openSync(WATCHER_LOCK, "wx");
5088
4886
  return { ok: true, fd };
5089
4887
  } catch (err) {
5090
4888
  if (err.code !== "EEXIST") {
5091
4889
  return { ok: false, reason: "lock-create-failed" };
5092
4890
  }
5093
4891
  try {
5094
- const stat = fs12.statSync(WATCHER_LOCK);
4892
+ const stat = fs11.statSync(WATCHER_LOCK);
5095
4893
  const ageMs = Date.now() - stat.mtimeMs;
5096
4894
  let pidAlive = false;
5097
4895
  try {
5098
- const pid = parseInt(fs12.readFileSync(WATCHER_LOCK, "utf-8").trim(), 10);
4896
+ const pid = parseInt(fs11.readFileSync(WATCHER_LOCK, "utf-8").trim(), 10);
5099
4897
  pidAlive = pid > 0 && isPidAlive(pid);
5100
4898
  } catch {
5101
4899
  }
@@ -5103,10 +4901,10 @@ function tryClaimWatcherLock() {
5103
4901
  return { ok: false, reason: "busy" };
5104
4902
  }
5105
4903
  try {
5106
- fs12.unlinkSync(WATCHER_LOCK);
4904
+ fs11.unlinkSync(WATCHER_LOCK);
5107
4905
  } catch {
5108
4906
  }
5109
- const fd = fs12.openSync(WATCHER_LOCK, "wx");
4907
+ const fd = fs11.openSync(WATCHER_LOCK, "wx");
5110
4908
  return { ok: true, fd };
5111
4909
  } catch (err2) {
5112
4910
  return { ok: false, reason: "lock-stale-replace-failed" };
@@ -5147,11 +4945,11 @@ function startCaptureWatcher() {
5147
4945
  return;
5148
4946
  }
5149
4947
  try {
5150
- fs12.writeSync(claim.fd, String(process.pid));
5151
- fs12.closeSync(claim.fd);
4948
+ fs11.writeSync(claim.fd, String(process.pid));
4949
+ fs11.closeSync(claim.fd);
5152
4950
  } catch {
5153
4951
  try {
5154
- fs12.unlinkSync(WATCHER_LOCK);
4952
+ fs11.unlinkSync(WATCHER_LOCK);
5155
4953
  } catch {
5156
4954
  }
5157
4955
  return;
@@ -5167,11 +4965,11 @@ function startCaptureWatcher() {
5167
4965
  const claim2 = tryClaimWatcherLock();
5168
4966
  if (claim2.ok) {
5169
4967
  try {
5170
- fs12.writeSync(claim2.fd, String(process.pid));
5171
- fs12.closeSync(claim2.fd);
4968
+ fs11.writeSync(claim2.fd, String(process.pid));
4969
+ fs11.closeSync(claim2.fd);
5172
4970
  } catch {
5173
4971
  try {
5174
- fs12.unlinkSync(WATCHER_LOCK);
4972
+ fs11.unlinkSync(WATCHER_LOCK);
5175
4973
  } catch {
5176
4974
  }
5177
4975
  return false;
@@ -5214,7 +5012,7 @@ function startCaptureWatcher() {
5214
5012
  childStartTime = Date.now();
5215
5013
  dlog(`startCaptureWatcher: spawned 'greprag opencode watch' pid=${child.pid ?? "<none>"}`);
5216
5014
  try {
5217
- fs12.writeFileSync(WATCHER_LOCK, String(child.pid));
5015
+ fs11.writeFileSync(WATCHER_LOCK, String(child.pid));
5218
5016
  } catch {
5219
5017
  }
5220
5018
  child.stderr?.on("data", (chunk2) => {
@@ -5226,9 +5024,9 @@ function startCaptureWatcher() {
5226
5024
  child.on("exit", (code, signal) => {
5227
5025
  dlog(`startCaptureWatcher: child pid=${child.pid ?? "<none>"} exited code=${code} signal=${signal || "none"}`);
5228
5026
  try {
5229
- const current = fs12.readFileSync(WATCHER_LOCK, "utf-8").trim();
5027
+ const current = fs11.readFileSync(WATCHER_LOCK, "utf-8").trim();
5230
5028
  if (current === String(child.pid))
5231
- fs12.unlinkSync(WATCHER_LOCK);
5029
+ fs11.unlinkSync(WATCHER_LOCK);
5232
5030
  } catch {
5233
5031
  }
5234
5032
  currentChild = null;
@@ -5257,7 +5055,7 @@ function startCaptureWatcher() {
5257
5055
  `
5258
5056
  );
5259
5057
  try {
5260
- fs12.unlinkSync(WATCHER_LOCK);
5058
+ fs11.unlinkSync(WATCHER_LOCK);
5261
5059
  } catch {
5262
5060
  }
5263
5061
  return;
@@ -5289,7 +5087,7 @@ function startCaptureWatcher() {
5289
5087
  }, 2e3).unref();
5290
5088
  }
5291
5089
  try {
5292
- fs12.unlinkSync(WATCHER_LOCK);
5090
+ fs11.unlinkSync(WATCHER_LOCK);
5293
5091
  } catch {
5294
5092
  }
5295
5093
  };
@@ -5359,7 +5157,7 @@ async function fetchSkillActivation(apiKey, cwd) {
5359
5157
  rows,
5360
5158
  apiUrl: API_URL,
5361
5159
  apiKey,
5362
- homeDir: os5.homedir(),
5160
+ homeDir: os4.homedir(),
5363
5161
  projectDir: cwd
5364
5162
  }).catch(() => void 0);
5365
5163
  return activationFromApiRows({
@@ -5434,11 +5232,11 @@ function startSessionRelay(sessionId, serverUrl) {
5434
5232
  return;
5435
5233
  }
5436
5234
  try {
5437
- fs12.writeSync(claim.fd, String(process.pid));
5438
- fs12.closeSync(claim.fd);
5235
+ fs11.writeSync(claim.fd, String(process.pid));
5236
+ fs11.closeSync(claim.fd);
5439
5237
  } catch {
5440
5238
  try {
5441
- fs12.unlinkSync(lockPath);
5239
+ fs11.unlinkSync(lockPath);
5442
5240
  } catch {
5443
5241
  }
5444
5242
  return;
@@ -5453,11 +5251,11 @@ function startSessionRelay(sessionId, serverUrl) {
5453
5251
  const claim2 = tryClaimRelayLock(lockPath);
5454
5252
  if (claim2.ok) {
5455
5253
  try {
5456
- fs12.writeSync(claim2.fd, String(process.pid));
5457
- fs12.closeSync(claim2.fd);
5254
+ fs11.writeSync(claim2.fd, String(process.pid));
5255
+ fs11.closeSync(claim2.fd);
5458
5256
  } catch {
5459
5257
  try {
5460
- fs12.unlinkSync(lockPath);
5258
+ fs11.unlinkSync(lockPath);
5461
5259
  } catch {
5462
5260
  }
5463
5261
  return false;
@@ -5493,7 +5291,7 @@ function startSessionRelay(sessionId, serverUrl) {
5493
5291
  childStartTime = Date.now();
5494
5292
  dlog(`startSessionRelay: spawned 'greprag opencode relay' pid=${child.pid ?? "<none>"}`);
5495
5293
  try {
5496
- fs12.writeFileSync(lockPath, String(child.pid));
5294
+ fs11.writeFileSync(lockPath, String(child.pid));
5497
5295
  } catch {
5498
5296
  }
5499
5297
  child.stderr?.on("data", (chunk2) => {
@@ -5504,9 +5302,9 @@ function startSessionRelay(sessionId, serverUrl) {
5504
5302
  });
5505
5303
  child.on("exit", (code, signal) => {
5506
5304
  try {
5507
- const current = fs12.readFileSync(lockPath, "utf-8").trim();
5305
+ const current = fs11.readFileSync(lockPath, "utf-8").trim();
5508
5306
  if (current === String(child.pid))
5509
- fs12.unlinkSync(lockPath);
5307
+ fs11.unlinkSync(lockPath);
5510
5308
  } catch {
5511
5309
  }
5512
5310
  currentChild = null;
@@ -5533,7 +5331,7 @@ function startSessionRelay(sessionId, serverUrl) {
5533
5331
  `
5534
5332
  );
5535
5333
  try {
5536
- fs12.unlinkSync(lockPath);
5334
+ fs11.unlinkSync(lockPath);
5537
5335
  } catch {
5538
5336
  }
5539
5337
  return;
@@ -5565,7 +5363,7 @@ function startSessionRelay(sessionId, serverUrl) {
5565
5363
  }, 2e3).unref();
5566
5364
  }
5567
5365
  try {
5568
- fs12.unlinkSync(lockPath);
5366
+ fs11.unlinkSync(lockPath);
5569
5367
  } catch {
5570
5368
  }
5571
5369
  };