opencode-rules-md 0.8.5 → 0.9.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 (62) hide show
  1. package/dist/cli.mjs +252 -261
  2. package/dist/src/cli/config.d.ts +11 -0
  3. package/dist/src/cli/config.d.ts.map +1 -1
  4. package/dist/src/cli/config.js +15 -0
  5. package/dist/src/cli/config.js.map +1 -1
  6. package/dist/src/cli/install.d.ts +35 -20
  7. package/dist/src/cli/install.d.ts.map +1 -1
  8. package/dist/src/cli/install.js +50 -131
  9. package/dist/src/cli/install.js.map +1 -1
  10. package/dist/src/cli/main.d.ts +5 -0
  11. package/dist/src/cli/main.d.ts.map +1 -1
  12. package/dist/src/cli/main.js +29 -26
  13. package/dist/src/cli/main.js.map +1 -1
  14. package/dist/src/cli/spawn.d.ts +29 -0
  15. package/dist/src/cli/spawn.d.ts.map +1 -0
  16. package/dist/src/cli/spawn.js +48 -0
  17. package/dist/src/cli/spawn.js.map +1 -0
  18. package/dist/src/cli/status.d.ts +15 -8
  19. package/dist/src/cli/status.d.ts.map +1 -1
  20. package/dist/src/cli/status.js +63 -31
  21. package/dist/src/cli/status.js.map +1 -1
  22. package/dist/src/cli/uninstall.d.ts +5 -2
  23. package/dist/src/cli/uninstall.d.ts.map +1 -1
  24. package/dist/src/cli/uninstall.js +78 -51
  25. package/dist/src/cli/uninstall.js.map +1 -1
  26. package/dist/src/cli/update.d.ts +50 -16
  27. package/dist/src/cli/update.d.ts.map +1 -1
  28. package/dist/src/cli/update.js +156 -124
  29. package/dist/src/cli/update.js.map +1 -1
  30. package/dist/src/rule-discovery.d.ts.map +1 -1
  31. package/dist/src/rule-discovery.js +18 -10
  32. package/dist/src/rule-discovery.js.map +1 -1
  33. package/dist/src/rule-filter.d.ts +9 -0
  34. package/dist/src/rule-filter.d.ts.map +1 -1
  35. package/dist/src/rule-filter.js +48 -11
  36. package/dist/src/rule-filter.js.map +1 -1
  37. package/dist/src/rule-metadata.d.ts +2 -0
  38. package/dist/src/rule-metadata.d.ts.map +1 -1
  39. package/dist/src/rule-metadata.js +4 -0
  40. package/dist/src/rule-metadata.js.map +1 -1
  41. package/dist/src/runtime-context.d.ts +6 -0
  42. package/dist/src/runtime-context.d.ts.map +1 -1
  43. package/dist/src/runtime-context.js +16 -0
  44. package/dist/src/runtime-context.js.map +1 -1
  45. package/dist/src/session-store.d.ts.map +1 -1
  46. package/dist/src/session-store.js +1 -0
  47. package/dist/src/session-store.js.map +1 -1
  48. package/dist/tui/index.js +13 -9
  49. package/dist/tui/index.js.map +4 -4
  50. package/package.json +1 -1
  51. package/src/cli/config.ts +19 -0
  52. package/src/cli/install.ts +66 -174
  53. package/src/cli/main.ts +34 -25
  54. package/src/cli/spawn.ts +76 -0
  55. package/src/cli/status.ts +83 -37
  56. package/src/cli/uninstall.ts +88 -57
  57. package/src/cli/update.ts +182 -148
  58. package/src/rule-discovery.ts +22 -10
  59. package/src/rule-filter.ts +73 -12
  60. package/src/rule-metadata.ts +8 -0
  61. package/src/runtime-context.ts +16 -0
  62. package/src/session-store.ts +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../src/cli/spawn.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,YAAY,KAAK,WAAW,CAAC;AAE9F,MAAM,WAAW,0BAA0B;IACzC,mFAAmF;IACnF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kFAAkF;IAClF,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,GAAE,0BAA+B,GACpC,OAAO,CAAC,WAAW,CAAC,CAKtB"}
