akm-cli 0.10.261003-beta → 0.10.261004-beta

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.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.10.261004] - 2026-10-13
10
+
11
+ ### Fixed
12
+
13
+ - **`akm feedback` fails when it cannot record the feedback** (also in 0.9.32). When `state.db` was read-only to the
14
+ process, as it is inside an agent sandbox that only allows writes in the workspace, the feedback row was silently
15
+ dropped and the command still printed `"ok": true`. It now fails with a `DATA_DIR_NOT_WRITABLE` config error (exit
16
+ 78) and records nothing. Add akm's data directory to the sandbox's writable paths.
17
+
9
18
  ## [0.10.261003] - 2026-10-12
10
19
 
11
20
  ### Fixed
@@ -13,17 +13,17 @@ import { parseFrontmatter, parseFrontmatterBlock, spliceFrontmatterLine } from "
13
13
  import { conceptIdFromTypeName, parseRefInput, typeNameFromConceptId } from "../core/asset/resolve-ref.js";
14
14
  import { isWithin, resolveStashDir, safeRealpath, writeFileAtomic } from "../core/common.js";
15
15
  import { loadConfig } from "../core/config/config.js";
16
- import { NotFoundError, UsageError } from "../core/errors.js";
16
+ import { ConfigError, NotFoundError, UsageError } from "../core/errors.js";
17
17
  import { appendEvent } from "../core/events.js";
18
18
  import { resolveMutationTarget } from "../core/mutation-target.js";
19
19
  import { isPathAbsent } from "../core/path-access.js";
20
20
  import { getDbPath } from "../core/paths.js";
21
- import { withStateDb } from "../core/state-db.js";
21
+ import { getStateDbPath, withStateDb } from "../core/state-db.js";
22
22
  import { warn } from "../core/warn.js";
23
23
  import { withWriteTargetMutation } from "../core/write-source.js";
24
24
  import { recomputeUtilityScores } from "../indexer/indexer.js";
25
25
  import { resolveSourceEntries } from "../indexer/search/search-source.js";
26
- import { insertUsageEvent, resolveUsageEventSource } from "../indexer/usage/usage-events.js";
26
+ import { insertUsageEventStrict, resolveUsageEventSource } from "../indexer/usage/usage-events.js";
27
27
  import { resolveSourcesForOrigin } from "../registry/origin-resolve.js";
28
28
  import { closeDatabase, openExistingDatabase } from "../storage/repositories/index-connection.js";
29
29
  import { findEntryIdByRef, getEntryFilePathById, getItemRefById, } from "../storage/repositories/index-entries-repository.js";
@@ -161,20 +161,28 @@ const UTILITY_REVIEW_THRESHOLD = 0.5;
161
161
  * boosting its own picks. This is by design and must not be removed. The
162
162
  * utility score is read by improve and metrics only; its update is best-effort
163
163
  * and its failure never fails the feedback record or changes the ranking effect.
164
+ * A failed usage-event write fails the command (DATA_DIR_NOT_WRITABLE).
164
165
  */
