akm-cli 0.7.4 → 0.8.0-rc.3

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 (162) hide show
  1. package/{CHANGELOG.md → .github/CHANGELOG.md} +34 -1
  2. package/.github/LICENSE +374 -0
  3. package/dist/cli/parse-args.js +86 -0
  4. package/dist/cli.js +1223 -650
  5. package/dist/commands/agent-dispatch.js +107 -0
  6. package/dist/commands/agent-support.js +62 -0
  7. package/dist/commands/config-cli.js +68 -84
  8. package/dist/commands/consolidate.js +812 -0
  9. package/dist/commands/curate.js +1 -0
  10. package/dist/commands/distill-promotion-policy.js +658 -0
  11. package/dist/commands/distill.js +224 -39
  12. package/dist/commands/eval-cases.js +40 -0
  13. package/dist/commands/events.js +12 -24
  14. package/dist/commands/graph.js +222 -0
  15. package/dist/commands/health.js +376 -0
  16. package/dist/commands/help/help-accept.md +9 -0
  17. package/dist/commands/help/help-improve.md +53 -0
  18. package/dist/commands/help/help-proposals.md +15 -0
  19. package/dist/commands/help/help-propose.md +17 -0
  20. package/dist/commands/help/help-reject.md +8 -0
  21. package/dist/commands/history.js +3 -30
  22. package/dist/commands/improve.js +1161 -0
  23. package/dist/commands/info.js +2 -2
  24. package/dist/commands/init.js +2 -2
  25. package/dist/commands/install-audit.js +5 -1
  26. package/dist/commands/installed-stashes.js +118 -138
  27. package/dist/commands/knowledge.js +133 -0
  28. package/dist/commands/lint/agent-linter.js +46 -0
  29. package/dist/commands/lint/base-linter.js +291 -0
  30. package/dist/commands/lint/command-linter.js +46 -0
  31. package/dist/commands/lint/default-linter.js +13 -0
  32. package/dist/commands/lint/index.js +145 -0
  33. package/dist/commands/lint/knowledge-linter.js +13 -0
  34. package/dist/commands/lint/memory-linter.js +58 -0
  35. package/dist/commands/lint/registry.js +33 -0
  36. package/dist/commands/lint/skill-linter.js +42 -0
  37. package/dist/commands/lint/task-linter.js +47 -0
  38. package/dist/commands/lint/types.js +1 -0
  39. package/dist/commands/lint/vault-key-rules.js +67 -0
  40. package/dist/commands/lint/workflow-linter.js +53 -0
  41. package/dist/commands/lint.js +1 -0
  42. package/dist/commands/migration-help.js +2 -2
  43. package/dist/commands/proposal.js +8 -7
  44. package/dist/commands/propose.js +106 -43
  45. package/dist/commands/reflect.js +167 -41
  46. package/dist/commands/registry-search.js +2 -2
  47. package/dist/commands/remember.js +55 -1
  48. package/dist/commands/schema-repair.js +130 -0
  49. package/dist/commands/search.js +21 -5
  50. package/dist/commands/show.js +135 -55
  51. package/dist/commands/source-add.js +10 -10
  52. package/dist/commands/source-manage.js +11 -19
  53. package/dist/commands/tasks.js +385 -0
  54. package/dist/commands/url-checker.js +39 -0
  55. package/dist/commands/vault.js +173 -87
  56. package/dist/core/action-contributors.js +25 -0
  57. package/dist/core/asset-ref.js +4 -0
  58. package/dist/core/asset-registry.js +5 -17
  59. package/dist/core/asset-spec.js +11 -1
  60. package/dist/core/common.js +100 -0
  61. package/dist/core/concurrent.js +22 -0
  62. package/dist/core/config.js +240 -127
  63. package/dist/core/events.js +87 -123
  64. package/dist/core/frontmatter.js +0 -6
  65. package/dist/core/markdown.js +17 -0
  66. package/dist/core/memory-improve.js +678 -0
  67. package/dist/core/parse.js +155 -0
  68. package/dist/core/paths.js +101 -3
  69. package/dist/core/proposal-validators.js +61 -0
  70. package/dist/core/proposals.js +49 -38
  71. package/dist/core/state-db.js +731 -0
  72. package/dist/core/time.js +51 -0
  73. package/dist/core/warn.js +59 -1
  74. package/dist/indexer/db-search.js +86 -472
  75. package/dist/indexer/db.js +418 -59
  76. package/dist/indexer/ensure-index.js +133 -0
  77. package/dist/indexer/graph-boost.js +247 -94
  78. package/dist/indexer/graph-db.js +201 -0
  79. package/dist/indexer/graph-dedup.js +99 -0
  80. package/dist/indexer/graph-extraction.js +417 -74
  81. package/dist/indexer/index-context.js +10 -0
  82. package/dist/indexer/indexer.js +480 -298
  83. package/dist/indexer/llm-cache.js +47 -0
  84. package/dist/indexer/matchers.js +124 -160
  85. package/dist/indexer/memory-inference.js +63 -29
  86. package/dist/indexer/metadata-contributors.js +26 -0
  87. package/dist/indexer/metadata.js +196 -197
  88. package/dist/indexer/path-resolver.js +89 -0
  89. package/dist/indexer/ranking-contributors.js +204 -0
  90. package/dist/indexer/ranking.js +74 -0
  91. package/dist/indexer/search-hit-enrichers.js +22 -0
  92. package/dist/indexer/search-source.js +24 -9
  93. package/dist/indexer/semantic-status.js +2 -16
  94. package/dist/indexer/walker.js +25 -0
  95. package/dist/integrations/agent/builders.js +109 -0
  96. package/dist/integrations/agent/config.js +203 -3
  97. package/dist/integrations/agent/index.js +5 -2
  98. package/dist/integrations/agent/model-aliases.js +63 -0
  99. package/dist/integrations/agent/profiles.js +67 -5
  100. package/dist/integrations/agent/prompts.js +114 -29
  101. package/dist/integrations/agent/sdk-runner.js +120 -0
  102. package/dist/integrations/agent/spawn.js +158 -34
  103. package/dist/integrations/lockfile.js +10 -18
  104. package/dist/integrations/session-logs/index.js +65 -0
  105. package/dist/integrations/session-logs/providers/claude-code.js +56 -0
  106. package/dist/integrations/session-logs/providers/opencode.js +52 -0
  107. package/dist/integrations/session-logs/types.js +1 -0
  108. package/dist/llm/call-ai.js +74 -0
  109. package/dist/llm/client.js +63 -86
  110. package/dist/llm/feature-gate.js +27 -16
  111. package/dist/llm/graph-extract.js +297 -64
  112. package/dist/llm/memory-infer.js +52 -71
  113. package/dist/llm/metadata-enhance.js +39 -22
  114. package/dist/llm/prompts/graph-extract-user-prompt.md +12 -0
  115. package/dist/output/cli-hints-full.md +277 -0
  116. package/dist/output/cli-hints-short.md +65 -0
  117. package/dist/output/cli-hints.js +2 -309
  118. package/dist/output/renderers.js +226 -257
  119. package/dist/output/shapes.js +109 -96
  120. package/dist/output/text.js +274 -36
  121. package/dist/registry/providers/skills-sh.js +61 -49
  122. package/dist/registry/providers/static-index.js +44 -48
  123. package/dist/registry/resolve.js +8 -16
  124. package/dist/setup/setup.js +510 -11
  125. package/dist/sources/provider-factory.js +2 -1
  126. package/dist/sources/providers/filesystem.js +16 -23
  127. package/dist/sources/providers/git.js +45 -4
  128. package/dist/sources/providers/website.js +15 -22
  129. package/dist/sources/website-ingest.js +4 -0
  130. package/dist/tasks/backends/cron.js +200 -0
  131. package/dist/tasks/backends/exec-utils.js +25 -0
  132. package/dist/tasks/backends/index.js +32 -0
  133. package/dist/tasks/backends/launchd-template.xml +19 -0
  134. package/dist/tasks/backends/launchd.js +184 -0
  135. package/dist/tasks/backends/schtasks-template.xml +29 -0
  136. package/dist/tasks/backends/schtasks.js +212 -0
  137. package/dist/tasks/parser.js +198 -0
  138. package/dist/tasks/resolveAkmBin.js +84 -0
  139. package/dist/tasks/runner.js +432 -0
  140. package/dist/tasks/schedule.js +208 -0
  141. package/dist/tasks/schema.js +13 -0
  142. package/dist/tasks/validator.js +59 -0
  143. package/dist/wiki/index-template.md +12 -0
  144. package/dist/wiki/ingest-workflow-template.md +54 -0
  145. package/dist/wiki/log-template.md +8 -0
  146. package/dist/wiki/schema-template.md +61 -0
  147. package/dist/wiki/wiki-templates.js +12 -0
  148. package/dist/wiki/wiki.js +10 -61
  149. package/dist/workflows/authoring.js +5 -25
  150. package/dist/workflows/db.js +9 -0
  151. package/dist/workflows/renderer.js +8 -3
  152. package/dist/workflows/runs.js +73 -88
  153. package/dist/workflows/scope-key.js +76 -0
  154. package/dist/workflows/validator.js +1 -1
  155. package/dist/workflows/workflow-template.md +24 -0
  156. package/docs/README.md +5 -2
  157. package/docs/migration/release-notes/0.7.0.md +1 -1
  158. package/docs/migration/release-notes/0.7.4.md +1 -1
  159. package/docs/migration/release-notes/0.7.5.md +20 -0
  160. package/docs/migration/release-notes/0.8.0.md +43 -0
  161. package/package.json +4 -3
  162. package/dist/templates/wiki-templates.js +0 -100
