akm-cli 0.9.30 → 0.9.32
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 +40 -0
- package/README.md +10 -10
- package/ROADMAP.md +112 -0
- package/dist/commands/feedback-cli.js +21 -13
- package/dist/commands/improve/improve-cli.js +33 -12
- package/dist/core/errors.js +1 -0
- package/dist/core/file-lock.js +10 -1
- package/dist/indexer/usage/usage-events.js +6 -2
- package/dist/llm/client.js +33 -3
- package/dist/scripts/akm-migrate-node.js +6 -1
- package/dist/scripts/akm-migrate.js +6 -1
- package/docs/README.md +42 -41
- package/docs/agents/README.md +15 -0
- package/docs/agents/agent-install.md +14 -0
- package/docs/architecture/README.md +67 -0
- package/docs/architecture/adapters.md +272 -0
- package/docs/architecture/akm-architecture-decision-history.md +2055 -0
- package/docs/architecture/akm-core-principles.md +126 -0
- package/docs/architecture/architecture.md +579 -0
- package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +550 -0
- package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +72 -0
- package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +142 -0
- package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +189 -0
- package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +97 -0
- package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +108 -0
- package/docs/architecture/decisions/0006-task-source-version-routing.md +124 -0
- package/docs/architecture/decisions/0007-workflow-composition-bounds.md +83 -0
- package/docs/architecture/decisions/0008-task-binding-normalization.md +88 -0
- package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +80 -0
- package/docs/architecture/decisions/0010-driver-protocol-cut.md +36 -0
- package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +125 -0
- package/docs/architecture/decisions/README.md +62 -0
- package/docs/architecture/improvement.md +440 -0
- package/docs/architecture/internals/classification.md +154 -0
- package/docs/architecture/internals/fresh-host-rebuild-runbook.md +40 -0
- package/docs/architecture/internals/functional-contract-patterns.md +340 -0
- package/docs/architecture/internals/health-advisories.md +110 -0
- package/docs/architecture/internals/improve-workflow.md +713 -0
- package/docs/architecture/internals/indexing.md +498 -0
- package/docs/architecture/internals/registry-network-boundary.md +57 -0
- package/docs/architecture/internals/search.md +249 -0
- package/docs/architecture/internals/storage-locations.md +943 -0
- package/docs/architecture/persisted-data-compat.md +59 -0
- package/docs/architecture/reviews/env-secret-access.md +319 -0
- package/docs/architecture/runtime-boundary-design.md +153 -0
- package/docs/architecture/specs/0.9.0-close-out-plan.md +361 -0
- package/docs/architecture/specs/0.9.0-decisions.md +528 -0
- package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +745 -0
- package/docs/architecture/specs/0.9.0-open-items-register.md +135 -0
- package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +740 -0
- package/docs/architecture/specs/0.9.0-release-surface-review.md +636 -0
- package/docs/architecture/specs/agent-command-engine-model-design.md +513 -0
- package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +501 -0
- package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +291 -0
- package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +2059 -0
- package/docs/architecture/specs/di-seams-plan.md +539 -0
- package/docs/architecture/specs/driver-protocol-keep-or-cut.md +275 -0
- package/docs/architecture/specs/fact-asset-type.md +142 -0
- package/docs/architecture/specs/improve-collapse-churn-detector-design.md +634 -0
- package/docs/architecture/specs/okf-support.md +148 -0
- package/docs/architecture/specs/ref.md +329 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/README.md +72 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +152 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +352 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +300 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +402 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +758 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +645 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +602 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +27 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +27 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +74 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +15 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +132 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +147 -0
- package/docs/architecture/specs/stash-conventions-code-spec.md +275 -0
- package/docs/architecture/specs/stash-organization-conventions.md +377 -0
- package/docs/architecture/specs/task-workflow-format-unification.md +721 -0
- package/docs/architecture/specs/workflow-engine-buy-vs-build.md +231 -0
- package/docs/architecture/specs/workflow-format-unification.md +437 -0
- package/docs/architecture/testing/manual-testing-checklist.md +3420 -0
- package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +924 -0
- package/docs/architecture/testing/task-workflow-manual-tests.md +1817 -0
- package/docs/architecture/testing/testing-workflow.md +446 -0
- package/docs/architecture/workflow-engine.md +274 -0
- package/docs/guides/README.md +33 -0
- package/docs/guides/author-bundles.md +310 -0
- package/docs/guides/author-workflows.md +520 -0
- package/docs/guides/bundles.md +321 -0
- package/docs/guides/capture-knowledge.md +136 -0
- package/docs/guides/claude-code-vs-akm-workflows.md +30 -0
- package/docs/guides/concepts.md +93 -0
- package/docs/guides/discover-and-load.md +158 -0
- package/docs/guides/getting-started.md +240 -0
- package/docs/guides/improve-the-library.md +246 -0
- package/docs/guides/knowledge-management.md +18 -0
- package/docs/guides/recipes/headless-install.md +97 -0
- package/docs/guides/recipes/website-source.md +28 -0
- package/docs/guides/run-workflows.md +279 -0
- package/docs/guides/scheduling.md +123 -0
- package/docs/guides/use-with-any-agent.md +129 -0
- package/docs/guides/wikis.md +81 -0
- package/docs/maintainers/README.md +19 -0
- package/docs/maintainers/curate-workmap.md +336 -0
- package/docs/maintainers/eval.md +3 -0
- package/docs/maintainers/local-development.md +108 -0
- package/docs/maintainers/release-checklist.md +103 -0
- package/docs/migration/README.md +2 -2
- package/docs/migration/release-notes/0.0.13.md +1 -1
- package/docs/migration/release-notes/0.1.0.md +1 -1
- package/docs/migration/release-notes/0.2.0.md +1 -1
- package/docs/migration/release-notes/0.3.0.md +1 -1
- package/docs/migration/release-notes/0.5.0.md +1 -1
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.7.3.md +2 -2
- package/docs/migration/release-notes/0.7.4.md +1 -1
- package/docs/migration/release-notes/0.7.5.md +1 -1
- package/docs/migration/release-notes/0.8.0.md +1 -1
- package/docs/migration/release-notes/0.9.0.md +1 -1
- package/docs/migration/release-notes/0.9.14.md +1 -1
- package/docs/migration/release-notes/0.9.15.md +1 -1
- package/docs/migration/release-notes/0.9.16.md +1 -1
- package/docs/migration/release-notes/0.9.17.md +1 -1
- package/docs/migration/release-notes/0.9.19.md +1 -1
- package/docs/migration/release-notes/0.9.2.md +1 -1
- package/docs/migration/release-notes/README.md +27 -31
- package/docs/migration/v0.5-to-v0.6.md +759 -0
- package/docs/migration/v0.8-to-v0.9.md +1 -1
- package/docs/plans/0.9.2-agent-command-workflow-plan.md +423 -0
- package/docs/posts/README.md +30 -0
- package/docs/posts/akm-command-tour.md +495 -0
- package/docs/posts/akm-logo-sized.webp +0 -0
- package/docs/posts/belief-aware-memory-12.md +139 -0
- package/docs/posts/config-v2-lessons-16.md +191 -0
- package/docs/posts/improve-loop-autonomous-10.md +225 -0
- package/docs/posts/improve-pipeline-debugging-0803.md +179 -0
- package/docs/posts/intro-part-01.md +76 -0
- package/docs/posts/intro-part-02.md +221 -0
- package/docs/posts/intro-part-03.md +190 -0
- package/docs/posts/intro-part-04.md +221 -0
- package/docs/posts/llm-mode-reflect-13.md +166 -0
- package/docs/posts/openpalm-built-on-akm.md +86 -0
- package/docs/posts/progressive-disclosure-06.md +129 -0
- package/docs/posts/proposal-safety-net-15.md +112 -0
- package/docs/posts/release-0.5.0.md +247 -0
- package/docs/posts/release-0.6.0.md +117 -0
- package/docs/posts/release-0.7.0.md +159 -0
- package/docs/posts/release-0.8.0.md +332 -0
- package/docs/posts/scattered-skills-05.md +100 -0
- package/docs/posts/task-assets-persistent-workflows-11.md +222 -0
- package/docs/posts/team-skills-07.md +198 -0
- package/docs/posts/wiki-agent-knowledge-08.md +223 -0
- package/docs/posts/workflows-vaults-09.md +321 -0
- package/docs/product-surface.md +54 -0
- package/docs/reference/README.md +1 -2
- package/docs/reference/asset-types.md +168 -0
- package/docs/reference/cli.md +5 -6
- package/docs/reference/data-and-telemetry.md +6 -0
- package/docs/reference/env-and-secrets.md +126 -0
- package/docs/reference/memory.md +124 -0
- package/docs/reference/refs.md +156 -0
- package/docs/reference/registry.md +489 -0
- package/docs/reference/website-sources.md +141 -0
- package/package.json +12 -15
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
# Architecture: The Improvement Loop
|
|
2
|
+
|
|
3
|
+
## Purpose and boundary
|
|
4
|
+
|
|
5
|
+
The improvement loop turns outcomes into ranking changes and reviewable proposals. This page is the
|
|
6
|
+
architecture-level reference for that loop — how a feedback signal becomes a
|
|
7
|
+
ranking change, how ranking and usage evidence become a proposal, and the
|
|
8
|
+
boundary around what AKM is allowed to write without a human or policy
|
|
9
|
+
reviewing the diff first.
|
|
10
|
+
|
|
11
|
+
The loop itself:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
agent selects capability -> agent records outcome -> AKM updates utility and analyzes evidence ->
|
|
15
|
+
AKM creates a proposal -> human or policy reviews the diff -> accept / reject / revert
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The user-facing command surface for this loop (`akm feedback`, `akm log`,
|
|
19
|
+
`akm improve`, `akm proposal ...`) is documented in
|
|
20
|
+
[Improve the Library](../guides/improve-the-library.md) and
|
|
21
|
+
[CLI Reference](../reference/cli.md). This page covers the implementation
|
|
22
|
+
detail behind those commands: how utility moves, how strategies configure
|
|
23
|
+
what runs, what the autonomy gate does and does not allow, how sync happens
|
|
24
|
+
at the end of a run, and how session extraction fits in.
|
|
25
|
+
|
|
26
|
+
**Boundary:** `akm improve` (and its subprocesses — reflect, distill,
|
|
27
|
+
consolidate) never write asset files directly. The only durable artifact they
|
|
28
|
+
produce is a proposal row in `state.db`. The narrow set of writes that *are*
|
|
29
|
+
allowed to happen without review is enumerated below, under
|
|
30
|
+
[The autonomy gate](#the-autonomy-gate);
|
|
31
|
+
everything else routes through `akm proposal accept`.
|
|
32
|
+
|
|
33
|
+
## Components
|
|
34
|
+
|
|
35
|
+
- **Utility policy** (`src/indexer/feedback/utility-policy.ts`) — pure
|
|
36
|
+
domain math that turns accumulated feedback counts into a new utility
|
|
37
|
+
score. No database access; unit-testable in isolation.
|
|
38
|
+
- **Strategies** (`src/commands/improve/improve-strategies.ts`,
|
|
39
|
+
`src/assets/improve-strategies/*.json`) — named presets that decide which
|
|
40
|
+
improve processes run and with what engine/model/limits.
|
|
41
|
+
- **Autonomy gate** (`src/commands/improve/autonomy-gate.ts`) — downgrades
|
|
42
|
+
the handful of processes that would otherwise mutate assets without review,
|
|
43
|
+
unless `experimental.improveAutonomy` is explicitly set.
|
|
44
|
+
- **Reflect / distill / consolidate subprocesses** — the improve pipeline's
|
|
45
|
+
proposal generators, invoked per asset (reflect, distill) or across the
|
|
46
|
+
whole memory corpus (consolidate). See
|
|
47
|
+
[Improve Workflow](internals/improve-workflow.md) for the full per-step
|
|
48
|
+
reference and flow diagram.
|
|
49
|
+
- **Proposal queue** (`state.db`) — written by `createProposal` (reflect,
|
|
50
|
+
distill, consolidate's promote operations, and the other proposal producers)
|
|
51
|
+
and by `createRetireProposal` (the pair pass's retire proposals).
|
|
52
|
+
- **Auto-sync** — the end-of-run commit/push step for git-backed bundles.
|
|
53
|
+
- **Session extraction** (`akm proposal extract`) — a separate entry point
|
|
54
|
+
that mines coding-agent session transcripts for durable insights and queues
|
|
55
|
+
them the same way.
|
|
56
|
+
|
|
57
|
+
## Data flow
|
|
58
|
+
|
|
59
|
+
1. An agent uses a capability and calls `akm feedback <ref> --positive|--negative`.
|
|
60
|
+
`--negative` is for content that is wrong or stale; a note that simply did
|
|
61
|
+
not fit the agent's task gets no feedback.
|
|
62
|
+
`--negative --reason "<what is wrong and what should change>"` flags the
|
|
63
|
+
asset: the next improve run may repair its frontmatter from the reason.
|
|
64
|
+
`--replace`/`--with`/`--source` attach an exact fix of its text once the
|
|
65
|
+
agent has verified the correct fact, which akm checks at once and queues as
|
|
66
|
+
a `feedback` proposal.
|
|
67
|
+
`--positive` records that the asset helped (it raises its ranking) and does
|
|
68
|
+
not trigger a rewrite.
|
|
69
|
+
2. The feedback event is appended to `state.db`, and the asset's utility
|
|
70
|
+
score is updated immediately via the bounded-step formula (below) — no
|
|
71
|
+
reindex required.
|
|
72
|
+
3. `akm improve` selects assets from the one bundle it writes to. A rewrite
|
|
73
|
+
(reflect) is planned only for an asset with negative feedback in the last
|
|
74
|
+
30 days that is newer than the stage's last attempt, or for an explicit ref;
|
|
75
|
+
a positive or note-only signal never plans one, and neither does a negative whose exact fix has since been accepted as a `feedback` proposal. Distill reads any feedback
|
|
76
|
+
on a memory in that window, but skips a memory flagged wrong and not edited
|
|
77
|
+
since: a negative feedback in the window judged the body it still has (or,
|
|
78
|
+
recorded without that body's hash, is newer than its file's last write). It
|
|
79
|
+
also skips a memory whose only feedback in the window is positive with no
|
|
80
|
+
reason or note, which gives the writer nothing to distil (10 of the 11
|
|
81
|
+
lessons made from such memories were rejected). Unless
|
|
82
|
+
`--require-feedback-signal` is set, the
|
|
83
|
+
fallback lanes (high salience, and proactive maintenance where the strategy
|
|
84
|
+
enables it) pick what the retrieval scope below admits, for scoring only:
|
|
85
|
+
they plan nothing, so improve does not rewrite assets on a proactive
|
|
86
|
+
cadence. It ranks the selected assets by salience, applies the limit, then
|
|
87
|
+
runs whichever processes the selected strategy enables against each one (see
|
|
88
|
+
[Improve Workflow](internals/improve-workflow.md#ledger-pre-filter-signal-delta)).
|
|
89
|
+
4. Reflect and distill each emit at most one proposal per asset per run;
|
|
90
|
+
consolidate runs two passes alongside each other — the promote pass emits
|
|
91
|
+
a proposal turning a memory into knowledge (and, once accepted, retires
|
|
92
|
+
the source memory) unless a neighbouring `knowledge/` doc already covers
|
|
93
|
+
the memory, and it offers a memory whose promotion was accepted or
|
|
94
|
+
rejected, or that the model judged and left alone, again only after the
|
|
95
|
+
memory's body changes; the pair pass judges
|
|
96
|
+
near-duplicate and superseding pairs in the memory tier and emits a
|
|
97
|
+
`retire` proposal for the `duplicate`/`subsumed`/`supersedes` classes;
|
|
98
|
+
`overlap`, `unrelated` and `contradicts` are recorded as
|
|
99
|
+
`judged_no_action` with no proposal. The judge first lists the durable
|
|
100
|
+
claims each side alone holds, and a side with any listed claim is never
|
|
101
|
+
retired. Knowledge is never retired in favour of a memory: when the judge would
|
|
102
|
+
do that, the memory is retired in favour of the note if the memory lists no claim of its own,
|
|
103
|
+
and the pair is left alone otherwise. A retirement whose retired side lists nothing (a duplicate: neither
|
|
104
|
+
side), confirmed by a second look, is staged for the triage drain to accept; every other
|
|
105
|
+
retirement waits for a person.
|
|
106
|
+
5. Every emitted proposal lands in the `proposals` table in `state.db`,
|
|
107
|
+
status `pending`.
|
|
108
|
+
6. A human (via `akm proposal diff` / `accept` / `reject`) or a configured
|
|
109
|
+
drain policy (`akm proposal drain`) reviews and resolves each proposal. A
|
|
110
|
+
rejection is not final: `akm proposal reopen` puts a rejected proposal back
|
|
111
|
+
to `pending`.
|
|
112
|
+
7. `akm proposal accept` promotes the proposal into the bundle; `akm proposal
|
|
113
|
+
revert` restores the prior content from the backup captured at promotion
|
|
114
|
+
time, if the proposal overwrote an existing asset. When the bundle is a git
|
|
115
|
+
repository (a `.git` directory, whatever its source kind), each accept is
|
|
116
|
+
committed as it happens, locally and with exactly the paths it wrote or
|
|
117
|
+
removed: `akm accept: <generator> <proposal-id-8> <ref>`. A retirement's
|
|
118
|
+
archived copy and tombstone, and the source memory a consolidate promotion
|
|
119
|
+
retires, go in the same commit. A commit that fails warns and the accept
|
|
120
|
+
stands.
|
|
121
|
+
8. For a git-backed bundle, `akm improve`'s end-of-run auto-sync commits the
|
|
122
|
+
rest of the run's changes as a single batch and pushes (see below).
|
|
123
|
+
|
|
124
|
+
## Current decisions
|
|
125
|
+
|
|
126
|
+
### Utility scoring
|
|
127
|
+
|
|
128
|
+
Utility moves by the MemRL bounded-step EMA formula (arXiv:2601.03192),
|
|
129
|
+
implemented in `computeNextUtility` (`src/indexer/feedback/utility-policy.ts`):
|
|
130
|
+
|
|
131
|
+
```text
|
|
132
|
+
reward = weighted average of positive (1.0) and negative (0.0) feedback in the batch
|
|
133
|
+
nextUtil = clamp(currentUtil + FEEDBACK_LR * (reward - currentUtil), 0, 1)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
`FEEDBACK_LR` is `0.1`, so a single feedback batch moves utility by at most
|
|
137
|
+
0.1 in either direction regardless of how lopsided the batch is — `reward` is
|
|
138
|
+
a proportion of the counts, not their magnitude. When a previously
|
|
139
|
+
high-utility asset (utility ≥ 0.5) crosses back below 0.5, the update is
|
|
140
|
+
flagged as a review-threshold crossing so callers can escalate it. Decay is
|
|
141
|
+
time-proportional rather than tied to index frequency, and usage history
|
|
142
|
+
(and the utility it drives) is preserved across schema resets and full index
|
|
143
|
+
rebuilds — see [Architecture: Utility Scoring](architecture.md#utility-scoring)
|
|
144
|
+
for the storage-level summary.
|
|
145
|
+
|
|
146
|
+
### Strategy inheritance
|
|
147
|
+
|
|
148
|
+
Improve presets live under `improve.strategies` (config) and the built-in
|
|
149
|
+
set: `default`, `quick`, `thorough`, `consolidate`, `catchup`,
|
|
150
|
+
`reflect-distill`, and `proactive-maintenance`
|
|
151
|
+
(`src/assets/improve-strategies/*.json`). Selection
|
|
152
|
+
order is `--strategy`, then `defaults.improveStrategy`, then `default`.
|
|
153
|
+
|
|
154
|
+
Resolution is a two-step deep merge (`resolveImproveStrategy`): a named
|
|
155
|
+
built-in strategy is first merged onto the built-in `default` strategy, then
|
|
156
|
+
any user-defined override for that same name (under `improve.strategies` in
|
|
157
|
+
config) is merged on top. So a strategy — built-in or user-defined — that
|
|
158
|
+
omits a field, or an entire process block, inherits it from `default`; an
|
|
159
|
+
explicit `enabled: true`/`false` in the more specific layer always wins. This
|
|
160
|
+
is why, for example, `proactiveMaintenance` stays off in `default` and
|
|
161
|
+
`reflect-distill`, but a preset that doesn't mention it at all still inherits
|
|
162
|
+
that "off" rather than defaulting to on.
|
|
163
|
+
|
|
164
|
+
### Retrieval scope
|
|
165
|
+
|
|
166
|
+
Improve reworks only what gets read (#986). Fresh feedback and an explicit ref
|
|
167
|
+
scope (`akm improve skills/x`) are usage evidence of their own. Every other
|
|
168
|
+
pick — the proactive-maintenance and high-salience lanes (which only score what
|
|
169
|
+
they pick), and the memories consolidation judges — must be in the retrieval
|
|
170
|
+
scope (`src/commands/improve/retrieval-scope.ts`):
|
|
171
|
+
|
|
172
|
+
- **Retrieved:** a user-attributed `search`, `curate` or `show` returned the
|
|
173
|
+
asset, or user `feedback` named it, inside the window. A hit on a
|
|
174
|
+
`.derived` memory counts for its parent. Machine traffic (`improve`, `task`,
|
|
175
|
+
`audit`) does not count.
|
|
176
|
+
- **New material:** the file was written inside the window and no improve
|
|
177
|
+
stage has processed the asset — no `improve_ledger` row and no proposal from
|
|
178
|
+
any source but a capture (`extract`, `propose`, `remember`, `import`).
|
|
179
|
+
|
|
180
|
+
The window is the usage log's retention (`USAGE_EVENT_RETENTION_DAYS`, 90
|
|
181
|
+
days): the log keeps nothing older, and a shorter window would drop assets
|
|
182
|
+
read less often than it. There is no config key. Refs left out are counted by
|
|
183
|
+
the plan's `retrieval` gate and reported as the `not_retrieved` skip reason;
|
|
184
|
+
consolidation reports them in its warnings. A bulk rewrite of old files
|
|
185
|
+
(a rename, a lint fix, a fresh clone) makes them look new until improve has
|
|
186
|
+
processed each once.
|
|
187
|
+
|
|
188
|
+
### Quality judge
|
|
189
|
+
|
|
190
|
+
Every reflect revision and every distilled lesson is scored by a judge before it
|
|
191
|
+
is queued (`runQualityJudge`, `src/commands/improve/stage.ts`): one call at
|
|
192
|
+
temperature 0, each criterion scored 1 to 5, failing closed (no runner, a
|
|
193
|
+
timeout, or an unparseable or incomplete reply never passes content and goes to
|
|
194
|
+
review). A reflect revision is scored on three criteria:
|
|
195
|
+
|
|
196
|
+
- **need**: does it fix a concrete problem in the source: something the
|
|
197
|
+
feedback reports as wrong or missing, a factual error, or broken, garbled,
|
|
198
|
+
truncated or missing text (frontmatter fields included)? A rewrite that only
|
|
199
|
+
rewords, restates or reformats a correct source, or adds headings, an
|
|
200
|
+
introduction or a table of contents, scores 1 or 2.
|
|
201
|
+
- **preservation**: does it keep every concrete fact, identifier, command, path,
|
|
202
|
+
number and example, without truncation?
|
|
203
|
+
- **quality**: is it coherent and accurate, with nothing the source or the
|
|
204
|
+
feedback does not support?
|
|
205
|
+
|
|
206
|
+
Content passes only when **every** criterion scores 4 or more (a lesson's
|
|
207
|
+
grounding is judged apart, see
|
|
208
|
+
[distill](internals/improve-workflow.md#distill-akmdistill)); a mean of 3.5
|
|
209
|
+
passed it before. A verdict that does not pass is a review when its mean is 2.5
|
|
210
|
+
or more and a rejection below that. The rubric and the rule were chosen on 90
|
|
211
|
+
labelled real rewrites, where judging on the mean let rewrites that only
|
|
212
|
+
reworded a correct asset through.
|
|
213
|
+
|
|
214
|
+
A reflect pass is stamped on the proposal as a `staged` decision from the
|
|
215
|
+
`quality-gate` with the per-criterion `scores` and the judge's `judgeReason`;
|
|
216
|
+
both stay on the proposal when the drain accepts it, so a later audit can read
|
|
217
|
+
why it passed (`akm proposal show --format json`). A distill pass is not staged:
|
|
218
|
+
the lesson or promotion is minted `deferred` for a person (reason
|
|
219
|
+
`distill-review`, same gate) with the same `scores` and `judgeReason`, and the
|
|
220
|
+
triage drain and its judgment tier leave it alone. On 2026-10-05 the gate had
|
|
221
|
+
staged 12 lessons and 10 were bad (they restated the memory, claimed what it
|
|
222
|
+
does not say, or filed a dated status as a lesson), and no score separated them
|
|
223
|
+
from the two good ones. Reflect revises only an asset's
|
|
224
|
+
`description`, `when_to_use` and title, never its body. On 396 labelled edits,
|
|
225
|
+
those that fixed a frontmatter defect and left the body alone were good 24
|
|
226
|
+
times in 26, and those that also rewrote the body were bad 175 times in 224.
|
|
227
|
+
|
|
228
|
+
### Retrieval regression gate
|
|
229
|
+
|
|
230
|
+
Reflect refuses a revision of an existing asset that grades lower on the
|
|
231
|
+
asset's own retrieval queries (#722, `src/commands/improve/retrieval-gate.ts`).
|
|
232
|
+
After the quality judge passes, up to five distinct user `search`/`curate`
|
|
233
|
+
queries that returned the asset (envelopes, the stash README line and inputs
|
|
234
|
+
over 2,000 characters dropped) are each graded 0–3 against the old and the new
|
|
235
|
+
content with the retrieval eval's prompt, `retrieval-relevance-judge.md`, and
|
|
236
|
+
its document shape: type, ref, name, description and the first 1,500 body
|
|
237
|
+
characters. A lower mean for the new content is a `quality_rejected` refusal
|
|
238
|
+
with the reflect rejection window. A grade that cannot be obtained refuses the
|
|
239
|
+
rewrite, as the quality judge fails closed. An asset with no such queries is
|
|
240
|
+
not graded.
|
|
241
|
+
|
|
242
|
+
The gate exists because it was measured first. Of 60 accepted reflect rewrites
|
|
243
|
+
(since 2026-07-01, stratified by lane) judged this way, 14 graded lower (23%,
|
|
244
|
+
95% CI 14–35%) and 12 higher. Grading the same content twice flipped 11 of 174
|
|
245
|
+
query grades, which puts 3 of 60 rewrites in the "lower" bucket by noise
|
|
246
|
+
alone. The threshold for building it was fixed before judging: a lower bound of
|
|
247
|
+
at least 10%.
|
|
248
|
+
|
|
249
|
+
### Retirement continuity
|
|
250
|
+
|
|
251
|
+
Before the consolidate pair pass mints a `retire` proposal (rule R3,
|
|
252
|
+
`src/commands/improve/consolidate/continuity-check.ts`), it replays up to five
|
|
253
|
+
of the retired asset's own past `search`/`curate` queries
|
|
254
|
+
(`loadRetrievalQueries`, the same cleaned set `../retrieval-gate.ts` replays
|
|
255
|
+
for the retrieval regression gate — boilerplate, harness/tool envelopes,
|
|
256
|
+
pastes and near-duplicates dropped before replay, S3a) through akm's own
|
|
257
|
+
search, in-process — the ranking a user actually gets, no LLM. For every
|
|
258
|
+
query where the retired asset ranked in the top 10, the successor must too
|
|
259
|
+
(N2: compared directly — search itself returns at most the top 10 hits, so
|
|
260
|
+
"ranked" and "absent from those hits" are the only two states there are, no
|
|
261
|
+
generic rank-change-report abstraction needed). An asset with no recorded
|
|
262
|
+
queries is not checked at all, and neither is a pair whose two bodies are
|
|
263
|
+
content-identical once whitespace is collapsed (S3b) — search's own
|
|
264
|
+
content-dedupe already hides the successor behind the retired asset for
|
|
265
|
+
every such query, so a "successor missing" finding there would not be a
|
|
266
|
+
real risk.
|
|
267
|
+
|
|
268
|
+
A failing pair still mints — the check flags, it never blocks — but the
|
|
269
|
+
proposal carries `continuityRisk` in its retirement metadata: the failing
|
|
270
|
+
query count and the rank pairs, visible in `akm proposal show`/`list`/`diff`. A
|
|
271
|
+
flagged proposal is excluded from every bulk accept path (`accept
|
|
272
|
+
--generator …`, with or without `--yes`); a person can still accept it by id.
|
|
273
|
+
Bulk *reject* is unaffected, since declining a flagged proposal is always the
|
|
274
|
+
safe direction.
|
|
275
|
+
|
|
276
|
+
A query that never ran (the search call threw) or that fell back to
|
|
277
|
+
keyword-only ranking instead of the real one (`mode: "fts-fallback"` — most
|
|
278
|
+
often a down or unreachable embedding endpoint) is "unverified": it is never
|
|
279
|
+
compared for rank at all, and on its own it is enough to set
|
|
280
|
+
`continuityRisk` (`unverifiedQueries` alongside the usual `ranks`), so an
|
|
281
|
+
endpoint outage reads as "risk unknown," never as the silent "no risk
|
|
282
|
+
found" a search that quietly used a degraded ranking would otherwise
|
|
283
|
+
produce. Once any query in a pair-pass run falls back, every later query in
|
|
284
|
+
that same run skips the semantic attempt entirely and goes straight to
|
|
285
|
+
keyword-only — a dead endpoint costs one failed attempt for the whole run,
|
|
286
|
+
not one per remaining query.
|
|
287
|
+
|
|
288
|
+
This check replaces the old per-run forgetting-safety lane (a one-time WS-1
|
|
289
|
+
cutover guard that compared improve's own salience ranking before and after
|
|
290
|
+
each run). The 30-day event window showed it made no pick the signal-delta
|
|
291
|
+
lane or the retrieval scope would not also have made, and it protected
|
|
292
|
+
`asset_salience.rank_score`, which only improve itself ever read — a rank drop
|
|
293
|
+
could not hide anything from search. `forgetting-safety` stays a valid
|
|
294
|
+
`eligibilitySource`/event-type value so old proposals and events still decode,
|
|
295
|
+
but nothing assigns or emits it any more.
|
|
296
|
+
|
|
297
|
+
### Dry-run planning boundary
|
|
298
|
+
|
|
299
|
+
Dry and live improve runs call the same selectors for signal-delta eligibility,
|
|
300
|
+
the fallback lanes (proactive maintenance and high salience, which score and
|
|
301
|
+
plan nothing), the retrieval scope, salience ranking, disk presence, and the
|
|
302
|
+
final cap, and resolve the bundle they plan the same way: `--bundle`, else
|
|
303
|
+
`defaultWriteTarget`, else the working bundle (`AKM_BUNDLE_DIR`, else
|
|
304
|
+
`defaultBundle`). Each invocation reports a best-effort observation assembled
|
|
305
|
+
while it runs; it is not an atomic cross-store snapshot, a reservation, or a
|
|
306
|
+
durable frozen plan. A later live invocation re-inspects mutable index, state,
|
|
307
|
+
filesystem, and session-log inputs and can therefore differ from an earlier
|
|
308
|
+
dry preview. Given equivalent observed inputs, both paths produce the same
|
|
309
|
+
selection. The public schema-v2 result projects the observation as `plan`: raw
|
|
310
|
+
in-scope count, each gate's removals, configured and effective limits, final
|
|
311
|
+
ranked refs with lane attribution, proactive due statistics, consolidation
|
|
312
|
+
pool/delta/minimum gates and chunk estimate, maintenance-stage decisions,
|
|
313
|
+
triage mode/caps, and the read-side index snapshot status. `plannedRefs` means
|
|
314
|
+
the effective post-limit work set in both modes.
|
|
315
|
+
|
|
316
|
+
The dry path stops at that projection boundary. It may read indexed assets,
|
|
317
|
+
the filesystem, and an existing `state.db`, but opens state read-only and does
|
|
318
|
+
not create it when absent. It does not acquire the improve lock or write the
|
|
319
|
+
index, state, events, proposals, assets, cache, sync journal, or persisted run
|
|
320
|
+
result, and it never dispatches an LLM. SQLite inputs are inspected through
|
|
321
|
+
disposable main/WAL copies so even a held source SHM file is not touched.
|
|
322
|
+
Consolidation pool inspection and the extract `minNewSessions` gate use shared
|
|
323
|
+
zero-LLM selectors, while live execution re-inspects mutable inputs immediately
|
|
324
|
+
before dispatch. A missing index or one without the current `entries` table
|
|
325
|
+
yields an explicit empty `plan.snapshot` (`missing` or `incompatible`) rather
|
|
326
|
+
than creating or migrating the database.
|
|
327
|
+
|
|
328
|
+
`plan.limits.effective` is the cap on the refs a run dispatches, resolved from
|
|
329
|
+
`--limit`, then the reflect process's `limit`, then the strategy's `limit`. The
|
|
330
|
+
replay lane is retired, so `additiveReplayAllowance` is always `0` (the field
|
|
331
|
+
stays so the schema-v2 plan shape keeps validating) and a finite `totalCeiling`
|
|
332
|
+
equals `effective`. When the run is unbounded, `totalCeiling` is omitted.
|
|
333
|
+
|
|
334
|
+
### The autonomy gate
|
|
335
|
+
|
|
336
|
+
`akm improve` runs by default and is review-first: reflect, distill, extract
|
|
337
|
+
candidates, validation, and proactive-maintenance selection are proposal-only
|
|
338
|
+
and never write assets directly regardless of this gate.
|
|
339
|
+
Three specific lanes *would* mutate assets without review and are downgraded
|
|
340
|
+
unless `experimental.improveAutonomy` is explicitly set to `true`:
|
|
341
|
+
|
|
342
|
+
| Lane | What it does when enabled | With autonomy off |
|
|
343
|
+
| --- | --- | --- |
|
|
344
|
+
| `memoryInference` | Writes `.derived.md` children and rewrites parent frontmatter | disabled |
|
|
345
|
+
| memory cleanup | Belief-state frontmatter rewrites, archive moves | analyzed but not applied |
|
|
346
|
+
| `triage` `applyMode: "promote"` | Auto-accepts queued proposals into the bundle | downgraded to `queue` — triage still runs, it just does not auto-accept |
|
|
347
|
+
|
|
348
|
+
Every downgrade is reported, not silent: it warns on stderr, appends an
|
|
349
|
+
`improve_skipped` event with `reason: "autonomy_gated"`, and is counted in
|
|
350
|
+
`akm health`'s improve skip-reason summary. Consolidation stays enabled with
|
|
351
|
+
autonomy off: both its passes only ever emit a reviewable proposal. The one
|
|
352
|
+
pair-pass `retire` proposal `triage` `applyMode: "promote"` accepts is a
|
|
353
|
+
retirement the pair pass staged (nothing unique to the retired side, confirmed
|
|
354
|
+
by a second look, no continuity risk); every other one waits for `akm proposal accept`. An absent `experimental`
|
|
355
|
+
section, an absent key, and an explicit `false` all read identically as off —
|
|
356
|
+
autonomy is never inferred. `akm proposal drain --promote` is a second,
|
|
357
|
+
explicit promote surface independent of this gate.
|
|
358
|
+
|
|
359
|
+
### Auto-sync
|
|
360
|
+
|
|
361
|
+
For git-backed bundles (detected by a `.git` directory), `akm improve`
|
|
362
|
+
automatically commits its changes as a single batch at the end of the run —
|
|
363
|
+
the same operation as `akm sync` — and pushes if the bundle is writable, per
|
|
364
|
+
the active strategy's `sync` setting. The `reflect-distill` and
|
|
365
|
+
`proactive-maintenance` strategies skip sync entirely, so an interrupted run
|
|
366
|
+
does not leave an uncommitted backlog. `--no-sync` disables sync for a single
|
|
367
|
+
run; `--no-push` commits without pushing. Strategy sync behavior is
|
|
368
|
+
configured via the `sync` block under `improve.strategies.<name>`.
|
|
369
|
+
|
|
370
|
+
The sync always commits the paths it is given. A branch it cannot push (no
|
|
371
|
+
upstream branch, or behind or diverged from its upstream) only skips the push,
|
|
372
|
+
and the result says why: `sync.reason` reads `not pushed: ...`. A branch that is
|
|
373
|
+
ahead of its upstream, as it is after the accept commits above, is pushed with
|
|
374
|
+
the sync commit. A clean tree that is ahead is not pushed: the sync pushes what
|
|
375
|
+
it commits.
|
|
376
|
+
|
|
377
|
+
The commit is scoped by **write provenance**, not by directory: every akm write
|
|
378
|
+
path records the file it mutated into a run-scoped journal
|
|
379
|
+
(`src/core/write-provenance.ts`), and the end-of-run sync stages exactly the
|
|
380
|
+
journaled paths that Git still reports as changed. A file someone else edits
|
|
381
|
+
under a managed directory while the run is in flight is therefore left dirty for
|
|
382
|
+
its author, while a file that was already dirty when the run started and was
|
|
383
|
+
then rewritten by the run IS committed. Deletions are journaled like writes, so
|
|
384
|
+
the final on-disk state is what lands — a path written and then reverted or
|
|
385
|
+
purged produces no commit at all. The run reports its journal as
|
|
386
|
+
`writtenPaths` on the improve result. Callers that supply no explicit path list
|
|
387
|
+
(`akm sync`, `akm push`) keep the managed-pathspec fallback in `saveGitStash`.
|
|
388
|
+
|
|
389
|
+
### Archive purge
|
|
390
|
+
|
|
391
|
+
A retirement's archived bytes (`.akm/memory-cleanup/archive/<stamp>-<ref>/`)
|
|
392
|
+
are not deleted at accept time — only the tombstone (`cleanup.md`) resolves
|
|
393
|
+
the ref going forward. `purgeGracedArchive`
|
|
394
|
+
(`src/commands/improve/memory/memory-improve.ts`) sweeps them later: run once
|
|
395
|
+
at the very start of every `akm improve` invocation, deterministic, no LLM,
|
|
396
|
+
before index bootstrap or triage. For a git-backed bundle, it deletes the
|
|
397
|
+
archived asset file(s) — never `cleanup.md` — of every retirement whose
|
|
398
|
+
tombstone `retiredAt` is more than 30 days old (`RETIRE_GRACE_DAYS`) AND
|
|
399
|
+
whose archive directory is entirely git-tracked and clean (`git ls-files`
|
|
400
|
+
plus `git status --porcelain -uall`, both checked once per sweep, not once
|
|
401
|
+
per directory). `.git` presence alone does not guarantee a retirement was
|
|
402
|
+
ever committed: an accept commits its own paths (`commitAcceptedPaths` in
|
|
403
|
+
`src/core/write-source.ts`), on a `kind: "filesystem"` source with a `.git`
|
|
404
|
+
directory too, but a commit that failed only warned, and a retirement accepted
|
|
405
|
+
by an older akm left archived bytes sitting on disk with no commit behind them
|
|
406
|
+
at all. A directory with even one untracked or modified file (the tombstone
|
|
407
|
+
included) is left whole for a later sweep, so the purge only ever removes
|
|
408
|
+
bytes git can already recover. Every deleted path is journaled individually,
|
|
409
|
+
so the end-of-run auto-sync commits the removal the same way it commits the
|
|
410
|
+
archive move itself. A bundle with no `.git` of its own has no history to
|
|
411
|
+
fall back on, so its archive is left untouched — `akm health` reports its
|
|
412
|
+
size and file count instead (`memory-cleanup-archive` advisory,
|
|
413
|
+
`src/commands/health/archive-usage.ts`).
|
|
414
|
+
|
|
415
|
+
### Session extraction
|
|
416
|
+
|
|
417
|
+
`akm proposal extract` is the standalone entry point for mining coding-agent
|
|
418
|
+
session transcripts (`--type claude`, `--type codex`, `--type opencode`, or
|
|
419
|
+
`--auto` to iterate every harness with a detectable session-log location) into
|
|
420
|
+
proposals.
|
|
421
|
+
It replaced the legacy session-checkpoint hook and runs independently of
|
|
422
|
+
whether a strategy's own `processes.extract` stage is enabled — no shipped
|
|
423
|
+
strategy turns that improve-stage extraction on, and a direct
|
|
424
|
+
`akm proposal extract --type <harness>` or `--auto` invocation is never gated
|
|
425
|
+
by that toggle. Session indexing writes are additive
|
|
426
|
+
(`sessions/**`), which is why they are one of the writes left deliberately
|
|
427
|
+
ungated by the autonomy gate above.
|
|
428
|
+
|
|
429
|
+
## See also
|
|
430
|
+
|
|
431
|
+
- [Improve the Library](../guides/improve-the-library.md) — the user-facing
|
|
432
|
+
command guide for this loop
|
|
433
|
+
- [Improve Workflow](internals/improve-workflow.md) — full per-step reference
|
|
434
|
+
and flow diagram for reflect/distill/consolidate
|
|
435
|
+
- [Architecture](architecture.md) — system-wide architecture summary,
|
|
436
|
+
including the Utility Scoring and Writing to Sources sections
|
|
437
|
+
- [Configuration Reference — Strategies](../reference/configuration.md#strategies)
|
|
438
|
+
and [Experimental opt-ins](../reference/configuration.md#experimental-opt-ins)
|
|
439
|
+
- [STABILITY.md](../../STABILITY.md#akm-improve-autonomy--opt-in-in-090) — the
|
|
440
|
+
normative autonomy-gate contract
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Classification System
|
|
2
|
+
|
|
3
|
+
akm recognizes files through **bundle adapters**. Each adapter owns a bundle
|
|
4
|
+
format and exposes a `recognize()` primitive that inspects a single file (path +
|
|
5
|
+
frontmatter + content) and returns an `IndexDocument` — the item's
|
|
6
|
+
subdir-qualified `conceptId`, type, renderer, and metadata — or `null` if the
|
|
7
|
+
adapter does not claim the file. There is no longer a global matcher registry;
|
|
8
|
+
the per-format adapter is the unit of recognition.
|
|
9
|
+
|
|
10
|
+
## Built-in adapters
|
|
11
|
+
|
|
12
|
+
The registry is a **static frozen list** (`BUILTIN_ADAPTERS` in
|
|
13
|
+
`src/core/adapter/adapters/index.ts`, exposed through
|
|
14
|
+
`src/core/adapter/registry.ts`) — always populated at module load, no
|
|
15
|
+
registration call required. Eleven built-ins, in probe order:
|
|
16
|
+
|
|
17
|
+
| Adapter id | Format | Recognizes |
|
|
18
|
+
| --- | --- | --- |
|
|
19
|
+
| `website-snapshot` | Crawled website snapshot bundle (read-only) | snapshot pages |
|
|
20
|
+
| `agent-skills` | Agent-skills package (root `SKILL.md`) | skills |
|
|
21
|
+
| `claude` | A `.claude/` tool directory | commands, agents, skills, settings-adjacent files |
|
|
22
|
+
| `opencode` | An `.opencode/` tool directory | commands, agents, skills |
|
|
23
|
+
| `dotenv` | Env-file bundle | env/secret whole-file assets (values never indexed) |
|
|
24
|
+
| `akm-workflow` | Workflow-dir component | workflow programs |
|
|
25
|
+
| `akm-task` | Task-dir component | scheduled task definitions |
|
|
26
|
+
| `llm-wiki` | LLM Wiki bundle | a wiki root (`schema.md` + `pages/`) and its pages, raw, xrefs, citations |
|
|
27
|
+
| `akm` | The classic AKM bundle layout | scripts, skills, commands, agents, knowledge, instructions, workflows, memories, lessons, env, secrets, facts, tasks, sessions |
|
|
28
|
+
| `okf` | Open Knowledge Format bundle | OKF concept documents of any open type |
|
|
29
|
+
| `generic-files` | Catch-all file mount | explicit configuration only — never auto-probed |
|
|
30
|
+
|
|
31
|
+
`looksLikeRoot` probes run most-specific-first in the list order above; the
|
|
32
|
+
first match wins and the winner is recorded per component. A root matching no
|
|
33
|
+
probe falls back to `akm` (see `FALLBACK_ADAPTER_ID` in
|
|
34
|
+
`src/indexer/installations.ts`).
|
|
35
|
+
`generic-files` never participates in probing.
|
|
36
|
+
|
|
37
|
+
Configured adapter ownership wins over probing. `akm add` records the detected
|
|
38
|
+
adapter so later indexing does not reinterpret a bundle. The broad OKF probe
|
|
39
|
+
also recognizes index-less typed Markdown, but strong AKM layout evidence runs
|
|
40
|
+
first because AKM Markdown is an OKF-compatible superset.
|
|
41
|
+
|
|
42
|
+
See [Bundle Types](../../reference/bundle-types.md) for the user-facing detail
|
|
43
|
+
per adapter — conceptId/ref shape, what's indexed, `validate()` checks, and
|
|
44
|
+
read/write status in 0.9.0.
|
|
45
|
+
|
|
46
|
+
## Item types
|
|
47
|
+
|
|
48
|
+
`type` is an open descriptive string. The core accepts every non-empty value;
|
|
49
|
+
the owning adapter decides whether a value receives specialized behavior. The
|
|
50
|
+
`akm` adapter emits its fourteen defined native types (`script`, `skill`,
|
|
51
|
+
`command`, `agent`, `knowledge`, `instruction`, `workflow`, `memory`,
|
|
52
|
+
`lesson`, `env`, `secret`, `fact`, `task`, `session`) — see
|
|
53
|
+
[Bundle Types](../../reference/bundle-types.md) for the full
|
|
54
|
+
purpose / agent-output table per type.
|
|
55
|
+
|
|
56
|
+
`wiki` is **no longer an item type**. Multi-page wikis are a bundle *format* owned
|
|
57
|
+
by the `llm-wiki` adapter, not a per-file type stamped by the classifier.
|
|
58
|
+
|
|
59
|
+
## Reserved structural files
|
|
60
|
+
|
|
61
|
+
`index.md` and `log.md` are reserved structural files for the `akm`, `okf`, and
|
|
62
|
+
`llm-wiki` adapters. OKF defines their meaning in OKF bundles; AKM and LLM Wiki
|
|
63
|
+
reserve the same names under their own format contracts. Other adapters own
|
|
64
|
+
their reserved-name rules.
|
|
65
|
+
|
|
66
|
+
## Adapter-owned filtering (AKM sensitive/infra abstention)
|
|
67
|
+
|
|
68
|
+
Each adapter decides which walked files it claims and which it abstains on — the
|
|
69
|
+
core always excludes VCS internals and symlink escapes. An OKF walk includes
|
|
70
|
+
ordinary dot directories and `bin/` because those paths can identify conformant
|
|
71
|
+
concepts; AKM keeps its existing cache/dot-directory hygiene. The `akm`
|
|
72
|
+
adapter's `recognize` abstains (returns `null`) on its own bundle's
|
|
73
|
+
non-content files, using **path/stat checks only** so the bytes of sensitive files
|
|
74
|
+
are never read to make the decision:
|
|
75
|
+
|
|
76
|
+
- an `env/…` `.env` file that has a sibling `.sensitive` marker;
|
|
77
|
+
- anything under the frozen legacy `vaults/` directory (the `vault` type was
|
|
78
|
+
removed in 0.9.0);
|
|
79
|
+
- a `secrets/` `.sensitive`/`.lock` marker, or a secret with a sibling
|
|
80
|
+
`<name>.sensitive` marker;
|
|
81
|
+
- a `wikis/<name>/` root-level infrastructure file (`schema.md`/`index.md`/`log.md`).
|
|
82
|
+
|
|
83
|
+
This policy previously lived in the indexer's `shouldIndexStashFile` pre-filter; it
|
|
84
|
+
now lives in the adapter (`akmStashAbstains` in
|
|
85
|
+
`src/core/adapter/adapters/akm-adapter.ts`), so each adapter owns its own bundle's
|
|
86
|
+
filtering (owner ruling 2026-07-21).
|
|
87
|
+
|
|
88
|
+
## The akm adapter's recognition signals
|
|
89
|
+
|
|
90
|
+
Inside the `akm` adapter, recognition picks a winner by **specificity descending**,
|
|
91
|
+
ties broken by registration order (later wins). The signals:
|
|
92
|
+
|
|
93
|
+
| Specificity | Signal | Result |
|
|
94
|
+
| --- | --- | --- |
|
|
95
|
+
| 25 | `SKILL.md` (skill directory) | `skill` |
|
|
96
|
+
| 20 | `tools` frontmatter | `agent` |
|
|
97
|
+
| 19 | workflow markdown structure | `workflow` |
|
|
98
|
+
| 18 | command frontmatter / `$ARGUMENTS` body placeholders | `command` |
|
|
99
|
+
| 15 | immediate parent dir hint | directory-specific type |
|
|
100
|
+
| 10 | ancestor dir hint | directory-specific type |
|
|
101
|
+
| 8 | `model` frontmatter only | weak `agent` signal |
|
|
102
|
+
| 5 | fallback markdown | `knowledge` |
|
|
103
|
+
| 3 | known script extension | `script` |
|
|
104
|
+
|
|
105
|
+
### Directory signals
|
|
106
|
+
|
|
107
|
+
- `scripts/` → `script`
|
|
108
|
+
- `skills/` → `skill`
|
|
109
|
+
- `commands/` → `command`
|
|
110
|
+
- `agents/` → `agent`
|
|
111
|
+
- `knowledge/` → `knowledge`
|
|
112
|
+
- `workflows/` → `workflow`
|
|
113
|
+
- `memories/` → `memory`
|
|
114
|
+
- `lessons/` → `lesson`
|
|
115
|
+
- `env/` → `env`
|
|
116
|
+
- `secrets/` → `secret`
|
|
117
|
+
- `tasks/` → `task`
|
|
118
|
+
|
|
119
|
+
### Markdown signals
|
|
120
|
+
|
|
121
|
+
| Signal | Type | Specificity |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `tools` in frontmatter | `agent` | 20 |
|
|
124
|
+
| workflow heading/step structure | `workflow` | 19 |
|
|
125
|
+
| `agent` in frontmatter | `command` | 18 |
|
|
126
|
+
| `$ARGUMENTS` or `$1`-`$3` in body | `command` | 18 |
|
|
127
|
+
| `model` in frontmatter only | `agent` | 8 |
|
|
128
|
+
| any other `.md` | `knowledge` | 5 |
|
|
129
|
+
|
|
130
|
+
## Asset quality values
|
|
131
|
+
|
|
132
|
+
The `quality` field marks how an item was produced. Four values are well-known:
|
|
133
|
+
|
|
134
|
+
| Value | Meaning |
|
|
135
|
+
| --- | --- |
|
|
136
|
+
| `"generated"` | Heuristically indexed; included in default search |
|
|
137
|
+
| `"curated"` | Human-authored; included in default search |
|
|
138
|
+
| `"enriched"` | Retired LLM enrichment pass (0.9.17-alpha.9) ran for this item; included in default search |
|
|
139
|
+
| `"proposed"` | Pending review; excluded from default search, opt-in via `--include-proposed` |
|
|
140
|
+
|
|
141
|
+
Unknown string values warn once at runtime and remain searchable.
|
|
142
|
+
|
|
143
|
+
## Examples
|
|
144
|
+
|
|
145
|
+
| File | Winning signal | conceptId |
|
|
146
|
+
| --- | --- | --- |
|
|
147
|
+
| `scripts/deploy.sh` | parent dir (15) → `script` | `scripts/deploy.sh` |
|
|
148
|
+
| `skills/review/SKILL.md` | `SKILL.md` (25) → `skill` | `skills/review` |
|
|
149
|
+
| `commands/release.md` with `agent: coder` | command frontmatter (18) | `commands/release` |
|
|
150
|
+
| `agents/reviewer.md` with `tools:` | frontmatter (20) → `agent` | `agents/reviewer` |
|
|
151
|
+
| `workflows/release.md` with workflow structure | structure (19) → `workflow` | `workflows/release` |
|
|
152
|
+
| `env/prod.env` | parent dir (15) → `env` | `env/prod` |
|
|
153
|
+
| `secrets/deploy-token` | parent dir (15) → `secret` | `secrets/deploy-token` |
|
|
154
|
+
| `docs/guide.md` | fallback (5) → `knowledge` | `knowledge/guide` |
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Fresh-Host Rebuild Runbook
|
|
2
|
+
|
|
3
|
+
Rebuild a working akm install on a new machine. Assumes your bundle lives in a
|
|
4
|
+
git remote and that a versioned `config.json` copy is committed to the bundle
|
|
5
|
+
git (the 08-F1 recovery pattern — see step 3).
|
|
6
|
+
|
|
7
|
+
1. **Install the CLI.** Prebuilt binary (no runtime needed):
|
|
8
|
+
`curl -fsSL https://github.com/itlackey/akm/releases/latest/download/install.sh | bash`
|
|
9
|
+
— or npm package (Node.js >= 22 required): `npm install -g akm-cli`.
|
|
10
|
+
If a working Bun >= 1.0 is also on `PATH`, the package prefers it after Node
|
|
11
|
+
bootstrap; old, unusable, or absent Bun installations fall back to Node.js.
|
|
12
|
+
The standalone binary is runtime-free.
|
|
13
|
+
(Windows: `irm https://github.com/itlackey/akm/releases/latest/download/install.ps1 | iex`.)
|
|
14
|
+
2. **Confirm the binary resolves:** `akm --version`.
|
|
15
|
+
3. **Restore `config.json`.** akm reads a single user config at
|
|
16
|
+
`~/.config/akm/config.json` (`%APPDATA%\akm\config.json` on Windows;
|
|
17
|
+
override with `AKM_CONFIG_DIR`). This file is gitignored on the host, so the
|
|
18
|
+
recovery source is the ONE versioned copy committed to the bundle git
|
|
19
|
+
(08-F1 pattern). Copy that file into place; it carries named `engines`,
|
|
20
|
+
`defaults.engine` / `defaults.llmEngine`, and cron-load-bearing improve
|
|
21
|
+
strategies that are otherwise unrecoverable.
|
|
22
|
+
4. **Provide secrets/env.** `config.json` references API keys via `${VAR}`
|
|
23
|
+
placeholders; export those environment variables (or restore your env/secret
|
|
24
|
+
assets) so named engines and the embedding connection resolve. Never commit
|
|
25
|
+
the resolved values.
|
|
26
|
+
5. **Restore the working bundle.** Clone your bundle git remote to the path
|
|
27
|
+
named by your working bundle's entry under `bundles` in the restored
|
|
28
|
+
config (`defaultBundle` selects which one; default path `~/akm`). There is
|
|
29
|
+
no top-level `stashDir` config key in 0.9 — it is retired and rejected at
|
|
30
|
+
load. If starting clean instead, run `akm setup --yes` to scaffold it.
|
|
31
|
+
6. **Re-add non-git sources.** For each managed source not carried in the bundle
|
|
32
|
+
git (websites, npm packages, GitHub repos), run `akm bundle add <ref>`. Verify the
|
|
33
|
+
full set with `akm bundle list`.
|
|
34
|
+
7. **Rebuild the index:** `akm index --full` (forces a complete reindex rather
|
|
35
|
+
than an incremental update).
|
|
36
|
+
8. **Verify health:** `akm health` (checks runtime, artifacts, and improve
|
|
37
|
+
metrics — exits non-zero if `state.db` is missing) and `akm info` for index
|
|
38
|
+
stats and effective config.
|
|
39
|
+
9. **Smoke-test discovery:** `akm search <term>` returns results, confirming the
|
|
40
|
+
index and bundle are wired correctly.
|