165
166
  function recordFeedbackUsage(indexDb, entryId, durableEntryRef, signal, metadataStr) {
166
167
  let utilityResult;
167
168
  let rankingSkippedReason;
168
169
  const eventSource = resolveUsageEventSource();
169
170
  withStateDb((stateDb) => {
170
- insertUsageEvent(stateDb, {
171
- event_type: "feedback",
172
- entry_ref: durableEntryRef,
173
- entry_id: entryId,
174
- signal,
175
- metadata: metadataStr,
176
- source: eventSource,
177
- });
171
+ // The usage event IS the feedback record, so a failed write fails the command
172
+ // instead of reporting ok while nothing was stored.
173
+ try {
174
+ insertUsageEventStrict(stateDb, {
175
+ event_type: "feedback",
176
+ entry_ref: durableEntryRef,
177
+ entry_id: entryId,
178
+ signal,
179
+ metadata: metadataStr,
180
+ source: eventSource,
181
+ });
182
+ }
183
+ catch (err) {
184
+ throw new ConfigError(`Feedback was not recorded: could not write ${getStateDbPath()} (${err instanceof Error ? err.message : String(err)}).`, "DATA_DIR_NOT_WRITABLE");
185
+ }
178
186
  if (eventSource !== "user") {
179
187
  rankingSkippedReason =
180
188
  `feedback source is "${eventSource}", not "user" — it does not count toward search ranking, which counts ` +
@@ -10,6 +10,7 @@ const CONFIG_HINTS = {
10
10
  STASH_DIR_NOT_A_DIRECTORY: "The configured default bundle path exists but isn't a directory. Update it to point at a folder.",
11
11
  STASH_DIR_UNREADABLE: "Check the path exists and your user has read permission, or update the default bundle path.",
12
12
  DATA_DIR_UNREADABLE: "The data directory is not readable by the user running akm. Check its owner and mode, or point AKM_DATA_DIR / XDG_DATA_HOME somewhere this user owns.",
13
+ DATA_DIR_NOT_WRITABLE: "Nothing was recorded. Make the akm data directory writable for this process (for an agent sandbox, add it to the writable paths), or point AKM_DATA_DIR / XDG_DATA_HOME somewhere this user can write, then retry.",
13
14
  INDEX_SCHEMA_INCOMPATIBLE: "Run `akm index --full` to rebuild the derived index from the currently materialized sources.",
14
15
  LLM_NOT_CONFIGURED: 'Run `akm setup` or configure an `engines` entry with `kind: "llm"`, then select it with `defaults.llmEngine`.',
15
16
  TEST_ISOLATION_MISSING: "Under bun test, when AKM_BUNDLE_DIR is set you MUST also set XDG_DATA_HOME (or AKM_DATA_DIR) and XDG_STATE_HOME (or AKM_STATE_DIR) to temp directories so the test does not touch the developer's real ~/.local/share/akm or ~/.local/state/akm.",
@@ -55,14 +55,18 @@ export function ensureUsageEventsSchema(db) {
55
55
  */
56
56
  export function insertUsageEvent(db, event) {
57
57
  try {
58
- db.prepare(`INSERT INTO usage_events (event_type, query, entry_id, entry_ref, signal, metadata, source)
59
- VALUES (?, ?, ?, ?, ?, ?, ?)`).run(event.event_type, event.query ?? null, event.entry_id ?? null, event.entry_ref ?? null, event.signal ?? null, event.metadata ?? null, event.source ?? "unknown");
58
+ insertUsageEventStrict(db, event);
60
59
  }
61
60
  catch (error) {
62
61
  rethrowIfTestIsolationError(error);
63
62
  /* fire-and-forget: silently ignore errors */
64
63
  }
65
64
  }
65
+ /** Insert a usage event and let a failed write throw, for callers whose record is the event itself. */
66
+ export function insertUsageEventStrict(db, event) {
67
+ db.prepare(`INSERT INTO usage_events (event_type, query, entry_id, entry_ref, signal, metadata, source)
68
+ VALUES (?, ?, ?, ?, ?, ?, ?)`).run(event.event_type, event.query ?? null, event.entry_id ?? null, event.entry_ref ?? null, event.signal ?? null, event.metadata ?? null, event.source ?? "unknown");
69
+ }
66
70
  // ── Query ────────────────────────────────────────────────────────────────────
67
71
  /**
68
72
  * User feedback counts for many assets at once, keyed by durable `entry_ref`.
@@ -25658,6 +25658,7 @@ var CONFIG_HINTS = {
25658
25658
  STASH_DIR_NOT_A_DIRECTORY: "The configured default bundle path exists but isn't a directory. Update it to point at a folder.",
25659
25659
  STASH_DIR_UNREADABLE: "Check the path exists and your user has read permission, or update the default bundle path.",
25660
25660
  DATA_DIR_UNREADABLE: "The data directory is not readable by the user running akm. Check its owner and mode, or point AKM_DATA_DIR / XDG_DATA_HOME somewhere this user owns.",
25661
+ DATA_DIR_NOT_WRITABLE: "Nothing was recorded. Make the akm data directory writable for this process (for an agent sandbox, add it to the writable paths), or point AKM_DATA_DIR / XDG_DATA_HOME somewhere this user can write, then retry.",
25661
25662
  INDEX_SCHEMA_INCOMPATIBLE: "Run `akm index --full` to rebuild the derived index from the currently materialized sources.",
25662
25663
  LLM_NOT_CONFIGURED: 'Run `akm setup` or configure an `engines` entry with `kind: "llm"`, then select it with `defaults.llmEngine`.',
25663
25664
  TEST_ISOLATION_MISSING: "Under bun test, when AKM_BUNDLE_DIR is set you MUST also set XDG_DATA_HOME (or AKM_DATA_DIR) and XDG_STATE_HOME (or AKM_STATE_DIR) to temp directories so the test does not touch the developer's real ~/.local/share/akm or ~/.local/state/akm.",
@@ -24986,6 +24986,7 @@ var CONFIG_HINTS = {
24986
24986
  STASH_DIR_NOT_A_DIRECTORY: "The configured default bundle path exists but isn't a directory. Update it to point at a folder.",
24987
24987
  STASH_DIR_UNREADABLE: "Check the path exists and your user has read permission, or update the default bundle path.",
24988
24988
  DATA_DIR_UNREADABLE: "The data directory is not readable by the user running akm. Check its owner and mode, or point AKM_DATA_DIR / XDG_DATA_HOME somewhere this user owns.",
24989
+ DATA_DIR_NOT_WRITABLE: "Nothing was recorded. Make the akm data directory writable for this process (for an agent sandbox, add it to the writable paths), or point AKM_DATA_DIR / XDG_DATA_HOME somewhere this user can write, then retry.",
24989
24990
  INDEX_SCHEMA_INCOMPATIBLE: "Run `akm index --full` to rebuild the derived index from the currently materialized sources.",
24990
24991
  LLM_NOT_CONFIGURED: 'Run `akm setup` or configure an `engines` entry with `kind: "llm"`, then select it with `defaults.llmEngine`.',
24991
24992
  TEST_ISOLATION_MISSING: "Under bun test, when AKM_BUNDLE_DIR is set you MUST also set XDG_DATA_HOME (or AKM_DATA_DIR) and XDG_STATE_HOME (or AKM_STATE_DIR) to temp directories so the test does not touch the developer's real ~/.local/share/akm or ~/.local/state/akm.",
@@ -79,6 +79,12 @@ mode and owner, and the uid you are running as. They do **not** report an empty
79
79
  index. `akm health` stays runnable in that state and reports it as a failing
80
80
  `state-db-readable` check, so it remains the command to reach for.
81
81
 
82
+ If akm can read this directory but **cannot write** it — an agent sandbox that
83
+ only allows writes inside the workspace, for instance — `akm feedback` fails with
84
+ a `DATA_DIR_NOT_WRITABLE` config error (exit 78) and records nothing, instead of
85
+ reporting success for feedback it could not store. Add the data directory to the
86
+ sandbox's writable paths.
87
+
82
88
  > **0.9.1 note.** A pre-release build briefly chmodded this directory to `0700`
83
89
  > and the databases to `0600` on every open. That was reverted: it silently
84
90
  > changed the permissions of directories akm did not create, which broke installs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akm-cli",
3
- "version": "0.10.261003-beta",
3
+ "version": "0.10.261004-beta",
4
4
  "type": "module",
5
5
  "description": "akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cursor.",
6
6
  "keywords": [