@@ -1,7 +1,5 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
1
  import { fetchWithRetry, jsonWithByteCap, toErrorMessage } from "../../core/common";
4
- import { getRegistryIndexCacheDir } from "../../core/paths";
2
+ import { closeDatabase, getRegistryIndexCache, openDatabase, upsertRegistryIndexCache } from "../../indexer/db";
5
3
  import { asString } from "../../integrations/github";
6
4
  import { registerProvider } from "../factory";
7
5
  // ── Constants ───────────────────────────────────────────────────────────────
@@ -114,13 +112,25 @@ function assetHitToPreview(hit) {
114
112
  registerProvider("static-index", (config) => new StaticIndexProvider(config));
115
113
  // ── Index loading with cache ────────────────────────────────────────────────
116
114
  async function loadIndex(entry) {
117
- const cachePath = indexCachePath(entry.url);
118
- const cached = readCachedIndex(cachePath);
119
- // Fresh cache: return immediately
120
- if (cached && !isCacheExpired(cached.mtime)) {
121
- return cached.index;
115
+ // ── Step 1: Try DB cache (index.db) ─────────────────────────────────────
116
+ let db;
117
+ let dbCacheResult;
118
+ try {
119
+ db = openDatabase();
120
+ dbCacheResult = getRegistryIndexCache(db, entry.url, CACHE_TTL_MS);
121
+ }
122
+ catch {
123
+ // index.db not available yet (pre-migration install or test env) — fall through
124
+ }
125
+ if (dbCacheResult) {
126
+ const index = parseRegistryIndex(JSON.parse(dbCacheResult.indexJson));
127
+ if (index) {
128
+ if (db)
129
+ closeDatabase(db);
130
+ return index;
131
+ }
122
132
  }
123
- // Try to fetch fresh index
133
+ // ── Step 2: Fetch fresh index from remote ────────────────────────────────
124
134
  try {
125
135
  const response = await fetchWithRetry(entry.url, undefined, { timeout: 10_000 });
126
136
  if (!response.ok) {
@@ -131,54 +141,40 @@ async function loadIndex(entry) {
131
141
  const data = await jsonWithByteCap(response, 50 * 1024 * 1024);
132
142
  const index = parseRegistryIndex(data);
133
143
  if (index) {
134
- writeCachedIndex(cachePath, index);
144
+ // Write to DB cache (primary)
145
+ if (db) {
146
+ try {
147
+ const etag = response.headers.get("etag") ?? undefined;
148
+ const lastModified = response.headers.get("last-modified") ?? undefined;
149
+ upsertRegistryIndexCache(db, entry.url, JSON.stringify(index), { etag, lastModified });
150
+ }
151
+ catch {
152
+ /* best-effort */
153
+ }
154
+ closeDatabase(db);
155
+ }
135
156
  return index;
136
157
  }
137
158
  throw new Error("Invalid registry index format");
138
159
  }
139
160
  catch (err) {
140
- // Fetch failed — use stale cache if available
141
- if (cached && !isCacheStale(cached.mtime)) {
142
- return cached.index;
161
+ if (db) {
162
+ try {
163
+ closeDatabase(db);
164
+ }
165
+ catch {
166
+ /* ignore */
167
+ }
168
+ }
169
+ // Fetch failed — use stale DB cache if available
170
+ if (dbCacheResult) {
171
+ const index = parseRegistryIndex(JSON.parse(dbCacheResult.indexJson));
172
+ if (index)
173
+ return index;
143
174
  }
144
175
  throw err;
145
176
  }
146
177
  }
147
- // ── Cache helpers (exported for reuse by other providers) ───────────────────
148
- export function indexCachePath(url) {
149
- const indexDir = getRegistryIndexCacheDir();
150
- // Deterministic filename from URL
151
- const slug = url
152
- .replace(/[^a-zA-Z0-9]+/g, "-")
153
- .replace(/^-+|-+$/g, "")
154
- .slice(0, 120);
155
- return path.join(indexDir, `${slug}.json`);
156
- }
157
- export function readCachedIndex(cachePath) {
158
- try {
159
- const stat = fs.statSync(cachePath);
160
- const raw = JSON.parse(fs.readFileSync(cachePath, "utf8"));
161
- const index = parseRegistryIndex(raw);
162
- if (!index)
163
- return null;
164
- return { index, mtime: stat.mtimeMs };
165
- }
166
- catch {
167
- return null;
168
- }
169
- }
170
- export function writeCachedIndex(cachePath, index) {
171
- try {
172
- const dir = path.dirname(cachePath);
173
- fs.mkdirSync(dir, { recursive: true });
174
- const tmpPath = `${cachePath}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`;
175
- fs.writeFileSync(tmpPath, JSON.stringify(index), "utf8");
176
- fs.renameSync(tmpPath, cachePath);
177
- }
178
- catch {
179
- // Best-effort caching — don't fail the search if we can't write
180
- }
181
- }
182
178
  export function isCacheExpired(mtimeMs) {
183
179
  return Date.now() - mtimeMs > CACHE_TTL_MS;
184
180
  }
@@ -340,6 +340,7 @@ async function resolveNpmArtifact(parsed) {
340
340
  }
341
341
  async function resolveGithubArtifact(parsed) {
342
342
  const gitUrl = `https://github.com/${encodeURIComponent(parsed.owner)}/${encodeURIComponent(parsed.repo)}.git`;
343
+ const repoBase = `${GITHUB_API_BASE}/repos/${encodeURIComponent(parsed.owner)}/${encodeURIComponent(parsed.repo)}`;
343
344
  // Prefer git-backed installs so private GitHub repos work with the user's
344
345
  // normal git credential helper rather than requiring API-specific auth.
345
346
  const gitResolvedRevision = resolveGitRevisionFromRemote(gitUrl, parsed.requestedRef);
@@ -355,18 +356,18 @@ async function resolveGithubArtifact(parsed) {
355
356
  }
356
357
  const headers = githubHeaders();
357
358
  if (parsed.requestedRef) {
358
- const commit = await tryFetchJson(`${GITHUB_API_BASE}/repos/${encodeURIComponent(parsed.owner)}/${encodeURIComponent(parsed.repo)}/commits/${encodeURIComponent(parsed.requestedRef)}`, headers);
359
+ const commit = await tryFetchJson(`${repoBase}/commits/${encodeURIComponent(parsed.requestedRef)}`, headers);
359
360
  const resolvedRevision = asString(commit?.sha) ?? parsed.requestedRef;
360
361
  return {
361
362
  id: parsed.id,
362
363
  source: parsed.source,
363
364
  ref: parsed.ref,
364
- artifactUrl: `${GITHUB_API_BASE}/repos/${encodeURIComponent(parsed.owner)}/${encodeURIComponent(parsed.repo)}/tarball/${encodeURIComponent(parsed.requestedRef)}`,
365
+ artifactUrl: `${repoBase}/tarball/${encodeURIComponent(parsed.requestedRef)}`,
365
366
  resolvedRevision,
366
367
  resolvedVersion: parsed.requestedRef,
367
368
  };
368
369
  }
369
- const latestRelease = await tryFetchJson(`${GITHUB_API_BASE}/repos/${encodeURIComponent(parsed.owner)}/${encodeURIComponent(parsed.repo)}/releases/latest`, headers);
370
+ const latestRelease = await tryFetchJson(`${repoBase}/releases/latest`, headers);
370
371
  if (latestRelease) {
371
372
  const tarballUrl = asString(latestRelease.tarball_url);
372
373
  if (tarballUrl) {
@@ -380,17 +381,17 @@ async function resolveGithubArtifact(parsed) {
380
381
  };
381
382
  }
382
383
  }
383
- const repoMeta = await fetchJson(`${GITHUB_API_BASE}/repos/${encodeURIComponent(parsed.owner)}/${encodeURIComponent(parsed.repo)}`, headers);
384
+ const repoMeta = await fetchJson(repoBase, headers);
384
385
  const defaultBranch = asString(repoMeta.default_branch);
385
386
  if (!defaultBranch) {
386
387
  throw new Error(`Unable to resolve default branch for ${parsed.owner}/${parsed.repo}.`);
387
388
  }
388
- const commit = await tryFetchJson(`${GITHUB_API_BASE}/repos/${encodeURIComponent(parsed.owner)}/${encodeURIComponent(parsed.repo)}/commits/${encodeURIComponent(defaultBranch)}`, headers);
389
+ const commit = await tryFetchJson(`${repoBase}/commits/${encodeURIComponent(defaultBranch)}`, headers);
389
390
  return {
390
391
  id: parsed.id,
391
392
  source: parsed.source,
392
393
  ref: parsed.ref,
393
- artifactUrl: `${GITHUB_API_BASE}/repos/${encodeURIComponent(parsed.owner)}/${encodeURIComponent(parsed.repo)}/tarball/${encodeURIComponent(defaultBranch)}`,
394
+ artifactUrl: `${repoBase}/tarball/${encodeURIComponent(defaultBranch)}`,
394
395
  resolvedVersion: defaultBranch,
395
396
  resolvedRevision: asString(commit?.sha) ?? defaultBranch,
396
397
  };
@@ -407,16 +408,7 @@ function resolveGitRevisionFromRemote(url, requestedRef) {
407
408
  return firstLine?.split(/\s/)[0] || undefined;
408
409
  }
409
410
  async function resolveGitArtifact(parsed) {
410
- validateGitUrl(parsed.url);
411
- const ref = parsed.requestedRef ?? "HEAD";
412
- if (parsed.requestedRef)
413
- validateGitRef(parsed.requestedRef);
414
- const result = spawnSync("git", ["ls-remote", parsed.url, ref], { encoding: "utf8", timeout: 30_000 });
415
- let resolvedRevision;
416
- if (result.status === 0) {
417
- const firstLine = result.stdout.trim().split(/\r?\n/)[0];
418
- resolvedRevision = firstLine?.split(/\s/)[0] || undefined;
419
- }
411
+ const resolvedRevision = resolveGitRevisionFromRemote(parsed.url, parsed.requestedRef);
420
412
  return {
421
413
  id: parsed.id,
422
414
  source: parsed.source,