# Public API review — tracked issue backlog (v0.9.0-rc.10)

Status: proposed — reconciled 2026-07-26 against the maintainer rulings on
Q-01..Q-19. Items carrying a `> Ruled 2026-07-26 (Q-NN)` note below are
settled, re-scoped, or partially cancelled by a ruling; where a ruling bears on
an item, **the ruling is authoritative**.
Source: implementation-only review of the CLI surface and code (documentation claims
deliberately ignored). Line references are against the tree at the time of review
and may drift; each item names the file and the observable behavior so it can be
re-verified independently.
Note: items below cite `docs/agents/AGENTS.md` / `AGENTS.full.md`. Those files
were deleted during the 0.9.0 docs sweep — they fed nothing at runtime after
R-006 and kept re-diverging from the embedded copy. Their still-true content
now lives in `src/assets/hints/cli-hints-full.md` / `cli-hints-short.md`, which
is what `akm hints` prints and what `loadHints` reads.
Baseline: items were found against `a8464f2` and re-verified 2026-07-26 against
the base branch `claude/0-9-0-release-review-bcjxxu` @ `453a0ba`, which has
since fixed some of them. A further pass on 2026-07-27 @ `2d2edc1` (code
identical to `453a0ba`) re-checked the contested items individually and added
`> Status 2026-07-27:` notes where the tree disagrees with the item as
written — including two items this register had over- or under-reported
(R-004 fixed-in-surface; R-046 superseded by the D6 ruling). Items carrying a **Fixed / Reframed / Rejected on the
base branch** note have been re-checked; the rest were not re-verified
individually and may have been incidentally affected. See the
"Implementation status against the base branch" table in the companion drift
register for per-ruling status.
Companion: `0.9.0-docs-code-drift-register.md` covers the docs-vs-code
comparison this review deliberately excluded — including the intent questions
(Q-01..Q-19) where the decision record and the code conflict. All 19 were ruled
by the maintainer on 2026-07-26; see the **"Maintainer rulings — 2026-07-26"**
table in that register for the authoritative direction.

## Framing

This backlog evaluates akm as what it has grown into: **a self-contained agent
toolkit** — one CLI that gives AI agents the capabilities that normally require a
stack of tools and a database server (indexed knowledge retrieval, secret/env
management, harness-agnostic workflow execution and delegation, scheduling), while
staying agent-, harness-, and content-format-agnostic (e.g. OKF alongside
markdown).

Under that identity, the env/secret manager, the workflow engine, the agent
dispatcher, the OS-scheduler integration, and the improve loop are **in-scope
features, not scope creep**, and no issue below asks for their removal. The
identity instead raises the bar in three specific ways, and most of this backlog
follows from them:

1. **Agents are the primary consumers.** Machine-facing guidance (`akm hints`,
   rendered command suggestions, help text, completions) is the product's API
   documentation *and* its runtime behavior. Every place it misleads an agent is a
   P0, not a docs nit.
2. **The abstraction claims must hold at the seams.** "Harness-agnostic" and
   "format-agnostic" are testable properties; half-wired normalizers and
   format special-cases are gaps in the core value proposition.
3. **An autonomous toolkit must be trustworthy by default.** Defaults that
   schedule LLM rewrites, push git remotes, or mine other tools' session
   transcripts need explicit opt-in or loud disclosure.

Severity legend:

- **P0** — the surface actively misleads its consumers, or an advertised path is
  broken/unreachable.
- **P1** — incorrect or surprising behavior/semantics; wrong results or side
  effects.
- **P2** — coherence, naming, and abstraction-seam debt.
- **P3** — cleanup: dead code, stale comments, duplication.

Counts: 9 × P0, 26 × P1, 21 × P2, 12 × P3 (68 tracked). The counts reflect the
tier labels as written; two items carry ruling-driven re-tier recommendations
not yet applied — R-045 (Q-18 makes it mandated feature work) and the `--format`
half of R-050 (Q-04 makes it Stable-tier contract work, and the item should be
split first). Recompute when those land.

---

## A. Agent-facing guidance correctness (P0)

- **R-001 (P0) — `akm hints` documents a `wiki` command that does not exist.**
  The short and full hints corpora instruct agents to run `akm wiki list`,
  `akm wiki show <name>`, `akm wiki ingest <name>`, use `--type wiki`, and
  `akm show wiki:<name>`. No `wiki` subcommand is registered in
  `src/cli.ts:509-550`; an agent following the tool's own onboarding issues
  failing commands. Either ship the command or strip it from
  `src/assets/hints/cli-hints-*.md` and `docs/agents/AGENTS*.md`.
  > Note (Q-02, ruled 2026-07-26): the quoted `akm show wiki:<name>` example
  > uses the colon grammar Q-02 removes — the hints sweep hits these lines
  > either way; if the wiki content is kept (ship-the-command path), its ref
  > examples must move to the slash form.

- **R-002 (P0) — `akm show --format text` renders copy-pasteable commands in the
  retired `type:name` ref grammar.** `appendShowDirectives` builds
  `` `${assetType}:${r.name}` `` and emits e.g.
  `akm feedback 'knowledge:guide' --positive` (`src/output/show-directives.ts:26,57,75,87`),
  which the 0.9 parser rejects. The same file renders `workflows/${name}`
  correctly two lines down. Every APPLY footer suggestion currently fails when
  executed.
  > Ruled 2026-07-26 (Q-02): the colon grammar is removed entirely — no alias,
  > no deprecation window — so re-accepting `type:name` in the parser is not a
  > fix option. `appendShowDirectives` must emit slash refs (as it already does
  > for `workflows/${name}`); include `show-directives.ts` in the Q-02 colon
  > sweep alongside `search --help`, `akm hints`, and the ref-prefix tests.
  > **Still open at base `0475870`** — and now strictly worse: Q-02 landed
  > (the colon browse grammar is gone) while `show-directives.ts:26` still
  > builds `` `${assetType}:${r.name}` ``. Raise with the Q-02 sweep.
  > Status 2026-07-27: confirmed still open; the file now lives at
  > `src/output/text/show-directives.ts` (`:26` builds the colon ref that
  > `:37,57,75` interpolate into `akm feedback` suggestions). The fix is one
  > line — build `assetRef` from the entry's conceptId (`workflows/${name}`
  > two lines down shows the pattern) — plus refreshing the show-format text
  > goldens that pin the footer.