@@ -0,0 +1,48 @@
1
+ // ---------------------------------------------------------------------------
2
+ // src/cli/spawn.ts — thin wrapper around `opencode plugin`.
3
+ //
4
+ // Why a wrapper? Two reasons:
5
+ // 1. OpenCode owns the schema for `data['plugin']` (singular) and the cache
6
+ // layout under ~/.cache/opencode/packages/. Re-implementing that logic
7
+ // drift-prone (the bug we are fixing). Delegating to OpenCode's own CLI
8
+ // keeps us correct by construction.
9
+ // 2. Tests need a deterministic, non-blocking seam. Defaulting to
10
+ // spawnSync with `stdio: 'inherit'` lets the real CLI talk directly to
11
+ // the user's terminal; tests inject a stub that returns canned output.
12
+ // ---------------------------------------------------------------------------
13
+ import { createRequire } from 'node:module';
14
+ const require = createRequire(import.meta.url);
15
+ /**
16
+ * Run `opencode plugin <args...>` and return the exit status plus captured
17
+ * stdout/stderr (only populated when `stdio: 'pipe'`).
18
+ *
19
+ * The default implementation uses spawnSync so the call blocks until the
20
+ * child process exits. This keeps `omd install` simple — the user's shell
21
+ * stays put until registration completes, then returns control with a
22
+ * non-zero status on failure.
23
+ */
24
+ export async function spawnOpencodePlugin(args, opts = {}) {
25
+ const env = opts.env ?? process.env;
26
+ const stdio = opts.stdio ?? 'inherit';
27
+ const spawnFn = opts.spawn ?? defaultSpawn;
28
+ return spawnFn('opencode', ['plugin', ...args], { env, stdio });
29
+ }
30
+ /**
31
+ * Default spawn implementation backed by node:child_process.spawnSync.
32
+ *
33
+ * The require is loaded lazily so test doubles can replace the spawn
34
+ * function entirely without ever touching node:child_process.
35
+ */
36
+ function defaultSpawn(command, args, options) {
37
+ const cp = require('node:child_process');
38
+ const result = cp.spawnSync(command, args, {
39
+ env: options.env,
40
+ stdio: options.stdio,
41
+ });
42
+ return {
43
+ status: result.status,
44
+ stdout: result.stdout?.toString() ?? '',
45
+ stderr: result.stderr?.toString() ?? '',
46
+ };
47
+ }
48
+ //# sourceMappingURL=spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../../src/cli/spawn.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,4DAA4D;AAC5D,EAAE;AACF,8BAA8B;AAC9B,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,yCAAyC;AACzC,oEAAoE;AACpE,4EAA4E;AAC5E,4EAA4E;AAC5E,8EAA8E;AAE9E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAwB/C;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAc,EACd,OAAmC,EAAE;IAErC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC;IAC3C,OAAO,OAAO,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;AAClE,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,OAAe,EAAE,IAAc,EAAE,OAAqB;IAC1E,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAwC,CAAC;IAChF,MAAM,MAAM,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE;QACzC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;IACH,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;QACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;KACxC,CAAC;AACJ,CAAC"}
@@ -1,4 +1,8 @@
1
1
  import { type CliFs } from './config.js';
