akm-cli 0.10.261015-beta → 0.10.261017-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +173 -0
- package/README.md +8 -10
- package/SECURITY.md +7 -99
- package/STABILITY.md +58 -98
- package/dist/assets/hints/cli-hints-full.md +6 -4
- package/dist/assets/hints/cli-hints-short.md +4 -2
- package/dist/assets/opencode/akm-plugin.js +16 -8
- package/dist/assets/prompts/workflow-unit-preamble.md +3 -1
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -2
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +11 -17
- package/dist/cli.js +32 -41
- package/dist/commands/feedback-cli.js +5 -4
- package/dist/commands/health/plugin-staleness.js +86 -22
- package/dist/commands/health.js +15 -16
- package/dist/commands/proposal/proposal-cli.js +1 -1
- package/dist/commands/read/registry-search.js +4 -1
- package/dist/commands/read/search-cli.js +2 -2
- package/dist/commands/read/search.js +6 -6
- package/dist/commands/read/show.js +15 -3
- package/dist/commands/sources/self-update.js +9 -5
- package/dist/commands/tasks/tasks.js +12 -13
- package/dist/core/adapter/adapters/agent-skills-adapter.js +7 -7
- package/dist/core/adapter/adapters/akm-task-adapter.js +1 -1
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
- package/dist/core/adapter/adapters/claude-adapter.js +1 -1
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +1 -1
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +1 -1
- package/dist/core/adapter/adapters/opencode-adapter.js +1 -1
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -1
- package/dist/core/asset/markdown.js +9 -0
- package/dist/core/bundle-rename.js +17 -7
- package/dist/core/config/config-walker.js +35 -32
- package/dist/core/config/schema/connections.js +6 -3
- package/dist/core/config/schema/harnesses.js +8 -1
- package/dist/core/config/schema/primitives.js +12 -1
- package/dist/core/config/schema/sources-bundles.js +2 -2
- package/dist/core/npm-package.js +48 -13
- package/dist/indexer/bundle-identity-guard.js +6 -6
- package/dist/indexer/index-written-assets.js +3 -3
- package/dist/indexer/indexer.js +12 -8
- package/dist/indexer/materialize-embeddings.js +12 -2
- package/dist/indexer/passes/metadata.js +103 -46
- package/dist/indexer/search/ranking.js +7 -3
- package/dist/indexer/search/search-fields.js +1 -1
- package/dist/indexer/usage/usage-events.js +30 -8
- package/dist/indexer/walk/walker.js +1 -1
- package/dist/output/renderers.js +2 -2
- package/dist/output/shapes/helpers.js +5 -3
- package/dist/output/text/command-format.js +5 -6
- package/dist/output/text/show-format.js +7 -0
- package/dist/registry/semver.js +12 -0
- package/dist/scripts/akm-migrate-node.js +21653 -5734
- package/dist/scripts/akm-migrate.js +21661 -5742
- package/dist/sources/providers/git-provider.js +2 -4
- package/dist/sources/providers/provider-utils.js +8 -13
- package/dist/sources/snapshot-fetchers/website-ingest.js +6 -7
- package/dist/storage/repositories/events-repository.js +15 -0
- package/dist/storage/repositories/improve-ledger-repository.js +13 -0
- package/dist/storage/repositories/index-entries-repository.js +43 -5
- package/dist/storage/repositories/outcome-repository.js +12 -0
- package/dist/storage/repositories/proposals-repository.js +5 -5
- package/dist/storage/repositories/salience-repository.js +13 -0
- package/dist/storage/repositories/task-history-repository.js +8 -7
- package/dist/storage/repositories/workflow-runs-repository.js +10 -8
- package/dist/tasks/backends/cron.js +19 -0
- package/docs/README.md +24 -60
- package/docs/agents/README.md +3 -8
- package/docs/architecture/README.md +18 -20
- package/docs/architecture/adapters.md +40 -43
- package/docs/architecture/architecture.md +171 -151
- package/docs/architecture/improvement.md +95 -91
- package/docs/architecture/internals/classification.md +101 -119
- package/docs/architecture/internals/fresh-host-rebuild-runbook.md +33 -35
- package/docs/architecture/internals/health-advisories.md +59 -46
- package/docs/architecture/internals/improve-workflow.md +166 -693
- package/docs/architecture/internals/indexing.md +65 -465
- package/docs/architecture/internals/storage-locations.md +301 -848
- package/docs/architecture/persisted-data-compat.md +6 -6
- package/docs/architecture/specs/okf-support.md +67 -95
- package/docs/architecture/specs/ref.md +67 -124
- package/docs/architecture/testing/testing-workflow.md +114 -175
- package/docs/architecture/workflow-engine.md +34 -33
- package/docs/guides/README.md +5 -5
- package/docs/guides/author-bundles.md +72 -98
- package/docs/guides/author-workflows.md +11 -18
- package/docs/guides/bundles.md +91 -123
- package/docs/guides/capture-knowledge.md +10 -9
- package/docs/guides/concepts.md +45 -30
- package/docs/guides/discover-and-load.md +51 -36
- package/docs/guides/getting-started.md +27 -26
- package/docs/guides/improve-the-library.md +98 -80
- package/docs/guides/recipes/headless-install.md +4 -4
- package/docs/guides/recipes/website-source.md +9 -5
- package/docs/guides/run-workflows.md +10 -11
- package/docs/guides/scheduling.md +11 -17
- package/docs/guides/use-with-any-agent.md +15 -11
- package/docs/guides/wikis.md +6 -9
- package/docs/integration/bundling-akm.md +21 -26
- package/docs/maintainers/README.md +2 -2
- package/docs/maintainers/local-development.md +3 -16
- package/docs/maintainers/release-checklist.md +15 -8
- package/docs/migration/README.md +2 -1
- package/docs/migration/release-notes/0.10.0.md +167 -22
- package/docs/migration/release-notes/README.md +2 -2
- package/docs/migration/v0.9-to-v0.10.md +47 -7
- package/docs/product-surface.md +10 -8
- package/docs/reference/README.md +26 -15
- package/docs/reference/asset-types.md +11 -12
- package/docs/reference/bundle-types.md +6 -5
- package/docs/reference/cli.md +74 -31
- package/docs/reference/configuration.md +46 -60
- package/docs/reference/data-and-telemetry.md +204 -421
- package/docs/reference/env-and-secrets.md +80 -83
- package/docs/reference/memory.md +1 -1
- package/docs/reference/refs.md +23 -36
- package/docs/reference/registry.md +138 -348
- package/docs/reference/supported-formats.md +8 -8
- package/docs/reference/tasks.md +13 -19
- package/docs/reference/website-sources.md +23 -15
- package/docs/reference/workflow-schema.md +28 -47
- package/docs/reference/workflows.md +33 -37
- package/package.json +4 -4
- package/schemas/akm-config.json +535 -302
|
@@ -69,20 +69,28 @@ export function insertUsageEventStrict(db, event) {
|
|
|
69
69
|
// ── Query ────────────────────────────────────────────────────────────────────
|
|
70
70
|
/**
|
|
71
71
|
* User feedback counts for many assets at once, keyed by durable `entry_ref`.
|
|
72
|
-
*
|
|
73
|
-
*
|
|
72
|
+
* A negative that carried an exact fix does not count once an accepted
|
|
73
|
+
* `feedback` proposal for the asset exists at or after it (the rule `akm
|
|
74
|
+
* improve` uses for a fix already acted on); reverting that proposal makes it
|
|
75
|
+
* count again. Refs with no user feedback are absent from the map. Read in one
|
|
76
|
+
* query per chunk of refs.
|
|
74
77
|
*/
|
|
75
78
|
export function countFeedbackSignalsByRef(db, refs) {
|
|
76
79
|
const counts = new Map();
|
|
77
80
|
for (let i = 0; i < refs.length; i += SQLITE_CHUNK_SIZE) {
|
|
78
81
|
const chunk = refs.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
79
82
|
const rows = db
|
|
80
|
-
.prepare(`SELECT entry_ref,
|
|
81
|
-
SUM(CASE WHEN signal = 'positive' THEN 1 ELSE 0 END) AS pos,
|
|
82
|
-
SUM(CASE WHEN signal = 'negative'
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
.prepare(`SELECT u.entry_ref,
|
|
84
|
+
SUM(CASE WHEN u.signal = 'positive' THEN 1 ELSE 0 END) AS pos,
|
|
85
|
+
SUM(CASE WHEN u.signal = 'negative' AND NOT (
|
|
86
|
+
json_extract(u.metadata, '$.fix') IS NOT NULL AND EXISTS (
|
|
87
|
+
SELECT 1 FROM proposals p
|
|
88
|
+
WHERE p.ref = u.entry_ref AND p.source = 'feedback' AND p.status = 'accepted'
|
|
89
|
+
AND julianday(p.created_at) >= julianday(u.created_at))
|
|
90
|
+
) THEN 1 ELSE 0 END) AS neg
|
|
91
|
+
FROM usage_events u
|
|
92
|
+
WHERE u.event_type = 'feedback' AND u.source = 'user' AND u.entry_ref IN (${chunk.map(() => "?").join(",")})
|
|
93
|
+
GROUP BY u.entry_ref`)
|
|
86
94
|
.all(...chunk);
|
|
87
95
|
for (const row of rows)
|
|
88
96
|
counts.set(row.entry_ref, { pos: row.pos, neg: row.neg });
|
|
@@ -150,3 +158,17 @@ export function purgeOldUsageEvents(db, retentionDays) {
|
|
|
150
158
|
/* Table may not exist yet */
|
|
151
159
|
}
|
|
152
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Rewrite every `usage_events.entry_ref` naming `oldBundleId` to `newBundleId`
|
|
163
|
+
* (`akm bundle rename`). Search ranking counts feedback by `entry_ref`, so an
|
|
164
|
+
* event left under the old prefix stops counting for the renamed bundle's
|
|
165
|
+
* assets. `entry_id` is untouched: the rename keeps every entry's row id. A
|
|
166
|
+
* legacy unqualified ref is not matched by the `<old>//` prefix and is left alone.
|
|
167
|
+
* Returns the number of rows rewritten.
|
|
168
|
+
*/
|
|
169
|
+
export function renameUsageEventRefs(db, oldBundleId, newBundleId) {
|
|
170
|
+
const prefix = `${oldBundleId}//`;
|
|
171
|
+
return Number(db
|
|
172
|
+
.prepare(`UPDATE usage_events SET entry_ref = ? || substr(entry_ref, length(?) + 1) WHERE substr(entry_ref, 1, length(?)) = ?`)
|
|
173
|
+
.run(newBundleId, oldBundleId, prefix, prefix).changes);
|
|
174
|
+
}
|
|
@@ -112,7 +112,7 @@ function walkStashGit(stashRoot, options) {
|
|
|
112
112
|
? ignoredResult.stdout.toString("utf8")
|
|
113
113
|
: String(ignoredResult.stdout ?? "");
|
|
114
114
|
// Data-hygiene filename skips: the legacy metadata sidecar (never indexed as
|
|
115
|
-
// content
|
|
115
|
+
// content) plus git dot-files.
|
|
116
116
|
const SKIP_FILES = new Set([".stash.json", ".gitignore", ".gitattributes"]);
|
|
117
117
|
const stdout = Buffer.isBuffer(result.stdout) ? result.stdout.toString("utf8") : String(result.stdout ?? "");
|
|
118
118
|
const files = [...stdout.split("\0"), ...ignoredStdout.split("\0")]
|
package/dist/output/renderers.js
CHANGED
|
@@ -217,8 +217,8 @@ const agentMdRenderer = {
|
|
|
217
217
|
},
|
|
218
218
|
};
|
|
219
219
|
// ── 4. knowledge-md ──────────────────────────────────────────────────────────
|
|
220
|
-
const KNOWLEDGE_ACTION = "Reference material - read the content below. For a large document,
|
|
221
|
-
"(
|
|
220
|
+
const KNOWLEDGE_ACTION = "Reference material - read the content below. For a large document, run `akm show <ref> --detail brief` for its " +
|
|
221
|
+
"outline (`toc`, no body), then `akm show <ref>#<slug>` for only the sections you need.";
|
|
222
222
|
const knowledgeMdRenderer = {
|
|
223
223
|
name: "knowledge-md",
|
|
224
224
|
buildShowResponse(ctx) {
|
|
@@ -71,7 +71,7 @@ export function shapeProposalEntry(entry, detail) {
|
|
|
71
71
|
if (detail === "normal") {
|
|
72
72
|
// `confidence` and `gateDecision` (#577) explain why a proposal is pending,
|
|
73
73
|
// so they are projected at `normal` for `akm proposal list/show` when present.
|
|
74
|
-
// `retirement`
|
|
74
|
+
// `retirement` is the same kind of field for a consolidate
|
|
75
75
|
// `retire` proposal: without it, "list/show" carries no reason a reviewer
|
|
76
76
|
// could act on (its `payload.content` is empty by design — a retire
|
|
77
77
|
// proposal deletes, it does not write).
|
|
@@ -278,7 +278,7 @@ export function shapeSearchHit(hit, detail) {
|
|
|
278
278
|
}
|
|
279
279
|
// Stash hit (local or remote)
|
|
280
280
|
// `ref` is included at `brief` so agents can run `akm show <ref>` without
|
|
281
|
-
// needing --detail full or --detail agent
|
|
281
|
+
// needing --detail full or --detail agent.
|
|
282
282
|
if (detail === "brief") {
|
|
283
283
|
return pickFields(hit, ["type", "name", "ref", "action", "estimatedTokens", "keys"]);
|
|
284
284
|
}
|
|
@@ -348,6 +348,7 @@ export function shapeShowOutput(result, detail, shape = "human") {
|
|
|
348
348
|
"editHint",
|
|
349
349
|
"description",
|
|
350
350
|
"action",
|
|
351
|
+
"toc",
|
|
351
352
|
"content",
|
|
352
353
|
"template",
|
|
353
354
|
"prompt",
|
|
@@ -375,12 +376,13 @@ export function shapeShowOutput(result, detail, shape = "human") {
|
|
|
375
376
|
const base = pickFields(result, [
|
|
376
377
|
"type",
|
|
377
378
|
"name",
|
|
378
|
-
// ref is always projected, same as path/editable below
|
|
379
|
+
// ref is always projected, same as path/editable below.
|
|
379
380
|
"ref",
|
|
380
381
|
"origin",
|
|
381
382
|
"action",
|
|
382
383
|
"description",
|
|
383
384
|
"tags",
|
|
385
|
+
"toc",
|
|
384
386
|
"content",
|
|
385
387
|
"template",
|
|
386
388
|
"prompt",
|
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
* events/history, search/curate, and the stash-lifecycle verbs (init,
|
|
8
8
|
* index, list, add, remove, update, upgrade, clone).
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* sibling module: unlike `show`/`workflow`/`proposal` (each a stateful,
|
|
10
|
+
* Unlike `show`/`workflow`/`proposal` (each a stateful,
|
|
12
11
|
* multi-branch renderer with its own module), these are flat
|
|
13
12
|
* field-extraction formatters with no shared state.
|
|
14
13
|
*/
|
|
@@ -308,7 +307,7 @@ export function formatSearchPlain(r, detail) {
|
|
|
308
307
|
if (parts.length > 0)
|
|
309
308
|
lines.push(`timing: ${parts.join(", ")}`);
|
|
310
309
|
}
|
|
311
|
-
//
|
|
310
|
+
// When stash hits exist, tell the agent the next required step so it
|
|
312
311
|
// doesn't skip `akm show` and write from training memory instead.
|
|
313
312
|
if (hits.length >= 1) {
|
|
314
313
|
// Prefer skill/command/agent type hits for the "Next:" ref — knowledge docs are
|
|
@@ -517,7 +516,7 @@ export function formatAddPlain(r) {
|
|
|
517
516
|
// writes a desired locator to config — nothing is synced until a later
|
|
518
517
|
// `akm bundle update`. Force-fitting the declarative shape's `added`/`entry`/`message`
|
|
519
518
|
// fields into the "Installed <ref> (N scanned...)" wording produced
|
|
520
|
-
// "Installed undefined (0 directories scanned...)"
|
|
519
|
+
// "Installed undefined (0 directories scanned...)" because it
|
|
521
520
|
// implied a sync that never happened. `AddResponse` always carries an
|
|
522
521
|
// `index` block (even when zero entries were scanned); `SourceAddResult`
|
|
523
522
|
// never does — that is the reliable shape discriminator used below to
|
|
@@ -630,11 +629,11 @@ export function formatBundleRenamePlain(r) {
|
|
|
630
629
|
return lines.join("\n");
|
|
631
630
|
}
|
|
632
631
|
export function formatUpdatePlain(r) {
|
|
633
|
-
//
|
|
632
|
+
// `processed` alone would conflate three cases into one empty array —
|
|
634
633
|
// a true no-op (--all with nothing configured), a source this call flatly
|
|
635
634
|
// never looked at (a plain source under --all), and a plain git/website
|
|
636
635
|
// source that WAS just synced successfully but has no `UpdateResultItem`
|
|
637
|
-
// shape to report (no version/lock to diff). All three
|
|
636
|
+
// shape to report (no version/lock to diff). All three would render as the
|
|
638
637
|
// same misleading "nothing to update". `plainSynced` and `skipped` (see
|
|
639
638
|
// sources/types.ts) cover the other two so this can report accurately.
|
|
640
639
|
const processed = r.processed;
|
|
@@ -59,6 +59,13 @@ export function formatShowPlain(r, detail) {
|
|
|
59
59
|
if (r.schemaVersion !== undefined)
|
|
60
60
|
lines.push(`schemaVersion: ${String(r.schemaVersion)}`);
|
|
61
61
|
}
|
|
62
|
+
if (Array.isArray(r.toc) && r.toc.length > 0) {
|
|
63
|
+
lines.push("");
|
|
64
|
+
lines.push("toc:");
|
|
65
|
+
for (const heading of r.toc) {
|
|
66
|
+
lines.push(` ${"#".repeat(heading.level)} ${heading.text} (#${heading.slug}, line ${heading.startLine})`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
62
69
|
const links = typeof r.links === "object" && r.links !== null ? r.links : undefined;
|
|
63
70
|
if (links) {
|
|
64
71
|
lines.push("");
|
package/dist/registry/semver.js
CHANGED
|
@@ -41,6 +41,18 @@ export function isSemverRange(input) {
|
|
|
41
41
|
export function maxSatisfying(versions, range) {
|
|
42
42
|
return semver.maxSatisfying(versions, range) ?? undefined;
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Highest of `versions` in semver order, prereleases included (`0.10.1-beta` sorts above `0.9.30`). Invalid entries
|
|
46
|
+
* are ignored; `undefined` when none is valid. Use this to order known versions, not `maxSatisfying(versions, "*")`,
|
|
47
|
+
* which skips every prerelease.
|
|
48
|
+
*/
|
|
49
|
+
export function highestVersion(versions) {
|
|
50
|
+
return semver.rsort(versions.filter((version) => semver.valid(version) !== null))[0];
|
|
51
|
+
}
|
|
52
|
+
/** True when `version` is a valid semver prerelease (`1.2.3-beta`). */
|
|
53
|
+
export function isPrerelease(version) {
|
|
54
|
+
return semver.valid(version) !== null && semver.prerelease(version) !== null;
|
|
55
|
+
}
|
|
44
56
|
/** True when `version` satisfies `range` (both real semver forms). False for an invalid version or range. */
|
|
45
57
|
export function satisfiesRange(version, range) {
|
|
46
58
|
return semver.satisfies(version, range);
|