akm-cli 0.9.0-beta.26 → 0.9.0-beta.28
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 +64 -0
- package/dist/cli.js +2 -0
- package/dist/commands/agent/contribute-cli.js +20 -0
- package/dist/commands/fact/fact-cli.js +155 -0
- package/dist/commands/fact/fact-context.js +149 -0
- package/dist/commands/improve/improve.js +281 -146
- package/dist/commands/lint/fact-linter.js +39 -0
- package/dist/commands/lint/index.js +1 -0
- package/dist/commands/lint/registry.js +2 -0
- package/dist/commands/read/curate.js +50 -1
- package/dist/commands/read/knowledge.js +7 -4
- package/dist/commands/read/show.js +67 -2
- package/dist/core/asset/asset-registry.js +2 -0
- package/dist/core/asset/asset-spec.js +14 -0
- package/dist/core/config/config-schema.js +14 -2
- package/dist/indexer/db/db.js +17 -0
- package/dist/indexer/db/graph-db.js +48 -0
- package/dist/indexer/graph/graph-extraction.js +203 -3
- package/dist/indexer/search/ranking-contributors.js +22 -0
- package/dist/indexer/walk/matchers.js +9 -0
- package/dist/integrations/agent/prompts.js +1 -0
- package/dist/output/renderers.js +73 -1
- package/dist/output/shapes/passthrough.js +3 -0
- package/dist/scripts/migrate-storage.js +88 -4
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +30 -0
- package/package.json +6 -5
package/dist/output/renderers.js
CHANGED
|
@@ -468,6 +468,44 @@ const sessionMdRenderer = {
|
|
|
468
468
|
};
|
|
469
469
|
},
|
|
470
470
|
};
|
|
471
|
+
// ── 9. fact-md ───────────────────────────────────────────────────────────────
|
|
472
|
+
/**
|
|
473
|
+
* Renderer for the `fact` asset type. A fact is durable stash-level semantic
|
|
474
|
+
* knowledge (personal/team/project details, coding conventions, stash-meta).
|
|
475
|
+
* It carries `category` (personal|team|project|convention|meta) and an
|
|
476
|
+
* optional `pinned` flag marking it as part of the always-injected core. The
|
|
477
|
+
* renderer surfaces a one-liner (category + pinned marker) so an agent can tell
|
|
478
|
+
* at a glance what kind of fact it is and whether it is core context.
|
|
479
|
+
*/
|
|
480
|
+
const factMdRenderer = {
|
|
481
|
+
name: "fact-md",
|
|
482
|
+
buildShowResponse(ctx) {
|
|
483
|
+
const name = deriveName(ctx);
|
|
484
|
+
const parsed = parseFrontmatter(ctx.content());
|
|
485
|
+
const fm = parsed.data;
|
|
486
|
+
const category = asNonEmptyString(fm.category);
|
|
487
|
+
const description = asNonEmptyString(fm.description);
|
|
488
|
+
const pinned = fm.pinned === true;
|
|
489
|
+
const headerParts = [
|
|
490
|
+
category ? `category: ${category}` : undefined,
|
|
491
|
+
pinned ? "pinned (core context)" : undefined,
|
|
492
|
+
].filter((p) => !!p);
|
|
493
|
+
const action = [
|
|
494
|
+
"Durable stash fact — apply it as background context.",
|
|
495
|
+
headerParts.length > 0 ? headerParts.join(" ") : undefined,
|
|
496
|
+
]
|
|
497
|
+
.filter((p) => !!p)
|
|
498
|
+
.join("\n");
|
|
499
|
+
return {
|
|
500
|
+
type: "fact",
|
|
501
|
+
name,
|
|
502
|
+
path: ctx.absPath,
|
|
503
|
+
action,
|
|
504
|
+
description,
|
|
505
|
+
content: parsed.content,
|
|
506
|
+
};
|
|
507
|
+
},
|
|
508
|
+
};
|
|
471
509
|
function applySessionMetadata(entry, ctx) {
|
|
472
510
|
try {
|
|
473
511
|
const fm = applyFrontmatterDescriptionAndTags(entry, ctx);
|
|
@@ -501,6 +539,34 @@ function applyTocMetadata(entry, ctx) {
|
|
|
501
539
|
// Non-fatal: skip TOC if file can't be read
|
|
502
540
|
}
|
|
503
541
|
}
|
|
542
|
+
/**
|
|
543
|
+
* Fact metadata: surface `category` and the `pinned` core marker as tags +
|
|
544
|
+
* search hints (no dedicated DB columns — same encoding pattern as session /
|
|
545
|
+
* task). `pinned` is mirrored to both a `pinned` tag and a `pinned` search
|
|
546
|
+
* hint so the ranking contributor can detect it and queries can target it.
|
|
547
|
+
*/
|
|
548
|
+
function applyFactMetadata(entry, ctx) {
|
|
549
|
+
try {
|
|
550
|
+
const fm = applyFrontmatterDescriptionAndTags(entry, ctx);
|
|
551
|
+
const tags = new Set([...(entry.tags ?? []), "fact"]);
|
|
552
|
+
const hints = new Set(entry.searchHints ?? []);
|
|
553
|
+
const category = asNonEmptyString(fm.category);
|
|
554
|
+
if (category) {
|
|
555
|
+
tags.add(category);
|
|
556
|
+
hints.add(`category:${category}`);
|
|
557
|
+
}
|
|
558
|
+
if (fm.pinned === true) {
|
|
559
|
+
tags.add("pinned");
|
|
560
|
+
hints.add("pinned");
|
|
561
|
+
}
|
|
562
|
+
entry.tags = Array.from(tags).filter(Boolean);
|
|
563
|
+
if (hints.size > 0)
|
|
564
|
+
entry.searchHints = Array.from(hints).filter(Boolean);
|
|
565
|
+
}
|
|
566
|
+
catch {
|
|
567
|
+
// Non-fatal: skip metadata extraction on parse error
|
|
568
|
+
}
|
|
569
|
+
}
|
|
504
570
|
/**
|
|
505
571
|
* Parse frontmatter, apply description (if not already set) and merge tags
|
|
506
572
|
* into `entry`. Returns the raw frontmatter data object so callers can access
|
|
@@ -660,6 +726,11 @@ registerMetadataContributor({
|
|
|
660
726
|
appliesTo: ({ rendererName }) => rendererName === "session-md",
|
|
661
727
|
contribute: (entry, ctx) => applySessionMetadata(entry, ctx.renderContext),
|
|
662
728
|
});
|
|
729
|
+
registerMetadataContributor({
|
|
730
|
+
name: "fact-md-metadata",
|
|
731
|
+
appliesTo: ({ rendererName }) => rendererName === "fact-md",
|
|
732
|
+
contribute: (entry, ctx) => applyFactMetadata(entry, ctx.renderContext),
|
|
733
|
+
});
|
|
663
734
|
// ── Registration ─────────────────────────────────────────────────────────────
|
|
664
735
|
/** All built-in renderers. */
|
|
665
736
|
const builtinRenderers = [
|
|
@@ -676,6 +747,7 @@ const builtinRenderers = [
|
|
|
676
747
|
secretFileRenderer,
|
|
677
748
|
taskMdRenderer,
|
|
678
749
|
sessionMdRenderer,
|
|
750
|
+
factMdRenderer,
|
|
679
751
|
];
|
|
680
752
|
/**
|
|
681
753
|
* Register all built-in renderers with the file-context registry.
|
|
@@ -687,4 +759,4 @@ export function registerBuiltinRenderers() {
|
|
|
687
759
|
}
|
|
688
760
|
}
|
|
689
761
|
// ── Named exports for testing ────────────────────────────────────────────────
|
|
690
|
-
export { agentMdRenderer, commandMdRenderer, envFileRenderer, INTERPRETER_MAP, knowledgeMdRenderer, lessonMdRenderer, memoryMdRenderer, SETUP_SIGNALS, scriptSourceRenderer, secretFileRenderer, skillMdRenderer, wikiMdRenderer, workflowMdRenderer, };
|
|
762
|
+
export { agentMdRenderer, commandMdRenderer, envFileRenderer, factMdRenderer, INTERPRETER_MAP, knowledgeMdRenderer, lessonMdRenderer, memoryMdRenderer, SETUP_SIGNALS, scriptSourceRenderer, secretFileRenderer, skillMdRenderer, wikiMdRenderer, workflowMdRenderer, };
|
|
@@ -8240,6 +8240,25 @@ function applyTocMetadata(entry, ctx) {
|
|
|
8240
8240
|
entry.toc = toc.headings;
|
|
8241
8241
|
} catch {}
|
|
8242
8242
|
}
|
|
8243
|
+
function applyFactMetadata(entry, ctx) {
|
|
8244
|
+
try {
|
|
8245
|
+
const fm = applyFrontmatterDescriptionAndTags(entry, ctx);
|
|
8246
|
+
const tags = new Set([...entry.tags ?? [], "fact"]);
|
|
8247
|
+
const hints = new Set(entry.searchHints ?? []);
|
|
8248
|
+
const category = asNonEmptyString(fm.category);
|
|
8249
|
+
if (category) {
|
|
8250
|
+
tags.add(category);
|
|
8251
|
+
hints.add(`category:${category}`);
|
|
8252
|
+
}
|
|
8253
|
+
if (fm.pinned === true) {
|
|
8254
|
+
tags.add("pinned");
|
|
8255
|
+
hints.add("pinned");
|
|
8256
|
+
}
|
|
8257
|
+
entry.tags = Array.from(tags).filter(Boolean);
|
|
8258
|
+
if (hints.size > 0)
|
|
8259
|
+
entry.searchHints = Array.from(hints).filter(Boolean);
|
|
8260
|
+
} catch {}
|
|
8261
|
+
}
|
|
8243
8262
|
function applyFrontmatterDescriptionAndTags(entry, ctx) {
|
|
8244
8263
|
const parsed = parseFrontmatter(ctx.content());
|
|
8245
8264
|
const fm = parsed.data;
|
|
@@ -8386,6 +8405,11 @@ var init_renderers = __esm(() => {
|
|
|
8386
8405
|
appliesTo: ({ rendererName }) => rendererName === "session-md",
|
|
8387
8406
|
contribute: (entry, ctx) => applySessionMetadata(entry, ctx.renderContext)
|
|
8388
8407
|
});
|
|
8408
|
+
registerMetadataContributor({
|
|
8409
|
+
name: "fact-md-metadata",
|
|
8410
|
+
appliesTo: ({ rendererName }) => rendererName === "fact-md",
|
|
8411
|
+
contribute: (entry, ctx) => applyFactMetadata(entry, ctx.renderContext)
|
|
8412
|
+
});
|
|
8389
8413
|
});
|
|
8390
8414
|
|
|
8391
8415
|
// src/core/asset/asset-registry.ts
|
|
@@ -8520,6 +8544,12 @@ var init_asset_spec = __esm(() => {
|
|
|
8520
8544
|
...markdownSpec,
|
|
8521
8545
|
rendererName: "session-md",
|
|
8522
8546
|
actionBuilder: (ref) => `akm show ${ref} -> read the session summary; follow the \`access\` frontmatter to open the raw log at \`log_path\``
|
|
8547
|
+
},
|
|
8548
|
+
fact: {
|
|
8549
|
+
stashDir: "facts",
|
|
8550
|
+
...markdownSpec,
|
|
8551
|
+
rendererName: "fact-md",
|
|
8552
|
+
actionBuilder: (ref) => `akm show ${ref} -> read the stash fact and apply it as durable context`
|
|
8523
8553
|
}
|
|
8524
8554
|
};
|
|
8525
8555
|
TYPE_DIRS = Object.fromEntries(Object.entries(ASSET_SPECS_INTERNAL).map(([type, spec]) => [type, spec.stashDir]));
|
|
@@ -15822,6 +15852,7 @@ var init_config_schema = __esm(() => {
|
|
|
15822
15852
|
requirePlannedRefs: exports_external.boolean().optional(),
|
|
15823
15853
|
dueDays: exports_external.number().int().min(0).optional(),
|
|
15824
15854
|
maxPerRun: positiveInt.optional(),
|
|
15855
|
+
topN: positiveInt.optional(),
|
|
15825
15856
|
minPendingCount: exports_external.number().int().min(0).optional(),
|
|
15826
15857
|
minNewSessions: exports_external.number().int().min(0).optional(),
|
|
15827
15858
|
maxSessionsPerRun: exports_external.number().int().min(0).optional(),
|
|
@@ -15920,6 +15951,7 @@ var init_config_schema = __esm(() => {
|
|
|
15920
15951
|
processes: ImproveProfileProcessesSchema.optional(),
|
|
15921
15952
|
autoAccept: nonNegativeNumber.optional(),
|
|
15922
15953
|
limit: positiveInt.optional(),
|
|
15954
|
+
maxCycles: positiveInt.optional(),
|
|
15923
15955
|
symmetricValence: exports_external.boolean().optional(),
|
|
15924
15956
|
sync: exports_external.object({
|
|
15925
15957
|
enabled: exports_external.boolean().optional(),
|
|
@@ -16046,7 +16078,8 @@ var init_config_schema = __esm(() => {
|
|
|
16046
16078
|
"workflow",
|
|
16047
16079
|
"lesson",
|
|
16048
16080
|
"task",
|
|
16049
|
-
"wiki"
|
|
16081
|
+
"wiki",
|
|
16082
|
+
"fact"
|
|
16050
16083
|
];
|
|
16051
16084
|
INDEX_PASS_PROVIDER_KEYS = new Set([
|
|
16052
16085
|
"endpoint",
|
|
@@ -16062,7 +16095,8 @@ var init_config_schema = __esm(() => {
|
|
|
16062
16095
|
"llm",
|
|
16063
16096
|
"graphExtractionBatchSize",
|
|
16064
16097
|
"graphExtractionIncludeTypes",
|
|
16065
|
-
"memoryInferenceBatchSize"
|
|
16098
|
+
"memoryInferenceBatchSize",
|
|
16099
|
+
"lazyGraphExtraction"
|
|
16066
16100
|
]);
|
|
16067
16101
|
IndexPassConfigSchema = exports_external.preprocess((raw, ctx) => {
|
|
16068
16102
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
@@ -16080,7 +16114,7 @@ var init_config_schema = __esm(() => {
|
|
|
16080
16114
|
if (!INDEX_PASS_KNOWN_KEYS.has(key)) {
|
|
16081
16115
|
ctx.addIssue({
|
|
16082
16116
|
code: exports_external.ZodIssueCode.custom,
|
|
16083
|
-
message: `Unknown key \`${[...ctx.path ?? [], key].join(".")}\`. Per-pass entries support \`llm\` ` + "(boolean opt-out), `graphExtractionBatchSize`, `graphExtractionIncludeTypes`,
|
|
16117
|
+
message: `Unknown key \`${[...ctx.path ?? [], key].join(".")}\`. Per-pass entries support \`llm\` ` + "(boolean opt-out), `graphExtractionBatchSize`, `graphExtractionIncludeTypes`, " + "`memoryInferenceBatchSize`, and `lazyGraphExtraction`."
|
|
16084
16118
|
});
|
|
16085
16119
|
return raw;
|
|
16086
16120
|
}
|
|
@@ -16097,7 +16131,8 @@ var init_config_schema = __esm(() => {
|
|
|
16097
16131
|
llm: exports_external.boolean().optional(),
|
|
16098
16132
|
graphExtractionBatchSize: positiveInt.optional(),
|
|
16099
16133
|
graphExtractionIncludeTypes: exports_external.array(exports_external.enum(GRAPH_EXTRACTION_INCLUDE_TYPES_ALLOWED)).nonempty().optional(),
|
|
16100
|
-
memoryInferenceBatchSize: positiveInt.optional()
|
|
16134
|
+
memoryInferenceBatchSize: positiveInt.optional(),
|
|
16135
|
+
lazyGraphExtraction: exports_external.boolean().optional()
|
|
16101
16136
|
}).passthrough());
|
|
16102
16137
|
MetadataEnhanceSchema = exports_external.object({ enabled: exports_external.boolean().optional() }).strict();
|
|
16103
16138
|
StalenessDetectionSchema = exports_external.object({
|
|
@@ -16968,6 +17003,22 @@ function ensureSchema(db, embeddingDim, options) {
|
|
|
16968
17003
|
FOREIGN KEY (stash_root, file_path, body_hash)
|
|
16969
17004
|
REFERENCES graph_files(stash_root, file_path, body_hash) ON DELETE CASCADE
|
|
16970
17005
|
);
|
|
17006
|
+
|
|
17007
|
+
-- #624-P3: lazy graph-extraction queue. Standalone table (NO FK to
|
|
17008
|
+
-- graph_files \u2014 a queued file by definition has no graph row yet).
|
|
17009
|
+
-- Idempotent on (stash_root, file_path); drained highest-priority-first.
|
|
17010
|
+
-- CREATE TABLE IF NOT EXISTS is the forward migration (no DB_VERSION bump).
|
|
17011
|
+
CREATE TABLE IF NOT EXISTS graph_extraction_queue (
|
|
17012
|
+
stash_root TEXT NOT NULL,
|
|
17013
|
+
file_path TEXT NOT NULL,
|
|
17014
|
+
body_hash TEXT NOT NULL,
|
|
17015
|
+
queued_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
17016
|
+
priority INTEGER NOT NULL DEFAULT 0,
|
|
17017
|
+
PRIMARY KEY (stash_root, file_path)
|
|
17018
|
+
);
|
|
17019
|
+
|
|
17020
|
+
CREATE INDEX IF NOT EXISTS idx_graph_extraction_queue_drain
|
|
17021
|
+
ON graph_extraction_queue(stash_root, priority DESC, queued_at);
|
|
16971
17022
|
`);
|
|
16972
17023
|
migrateGraphDataFromLegacy(db);
|
|
16973
17024
|
db.exec(`
|
|
@@ -17035,6 +17086,7 @@ function handleVersionUpgrade(db) {
|
|
|
17035
17086
|
db.exec("DROP TABLE IF EXISTS index_dir_state");
|
|
17036
17087
|
db.exec("DROP TABLE IF EXISTS llm_enrichment_cache");
|
|
17037
17088
|
db.exec("DROP INDEX IF EXISTS idx_llm_cache_updated");
|
|
17089
|
+
db.exec("DROP TABLE IF EXISTS graph_extraction_queue");
|
|
17038
17090
|
db.exec("DROP TABLE IF EXISTS graph_file_relations");
|
|
17039
17091
|
db.exec("DROP TABLE IF EXISTS graph_file_entities");
|
|
17040
17092
|
db.exec("DROP TABLE IF EXISTS graph_files");
|
|
@@ -18058,6 +18110,8 @@ __export(exports_graph_db, {
|
|
|
18058
18110
|
loadGraphFilesOnly: () => loadGraphFilesOnly,
|
|
18059
18111
|
loadGraphEntitiesByPath: () => loadGraphEntitiesByPath,
|
|
18060
18112
|
hasGraphData: () => hasGraphData,
|
|
18113
|
+
enqueueGraphExtraction: () => enqueueGraphExtraction,
|
|
18114
|
+
drainExtractionQueue: () => drainExtractionQueue,
|
|
18061
18115
|
deleteStoredGraph: () => deleteStoredGraph
|
|
18062
18116
|
});
|
|
18063
18117
|
import fs13 from "fs";
|
|
@@ -18187,6 +18241,36 @@ function hasGraphData(db, stashRoot, filePath) {
|
|
|
18187
18241
|
return false;
|
|
18188
18242
|
}
|
|
18189
18243
|
}
|
|
18244
|
+
function enqueueGraphExtraction(db, stashRoot, filePath, bodyHash, priority = 0) {
|
|
18245
|
+
try {
|
|
18246
|
+
db.prepare(`INSERT INTO graph_extraction_queue (stash_root, file_path, body_hash, priority)
|
|
18247
|
+
VALUES (?, ?, ?, ?)
|
|
18248
|
+
ON CONFLICT(stash_root, file_path) DO UPDATE SET
|
|
18249
|
+
body_hash = excluded.body_hash,
|
|
18250
|
+
priority = MAX(graph_extraction_queue.priority, excluded.priority),
|
|
18251
|
+
queued_at = datetime('now')`).run(stashRoot, filePath, bodyHash, priority);
|
|
18252
|
+
} catch (err) {
|
|
18253
|
+
rethrowIfTestIsolationError(err);
|
|
18254
|
+
}
|
|
18255
|
+
}
|
|
18256
|
+
function drainExtractionQueue(db, stashRoot, limit) {
|
|
18257
|
+
try {
|
|
18258
|
+
return db.transaction(() => {
|
|
18259
|
+
const rows = db.prepare(`SELECT file_path, body_hash, priority
|
|
18260
|
+
FROM graph_extraction_queue
|
|
18261
|
+
WHERE stash_root = ?
|
|
18262
|
+
ORDER BY priority DESC, queued_at ASC
|
|
18263
|
+
LIMIT ?`).all(stashRoot, limit);
|
|
18264
|
+
const del = db.prepare("DELETE FROM graph_extraction_queue WHERE stash_root = ? AND file_path = ?");
|
|
18265
|
+
for (const row of rows)
|
|
18266
|
+
del.run(stashRoot, row.file_path);
|
|
18267
|
+
return rows.map((row) => ({ filePath: row.file_path, bodyHash: row.body_hash, priority: row.priority }));
|
|
18268
|
+
})();
|
|
18269
|
+
} catch (err) {
|
|
18270
|
+
rethrowIfTestIsolationError(err);
|
|
18271
|
+
return [];
|
|
18272
|
+
}
|
|
18273
|
+
}
|
|
18190
18274
|
function loadGraphMetaOnly(stashPath, db) {
|
|
18191
18275
|
return loadStoredGraphMeta(stashPath, db);
|
|
18192
18276
|
}
|
|
@@ -8126,6 +8126,25 @@ function applyTocMetadata(entry, ctx) {
|
|
|
8126
8126
|
entry.toc = toc.headings;
|
|
8127
8127
|
} catch {}
|
|
8128
8128
|
}
|
|
8129
|
+
function applyFactMetadata(entry, ctx) {
|
|
8130
|
+
try {
|
|
8131
|
+
const fm = applyFrontmatterDescriptionAndTags(entry, ctx);
|
|
8132
|
+
const tags = new Set([...entry.tags ?? [], "fact"]);
|
|
8133
|
+
const hints = new Set(entry.searchHints ?? []);
|
|
8134
|
+
const category = asNonEmptyString(fm.category);
|
|
8135
|
+
if (category) {
|
|
8136
|
+
tags.add(category);
|
|
8137
|
+
hints.add(`category:${category}`);
|
|
8138
|
+
}
|
|
8139
|
+
if (fm.pinned === true) {
|
|
8140
|
+
tags.add("pinned");
|
|
8141
|
+
hints.add("pinned");
|
|
8142
|
+
}
|
|
8143
|
+
entry.tags = Array.from(tags).filter(Boolean);
|
|
8144
|
+
if (hints.size > 0)
|
|
8145
|
+
entry.searchHints = Array.from(hints).filter(Boolean);
|
|
8146
|
+
} catch {}
|
|
8147
|
+
}
|
|
8129
8148
|
function applyFrontmatterDescriptionAndTags(entry, ctx) {
|
|
8130
8149
|
const parsed = parseFrontmatter(ctx.content());
|
|
8131
8150
|
const fm = parsed.data;
|
|
@@ -8272,6 +8291,11 @@ var init_renderers = __esm(() => {
|
|
|
8272
8291
|
appliesTo: ({ rendererName }) => rendererName === "session-md",
|
|
8273
8292
|
contribute: (entry, ctx) => applySessionMetadata(entry, ctx.renderContext)
|
|
8274
8293
|
});
|
|
8294
|
+
registerMetadataContributor({
|
|
8295
|
+
name: "fact-md-metadata",
|
|
8296
|
+
appliesTo: ({ rendererName }) => rendererName === "fact-md",
|
|
8297
|
+
contribute: (entry, ctx) => applyFactMetadata(entry, ctx.renderContext)
|
|
8298
|
+
});
|
|
8275
8299
|
});
|
|
8276
8300
|
|
|
8277
8301
|
// src/core/asset/asset-registry.ts
|
|
@@ -8406,6 +8430,12 @@ var init_asset_spec = __esm(() => {
|
|
|
8406
8430
|
...markdownSpec,
|
|
8407
8431
|
rendererName: "session-md",
|
|
8408
8432
|
actionBuilder: (ref) => `akm show ${ref} -> read the session summary; follow the \`access\` frontmatter to open the raw log at \`log_path\``
|
|
8433
|
+
},
|
|
8434
|
+
fact: {
|
|
8435
|
+
stashDir: "facts",
|
|
8436
|
+
...markdownSpec,
|
|
8437
|
+
rendererName: "fact-md",
|
|
8438
|
+
actionBuilder: (ref) => `akm show ${ref} -> read the stash fact and apply it as durable context`
|
|
8409
8439
|
}
|
|
8410
8440
|
};
|
|
8411
8441
|
TYPE_DIRS = Object.fromEntries(Object.entries(ASSET_SPECS_INTERNAL).map(([type, spec]) => [type, spec.stashDir]));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akm-cli",
|
|
3
|
-
"version": "0.9.0-beta.
|
|
3
|
+
"version": "0.9.0-beta.28",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "akm (Agent Knowledge Management) — A package manager for AI agent skills, commands, tools, and knowledge. Works with Claude Code, OpenCode, Cursor, and any AI coding assistant.",
|
|
6
6
|
"keywords": [
|
|
@@ -56,12 +56,13 @@
|
|
|
56
56
|
"check:fast": "bun run lint && bunx tsc --noEmit && bun run test:unit",
|
|
57
57
|
"check:changed": "bun test tests/output-baseline.test.ts tests/integration/e2e.test.ts tests/stash-search.test.ts && bun run lint && bunx tsc --noEmit",
|
|
58
58
|
"sweep:tmp": "bun scripts/sweep-test-tmp.ts",
|
|
59
|
-
"test": "bun run sweep:tmp && bun test --parallel=${TEST_PARALLEL:-
|
|
60
|
-
"test:unit": "bun run sweep:tmp && bun test --parallel=${TEST_PARALLEL:-
|
|
61
|
-
"test:integration": "bun run sweep:tmp && bun test --parallel=${TEST_PARALLEL:-
|
|
59
|
+
"test": "bun run sweep:tmp && bun test --parallel=${TEST_PARALLEL:-1} --timeout=30000 ./tests --path-ignore-patterns=tests/integration",
|
|
60
|
+
"test:unit": "bun run sweep:tmp && bun test --parallel=${TEST_PARALLEL:-1} --timeout=30000 ./tests --path-ignore-patterns=tests/integration",
|
|
61
|
+
"test:integration": "bun run sweep:tmp && bun test --parallel=${TEST_PARALLEL:-1} --timeout=30000 ./tests/integration ./tests/commands ./tests/workflows",
|
|
62
|
+
"test:unit:shard": "bun run sweep:tmp && bun test --parallel=1 --timeout=30000 ./tests --path-ignore-patterns=tests/integration --shard=${SHARD:?set SHARD=k/N}",
|
|
63
|
+
"test:integration:shard": "bun run sweep:tmp && bun test --parallel=1 --timeout=30000 ./tests/integration ./tests/commands ./tests/workflows --shard=${SHARD:?set SHARD=k/N}",
|
|
62
64
|
"test:node-smoke": "bun scripts/node-smoke.ts",
|
|
63
65
|
"test:node-compat": "AKM_NODE_COMPAT_TESTS=1 bun test --timeout=120000 tests/integration/node-compat.test.ts",
|
|
64
|
-
"test:sharded": "bun test ./tests --shard=1/4 & bun test ./tests --shard=2/4 & bun test ./tests --shard=3/4 & bun test ./tests --shard=4/4 & wait",
|
|
65
66
|
"test:time": "bun scripts/test-timing-report.ts",
|
|
66
67
|
"lint:isolation": "bun scripts/lint-tests-isolation.ts",
|
|
67
68
|
"lint:devto-posts": "bun scripts/lint-devto-posts.ts",
|