- **R-003 (P0) — `akm feedback` help contradicts the implementation.** Help
  (`src/cli.ts` command description; `src/commands/feedback-cli.ts:189-206`)
  states negative feedback "does NOT immediately lower the asset's ranking — run
  `akm index` after". The code applies the EMA utility update unconditionally
  and immediately for both signals (`feedback-cli.ts:170-176`). Fix the text or
  the behavior — currently agents are told to run an unnecessary reindex.

- **R-004 (P0) — feedback threshold hint references a nonexistent command.**
  `feedback-cli.ts:365` prints "run `akm events list --type improve_review_needed`";
  the command is `akm log`. (`events-list`/`events-tail` shape names and text
  formatter headers carry the same retired name — see R-060.)
  > Status 2026-07-27: ✅ **fixed in surface** — the printed hint no longer
  > exists; `akm events list` survives only in two code comments
  > (`feedback-cli.ts:341,365`). Downgrade to comment cleanup and fold into
  > R-065; the R-060 shape-name half is unaffected.

- **R-005 (P0) — the shipped conventions fact contradicts `akm mv`.** The
  scaffolded `facts/conventions/organization.md` asset teaches "A rename is
  delete plus create. There is no command that preserves an asset's identity or
  learned state across one" and demonstrates raw `mv` + manual grep — while
  top-level `akm mv` exists precisely to move the file, rewrite inbound refs,
  and re-key the index row plus usage/salience history in place
  (`src/commands/mv-cli.ts`). Agents reading the stash's own guidance will avoid
  the safe command and hand-roll the dangerous procedure it automates.
  > Ruled 2026-07-26 (Q-01): `akm mv` stays; D3 is superseded. The fix is
  > one-directional — rewrite `facts/conventions/organization.md` and the other
  > D3-side docs to teach `mv`, and add the missing Experimental tier entry for
  > `mv` to STABILITY.md. Removing `mv` is off the table.

- **R-006 (P0) — `akm hints` output depends on install method, and the copies
  have drifted.** `loadHints` prefers `<pkgroot>/docs/agents/AGENTS[.full].md`
  on disk and falls back to embedded `src/assets/hints/cli-hints-*.md`
  (`src/commands/observability-cli.ts:240-257`). npm packs neither `docs/agents/`
  nor `src/` (`package.json` `files`), so npm installs always get the embedded
  copy while repo checkouts get `docs/` — and the two corpora already differ in
  size and content. Single-source the corpus.
  > Note (Q-02/Q-08, ruled 2026-07-26): both rulings mandate spelling sweeps of
  > `akm hints` (colon→slash ref grammar; `env:`/`secret:`→slash) — land the
  > single-sourcing first, or sweep both copies atomically, so the ruled
  > changes don't re-drift the corpora.

