akm-cli 0.9.0-beta.5 → 0.9.0-beta.9

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.
@@ -8882,6 +8882,7 @@ var init_improve_types = () => {};
8882
8882
  // src/core/state-db.ts
8883
8883
  var exports_state_db = {};
8884
8884
  __export(exports_state_db, {
8885
+ withImmediateTransaction: () => withImmediateTransaction,
8885
8886
  upsertTaskHistory: () => upsertTaskHistory,
8886
8887
  upsertProposal: () => upsertProposal,
8887
8888
  upsertExtractedSession: () => upsertExtractedSession,
@@ -8979,7 +8980,8 @@ function proposalRowToProposal(row) {
8979
8980
  ...meta.review !== undefined ? { review: meta.review } : {},
8980
8981
  ...typeof meta.confidence === "number" ? { confidence: meta.confidence } : {},
8981
8982
  ...meta.gateDecision !== undefined ? { gateDecision: meta.gateDecision } : {},
8982
- ...typeof meta.backupContent === "string" ? { backupContent: meta.backupContent } : {}
8983
+ ...typeof meta.backupContent === "string" ? { backupContent: meta.backupContent } : {},
8984
+ ...typeof meta.eligibilitySource === "string" ? { eligibilitySource: meta.eligibilitySource } : {}
8983
8985
  };
8984
8986
  }
8985
8987
  function proposalToRowValues(proposal, stashDir) {
@@ -8994,6 +8996,8 @@ function proposalToRowValues(proposal, stashDir) {
8994
8996
  metaObj.gateDecision = proposal.gateDecision;
8995
8997
  if (proposal.backupContent !== undefined)
8996
8998
  metaObj.backupContent = proposal.backupContent;
8999
+ if (proposal.eligibilitySource !== undefined)
9000
+ metaObj.eligibilitySource = proposal.eligibilitySource;
8997
9001
  return {
8998
9002
  id: proposal.id,
8999
9003
  stash_dir: stashDir,
@@ -9120,6 +9124,19 @@ function insertProposalIfAbsent(db, proposal, stashDir) {
9120
9124
  const changes = result.changes ?? 0;
9121
9125
  return Number(changes) > 0;
9122
9126
  }
9127
+ function withImmediateTransaction(db, fn) {
9128
+ db.exec("BEGIN IMMEDIATE");
9129
+ try {
9130
+ const result = fn();
9131
+ db.exec("COMMIT");
9132
+ return result;
9133
+ } catch (err) {
9134
+ try {
9135
+ db.exec("ROLLBACK");
9136
+ } catch {}
9137
+ throw err;
9138
+ }
9139
+ }
9123
9140
  function upsertTaskHistory(db, row) {
9124
9141
  db.prepare(`
9125
9142
  INSERT OR IGNORE INTO task_history
@@ -9402,7 +9419,7 @@ var init_state_db = __esm(() => {
9402
9419
  -- metadata_json TEXT \u2014 JSON object for future proposal fields.
9403
9420
  -- Current fields stored here: sourceRun,
9404
9421
  -- review, confidence, gateDecision (#577),
9405
- -- backupContent.
9422
+ -- backupContent, eligibilitySource.
9406
9423
  --
9407
9424
  -- ADD COLUMN extension points (future migrations):
9408
9425
  -- ALTER TABLE proposals ADD COLUMN source_run TEXT DEFAULT NULL;
@@ -9599,6 +9616,13 @@ var init_state_db = __esm(() => {
9599
9616
  imported_count INTEGER NOT NULL DEFAULT 0
9600
9617
  );
9601
9618
  `
9619
+ },
9620
+ {
9621
+ id: "006-proposals-pending-ref-source",
9622
+ up: `
9623
+ CREATE INDEX IF NOT EXISTS idx_proposals_stash_status_ref_source
9624
+ ON proposals(stash_dir, status, ref, source);
9625
+ `
9602
9626
  }
9603
9627
  ];
9604
9628
  });
@@ -10512,7 +10536,7 @@ class ClaudeCodeProvider {
10512
10536
  const full = path8.join(dir, entry.name);
10513
10537
  if (entry.isDirectory())
10514
10538
  yield* this.#walkJsonl(full);
10515
- else if (entry.name.endsWith(".jsonl"))
10539
+ else if (entry.name.endsWith(".jsonl") && entry.name !== "journal.jsonl")
10516
10540
  yield full;
10517
10541
  }
10518
10542
  } catch {}
@@ -15510,6 +15534,14 @@ var init_config_schema = __esm(() => {
15510
15534
  maxTotalChars: positiveInt.optional(),
15511
15535
  minContentChars: exports_external.number().int().min(0).optional(),
15512
15536
  maxChunkSize: exports_external.number().int().min(1).max(50).optional(),
15537
+ incrementalSince: exports_external.string().optional(),
15538
+ limit: positiveInt.optional(),
15539
+ neighborsPerChanged: exports_external.number().int().min(1).optional(),
15540
+ requirePlannedRefs: exports_external.boolean().optional(),
15541
+ dueDays: exports_external.number().int().min(0).optional(),
15542
+ maxPerRun: positiveInt.optional(),
15543
+ importanceWeights: exports_external.record(exports_external.string().min(1), exports_external.number()).optional(),
15544
+ minPendingCount: exports_external.number().int().min(0).optional(),
15513
15545
  minNewSessions: exports_external.number().int().min(0).optional(),
15514
15546
  indexSessions: exports_external.boolean().optional(),
15515
15547
  minSessionDuration: exports_external.number().min(0).optional(),
@@ -15531,7 +15563,8 @@ var init_config_schema = __esm(() => {
15531
15563
  memoryInference: ImproveProcessConfigSchema.optional(),
15532
15564
  graphExtraction: ImproveProcessConfigSchema.optional(),
15533
15565
  validation: ImproveProcessConfigSchema.optional(),
15534
- triage: ImproveProcessConfigSchema.optional()
15566
+ triage: ImproveProcessConfigSchema.optional(),
15567
+ proactiveMaintenance: ImproveProcessConfigSchema.optional()
15535
15568
  }).passthrough().superRefine((val, ctx) => {
15536
15569
  const raw = val;
15537
15570
  if ("feedbackDistillation" in raw) {
@@ -15549,7 +15582,8 @@ var init_config_schema = __esm(() => {
15549
15582
  "graphExtraction",
15550
15583
  "validation",
15551
15584
  "extract",
15552
- "triage"
15585
+ "triage",
15586
+ "proactiveMaintenance"
15553
15587
  ]);
15554
15588
  for (const k of Object.keys(raw)) {
15555
15589
  if (!allowed.has(k)) {
@@ -16288,6 +16322,7 @@ __export(exports_db, {
16288
16322
  getMeta: () => getMeta,
16289
16323
  getLlmCacheEntry: () => getLlmCacheEntry,
16290
16324
  getLlmCacheEntriesByRefs: () => getLlmCacheEntriesByRefs,
16325
+ getIndexedFilePaths: () => getIndexedFilePaths,
16291
16326
  getIndexDirState: () => getIndexDirState,
16292
16327
  getEntryRefRowsForStashRoot: () => getEntryRefRowsForStashRoot,
16293
16328
  getEntryIdByFilePath: () => getEntryIdByFilePath,
@@ -17187,6 +17222,10 @@ function getEntryIdByFilePath(db, filePath) {
17187
17222
  const row = db.prepare("SELECT id FROM entries WHERE file_path = ? LIMIT 1").get(filePath);
17188
17223
  return row?.id;
17189
17224
  }
17225
+ function getIndexedFilePaths(db) {
17226
+ const rows = db.prepare("SELECT DISTINCT file_path FROM entries WHERE file_path IS NOT NULL AND file_path <> ''").all();
17227
+ return new Set(rows.map((r) => r.file_path));
17228
+ }
17190
17229
  function getEntryFilePathById(db, id) {
17191
17230
  const row = db.prepare("SELECT file_path FROM entries WHERE id = ?").get(id);
17192
17231
  return row?.file_path;
@@ -17314,18 +17353,56 @@ function clearStaleCacheEntries(db) {
17314
17353
  function computeBodyHash(body) {
17315
17354
  return sha256Hex(body);
17316
17355
  }
17356
+ function bareRef(ref) {
17357
+ try {
17358
+ const parsed = parseAssetRef(ref);
17359
+ return `${parsed.type}:${parsed.name}`;
17360
+ } catch {
17361
+ return ref;
17362
+ }
17363
+ }
17317
17364
  function getRetrievalCounts(db, refs) {
17318
17365
  if (refs.length === 0)
17319
17366
  return new Map;
17320
- const result = new Map;
17321
- for (let i = 0;i < refs.length; i += SQLITE_CHUNK_SIZE) {
17322
- const chunk = refs.slice(i, i + SQLITE_CHUNK_SIZE);
17367
+ const bareToInputs = new Map;
17368
+ for (const ref of refs) {
17369
+ const bare = bareRef(ref);
17370
+ const existing = bareToInputs.get(bare);
17371
+ if (existing)
17372
+ existing.push(ref);
17373
+ else
17374
+ bareToInputs.set(bare, [ref]);
17375
+ }
17376
+ const bareForms = [...bareToInputs.keys()];
17377
+ const countsByBare = new Map;
17378
+ for (let i = 0;i < bareForms.length; i += SQLITE_CHUNK_SIZE) {
17379
+ const chunk = bareForms.slice(i, i + SQLITE_CHUNK_SIZE);
17323
17380
  const placeholders = chunk.map(() => "?").join(", ");
17324
- const rows = db.prepare(`SELECT entry_ref, COUNT(*) AS cnt FROM usage_events
17325
- WHERE event_type IN ('search','show') AND entry_ref IN (${placeholders})
17326
- GROUP BY entry_ref`).all(...chunk);
17327
- for (const r of rows)
17328
- result.set(r.entry_ref, r.cnt);
17381
+ const rows = db.prepare(`SELECT
17382
+ CASE
17383
+ WHEN instr(entry_ref, '//') > 0
17384
+ THEN substr(entry_ref, instr(entry_ref, '//') + 2)
17385
+ ELSE entry_ref
17386
+ END AS bare_ref,
17387
+ COUNT(*) AS cnt
17388
+ FROM usage_events
17389
+ WHERE event_type IN ('search','show','curate')
17390
+ AND entry_ref IS NOT NULL
17391
+ AND CASE
17392
+ WHEN instr(entry_ref, '//') > 0
17393
+ THEN substr(entry_ref, instr(entry_ref, '//') + 2)
17394
+ ELSE entry_ref
17395
+ END IN (${placeholders})
17396
+ GROUP BY bare_ref`).all(...chunk);
17397
+ for (const r of rows) {
17398
+ countsByBare.set(r.bare_ref, (countsByBare.get(r.bare_ref) ?? 0) + r.cnt);
17399
+ }
17400
+ }
17401
+ const result = new Map;
17402
+ for (const [bare, count] of countsByBare) {
17403
+ for (const input of bareToInputs.get(bare) ?? []) {
17404
+ result.set(input, count);
17405
+ }
17329
17406
  }
17330
17407
  return result;
17331
17408
  }
@@ -8708,7 +8708,7 @@ var MIGRATIONS = [
8708
8708
  -- metadata_json TEXT \u2014 JSON object for future proposal fields.
8709
8709
  -- Current fields stored here: sourceRun,
8710
8710
  -- review, confidence, gateDecision (#577),
8711
- -- backupContent.
8711
+ -- backupContent, eligibilitySource.
8712
8712
  --
8713
8713
  -- ADD COLUMN extension points (future migrations):
8714
8714
  -- ALTER TABLE proposals ADD COLUMN source_run TEXT DEFAULT NULL;
@@ -8905,6 +8905,13 @@ var MIGRATIONS = [
8905
8905
  imported_count INTEGER NOT NULL DEFAULT 0
8906
8906
  );
8907
8907
  `
8908
+ },
8909
+ {
8910
+ id: "006-proposals-pending-ref-source",
8911
+ up: `
8912
+ CREATE INDEX IF NOT EXISTS idx_proposals_stash_status_ref_source
8913
+ ON proposals(stash_dir, status, ref, source);
8914
+ `
8908
8915
  }
8909
8916
  ];
8910
8917
  function runMigrations2(db) {
@@ -12,12 +12,12 @@
12
12
  * providers that fetch tarballs (currently `NpmSourceProvider` and the
13
13
  * registry index builder).
14
14
  */
15
- import { spawnSync } from "node:child_process";
16
15
  import { createHash } from "node:crypto";
17
16
  import fs from "node:fs";
18
17
  import path from "node:path";
19
18
  import { isWithin } from "../../core/common.js";
20
19
  import { warn } from "../../core/warn.js";
20
+ import { spawnSync } from "../../runtime.js";
21
21
  /**
22
22
  * Verify an archive's integrity against a known hash. Throws and removes
23
23
  * the archive when verification fails.
@@ -65,17 +65,25 @@ export function verifyArchiveIntegrity(archivePath, expected, source) {
65
65
  * tree for symlinks that would escape the destination.
66
66
  */
67
67
  export function extractTarGzSecure(archivePath, destinationDir) {
68
- const listResult = spawnSync("tar", ["tzf", archivePath], { encoding: "utf8" });
69
- if (listResult.status !== 0) {
70
- const err = listResult.stderr?.trim() || listResult.error?.message || "unknown error";
68
+ const listResult = spawnSync(["tar", "tzf", archivePath]);
69
+ if (!listResult.success) {
70
+ const err = listResult.stderr?.toString().trim() || "unknown error";
71
71
  throw new Error(`Failed to inspect archive ${archivePath}: ${err}`);
72
72
  }
73
- validateTarEntries(listResult.stdout);
73
+ validateTarEntries(listResult.stdout.toString());
74
74
  fs.rmSync(destinationDir, { recursive: true, force: true });
75
75
  fs.mkdirSync(destinationDir, { recursive: true });
76
- const extractResult = spawnSync("tar", ["xzf", archivePath, "--no-same-owner", "--strip-components=1", "-C", destinationDir], { encoding: "utf8" });
77
- if (extractResult.status !== 0) {
78
- const err = extractResult.stderr?.trim() || extractResult.error?.message || "unknown error";
76
+ const extractResult = spawnSync([
77
+ "tar",
78
+ "xzf",
79
+ archivePath,
80
+ "--no-same-owner",
81
+ "--strip-components=1",
82
+ "-C",
83
+ destinationDir,
84
+ ]);
85
+ if (!extractResult.success) {
86
+ const err = extractResult.stderr?.toString().trim() || "unknown error";
79
87
  throw new Error(`Failed to extract archive ${archivePath}: ${err}`);
80
88
  }
81
89
  // Post-extraction scan: verify all extracted files are within destinationDir
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akm-cli",
3
- "version": "0.9.0-beta.5",
3
+ "version": "0.9.0-beta.9",
4
4
  "type": "module",
5
5
  "description": "akm (Agent Knowledge Management) — A package manager for AI agent skills, commands, tools, and knowledge. Works with Claude Code, OpenCode, Cursor, and any AI coding assistant.",
6
6
  "keywords": [
@@ -51,7 +51,7 @@
51
51
  },
52
52
  "scripts": {
53
53
  "preinstall": "node -e \"var ua=process.env.npm_config_user_agent||'';var major=parseInt((process.versions.node||'0').split('.')[0],10);if(process.versions.bun||ua.startsWith('bun/')||process.env.BUN_INSTALL||major>=20){process.exit(0)}console.error('\\n ERROR: akm-cli requires the Bun runtime (https://bun.sh), Node.js >= 20, or the prebuilt binary.\\n Install options:\\n 1. Bun: curl -fsSL https://bun.sh/install | bash && bun install -g akm-cli\\n 2. Binary: curl -fsSL https://github.com/itlackey/akm/releases/latest/download/install.sh | bash\\n');process.exit(1)\"",
54
- "build": "rm -rf dist && bun run tsc --project ./tsconfig.build.json && bun scripts/copy-assets.ts && bun scripts/fix-esm-extensions.ts",
54
+ "build": "rm -rf dist && bun scripts/gen-config-schema.ts &&bun run tsc --project ./tsconfig.build.json && bun scripts/copy-assets.ts && bun scripts/fix-esm-extensions.ts",
55
55
  "check": "bun run lint && bunx tsc --noEmit && bun run test:unit && bun run test:integration",
56
56
  "check:fast": "bun run lint && bunx tsc --noEmit && bun run test:unit",
57
57
  "check:changed": "bun test tests/output-baseline.test.ts tests/integration/e2e.test.ts tests/stash-search.test.ts && bun run lint && bunx tsc --noEmit",