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:
- 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. - 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.
- 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 hintsdocuments awikicommand that does not exist. The short and full hints corpora instruct agents to runakm wiki list,akm wiki show <name>,akm wiki ingest <name>, use--type wiki, andakm show wiki:<name>. Nowikisubcommand is registered insrc/cli.ts:509-550; an agent following the tool's own onboarding issues failing commands. Either ship the command or strip it fromsrc/assets/hints/cli-hints-*.mdanddocs/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 textrenders copy-pasteable commands in the retiredtype:nameref grammar.appendShowDirectivesbuilds`${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 rendersworkflows/${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:namein the parser is not a fix option.appendShowDirectivesmust emit slash refs (as it already does forworkflows/${name}); includeshow-directives.tsin the Q-02 colon sweep alongsidesearch --help,akm hints, and the ref-prefix tests. Still open at base0475870— and now strictly worse: Q-02 landed (the colon browse grammar is gone) whileshow-directives.ts:26still builds`${assetType}:${r.name}`. Raise with the Q-02 sweep. Status 2026-07-27: confirmed still open; the file now lives atsrc/output/text/show-directives.ts(:26builds the colon ref that:37,57,75interpolate intoakm feedbacksuggestions). The fix is one line — buildassetReffrom 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 feedbackhelp contradicts the implementation. Help (src/cli.tscommand description;src/commands/feedback-cli.ts:189-206) states negative feedback "does NOT immediately lower the asset's ranking — runakm indexafter". 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:365prints "runakm events list --type improve_review_needed"; the command isakm log. (events-list/events-tailshape 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 listsurvives 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 scaffoldedfacts/conventions/organization.mdasset teaches "A rename is delete plus create. There is no command that preserves an asset's identity or learned state across one" and demonstrates rawmv+ manual grep — while top-levelakm mvexists 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 mvstays; D3 is superseded. The fix is one-directional — rewritefacts/conventions/organization.mdand the other D3-side docs to teachmv, and add the missing Experimental tier entry formvto STABILITY.md. Removingmvis off the table. -
R-006 (P0) —
akm hintsoutput depends on install method, and the copies have drifted.loadHintsprefers<pkgroot>/docs/agents/AGENTS[.full].mdon disk and falls back to embeddedsrc/assets/hints/cli-hints-*.md(src/commands/observability-cli.ts:240-257). npm packs neitherdocs/agents/norsrc/(package.jsonfiles), so npm installs always get the embedded copy while repo checkouts getdocs/— 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/reposhorthand is unreachable.add-cli.ts:234andgit-install.ts:489advertise the form, butisPathLikeRefreturns true for any string containing/(src/registry/resolve.ts:298), sotryParseLocalRefthrowsLocal path not foundbefore theparseGithubShorthandfallback atresolve.ts:86-90can run. The fallback is dead code;akm add itlackey/akm-stashfails. Reorder the dispatch (try shorthand when the local path doesn't exist).Note (Q-19, ruled 2026-07-26): the resolver fix (
resolveSourcesForOriginmatchinggithub:owner/repoinstall 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 soshow //meta's "Run: akm add …" hint chain works end to end. -
R-008 (P0) —
akm registry searchignores registries added viaakm registry add.registry-cli.ts:128callssearchRegistrywithout aregistriesoption; the fallback resolvesDEFAULT_CONFIG.registries, never the on-disk config (src/commands/read/registry-search.ts:35,166). Meanwhileakm search --source registrypassesconfig.registriesand honors them. Configured registries are listed byregistry listbut never searched byregistry search. -
R-009 (P0) —
akm searchrejects 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 throwsMISSING_REQUIRED_ARGUMENTfor an empty query (:79-86), making theenumerateEntriesbrowse 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.lockrecordsresolvedVersion/resolvedRevision/integrity, but the only field consumed for behavior islocalRoot(src/integrations/lockfile.ts:122-130).akm updatere-resolves the original ref (npmlatest, 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.
verifyArchiveIntegrityreturns 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 fromakm listwith no warning. -
R-013 (P1) —
akm add --providercombinations are broken.providerTypeis honored only when the target is a remote URL (source-manage.ts:71-100):akm add lodash --provider npmsilently creates a filesystem bundle at./lodash;akm add <url> --provider npmstores 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) returnsSourceAddResult, Path B returnsAddResponse; the shared text renderer reads Path B fields and printsInstalled undefined (0 directories scanned, 0 total assets indexed)for Path A (output/text/command-format.ts:510-514). -
R-015 (P1) —
akm update --allsilently skips plain (non-lock-backed) sources.selectManagedTargetsreturns lock-backed installs only (installed-stashes.ts:519-522); a configured plaingit/websitebundle is never refreshed by--alland 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 --yessilently skips 7 of 8 wizard steps. Only thestash-dirstep setsnonInteractive: true(setup/setup.ts:436; skip logicsetup/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). AlsorunSetupWithDefaultshardcodesonline: falseyet still runs network detection (setup.ts:779,788). -
R-017 (P1) —
akm setup --config/--fromsilently drops five valid config keys.ALLOWED_KEYS(setup.ts:1013-1027) omitsindex,search,feedback,workflow,archiveRetentionDays— all present inAkmConfigShape— deleting them with only a stderr warn. -
R-018 (P1) —
akm curate --typebypasses the entire curation algorithm. With an explicit type the result isstashHits.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 showdrops the canonicalreffrom default and summary output.showLocalcomputes it, brief/summary builders include it, and the shaper'spickFieldsallow-lists omit"ref"for human and summary shapes (output/shapes/helpers.ts:453-496). Only--shape agentemits the one identifier agents need for follow-up commands. -
R-021 (P1) —
--detail briefbehaves differently as a flag vs as config default.showCommanddetects only the literal CLI token viagetFlagValue("--detail")to triggerbuildBriefResponse(search-cli.ts:223-227); configoutput.detail: "brief"reaches only the shaper, which treats brief and normal identically. Same nominal level, two payloads. -
R-022 (P1) —
akm index --dry-runalone performs a full real index. The flag is only consulted inside the--cleanbranch (indexer.ts:715-726). -
R-023 (P1) —
akm index --backgroundclaims 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 usessources[0](graph.ts:529-538,graph-extraction.ts:406). -
R-025 (P1) —
akm config get <scalar>returns secrets unredacted.redactConfigValueonly redacts inside objects (config-cli.ts:66):akm config get embedding.apiKeyprints the literal value whileakm config get embeddingredacts it. (Mitigated by write-time sanitization, but the read surface is inconsistent.) -
R-026 (P1) —
akm env unsetargv 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 namedjsonwhile--format jsonis set is a silent no-op;--targetis wrongly included in the global-flag list; the comment citescli.ts:1335in 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_ARGSnow declares the global output flags on every leaf so their values are consumed by the parser, and keys literally namedjsonunset correctly (verified end-to-end alongside thesync --format jsoncase). See R-051's companion note. -
R-027 (P1) —
akm secret path/removecan resolve to different files than the read path for the same ref. Reads usefindEnvSource(all sources); mutations useresolveMutationTarget(core/env-secret-ref.ts:64-85vs198-255). -
R-028 (P1) —
akm import <url>'s private-host allowance is gated on a test-shaped predicate in production.allowPrivateHostsdefaults toshouldAllowPrivateWebsiteUrlForTests(source)(stash-cli.ts:256,knowledge.ts:141-146). -
R-029 (P1) —
akm backupdoes not back up the stash. Artifact set isconfig.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--foraccepts only the literal"0.9.0"(backup-cli.ts:9-16), and bothbackupandmigratehard-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):
backupmust 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.tsdeleted and thebackupregistration dropped; the capability remains atakm-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 forbackupis moot. ✅ landed same day. -
R-030 (P1) —
akm healthwrites to the append-only event stream on every run. The state-db round-trip probe appends ahealth_probeevent (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 htmloverrides--group-by(forcesgroupBy: "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 healthno longer branches on--formatanywhere:--reportis now a data flag carrying runs/deltas/the pending-proposal queue in the envelope, the md/html renderers are pure functions of the result,setHealthHtmlContextis gone, and the html-only--comparewas removed in favor of--window-compare. Breaking: bareakm health --format htmlrenders the plain check generically — use--report. Verify and close. Follow-up in453a0ba:--reporthad been seedingwindowComparefrom--sinceunconditionally, so an absolute date/ISO/epoch--sincereached a duration-only parser and threw, and an explicit--windowstripped 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-bogusexits 1;akm wiki listprints 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 --tagreads raw argv, including tokens after--. The declared citty arg is decorative;parseAllFlagValues("--tag")scans the whole argv (feedback-cli.ts:220,288). Also--applied-tois a silent no-op for non-lesson refs (:397). -
R-034 (P1) — feedback silently skips the ranking update for non-
userevent sources. WithAKM_EVENT_SOURCEset 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_REGISTRYhint is false. The env var only widens the tarball-host allowlist (resolve.ts:332-344); metadata fetches are hardcoded toregistry.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 setupinstalls five cron/launchd/schtasks entries by default (hourly/4-hourly/nightlyakm improvevariants,commands/tasks/default-tasks.ts:51-92), and embedded task templates addakm extract --autoevery 30 minutes. An OS-scheduler mutation deserves an explicit, itemized opt-in step in the wizard and a flag in--yesmode.Ruled 2026-07-26 (Q-05/Q-14):
experimental.improveAutonomyships as STABILITY.md documents it, andextractis tiered Experimental. The scheduledimproveentries must sit behind that off-by-default gate, and the embeddedakm extract --autotemplate schedules an Experimental-tier command — implement the opt-in asked for here as the gate plus an explicit wizard step (and a flag in--yesmode). -
R-037 (P1) —
akm improvecommits 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.pushstays 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 triageapplyMode: "promote"— andpushjoins 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 extractmines 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--watchmode 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):
extractis 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 indexattempts an implicit ~130 MB embedding model download. WithsemanticSearchMode: "auto"and no endpoint,embedBatchfalls 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):semanticSearchModenow defaults to"off"— a bare/headless install never attempts the download; the interactiveakm setupwizard 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/.jsfrom<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 --outwrites anywhere with default 0644 (graph.ts:302-315) whileakm env exportenforces 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.tsnormalizers, 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 insideworkflow 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 bypassparseRefInput. The renderer-registry half remains this item's ask and aligns with the ruling. Largely fixed on the base branch (453a0ba).show'sindexedEntry?.adapterId === "okf"branch becameusesIndexedProjection(read/show.ts:536-559): OKF plus any indexed item whose type AKM does not place keeps its adapter's projection, so awebsiteentry no longer comes back typed as AKM placement and a genericfileno longer loses its content. OKF is still named explicitly — deliberately, since itstypeis open frontmatter and may collide with an AKM placement type — andenv/secretstay 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
$VARconfig refs (config.ts:437-444) and cannot be supplied fromakm secret. Letting config referencesecrets/<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 thesecret:NAMEform this item originally proposed. -
R-045 (P2) — the
instructionasset type is half-registered. It exists inKNOWN_TYPES/TYPE_PRESENTATIONbut notPLACEMENT_SPECS(core/asset/asset-placement.ts:89-166vscore/recognition-util.ts:92-106), so it is invisible toakm 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.instructiongains aPLACEMENT_SPECSentry with aninstructions/stash dir on the markdown spec, becoming creatable, browsable, and listed byakm infolike knowledge; adapter-emittedinstructiondocs round-trip via the Q-07 opaque-conceptId fix. This is now mandated 0.9.0 feature work — raise to P1. -
R-046 (P2) —
--typeis unvalidated everywhere, and the help enumerates 11 of the 13 real types (missingfact,task,session;search-cli.ts:41-43,125-127).--type bogussilently returns zero hits. Validate againstplacementTypes()and generate the help list from it.Note (Q-18, ruled 2026-07-26):
instructionbecomes a placement type, shifting the real-type count from 13 to 14 — a further reason to generate the help list and validation fromplacementTypes()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.typeis a free-form open string BY DESIGN (adapters emitwebsite,wiki-source, OKF frontmatter types outside any placement list), so validating againstplacementTypes()would reject valid filters; D6 andSTABILITY.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--typehelp 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 --filtervsshow --scopefor the identicaluser=/agent=/run=/channel=narrowing. Pick one (keep the other as a hidden alias for one release).Ruled 2026-07-27: unify on
--filter, remove--scopewith no alias. ✅ landed same day:showdeclaresfilter, parses repeatable--filterthrough the sameparseScopeFilterFlagshelper assearch; 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, whererejectExtraShowPositionalsraises exit 2 (pinned by a new CLI test inscope-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/syncare three unrelated operations wearing package-manager names. Refresh sources / self-update the akm binary / git-commit-and-push the stash. Given the toolkit identity, considerakm self update(orself-upgrade) andakm stash sync(orsave) to free the ecosystem-conventional meanings;syncstill emitseventType: "save"andoutput("save", …)from its retired name (sources-cli.ts:181-185). -
R-050 (P2) — global flags that are mostly not global.
--detailis an identity no-op forinit/index/info/import/remember(and brief==normal onshow);--format md|htmlis accepted globally but valid only forhealth;--shape summaryonly forshow. Either scope the flags to the commands that honor them in help output, or implement them uniformly.Ruled 2026-07-26 (Q-04): for
--formatthe either/or is settled — implement basic support on every non-exempt command, withtextandmdcollapsed into a single format, plus alignment of the persistedoutput.formatschema and theINVALID_FORMAT_VALUEhint. Only the--detail/--shapehalves of this item remain an open choice. Split the ruled--formatwork 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 informat-exempt.ts,output.formatschema widened to six), but as SIX formats — the text/md collapse was not applied, and theINVALID_FORMAT_VALUEhint 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/--shapedeclarations are decorative. Declared onsearch/curate/showbut never read fromargs; 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 jsonsynced a bundle named "json").GLOBAL_OUTPUT_ARGSnow redeclares--format/--detail/--shape/--outputon 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 in453a0ba: the first pass covered onlydefineJsonCommandleaves, soimprove,propose, andtasks run(plaindefineCommand) still had citty parse--formatas a boolean and spill its value into the next positional —improve --dry-run --format mdread "md" as the scope,tasks run --format md nightlylost the task id. Each leaf now declares the flags. -
R-052 (P2) — bash completions advertise wrong values.
FLAG_VALUESoffers--detail … summary(a--shapevalue that errors) and omitsmd/htmlfrom--format(see the Q-04 note below); the table is keyed globally by flag name, sograph --source <TAB>suggests search'sstash registry both(commands/completions.ts:15-21). Thecompletionshandler is also the only one not wrapped inrunWithJsonErrors, so a non-bash shell error surfaces asUNHANDLED_REJECTION/exit 1 instead of a usage error/exit 2 (cli.ts:449-452).Ruled 2026-07-26 (Q-04):
textandmdcollapse into a single format, so the accepted--formatvalue set is changing — fix the completions table against the post-Q-04 set rather than addingmd/htmlto today's list. -
R-053 (P2) — bare-group behavior is inconsistent three ways.
akm log/akm lessonsprint help and exit 0;akm backup/akm migratethrow usage errors (exit 2);akm env/akm config/akm graphrun a default action. Pick one convention. -
R-054 (P2) —
akm lessonsadvertises "strength queries" that don't exist. The group description promises them (observability-cli.ts:205);lessonStrengthis written by feedback and read by ranking but not queryable from any command. Implementlessons strength <ref>or fix the description. -
R-055 (P2) — reads are writes, undisclosed.
search/show/curateappend 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 internalskipLoggingalready exists). -
R-056 (P2) —
akm indexwrites toconfig.json(persisting detected adapters viamutateConfig,indexer.ts:600-622). Surprising for an "build the index" command; disclose or relocate toadd/setup. -
R-057 (P2) —
akm infoomits the most basic facts. NostashDir, nodefaultBundle, no per-type asset counts (info.ts:64-78);searchModesreports semantic readiness from a cached status file, not a live probe; its stats warning writes rawprocess.stderr, bypassing--quiet(info.ts:103). -
R-058 (P2) — remove/update destructive-action asymmetry.
akm removeprompts for confirmation;akm update, which canrm -rfthe prior materialized root (installed-stashes.ts:421-428), does not. Also removing a plain git/website bundle leaves its mirror cache behind, andakm cloneof 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 keygetRegistryIndexCacheDir()by URL hash — adding the same repo both ways stores two copies. -
R-060 (P2) —
akm logis stillakm eventsinternally. Output shapesevents-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
normalizeShowArgvrewrite; theParsedInvocationraw-argv singleton for repeatable flags; plus ad-hocprocess.argv.includes("--no-init")and therememberpositional-swallowing heuristic that covers--format/--detailbut 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):
normalizeShowArgvand 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 byGLOBAL_OUTPUT_ARGS). Remaining: theParsedInvocationsingleton (now load-bearing by design — the one-parse rule), ad-hocprocess.argv.includesprobes, and therememberpositional-swallowing heuristic, whichGLOBAL_OUTPUT_ARGSon therememberleaf may make deletable — verify againstremember.ts:303-370before consolidating. -
R-062 (P2) —
--showSimilaris the CLI's only camelCase flag (remember-cli.ts:141-144); everything else is kebab-case, andmigrate applydeclaresdryRunwhere the codebase convention is"dry-run".
F. Cleanup batch (P3)
-
R-063 (P3) — confirmed dead code.
parseGithubShorthandbranch (unreachable, see R-007);injectIntoEnv(env.ts:115— mutatesprocess.env, forbidden by its own module docstring); secretlistNames(secret.ts:96);loadGraphMetaOnly/loadGraphEntitiesByPath(graph-db.ts:343,403);parseConfigValueshim and the unreachabletoggleComponentthrow and dead--listflag (config-cli.ts:44,129,136);listStashes/SourceListResult(source-manage.ts:36-39);resolveRegistrieson the search path (registry-search.ts:35); thesemanticSearchprojection branch (helpers.ts:290); curate's colon-grammar family regexes (curate.ts:769,779); thesession-log-failuresadvisory hardwired to pass (checks.ts:464-482);setup.taskSchedulesschema 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);durationMscomputed thenvoid-ed (improve-cli.ts:359-360);SourceEntry.updatableand.providerset-but-never-read;installedKitCount(retired "Agent Kit Manager" naming) still in the public JSON envelope of add/remove/update;workflow.dbstill 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 thegetDbPath()call it makes);graph-extraction.ts:34-37(describes retired fs.writeFile storage);history.ts:11-15(events.jsonlvs actualstate.db); the fourTODO(R2)markers inworkflows/program/{parser,schema}.tsandir/compile.tsdescribing gate loops / retry / isolation / schema validation as unimplemented — all four are implemented innative-executor.ts;reflect.ts:6/distill.ts/consolidate.tsheaders documentingakm reflectetc. as CLI commands that were never registered;metrics.ts:270-274documenting a deleted metric;setup.ts:776(R-016). -
R-066 (P3) — duplicated logic. Two secret-directory walkers (
secret.ts:96-115vssecret-cli.ts:50-74);ACTIVE_RUN_WARN_MSdefined twice (health/types-result.ts:37,health/checks.ts:20); the--limitguard copy-pasted five times ingraph.ts;assertSetupSandboxinvoked 2–3× per setup path;getEffectiveRegistries()exists butregistry listre-implements it inline. -
R-067 (P3) —
process.exit()mid-command bypasses cleanup.env run,secret run(env-cli.ts:305,secret-cli.ts:257), andrunMigrationToolexit directly, skipping thedisposeDispatchResources()finally incli.ts:663-665. -
R-068 (P3) — misc small fixes.
show linescoercesstartwithNumberandendwithparseInt(NaN accepted,search-cli.ts:206-212);initnever checksgit init's exit status (init.ts:183-188);.akm-includereferenced in seven comments but the real mechanism ispackage.jsonakm.include; thesemvernpm package is a runtime dependency imported nowhere insrc/while a hand-rolled subset rejects valid ranges (registry/semver.ts:58-99);graphPathin 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;--beliefis described as memory-only but filters any entry with abeliefState(db-search.ts:770-787).Ruled 2026-07-26 (Q-03): drop the
show linescoercion sub-item — thelinesview mode and thenormalizeShowArgv/--akmStart/--akmEndplumbing 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 theshow linessub-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.