- **R-007 (P0) — advertised `owner/repo` shorthand is unreachable.**
  `add-cli.ts:234` and `git-install.ts:489` advertise the form, but
  `isPathLikeRef` returns true for any string containing `/`
  (`src/registry/resolve.ts:298`), so `tryParseLocalRef` throws
  `Local path not found` before the `parseGithubShorthand` fallback at
  `resolve.ts:86-90` can run. The fallback is dead code; `akm add itlackey/akm-stash`
  fails. Reorder the dispatch (try shorthand when the local path doesn't exist).
  > Note (Q-19, ruled 2026-07-26): the resolver fix (`resolveSourcesForOrigin`
  > matching `github:owner/repo` install refs) confirms install-ref shorthand is
  > intended surface, so the fix direction here — reorder the dispatch, don't
  > retire the advertised form — is sanctioned. Land both together so
  > `show //meta`'s "Run: akm add …" hint chain works end to end.

- **R-008 (P0) — `akm registry search` ignores registries added via
  `akm registry add`.** `registry-cli.ts:128` calls `searchRegistry` without a
  `registries` option; the fallback resolves `DEFAULT_CONFIG.registries`, never
  the on-disk config (`src/commands/read/registry-search.ts:35,166`). Meanwhile
  `akm search --source registry` passes `config.registries` and honors them.
  Configured registries are listed by `registry list` but never searched by
  `registry search`.

- **R-009 (P0) — `akm search` rejects the empty query its own help advertises.**
  The positional's description says "omit to list all assets"
  (`src/commands/read/search-cli.ts:36-39`) but the handler throws
  `MISSING_REQUIRED_ARGUMENT` for an empty query (`:79-86`), making the
  `enumerateEntries` browse path reachable only via `<type>:` prefix queries or
  queries that sanitize to empty. Allow the bare listing or fix the description.
  > Note (Q-02, ruled 2026-07-26): the `<type>:` escape hatch named here is
  > removed with the colon grammar; post-ruling the browse path is reachable via
  > the slash forms (`memories/`, `bundle//`). The empty-query question itself
  > is unaffected — update the parenthetical when Q-02 lands.

---

## B. Broken or surprising command behavior (P1)

- **R-010 (P1) — the lockfile locks nothing.** `akm.lock` records
  `resolvedVersion`/`resolvedRevision`/`integrity`, but the only field consumed
  for behavior is `localRoot` (`src/integrations/lockfile.ts:122-130`).
  `akm update` re-resolves the original ref (npm `latest`, git branch HEAD) and
  overwrites the lock (`installed-stashes.ts:384`); nothing reproduces a locked
  state; stored integrity is never re-verified. Either implement
  lock-consumption (frozen installs, integrity re-check) or stop recording the
  fields and drop the "lockfile" concept from the surface.

- **R-011 (P1) — git/github installs have no integrity verification at all.**
  `verifyArchiveIntegrity` returns early for git sources
  (`src/sources/providers/tar-utils.ts:42`); the sha256 computed at install time
  is stored and never compared.

- **R-012 (P1) — corrupt lockfile fails silently open.** Unparseable JSON →
  `return []`; malformed entries silently filtered (`lockfile.ts:99-106`). Every
  managed bundle vanishes from `akm list` with no warning.

- **R-013 (P1) — `akm add --provider` combinations are broken.**
  `providerType` is honored only when the target is a remote URL
  (`source-manage.ts:71-100`): `akm add lodash --provider npm` silently creates
  a *filesystem* bundle at `./lodash`; `akm add <url> --provider npm` stores the
  URL as an npm path that later resolves as a filesystem path
  (`config-sources.ts:102-104`, `npm.ts:54-59`).

- **R-014 (P1) — `akm add`'s two paths return two incompatible response
  shapes.** Path A (`--provider`) returns `SourceAddResult`, Path B returns
  `AddResponse`; the shared text renderer reads Path B fields and prints
  `Installed undefined (0 directories scanned, 0 total assets indexed)` for
  Path A (`output/text/command-format.ts:510-514`).

- **R-015 (P1) — `akm update --all` silently skips plain (non-lock-backed)
  sources.** `selectManagedTargets` returns lock-backed installs only
  (`installed-stashes.ts:519-522`); a configured plain `git`/`website` bundle is
  never refreshed by `--all` and must be named individually. Skip should at
  minimum be reported.
  > Note (Q-09, ruled 2026-07-26): the user-facing kind axis stays
  > `filesystem`/`git`/`npm`/`website`, so the lock-backed "managed" split stays
  > behavioral-only with no taxonomy surface — making the skip report asked for
  > here the sole disclosure of it.

- **R-016 (P1) — `akm setup --yes` silently skips 7 of 8 wizard steps.** Only
  the `stash-dir` step sets `nonInteractive: true` (`setup/setup.ts:436`;
  skip logic `setup/steps.ts:98`); embedding, llm, semantic-search, registries,
  stash-sources, agent-cli, and output steps never run, while the call-site
  comment claims defaults are applied (`setup.ts:776`). Also
  `runSetupWithDefaults` hardcodes `online: false` yet still runs network
  detection (`setup.ts:779,788`).

- **R-017 (P1) — `akm setup --config/--from` silently drops five valid config
  keys.** `ALLOWED_KEYS` (`setup.ts:1013-1027`) omits `index`, `search`,
  `feedback`, `workflow`, `archiveRetentionDays` — all present in
  `AkmConfigShape` — deleting them with only a stderr warn.

- **R-018 (P1) — `akm curate --type` bypasses the entire curation algorithm.**
  With an explicit type the result is `stashHits.slice(0, limit)` — no family
  collapse, no intent nudges, no score floor (`curate.ts:255-262`). Two
  qualitatively different products under one command name.

- **R-019 (P1) — curate hard-caps registry results at 2 regardless of
  `--limit`** (`curate.ts:264-265`), and the fallback path can issue up to 7
  registry searches per invocation (`curate.ts:549-566`).

- **R-020 (P1) — `akm show` drops the canonical `ref` from default and summary
  output.** `showLocal` computes it, brief/summary builders include it, and the
  shaper's `pickFields` allow-lists omit `"ref"` for human and summary shapes
  (`output/shapes/helpers.ts:453-496`). Only `--shape agent` emits the one
  identifier agents need for follow-up commands.

- **R-021 (P1) — `--detail brief` behaves differently as a flag vs as config
  default.** `showCommand` detects only the literal CLI token via
  `getFlagValue("--detail")` to trigger `buildBriefResponse`
  (`search-cli.ts:223-227`); config `output.detail: "brief"` reaches only the
  shaper, which treats brief and normal identically. Same nominal level, two
  payloads.

- **R-022 (P1) — `akm index --dry-run` alone performs a full real index.** The
  flag is only consulted inside the `--clean` branch (`indexer.ts:715-726`).

- **R-023 (P1) — `akm index --background` claims to manage a PID file; none
  exists.** The flag only suppresses the spinner and the final output
  (`stash-cli.ts:95-99,127,157`) — the command still runs in the foreground and
  prints nothing.

- **R-024 (P1) — `akm graph update --source <bundle>` validates the name, then
  extracts the primary stash anyway.** The validated result is discarded and
  extraction always uses `sources[0]` (`graph.ts:529-538`,
  `graph-extraction.ts:406`).

- **R-025 (P1) — `akm config get <scalar>` returns secrets unredacted.**
  `redactConfigValue` only redacts inside objects (`config-cli.ts:66`):
  `akm config get embedding.apiKey` prints the literal value while
  `akm config get embedding` redacts it. (Mitigated by write-time
  sanitization, but the read surface is inconsistent.)

- **R-026 (P1) — `akm env unset` argv workaround can silently drop keys.** The
  positional filter removes any token equal to a global flag's *value*
  (`env-cli.ts:474-482`), so unsetting a key literally named `json` while
  `--format json` is set is a silent no-op; `--target` is wrongly included in
  the global-flag list; the comment cites `cli.ts:1335` in a 666-line file.
  > Status 2026-07-27: ✅ **fixed** (`0475870`) — the workaround is deleted
  > outright. The root cause was citty parsing each command level against only
  > its own declared args; `GLOBAL_OUTPUT_ARGS` now declares the global output
  > flags on every leaf so their values are consumed by the parser, and keys
  > literally named `json` unset correctly (verified end-to-end alongside the
  > `sync --format json` case). See R-051's companion note.

- **R-027 (P1) — `akm secret path`/`remove` can resolve to different files than
  the read path for the same ref.** Reads use `findEnvSource` (all sources);
  mutations use `resolveMutationTarget` (`core/env-secret-ref.ts:64-85` vs
  `198-255`).

- **R-028 (P1) — `akm import <url>`'s private-host allowance is gated on a
  test-shaped predicate in production.** `allowPrivateHosts` defaults to
  `shouldAllowPrivateWebsiteUrlForTests(source)` (`stash-cli.ts:256`,
  `knowledge.ts:141-146`).

- **R-029 (P1) — `akm backup` does not back up the stash.** Artifact set is
  `config.json`, `state.db`, `workflow.db`, `index.db`
  (`scripts/akm-migrate/migration-backup.ts:57-61`) — the markdown assets, env
  files, and secrets are excluded. Additionally `--for` accepts only the literal
  `"0.9.0"` (`backup-cli.ts:9-16`), and both `backup` and `migrate` hard-require
  Bun on PATH under the supported Node install (`migration-tool.ts:21`). Rename
  the command to match its migration-snapshot scope, or extend it to cover the
  knowledge.
  > Note (Q-14, ruled 2026-07-26): `backup` must receive a stability tier and
  > either a cli.md section or an explicit internal listing — make the
  > rename-vs-extend decision as part of that follow-through.
  > Ruled 2026-07-27: **removed from the CLI** — neither renamed nor extended.
  > `backup-cli.ts` deleted and the `backup` registration dropped; the
  > capability remains at `akm-migrate backup` / `akm-migrate restore` (already
  > present in that binary's surface). A cleaner backup story is deferred past
  > 0.9.0. Migration guide + 0.9.0 release notes swept to the new spelling; the
  > Q-14 tier question for `backup` is moot. ✅ landed same day.

- **R-030 (P1) — `akm health` writes to the append-only event stream on every
  run.** The state-db round-trip probe appends a `health_probe` event
  (`health/metrics.ts:35-38`); CI polling accumulates rows indefinitely. Use a
  transaction-rollback probe or a dedicated probe table.

- **R-031 (P1) — `akm health --format html` overrides `--group-by`** (forces
  `groupBy: "run"`, `cli.ts:341-360`) and runs the health computation twice with
  a second window read — undocumented and inconsistent with the other formats.
  > **Fixed on the base branch (`0475870`).** `akm health` no longer branches on
  > `--format` anywhere: `--report` is now a data flag carrying runs/deltas/the
  > pending-proposal queue in the envelope, the md/html renderers are pure
  > functions of the result, `setHealthHtmlContext` is gone, and the html-only
  > `--compare` was removed in favor of `--window-compare`. Breaking: bare
  > `akm health --format html` renders the plain check generically — use
  > `--report`. Verify and close.
  > Follow-up in `453a0ba`: `--report` had been seeding `windowCompare` from
  > `--since` unconditionally, so an absolute date/ISO/epoch `--since` reached a
  > duration-only parser and threw, and an explicit `--windows` tripped the
  > mutual-exclusivity guard. Precedence is now `--window-compare`, then a
  > duration-valued `--since`, and nothing alongside `--windows`.

- **R-032 (P1) — unknown-command handling is inconsistent with the exit-code
  contract.** `akm totally-bogus` exits 1; `akm wiki list` prints top-level
  usage and exits **0**; the CLI's own table says usage errors are exit 2.
  Verified against the running CLI.

- **R-033 (P1) — `akm feedback --tag` reads raw argv, including tokens after
  `--`.** The declared citty arg is decorative; `parseAllFlagValues("--tag")`
  scans the whole argv (`feedback-cli.ts:220,288`). Also `--applied-to` is a
  silent no-op for non-lesson refs (`:397`).

- **R-034 (P1) — feedback silently skips the ranking update for non-`user`
  event sources.** With `AKM_EVENT_SOURCE` set to anything else — including
  invalid values coerced to `"unknown"` — the usage event is recorded but the
  utility score is untouched, with no output signal (`feedback-cli.ts:170`,
  `usage-events.ts:31-35`).

- **R-035 (P1) — the `AKM_NPM_REGISTRY` hint is false.** The env var only
  widens the tarball-host allowlist (`resolve.ts:332-344`); metadata fetches are
  hardcoded to `registry.npmjs.org` (`resolve.ts:375`), so installs from a
  private mirror do not work despite the error hint saying they do
  (`resolve.ts:322`).

---

## C. Trust and safety defaults (P1)

- **R-036 (P1) — `akm setup` installs five cron/launchd/schtasks entries by
  default** (hourly/4-hourly/nightly `akm improve` variants,
  `commands/tasks/default-tasks.ts:51-92`), and embedded task templates add
  `akm extract --auto` every 30 minutes. An OS-scheduler mutation deserves an
  explicit, itemized opt-in step in the wizard and a flag in `--yes` mode.
  > Ruled 2026-07-26 (Q-05/Q-14): `experimental.improveAutonomy` ships as
  > STABILITY.md documents it, and `extract` is tiered Experimental. The
  > scheduled `improve` entries must sit behind that off-by-default gate, and
  > the embedded `akm extract --auto` template schedules an Experimental-tier
  > command — implement the opt-in asked for here as the gate plus an explicit
  > wizard step (and a flag in `--yes` mode).

- **R-037 (P1) — `akm improve` commits and pushes the stash by default** for
  git-backed stashes (`improve-cli.ts:145-154`). Combined with R-036 this means
  a default setup schedules unattended LLM rewrites that push to a remote.
  Default should be commit-only (or off) with push as explicit opt-in.
  > **Rejected on the base branch (`84bba7a`, 2026-07-26)** — supersedes this
  > item's recommendation and the earlier Q-05 note here. `sync.push` stays
  > default-on and *outside* the autonomy gate: it publishes already-committed
  > content to a remote configured for that purpose rather than mutating or
  > deleting assets without review, and it already has two documented opt-outs
  > (`sync.push: false`, `--no-push`). D8 gates five lanes — consolidate
  > merge/delete/contradict, memory-cleanup and contradiction passes,
  > memory-inference writes, and triage `applyMode: "promote"` — and `push`
  > joins extract's session indexing as an ungated-by-design write. The R-036
  > half (scheduling unattended runs) is unaffected and still stands.

- **R-038 (P1) — `akm extract` mines other harnesses' private session
  transcripts (claude-code JSONL, opencode storage) and sends content to the
  configured LLM** (`improve/extract.ts`, `integrations/session-logs/`), with a
  `--watch` mode that tails those directories indefinitely
  (`extract-cli.ts:267-319`). Legitimate feature; needs first-run consent and
  prominent disclosure given it reads data the user may not consider akm's.
  > Ruled 2026-07-26 (Q-14): `extract` is tiered **Experimental** and must be
  > documented (or explicitly listed internal) in cli.md. Land the first-run
  > consent and prominent-disclosure requirements in that new STABILITY.md tier
  > entry and reference section rather than as a standalone fix.

- **R-039 (P1) — default `akm index` attempts an implicit ~130 MB embedding
  model download.** With `semanticSearchMode: "auto"` and no endpoint,
  `embedBatch` falls through to `@huggingface/transformers` →
  `Xenova/bge-small-en-v1.5` (`llm/embedder.ts:158-176`). Failure downgrades
  gracefully, but the download itself should be prompted.
  > Ruled (owner ruling 9, X-RULING-9, `f04932f`): `semanticSearchMode` now
  > defaults to `"off"` — a bare/headless install never attempts the
  > download; the interactive `akm setup` wizard still pre-selects it on,
  > with the download warning moved ahead of the prompt.

- **R-040 (P1) — dynamic code loading from the stash.** Wiki snapshot fetchers
  `import()` arbitrary `.ts`/`.js` from `<stashDir>/scripts/wiki-fetchers/`
  (`sources/snapshot-fetchers/registry.ts:34-46`) — a code-execution surface
  reachable from synced content. Should be gated by the same
  third-party/first-party activation policy used for env keys. Related: the
  built-in YouTube fetcher calls the private InnerTube API with a hardcoded key
  impersonating the Android client (`snapshot-fetchers/youtube.ts:35-42`) —
  fragile and worth an explicit support decision.

- **R-041 (P1) — `akm graph export --out` writes anywhere with default 0644**
  (`graph.ts:302-315`) while `akm env export` enforces 0600. Graph contents are
  LLM-extracted from the user's knowledge; align the posture.

---

## D. Abstraction-seam gaps (P2) — where the agnosticism claims leak

- **R-042 (P2) — harness result normalization is half-wired.** All harnesses
  ship `result-extractor.ts` normalizers, but only the workflow native engine
  consumes them (`workflows/exec/native-executor.ts:1259-1267`); `akm agent`,
  `akm propose`, and reflect return raw harness stdout. Harness-agnosticism
  currently holds only inside `workflow run`.

- **R-043 (P2) — OKF is special-cased in `akm show`.** OKF-adapter entries
  bypass the renderer registry for a hand-rolled markdown path
  (`show.ts:369-370,545-586`). If format-agnosticism is the goal, OKF should go
  through the same adapter/renderer seam as markdown assets.
  > Ruled 2026-07-26 (Q-07): the parser half of this special-casing is settled
  > — the ref-parser seam is fixed centrally so opaque conceptIds are accepted
  > across graph, tasks, improve, proposals, the utility repo, and the indexer
  > walk, removing `show`'s need to bypass `parseRefInput`. The
  > renderer-registry half remains this item's ask and aligns with the ruling.
  > **Largely fixed on the base branch (`453a0ba`).** `show`'s
  > `indexedEntry?.adapterId === "okf"` branch became `usesIndexedProjection`
  > (`read/show.ts:536-559`): OKF plus any indexed item whose type AKM does not
  > place keeps its adapter's projection, so a `website` entry no longer comes
  > back typed as AKM placement and a generic `file` no longer loses its
  > content. OKF is still named explicitly — deliberately, since its `type` is
  > open frontmatter and may collide with an AKM placement type — and
  > `env`/`secret` stay pinned to the dotenv renderer so values are never
  > dumped. What remains of this item is only that residual OKF name-check;
  > the general seam now exists.

- **R-044 (P2) — two disjoint secret systems; the toolkit doesn't dogfood its
  own.** akm's LLM/embedding keys come from env vars or `$VAR` config refs
  (`config.ts:437-444`) and cannot be supplied from `akm secret`. Letting config
  reference `secrets/<name>` would close the loop and demonstrate the feature.
  > Ruled 2026-07-26 (Q-08): slash spelling only, no colon alias — if config
  > learns to reference managed secrets, the spelling must be the slash form
  > `secrets/<name>` (e.g. `secrets/OPENAI_KEY`), not the `secret:NAME` form
  > this item originally proposed.

- **R-045 (P2) — the `instruction` asset type is half-registered.** It exists
  in `KNOWN_TYPES`/`TYPE_PRESENTATION` but not `PLACEMENT_SPECS`
  (`core/asset/asset-placement.ts:89-166` vs `core/recognition-util.ts:92-106`),
  so it is invisible to `akm info`, unbrowsable via prefix queries, and its refs
  don't round-trip. Register or remove it; add a compile-time exhaustiveness
  check tying the two registries together.
  > Ruled 2026-07-26 (Q-18): "register or remove" is settled — **register**.
  > The two-registry split stays the core truth (`KNOWN_TYPES` = presentation
  > vocabulary, `PLACEMENT_SPECS` = stash-resident subset), so the
  > exhaustiveness check is a **subset** assertion (placement keys ⊆ known
  > types), not equality. `instruction` gains a `PLACEMENT_SPECS` entry with an
  > `instructions/` stash dir on the markdown spec, becoming creatable,
  > browsable, and listed by `akm info` like knowledge; adapter-emitted
  > `instruction` docs round-trip via the Q-07 opaque-conceptId fix. This is now
  > mandated 0.9.0 feature work — **raise to P1**.

- **R-046 (P2) — `--type` is unvalidated everywhere, and the help enumerates 11
  of the 13 real types** (missing `fact`, `task`, `session`;
  `search-cli.ts:41-43,125-127`). `--type bogus` silently returns zero hits.
  Validate against `placementTypes()` and generate the help list from it.
  > Note (Q-18, ruled 2026-07-26): `instruction` becomes a placement type,
  > shifting the real-type count from 13 to 14 — a further reason to generate
  > the help list and validation from `placementTypes()` rather than
  > re-hardcoding.
  > Status 2026-07-27: **superseded by the D6 decision** — the validation half
  > of this item conflicts with a maintainer ruling this register missed.
  > `type` is a free-form open string BY DESIGN (adapters emit `website`,
  > `wiki-source`, OKF frontmatter types outside any placement list), so
  > validating against `placementTypes()` would reject valid filters; D6 and
  > `STABILITY.md`'s Stable-tier bullet both pin "deliberately not validated:
  > an unrecognized type returns zero hits, not an error". The help half is
  > already fixed: `search`/`curate` `--type` help now enumerates all 14
  > built-ins **and states the set is open** (`search-cli.ts:43`). Nothing
  > remains except keeping that string current — do not implement validation.

- **R-047 (P2) — same concept, two flag names: `search --filter` vs
  `show --scope`** for the identical `user=/agent=/run=/channel=` narrowing.
  Pick one (keep the other as a hidden alias for one release).
  > Ruled 2026-07-27: **unify on `--filter`, remove `--scope` with no alias.**
  > ✅ landed same day: `show` declares `filter`, parses repeatable `--filter`
  > through the same `parseScopeFilterFlags` helper as `search`; cli.md swept.
  > The removed spelling fails loudly rather than silently un-narrowing —
  > citty drops the unknown flag and its value lands in the positional slot,
  > where `rejectExtraShowPositionals` raises exit 2 (pinned by a new CLI test
  > in `scope-flags.test.ts`).

- **R-048 (P2) — package identity: the npm description still says "package
  manager".** Under the accepted toolkit framing this misstates the product to
  its distribution channel and sets the wrong expectations for the verbs in §E.
  Reposition the one-liner (`package.json:5`).

---

## E. Verb semantics and surface coherence (P2)

- **R-049 (P2) — `update` / `upgrade` / `sync` are three unrelated operations
  wearing package-manager names.** Refresh sources / self-update the akm binary
  / git-commit-and-push the stash. Given the toolkit identity, consider
  `akm self update` (or `self-upgrade`) and `akm stash sync` (or `save`) to
  free the ecosystem-conventional meanings; `sync` still emits
  `eventType: "save"` and `output("save", …)` from its retired name
  (`sources-cli.ts:181-185`).

- **R-050 (P2) — global flags that are mostly not global.** `--detail` is an
  identity no-op for `init`/`index`/`info`/`import`/`remember` (and
  brief==normal on `show`); `--format md|html` is accepted globally but valid
  only for `health`; `--shape summary` only for `show`. Either scope the flags
  to the commands that honor them in help output, or implement them uniformly.
  > Ruled 2026-07-26 (Q-04): for `--format` the either/or is settled —
  > implement basic support on every non-exempt command, with `text` and `md`
  > collapsed into a single format, plus alignment of the persisted
  > `output.format` schema and the `INVALID_FORMAT_VALUE` hint. Only the
  > `--detail`/`--shape` halves of this item remain an open choice. Split the
  > ruled `--format` work into its own item and **raise it to P1**: it is
  > mandated Stable-tier contract work, not coherence debt.
  > Status 2026-07-27: the "implement on every non-exempt command" half
  > **landed** (D7: renderer registries, generic md/html fallbacks, declared
  > exemptions in `format-exempt.ts`, `output.format` schema widened to six),
  > but as SIX formats — the text/md collapse was not applied, and the
  > `INVALID_FORMAT_VALUE` hint still lists four values (`errors.ts:111`).
  > The Q-04 conflict in the drift register is the open decision; the hint
  > fix is deferred until that call so it is corrected once, to the final set.

- **R-051 (P2) — per-command `--format/--detail/--shape` declarations are
  decorative.** Declared on `search`/`curate`/`show` but never read from
  `args`; values come from the process-wide singleton (`search-cli.ts:63-64,
  131-136`). Users see help entries for flags the handler ignores.
  > **Reframed by the base branch (`0475870`).** The redundant declarations turn
  > out to be load-bearing: citty parses each command level against only its own
  > declared args, so a root-declared global was unknown at the leaf and its
  > space-separated value fell through as a positional (`akm sync --format json`
  > synced a bundle named "json"). `GLOBAL_OUTPUT_ARGS` now redeclares
  > `--format`/`--detail`/`--shape`/`--output` on **every** leaf, parse-only,
  > with the mode still read once from the invocation singleton
  > (`cli/shared.ts:138-159`). The declarations are no longer decorative — this
  > item is closed as fixed-by-design; only the help-text clarity ask remains.
  > **Completed in `453a0ba`:** the first pass covered only `defineJsonCommand`
  > leaves, so `improve`, `propose`, and `tasks run` (plain `defineCommand`)
  > still had citty parse `--format` as a boolean and spill its value into the
  > next positional — `improve --dry-run --format md` read "md" as the scope,
  > `tasks run --format md nightly` lost the task id. Each leaf now declares
  > the flags.

- **R-052 (P2) — bash completions advertise wrong values.** `FLAG_VALUES`
  offers `--detail … summary` (a `--shape` value that errors) and omits
  `md`/`html` from `--format` (see the Q-04 note below); the table is keyed globally by flag name, so
  `graph --source <TAB>` suggests search's `stash registry both`
  (`commands/completions.ts:15-21`). The `completions` handler is also the only
  one not wrapped in `runWithJsonErrors`, so a non-bash shell error surfaces as
  `UNHANDLED_REJECTION`/exit 1 instead of a usage error/exit 2 (`cli.ts:449-452`).
  > Ruled 2026-07-26 (Q-04): `text` and `md` collapse into a single format, so
  > the accepted `--format` value set is changing — fix the completions table
  > against the post-Q-04 set rather than adding `md`/`html` to today's list.

- **R-053 (P2) — bare-group behavior is inconsistent three ways.**
  `akm log`/`akm lessons` print help and exit 0; `akm backup`/`akm migrate`
  throw usage errors (exit 2); `akm env`/`akm config`/`akm graph` run a default
  action. Pick one convention.

- **R-054 (P2) — `akm lessons` advertises "strength queries" that don't
  exist.** The group description promises them (`observability-cli.ts:205`);
  `lessonStrength` is written by feedback and read by ranking but not queryable
  from any command. Implement `lessons strength <ref>` or fix the description.

- **R-055 (P2) — reads are writes, undisclosed.** `search`/`show`/`curate`
  append events, insert usage rows, and search bumps EMA utility scores —
  running a search changes future rankings (`search.ts:393`). Legitimate design
  for a learning index, but it should be stated on the command surface and
  offer an opt-out (the internal `skipLogging` already exists).

- **R-056 (P2) — `akm index` writes to `config.json`** (persisting detected
  adapters via `mutateConfig`, `indexer.ts:600-622`). Surprising for an "build
  the index" command; disclose or relocate to `add`/`setup`.

- **R-057 (P2) — `akm info` omits the most basic facts.** No `stashDir`, no
  `defaultBundle`, no per-type asset counts (`info.ts:64-78`); `searchModes`
  reports semantic readiness from a cached status file, not a live probe; its
  stats warning writes raw `process.stderr`, bypassing `--quiet`
  (`info.ts:103`).

- **R-058 (P2) — remove/update destructive-action asymmetry.** `akm remove`
  prompts for confirmation; `akm update`, which can `rm -rf` the prior
  materialized root (`installed-stashes.ts:421-428`), does not. Also removing a
  plain git/website bundle leaves its mirror cache behind, and `akm clone` of an
  unregistered origin downloads a full package into the cache with no bundle or
  lock record (orphaned disk).

- **R-059 (P2) — two parallel cache schemes for the same upstream.** Managed
  installs key `getRegistryCacheDir()` by version/revision; plain git/website
  mirrors key `getRegistryIndexCacheDir()` by URL hash — adding the same repo
  both ways stores two copies.

- **R-060 (P2) — `akm log` is still `akm events` internally.** Output shapes
  `events-list`/`events-tail`, text headers, and the R-004 hint all use the old
  name. Rename the shapes at the next schemaVersion bump.

- **R-061 (P2) — argv is parsed in three layers with four workaround
  patterns.** citty; the pre-citty `normalizeShowArgv` rewrite; the
  `ParsedInvocation` raw-argv singleton for repeatable flags; plus ad-hoc
  `process.argv.includes("--no-init")` and the `remember` positional-swallowing
  heuristic that covers `--format`/`--detail` but not `--shape`/`--output`
  (`remember.ts:303-370`). Consolidate on one parse or replace the framework —
  each workaround has already produced user-visible bugs (R-026, R-033).
  > Ruled 2026-07-26 (Q-03): `normalizeShowArgv` and the hidden `--akm*` flags
  > it feeds are deleted with the show view modes, removing one of the four
  > workaround patterns outright. Consolidate the remaining three; do not invest
  > further in the pre-citty rewrite layer.
  > Status 2026-07-27: two of the four are gone — `normalizeShowArgv` (Q-03)
  > and the env-unset value filter (R-026, root-caused by
  > `GLOBAL_OUTPUT_ARGS`). Remaining: the `ParsedInvocation` singleton (now
  > load-bearing by design — the one-parse rule), ad-hoc
  > `process.argv.includes` probes, and the `remember` positional-swallowing
  > heuristic, which `GLOBAL_OUTPUT_ARGS` on the `remember` leaf may make
  > deletable — verify against `remember.ts:303-370` before consolidating.

- **R-062 (P2) — `--showSimilar` is the CLI's only camelCase flag**
  (`remember-cli.ts:141-144`); everything else is kebab-case, and
  `migrate apply` declares `dryRun` where the codebase convention is
  `"dry-run"`.

---

## F. Cleanup batch (P3)

- **R-063 (P3) — confirmed dead code.** `parseGithubShorthand` branch
  (unreachable, see R-007); `injectIntoEnv` (`env.ts:115` — mutates
  `process.env`, forbidden by its own module docstring); secret `listNames`
  (`secret.ts:96`); `loadGraphMetaOnly` / `loadGraphEntitiesByPath`
  (`graph-db.ts:343,403`); `parseConfigValue` shim and the unreachable
  `toggleComponent` throw and dead `--list` flag (`config-cli.ts:44,129,136`);
  `listStashes`/`SourceListResult` (`source-manage.ts:36-39`);
  `resolveRegistries` on the search path (`registry-search.ts:35`); the
  `semanticSearch` projection branch (`helpers.ts:290`); curate's
  colon-grammar family regexes (`curate.ts:769,779`); the
  `session-log-failures` advisory hardwired to pass (`checks.ts:464-482`);
  `setup.taskSchedules` schema key nothing reads or writes.
  > Note (Q-02, ruled 2026-07-26): curate's colon-grammar family regexes
  > (`curate.ts:769,779`) are now part of the mandated colon-removal sweep —
  > schedule their deletion with the Q-02 work, not as standalone cleanup.

- **R-064 (P3) — dead fields threaded through live signatures.**
  `IndexOptions.reEnrich` (flag removed, parameter still threaded three layers;
  `stash-cli.ts:103-112`, `indexer.ts:179-183`); `IndexResponse.graphQuality`
  (declared, never assigned); `acceptedActions` "always 0 since the 0.9.0
  confidence-gate deletion" (`loop-stages.ts:746-750`); `durationMs` computed
  then `void`-ed (`improve-cli.ts:359-360`); `SourceEntry.updatable` and
  `.provider` set-but-never-read; `installedKitCount` (retired "Agent Kit
  Manager" naming) still in the public JSON envelope of add/remove/update;
  `workflow.db` still in the backup artifact set after the 0.9 state.db merge.

- **R-065 (P3) — stale comments that assert the opposite of adjacent code.**
  `init.ts:9` ("ensures ripgrep is available" — nothing uses ripgrep);
  `info.ts:57-61` (claims to avoid the `getDbPath()` call it makes);
  `graph-extraction.ts:34-37` (describes retired fs.writeFile storage);
  `history.ts:11-15` (`events.jsonl` vs actual `state.db`); the four
  `TODO(R2)` markers in `workflows/program/{parser,schema}.ts` and
  `ir/compile.ts` describing gate loops / retry / isolation / schema validation
  as unimplemented — all four are implemented in `native-executor.ts`;
  `reflect.ts:6` / `distill.ts` / `consolidate.ts` headers documenting
  `akm reflect` etc. as CLI commands that were never registered;
  `metrics.ts:270-274` documenting a deleted metric; `setup.ts:776` (R-016).

- **R-066 (P3) — duplicated logic.** Two secret-directory walkers
  (`secret.ts:96-115` vs `secret-cli.ts:50-74`); `ACTIVE_RUN_WARN_MS` defined
  twice (`health/types-result.ts:37`, `health/checks.ts:20`); the `--limit`
  guard copy-pasted five times in `graph.ts`; `assertSetupSandbox` invoked
  2–3× per setup path; `getEffectiveRegistries()` exists but `registry list`
  re-implements it inline.

- **R-067 (P3) — `process.exit()` mid-command bypasses cleanup.**
  `env run`, `secret run` (`env-cli.ts:305`, `secret-cli.ts:257`), and
  `runMigrationTool` exit directly, skipping the `disposeDispatchResources()`
  finally in `cli.ts:663-665`.

- **R-068 (P3) — misc small fixes.** `show lines` coerces `start` with
  `Number` and `end` with `parseInt` (NaN accepted, `search-cli.ts:206-212`);
  `init` never checks `git init`'s exit status (`init.ts:183-188`);
  `.akm-include` referenced in seven comments but the real mechanism is
  `package.json` `akm.include`; the `semver` npm package is a runtime
  dependency imported nowhere in `src/` while a hand-rolled subset rejects
  valid ranges (`registry/semver.ts:58-99`); `graphPath` in every graph
  command's output is the index.db path (field name fossil,
  `graph-db.ts:471`); graph read commands open/close index.db twice per
  invocation; `--belief` is described as memory-only but filters any entry
  with a `beliefState` (`db-search.ts:770-787`).
  > Ruled 2026-07-26 (Q-03): drop the `show lines` coercion sub-item — the
  > `lines` view mode and the `normalizeShowArgv`/`--akmStart`/`--akmEnd`
  > plumbing it lives in are deleted per D2, with fragment refs as the
  > successor. The remaining sub-items stand.
  > Status 2026-07-27: D2 has landed, so the `show lines` sub-item is now moot
  > in code, not just ruled away. The remaining sub-items were not
  > individually re-verified.

---

## Explicitly reclassified as in-scope (no issue filed)

Under the agent-toolkit identity, the following were reviewed and are **not**
defects of scope, only subject to the coherence/safety issues above:
`akm env`/`akm secret` (including run-injection and `${secret:}` interpolation),
`akm agent` and the ten harness integrations, the workflow engine including the
`brief`/`report` external-driver protocol, `akm tasks` and its three OS
backends, the improve/proposal/collapse-detector loop, and the health
observability surface.

Also noted as genuinely strong and worth preserving: the journaled
fs-transaction promotion/revert machinery, tar-extraction and website-crawl
SSRF hardening, git-URL scheme allowlisting, the exact-path git staging in
stash sync, the values-never-in-stdout secret discipline, and the uniform
`{ok, error, code, hint}` error envelope.