2
+ export interface StatusOptions {
3
+ /** Override latest version for testing — skips the npm registry call */
4
+ latestVersion?: string | null;
5
+ }
2
6
  export interface StatusEntry {
3
7
  basename: string;
4
8
  path: string;
@@ -27,16 +31,19 @@ export interface DoctorResult {
27
31
  * Run the status command: read-only probe for both opencode.json and tui.json.
28
32
  * Reports path, format, installed specifier, other plugins, and freshness.
29
33
  */
30
- export declare const runStatus: (fs: CliFs, env: NodeJS.ProcessEnv, log: (s: string) => void) => Promise<StatusResult>;
34
+ export declare const runStatus: (fs: CliFs, env: NodeJS.ProcessEnv, log: (s: string) => void, opts?: StatusOptions) => Promise<StatusResult>;
31
35
  /**
32
36
  * Run the doctor command: health checks for the plugin environment.
33
- * - Node >= 20: issue if below
34
- * - Bun on PATH: issue if absent
35
- * - Configs readable: issue if absent or malformed
36
- * - Plugin shape valid: issue if malformed
37
- * - Rule dir existence: warning if absent
38
- * - Config dir writable: issue if not writable
39
- * - Package freshness: info line about update availability
37
+ *
38
+ * Checks:
39
+ * - Node >= 20: issue if below
40
+ * - Bun on PATH: issue if absent
41
+ * - Both configs readable and valid: issue if absent or malformed
42
+ * - Legacy `plugins` field present: warning (no-op for the runtime, but
43
+ * indicates a previous buggy install)
44
+ * - Rule dir existence: warning if absent
45
+ * - Config dir writable: issue if not writable
46
+ * - Package freshness: info line about update availability
40
47
  *
41
48
  * Exit 1 if any issues found.
42
49
  */
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"AAWA,OAAO,EAIL,KAAK,KAAK,EACX,MAAM,aAAa,CAAC;AAKrB,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAID,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAWD;;;GAGG;AACH,eAAO,MAAM,SAAS,GACpB,IAAI,KAAK,EACT,KAAK,MAAM,CAAC,UAAU,EACtB,KAAK,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,KACvB,OAAO,CAAC,YAAY,CA+CtB,CAAC;AAIF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,GACpB,IAAI,KAAK,EACT,KAAK,MAAM,CAAC,UAAU,EACtB,KAAK,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EACxB,OAAO,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAC1B,OAAM,aAAkB,KACvB,OAAO,CAAC,YAAY,CA6GtB,CAAC"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"AAiBA,OAAO,EAIL,KAAK,KAAK,EAEX,MAAM,aAAa,CAAC;AAMrB,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAID,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAWD;;;GAGG;AACH,eAAO,MAAM,SAAS,GACpB,IAAI,KAAK,EACT,KAAK,MAAM,CAAC,UAAU,EACtB,KAAK,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EACxB,OAAM,aAAkB,KACvB,OAAO,CAAC,YAAY,CAoDtB,CAAC;AAIF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,GACpB,IAAI,KAAK,EACT,KAAK,MAAM,CAAC,UAAU,EACtB,KAAK,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EACxB,OAAO,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAC1B,OAAM,aAAkB,KACvB,OAAO,CAAC,YAAY,CAqItB,CAAC"}
@@ -1,15 +1,22 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // src/cli/status.ts — `omd status` and `omd doctor` command implementations.
3
3
  //
4
- // runStatus: read-only probe for both configs. Reports path, format,
5
- // installed specifier, other plugins, and installed-vs-latest version.
6
- // runDoctor: health checks grouped into issues (exit 1), warnings, and info.
4
+ // Three correctness fixes vs. the previous implementation:
5
+ //
6
+ // 1. We read `data['plugin']` (singular) as the source of truth, with a
7
+ // backward-compat fallback to `data['plugins']`. The legacy plural
8
+ // field is no longer authoritative.
9
+ // 2. `runDoctor` warns when a legacy `plugins` field is present, so users
10
+ // upgrading from the buggy version are nudged to clean up.
11
+ // 3. The cache freshness check uses ~/.cache/opencode/packages/ (where
12
+ // OpenCode actually stores plugin installs) instead of the legacy
13
+ // ~/.cache/opencode/node_modules/ path.
7
14
  // ---------------------------------------------------------------------------
8
- import { join, dirname } from 'path';
15
+ import { join, dirname, extname } from 'path';
9
16
  import { homedir } from 'os';
10
- import { extname } from 'path';
11
- import { loadGlobalConfig, matchesPlugin, normalizePlugin, } from './config.js';
17
+ import { loadGlobalConfig, matchesPlugin, readInstalledPlugins, } from './config.js';
12
18
  import { fetchLatestVersion } from './registry.js';
19
+ import { resolveCachePaths } from './update.js';
13
20
  // ─── Constants ───────────────────────────────────────────────────────────────
14
21
  const RULE_DIR_NAME = 'opencode-rules-md';
15
22
  const MIN_NODE_VERSION = 20;
@@ -19,26 +26,29 @@ const CONFIG_BASENAMES = ['opencode', 'tui'];
19
26
  * Run the status command: read-only probe for both opencode.json and tui.json.
20
27
  * Reports path, format, installed specifier, other plugins, and freshness.
21
28
  */
22
- export const runStatus = async (fs, env, log) => {
29
+ export const runStatus = async (fs, env, log, opts = {}) => {
23
30
  const configs = [];
24
- const latest = await fetchLatestVersion();
31
+ const latest = opts.latestVersion !== undefined
32
+ ? opts.latestVersion
33
+ : await fetchLatestVersion();
25
34
  for (const basename of CONFIG_BASENAMES) {
26
35
  const loaded = loadGlobalConfig(fs, env, basename);
27
36
  const format = extname(loaded.path); // '.json' or '.jsonc'
28
- const plugins = normalizePlugin(loaded.data['plugins']);
29
- const match = plugins.find(p => matchesPlugin(p));
37
+ const plugins = readInstalledPlugins(loaded);
38
+ const match = plugins.find((p) => matchesPlugin(p)) ?? null;
30
39
  const entry = {
31
40
  basename,
32
41
  path: loaded.path,
33
42
  format,
34
- installed: match ?? null,
35
- notInstalled: !loaded.exists ? true : match === undefined || match === null,
36
- otherPlugins: plugins.filter(p => !matchesPlugin(p)),
43
+ installed: match,
44
+ notInstalled: !loaded.exists || match === null,
45
+ otherPlugins: plugins.filter((p) => !matchesPlugin(p)),
37
46
  latest,
38
- isLatest: match !== undefined && latest !== null ? match === `opencode-rules-md@${latest}` : null,
47
+ isLatest: match !== null && latest !== null
48
+ ? match === `opencode-rules-md@${latest}`
49
+ : null,
39
50
  };
40
51
  configs.push(entry);
41
- // ── Print status lines ──────────────────────────────────────────────────
42
52
  if (!loaded.exists) {
43
53
  log(`omd: ${basename}.json — config not found at ${loaded.path}`);
44
54
  continue;
@@ -53,7 +63,7 @@ export const runStatus = async (fs, env, log) => {
53
63
  log(` opencode-rules-md: ${match}${isLatestLabel}`);
54
64
  }
55
65
  else {
56
- log(` opencode-rules-md: not installed`);
66
+ log(' opencode-rules-md: not installed');
57
67
  }
58
68
  if (entry.otherPlugins.length > 0) {
59
69
  log(` other plugins: ${entry.otherPlugins.join(', ')}`);
@@ -64,13 +74,16 @@ export const runStatus = async (fs, env, log) => {
64
74
  // ─── runDoctor ────────────────────────────────────────────────────────────────
65
75
  /**
66
76
  * Run the doctor command: health checks for the plugin environment.
67
- * - Node >= 20: issue if below
68
- * - Bun on PATH: issue if absent
69
- * - Configs readable: issue if absent or malformed
70
- * - Plugin shape valid: issue if malformed
71
- * - Rule dir existence: warning if absent
72
- * - Config dir writable: issue if not writable
73
- * - Package freshness: info line about update availability
77
+ *
78
+ * Checks:
79
+ * - Node >= 20: issue if below
80
+ * - Bun on PATH: issue if absent
81
+ * - Both configs readable and valid: issue if absent or malformed
82
+ * - Legacy `plugins` field present: warning (no-op for the runtime, but
83
+ * indicates a previous buggy install)
84
+ * - Rule dir existence: warning if absent
85
+ * - Config dir writable: issue if not writable
86
+ * - Package freshness: info line about update availability
74
87
  *
75
88
  * Exit 1 if any issues found.
76
89
  */
@@ -84,7 +97,7 @@ export const runDoctor = async (fs, env, log, error, opts = {}) => {
84
97
  let hasBun = opts.hasBun;
85
98
  if (hasBun === undefined) {
86
99
  const pathEnv = (env.PATH ?? '').split(':');
87
- hasBun = pathEnv.some(p => {
100
+ hasBun = pathEnv.some((p) => {
88
101
  try {
89
102
  const { existsSync } = require('node:fs');
90
103
  return existsSync(p + '/bun');
@@ -123,23 +136,32 @@ export const runDoctor = async (fs, env, log, error, opts = {}) => {
123
136
  continue;
124
137
  }
125
138
  log(` ${basename}${extname(loaded.path)}: ${loaded.path}`);
126
- const plugins = normalizePlugin(loaded.data['plugins']);
127
- const match = plugins.find(p => matchesPlugin(p));
139
+ const plugins = readInstalledPlugins(loaded);
140
+ const match = plugins.find((p) => matchesPlugin(p)) ?? null;
128
141
  if (match) {
129
- info.push(`${basename}: opencode-rules-md@${match ?? 'unknown'} installed`);
142
+ info.push(`${basename}: opencode-rules-md installed (${match})`);
130
143
  log(` opencode-rules-md: ${match}`);
131
144
  }
132
145
  else {
133
146
  warnings.push(`${basename}: plugin not installed`);
134
- log(` opencode-rules-md: not installed`);
147
+ log(' opencode-rules-md: not installed');
148
+ }
149
+ // ── Check legacy `plugins` field (backward-compat warning) ──────────────
150
+ if (loaded.data['plugins'] !== undefined && loaded.data['plugin'] === undefined) {
151
+ warnings.push(`${basename}: legacy "plugins" field present (should be "plugin") — run "omd uninstall && omd install" to migrate`);
152
+ log(` [WARN] ${basename}: legacy "plugins" field present (should be "plugin")`);
135
153
  }
136
154
  // ── Check plugin shape ────────────────────────────────────────────────────
137
- if (loaded.data['plugins'] !== undefined && !Array.isArray(loaded.data['plugins']) && typeof loaded.data['plugins'] !== 'object') {
138
- issues.push(`${basename}: plugins field has invalid type — expected array or object`);
155
+ const pluginField = loaded.data['plugin'] ?? loaded.data['plugins'];
156
+ if (pluginField !== undefined &&
157
+ !Array.isArray(pluginField) &&
158
+ typeof pluginField !== 'object' &&
159
+ typeof pluginField !== 'string') {
160
+ issues.push(`${basename}: plugin field has invalid type — expected array, object, or string`);
139
161
  error(`[ISSUE] ${basename}: invalid plugin shape`);
140
162
  }
141
163
  else {
142
- log(` plugins field: valid`);
164
+ log(' plugin field: valid');
143
165
  }
144
166
  }
145
167
  // ── Check: rule dir existence (warning, not issue) ─────────────────────────
@@ -152,6 +174,16 @@ export const runDoctor = async (fs, env, log, error, opts = {}) => {
152
174
  else {
153
175
  log(` ${ruleBase}: exists`);
154
176
  }
177
+ // ── Check: package cache directory ────────────────────────────────────────
178
+ log('Checking OpenCode package cache...');
179
+ const cachePaths = resolveCachePaths(env, fs);
180
+ if (cachePaths.length === 0) {
181
+ info.push('No opencode-rules-md cache found under ~/.cache/opencode/packages/');
182
+ log(' no cache entries match opencode-rules-md*');
183
+ }
184
+ else {
185
+ log(` cache entries: ${cachePaths.join(', ')}`);
186
+ }
155
187
  // ── Check: config dir writable ─────────────────────────────────────────────
156
188
  const configDir = env.OPENCODE_CONFIG_DIR ?? join(homedir(), '.config', 'opencode');
157
189
  log('Checking config directory write access...');
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,11 @@
1
1
  import { type CliFs } from './config.js';
2
2
  export declare const CONFIG_BASENAMES: readonly ["opencode", "tui"];
3
3
  export interface UninstallOptions {
4
+ /** Also remove ~/.cache/opencode/packages/opencode-rules-md*. */
4
5
  purge?: boolean;
6
+ /** Run the full pipeline without writing to disk. */
5
7
  dryRun?: boolean;
8
+ /** Reserved for future prompts — no-op today. */
6
9
  yes?: boolean;
7
10
  }
8
11
  export interface UninstallResultPerFile {
@@ -19,9 +22,9 @@ export interface UninstallResult {
19
22
  * Uninstall opencode-rules-md from both opencode.json and tui.json configs.
20
23
  *
21
24
  * Options:
22
- * purge — also remove ~/.cache/opencode/node_modules/opencode-rules-md
25
+ * purge — also remove ~/.cache/opencode/packages/opencode-rules-md*
23
26
  * dryRun — run full pipeline without writing to disk
24
- * yes — accepted for future prompts, no-op here
27
+ * yes — reserved
25
28
  */
26
29
  export declare const runUninstall: (opts: UninstallOptions | undefined, fs: CliFs, env: NodeJS.ProcessEnv) => UninstallResult;
27
30
  //# sourceMappingURL=uninstall.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../../src/cli/uninstall.ts"],"names":[],"mappings":"AAUA,OAAO,EAOL,KAAK,KAAK,EACX,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,gBAAgB,8BAA+B,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACtC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,gBAAgB,YAAK,EAC3B,IAAI,KAAK,EACT,KAAK,MAAM,CAAC,UAAU,KACrB,eA6FF,CAAC"}
1
+ {"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../../src/cli/uninstall.ts"],"names":[],"mappings":"AAoBA,OAAO,EAKL,KAAK,KAAK,EACX,MAAM,aAAa,CAAC;AAGrB,eAAO,MAAM,gBAAgB,8BAA+B,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACtC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC;CACjB;AA6CD;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,gBAAgB,YAAK,EAC3B,IAAI,KAAK,EACT,KAAK,MAAM,CAAC,UAAU,KACrB,eAqEF,CAAC"}
@@ -1,21 +1,69 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // src/cli/uninstall.ts — `omd uninstall` command implementation.
3
3
  //
4
- // Dual-config uninstall: removes opencode-rules-md entries from both configs.
5
- // --purge removes ONLY ~/.cache/opencode/node_modules/opencode-rules-md and
6
- // NEVER touches rule directories.
4
+ // Removes opencode-rules-md from opencode.json and tui.json, and (with
5
+ // `--purge`) wipes the OpenCode package cache. Two important fixes vs.
6
+ // the previous implementation:
7
+ //
8
+ // 1. We read & write `data['plugin']` (singular), the field OpenCode
9
+ // actually honors. The previous code wrote `data['plugins']` (plural),
10
+ // which OpenCode silently ignored — so "uninstall" used to leave
11
+ // the plugin effectively installed.
12
+ // 2. We also strip a stale `data['plugins']` entry if it exists, so
13
+ // users who upgraded from a buggy `omd install` get their legacy
14
+ // field cleaned up too.
15
+ // 3. We purge ~/.cache/opencode/packages/opencode-rules-md* (the real
16
+ // cache OpenCode uses), not the old ~/.cache/opencode/node_modules
17
+ // path.
7
18
  // ---------------------------------------------------------------------------
8
- import { dirname, join } from 'path';
9
- import { homedir } from 'os';
10
- import { loadGlobalConfig, matchesPlugin, normalizePlugin, backupIfWritable, rotateBackups, writeAtomically, } from './config.js';
19
+ import { join } from 'path';
20
+ import { loadGlobalConfig, backupIfWritable, rotateBackups, writeAtomically, } from './config.js';
21
+ import { resolveCachePaths, purgeDirectory } from './update.js';
11
22
  export const CONFIG_BASENAMES = ['opencode', 'tui'];
23
+ /**
24
+ * Strip `opencode-rules-md` entries from a config payload, cleaning both
25
+ * the modern `plugin` field (array or single string) and any legacy
26
+ * `plugins` field. Returns a tuple [newData, removedCount].
27
+ *
28
+ * `removedCount > 0` indicates the file actually needs to be rewritten.
29
+ */
30
+ function stripFromData(data) {
31
+ let removed = 0;
32
+ const next = { ...data };
33
+ // Modern field: `plugin` (singular). Accept array or single string.
34
+ const currentRaw = next['plugin'] ?? next['plugins'];
35
+ if (currentRaw !== undefined) {
36
+ if (typeof currentRaw === 'string') {
37
+ if (currentRaw.startsWith('opencode-rules-md')) {
38
+ delete next['plugin'];
39
+ delete next['plugins'];
40
+ removed += 1;
41
+ }
42
+ }
43
+ else if (Array.isArray(currentRaw)) {
44
+ const filtered = currentRaw.filter((p) => !(typeof p === 'string' && p.startsWith('opencode-rules-md')));
45
+ if (filtered.length !== currentRaw.length) {
46
+ removed += currentRaw.length - filtered.length;
47
+ if (filtered.length === 0) {
48
+ delete next['plugin'];
49
+ delete next['plugins'];
50
+ }
51
+ else {
52
+ next['plugin'] = filtered;
53
+ delete next['plugins'];
54
+ }
55
+ }
56
+ }
57
+ }
58
+ return { next, removed };
59
+ }
12
60
  /**
13
61
  * Uninstall opencode-rules-md from both opencode.json and tui.json configs.
14
62
  *
15
63
  * Options:
16
- * purge — also remove ~/.cache/opencode/node_modules/opencode-rules-md
64
+ * purge — also remove ~/.cache/opencode/packages/opencode-rules-md*
17
65
  * dryRun — run full pipeline without writing to disk
18
- * yes — accepted for future prompts, no-op here
66
+ * yes — reserved
19
67
  */
20
68
  export const runUninstall = (opts = {}, fs, env) => {
21
69
  const results = [];
@@ -23,67 +71,46 @@ export const runUninstall = (opts = {}, fs, env) => {
23
71
  let purged = false;
24
72
  // ── Purge cache if requested ────────────────────────────────────────────
25
73
  if (opts.purge) {
26
- const cachePath = join(homedir(), '.cache', 'opencode', 'node_modules', 'opencode-rules-md');
27
- if (fs.existsSync(cachePath)) {
74
+ const cachePaths = resolveCachePaths(env, fs);
75
+ for (const cachePath of cachePaths) {
28
76
  try {
29
- // Check if it's a directory or a file
30
- const entries = fs.readdirSync(cachePath);
31
- if (entries.length === 0) {
32
- // Empty directory — remove it
33
- fs.rmdirSync(cachePath);
34
- }
35
- else {
36
- // Has contents — remove contents then the dir
37
- for (const entry of entries) {
38
- const entryPath = join(cachePath, entry);
39
- if (fs.existsSync(entryPath)) {
40
- try {
41
- fs.unlinkSync(entryPath);
42
- }
43
- catch {
44
- // ignore individual file failures
45
- }
46
- }
47
- }
48
- fs.rmdirSync(cachePath);
77
+ if (fs.existsSync(cachePath)) {
78
+ purgeDirectory(fs, cachePath);
79
+ purged = true;
49
80
  }
50
- purged = true;
51
81
  }
52
82
  catch {
53
- // best-effort — cache purge failure is non-fatal
83
+ // best-effort — purge failure is non-fatal
54
84
  }
55
85
  }
56
86
  }
57
87
  // ── Remove plugin from both configs ─────────────────────────────────────
58
88
  for (const basename of CONFIG_BASENAMES) {
59
89
  const loaded = loadGlobalConfig(fs, env, basename);
60
- const plugins = normalizePlugin(loaded.data['plugins']);
61
- // Filter out all opencode-rules-md entries
62
- const remaining = plugins.filter(p => !matchesPlugin(p));
63
- if (remaining.length === plugins.length) {
64
- // Nothing to remove no-op for this file
90
+ if (!loaded.exists) {
91
+ results.push({ path: loaded.path, status: 'skipped', backup: null });
92
+ continue;
93
+ }
94
+ const { next, removed } = stripFromData(loaded.data);
95
+ if (removed === 0) {
65
96
  results.push({ path: loaded.path, status: 'skipped', backup: null });
66
97
  continue;
67
98
  }
68
99
  anyProcessed = true;
69
- const newData = { ...loaded.data, plugins: remaining };
70
- const newContent = JSON.stringify(newData, null, 2) + '\n';
100
+ const newContent = JSON.stringify(next, null, 2) + '\n';
71
101
  if (opts.dryRun) {
72
102
  results.push({ path: loaded.path, status: 'wrote', backup: null });
73
103
  continue;
74
104
  }
75
- // Backup the existing file if it exists
76
- let backup;
77
- if (loaded.exists) {
78
- backup = backupIfWritable(fs, loaded.path);
79
- if (backup !== undefined) {
80
- const dir = dirname(loaded.path);
81
- const segs = loaded.path.replace(/\\/g, '/').split('/');
82
- const base = segs[segs.length - 1] ?? loaded.path;
83
- const dot = base.lastIndexOf('.');
84
- const name = dot >= 0 ? base.slice(0, dot) : base;
85
- rotateBackups(fs, dir, name, 3);
86
- }
105
+ // Backup the existing file before rewriting.
106
+ const backup = backupIfWritable(fs, loaded.path);
107
+ if (backup !== undefined) {
108
+ const segs = loaded.path.replace(/\\/g, '/').split('/');
109
+ const base = segs[segs.length - 1] ?? loaded.path;
110
+ const dot = base.lastIndexOf('.');
111
+ const name = dot >= 0 ? base.slice(0, dot) : base;
112
+ const dir = join(...segs.slice(0, -1));
113
+ rotateBackups(fs, dir, name, 3);
87
114
  }
88
115
  writeAtomically(fs, loaded.path, newContent);
89
116
  results.push({
@@ -1 +1 @@
1
- {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../../src/cli/uninstall.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../../src/cli/uninstall.ts"],"names":[],"mappings":"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"}
@@ -1,31 +1,65 @@
1
- import type { CliFs } from './config.js';
2
- export declare const CACHE_PATH: string;
1
+ import { type CliFs } from './config.js';
2
+ import { spawnOpencodePlugin } from './spawn.js';
3
+ /** Package directory used by OpenCode to cache plugin installs. */
4
+ export declare const PACKAGES_DIR_BASENAME: readonly [".cache", "opencode", "packages"];
5
+ /** Exact cache directory name we look for (bare specifier, no version suffix). */
6
+ export declare const CACHE_DIR_BASENAME = "opencode-rules-md";
7
+ /**
8
+ * Resolve the user's home directory, honoring a custom HOME env var.
9
+ * Used by both resolveCachePaths and the config loader.
10
+ */
11
+ export declare function resolveHome(env?: NodeJS.ProcessEnv): string;
12
+ /**
13
+ * Return the absolute path of the OpenCode packages cache directory.
14
+ */
15
+ export declare function resolvePackagesDir(env?: NodeJS.ProcessEnv): string;
16
+ /**
17
+ * Return the cache directories that match the opencode-rules-md prefix.
18
+ *
19
+ * Real-world layout under ~/.cache/opencode/packages/ looks like:
20
+ * opencode-rules-md/
21
+ * opencode-rules-md@latest/
22
+ * some-other-plugin/
23
+ *
24
+ * We glob-match anything starting with `opencode-rules-md` (exact or with
25
+ * an `@<version>` suffix). When an injected fs is provided we list the
26
+ * directory and filter; without one we return the two most common shapes
27
+ * so callers can pre-check existence cheaply.
28
+ */
29
+ export declare function resolveCachePaths(env?: NodeJS.ProcessEnv, fs?: CliFs): string[];
3
30
  export interface UpdateOptions {
31
+ /** Injected latest version (test seam). Defaults to a real npm lookup. */
4
32
  latestVersion?: string | null | undefined;
33
+ /** Print the plan without writing or spawning. */
5
34
  dryRun?: boolean;
35
+ /** Injected spawn function (test seam). Defaults to spawnOpencodePlugin. */
36
+ spawn?: typeof spawnOpencodePlugin;
6
37
  }
7
38
  export interface UpdateResult {
8
39
  status: 'stale' | 'current' | 'unreachable';
9
- cachePath: string;
40
+ cachePaths: string[];
41
+ /** Re-install instruction; empty when status === 'current'. */
10
42
  instruction: string;
11
43
  }
12
44
  /**
13
- * Resolve the local cache directory, honoring a custom HOME environment.
14
- * Falls back to os.homedir() when HOME is not set, matching the
15
- * resolveConfigDir fallback strategy.
45
+ * Extract the version portion of an `opencode-rules-md@<version>` specifier.
46
+ * Returns null when the specifier has no `@version` segment.
16
47
  */
17
- export declare function resolveCachePath(env?: NodeJS.ProcessEnv): string;
48
+ export declare function extractVersion(specifier: string): string | null;
18
49
  /**
19
- * Run the update command:
20
- * 1. Fetch latest version from npm (or use provided mock)
21
- * 2. Compare to installed version in config
22
- * 3. If stale: purge cache, print reinstall instruction
23
- * 4. If current: print "already current"
24
- * 5. If unreachable: noop
50
+ * Recursively delete a directory and all its contents using the injected fs.
51
+ * Best-effort a failed purge is not fatal; we want the update to keep going.
25
52
  */
26
- export declare const runUpdate: (fs: CliFs, env: NodeJS.ProcessEnv, log: (s: string) => void, _error: (s: string) => void, opts?: UpdateOptions) => Promise<UpdateResult>;
53
+ export declare function purgeDirectory(fs: CliFs, dirPath: string): void;
27
54
  /**
28
- * Recursively delete a directory and all its contents using the given fs.
55
+ * Run the update command.
56
+ *
57
+ * 1. Resolve the latest published version from npm (or use the injected mock).
58
+ * 2. Read the installed version from the user's opencode config.
59
+ * 3. If unreachable, log and return.
60
+ * 4. If current, log and return.
61
+ * 5. Otherwise: purge stale cache directories, then spawn
62
+ * `opencode plugin opencode-rules-md --global --force`.
29
63
  */
30
- export declare function purgeDirectory(fs: CliFs, dirPath: string): void;
64
+ export declare const runUpdate: (fs: CliFs, env: NodeJS.ProcessEnv, log: (s: string) => void, _error: (s: string) => void, opts?: UpdateOptions) => Promise<UpdateResult>;
31
65
  //# sourceMappingURL=update.d.ts.map