akm-cli 0.9.17-alpha.7 → 0.9.17-alpha.9
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 +473 -0
- package/STABILITY.md +9 -8
- package/dist/akm +55 -22
- package/dist/akm-migrate +38 -19
- package/dist/assets/hints/cli-hints-full.md +6 -7
- package/dist/assets/improve-strategies/catchup.json +0 -3
- package/dist/assets/improve-strategies/consolidate.json +0 -1
- package/dist/assets/improve-strategies/default.json +1 -2
- package/dist/assets/improve-strategies/proactive-maintenance.json +1 -2
- package/dist/assets/improve-strategies/quick.json +1 -2
- package/dist/assets/improve-strategies/reflect-distill.json +1 -2
- package/dist/assets/improve-strategies/thorough.json +0 -3
- package/dist/assets/prompts/consolidate-pair.md +20 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
- package/dist/assets/templates/html/health.html +3 -5
- package/dist/cli/retired-commands.js +1 -1
- package/dist/commands/health/archive-usage.js +98 -0
- package/dist/commands/health/data-dir-usage.js +25 -13
- package/dist/commands/health/html-report.js +1 -4
- package/dist/commands/health/improve-metrics.js +0 -25
- package/dist/commands/health/md-report.js +1 -6
- package/dist/commands/health/report-view-model.js +4 -14
- package/dist/commands/health/windows.js +0 -1
- package/dist/commands/health.js +13 -0
- package/dist/commands/improve/consolidate/continuity-check.js +137 -0
- package/dist/commands/improve/consolidate/pair-pass.js +791 -0
- package/dist/commands/improve/consolidate.js +38 -63
- package/dist/commands/improve/extract-prompt.js +1 -2
- package/dist/commands/improve/improve-cli.js +1 -1
- package/dist/commands/improve/improve-strategies.js +23 -5
- package/dist/commands/improve/improve.js +19 -30
- package/dist/commands/improve/ledger.js +3 -2
- package/dist/commands/improve/loop-stages.js +5 -84
- package/dist/commands/improve/memory/memory-belief.js +3 -1
- package/dist/commands/improve/memory/memory-improve.js +269 -11
- package/dist/commands/improve/planner.js +0 -5
- package/dist/commands/improve/preparation.js +20 -135
- package/dist/commands/improve/retrieval-scope.js +19 -4
- package/dist/commands/improve/salience.js +1 -14
- package/dist/commands/improve/stage.js +0 -1
- package/dist/commands/lint/base-linter.js +19 -11
- package/dist/commands/proposal/drain.js +8 -1
- package/dist/commands/proposal/proposal-cli.js +16 -2
- package/dist/commands/proposal/proposal-types.js +7 -0
- package/dist/commands/proposal/proposal.js +37 -6
- package/dist/commands/proposal/repository.js +613 -4
- package/dist/commands/proposal/validators/proposals.js +9 -0
- package/dist/commands/read/curate.js +40 -13
- package/dist/commands/read/knowledge.js +3 -2
- package/dist/commands/read/show.js +55 -16
- package/dist/commands/sources/info.js +3 -0
- package/dist/commands/sources/stash-cli.js +2 -2
- package/dist/core/adapter/adapters/akm-adapter.js +2 -0
- package/dist/core/adapter/adapters/akm-metadata.js +31 -0
- package/dist/core/bundle-rename.js +1 -7
- package/dist/core/config/config-schema.js +8 -1
- package/dist/core/config/config.js +23 -48
- package/dist/core/config/engine-semantics.js +0 -2
- package/dist/core/config/schema/improve-processes.js +17 -42
- package/dist/core/config/schema/index-config.js +5 -25
- package/dist/core/file-change.js +13 -5
- package/dist/core/improve-result.js +16 -5
- package/dist/core/improve-types.js +0 -1
- package/dist/core/loopback.js +7 -12
- package/dist/core/parse.js +13 -16
- package/dist/core/state/migrations.js +15 -0
- package/dist/core/time.js +0 -20
- package/dist/indexer/db/llm-cache.js +2 -2
- package/dist/indexer/ensure-index.js +2 -2
- package/dist/indexer/index-written-assets.js +2 -3
- package/dist/indexer/indexer.js +18 -418
- package/dist/indexer/links/declared-links.js +90 -0
- package/dist/indexer/passes/metadata.js +0 -19
- package/dist/indexer/scan/doc-to-entry.js +1 -0
- package/dist/indexer/walk/walker.js +3 -4
- package/dist/llm/client.js +8 -10
- package/dist/llm/embedders/remote.js +1 -2
- package/dist/llm/feature-gate.js +0 -5
- package/dist/output/shapes/helpers.js +23 -4
- package/dist/output/text/command-format.js +0 -8
- package/dist/output/text/proposal-format.js +47 -1
- package/dist/output/text/show-format.js +13 -17
- package/dist/scripts/akm-migrate-node.js +2754 -2836
- package/dist/scripts/akm-migrate.js +2754 -2836
- package/dist/setup/steps/connection.js +5 -6
- package/dist/setup/steps/platforms.js +2 -2
- package/dist/sources/providers/git-stash.js +55 -4
- package/dist/storage/repositories/improve-ledger-repository.js +48 -7
- package/dist/storage/repositories/index-entries-repository.js +16 -13
- package/dist/storage/repositories/index-entry-schema.js +22 -3
- package/dist/storage/repositories/index-links-repository.js +143 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +7 -26
- package/dist/storage/repositories/index-schema.js +82 -104
- package/dist/storage/repositories/proposals-repository.js +61 -0
- package/dist/storage/repositories/salience-repository.js +1 -19
- package/dist/tasks/source/task-to-v4.js +462 -74
- package/docs/migration/release-notes/0.9.17.md +7 -5
- package/docs/reference/cli.md +33 -21
- package/docs/reference/configuration.md +21 -12
- package/docs/reference/data-and-telemetry.md +0 -1
- package/package.json +1 -1
- package/schemas/akm-config.json +0 -342
- package/dist/assets/improve-strategies/graph-refresh.json +0 -15
- package/dist/assets/prompts/contradiction-judge.md +0 -33
- package/dist/assets/prompts/graph-extract-system.md +0 -1
- package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
- package/dist/assets/prompts/metadata-enhance-system.md +0 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
- package/dist/indexer/db/graph-db.js +0 -431
- package/dist/indexer/graph/graph-extraction.js +0 -807
- package/dist/indexer/graph/graph-related.js +0 -131
- package/dist/indexer/graph/graph-types.js +0 -4
- package/dist/llm/graph-extract.js +0 -903
- package/dist/llm/metadata-enhance.js +0 -95
- package/dist/tasks/source/task-to-v3.js +0 -453
|
@@ -4,12 +4,21 @@
|
|
|
4
4
|
/** Proposal validation and the one content repair applied before promotion. */
|
|
5
5
|
import { repairTruncatedDescription } from "../../../core/text-truncation.js";
|
|
6
6
|
import { splitFrontmatter } from "../../improve/reflect-noise.js";
|
|
7
|
+
import { isRetireProposal } from "../proposal-types.js";
|
|
7
8
|
import { runProposalValidators } from "./proposal-validators.js";
|
|
8
9
|
/**
|
|
9
10
|
* Validate a proposal before promotion: it must parse and carry a body, and a
|
|
10
11
|
* type with a canonical validator runs it.
|
|
12
|
+
*
|
|
13
|
+
* A retire proposal (alpha.9 consolidate pair pass) writes no new content —
|
|
14
|
+
* it deletes an asset that already passed validation when IT was created —
|
|
15
|
+
* so the content-quality validators (built for new/updated bodies: a
|
|
16
|
+
* description, lesson shape, reflect size ratio, …) do not apply and are
|
|
17
|
+
* skipped entirely rather than misreading the empty body as a defect.
|
|
11
18
|
*/
|
|
12
19
|
export function validateProposal(proposal) {
|
|
20
|
+
if (isRetireProposal(proposal))
|
|
21
|
+
return { ok: true, findings: [] };
|
|
13
22
|
return runProposalValidators(proposal);
|
|
14
23
|
}
|
|
15
24
|
/**
|
|
@@ -9,12 +9,15 @@
|
|
|
9
9
|
* needed to act (ref, run, parameters, follow-up command).
|
|
10
10
|
*
|
|
11
11
|
* Curation is one search with the fused ranking, the top `limit` hits, and
|
|
12
|
-
* per-hit enrichment (preview, run and parameters,
|
|
13
|
-
* optional reranker reorders the top fused
|
|
12
|
+
* per-hit enrichment (preview, run and parameters, support refs from the
|
|
13
|
+
* hit's declared links). An optional reranker reorders the top fused
|
|
14
|
+
* candidates first.
|
|
14
15
|
*
|
|
15
16
|
* The exported `akmCurate()` API is the single entry point; tests can also
|
|
16
17
|
* drive `curateSearchResults` with a fixture search response.
|
|
17
18
|
*/
|
|
19
|
+
import { parseBundleRef } from "../../core/asset/asset-ref.js";
|
|
20
|
+
import { typeNameFromConceptId } from "../../core/asset/resolve-ref.js";
|
|
18
21
|
import { loadConfig } from "../../core/config/config.js";
|
|
19
22
|
import { rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
|
|
20
23
|
import { appendEvent } from "../../core/events.js";
|
|
@@ -212,7 +215,7 @@ async function enrichCuratedStashHit(query, hit, selectedRefs, eventSource) {
|
|
|
212
215
|
}
|
|
213
216
|
const description = shown?.description ?? hit.description;
|
|
214
217
|
const preview = buildCuratedPreview(shown, hit);
|
|
215
|
-
const supportRefs = buildCurateSupportRefs(shown?.
|
|
218
|
+
const supportRefs = buildCurateSupportRefs(shown?.links, selectedRefs, hit.ref);
|
|
216
219
|
const item = {
|
|
217
220
|
source: "local",
|
|
218
221
|
type: shown?.type ?? hit.type,
|
|
@@ -324,17 +327,41 @@ async function maybeRerankCuratedStashHits(query, hits) {
|
|
|
324
327
|
function rerankDocumentTexts(hits) {
|
|
325
328
|
return hits.map((hit) => [hit.name, hit.description, searchHitContent(hit)].filter(Boolean).join("\n").slice(0, RERANK_DOCUMENT_CHARS));
|
|
326
329
|
}
|
|
327
|
-
/**
|
|
328
|
-
|
|
330
|
+
/**
|
|
331
|
+
* Up to {@link MAX_CURATE_SUPPORT_REFS} assets the hit's declared links (#935)
|
|
332
|
+
* name, not already selected: what the hit links to first, then what links to
|
|
333
|
+
* it, in the order `akm show` lists them. The LLM entity graph's `related`
|
|
334
|
+
* list no longer feeds them.
|
|
335
|
+
*/
|
|
336
|
+
function buildCurateSupportRefs(links, selectedRefs, ownerRef) {
|
|
329
337
|
const supportRefs = [];
|
|
330
|
-
for (const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
+
for (const [part, direction] of [
|
|
339
|
+
["outgoing", "from"],
|
|
340
|
+
["incoming", "to"],
|
|
341
|
+
]) {
|
|
342
|
+
for (const [kind, group] of Object.entries(links?.[part] ?? {})) {
|
|
343
|
+
for (const ref of group.refs) {
|
|
344
|
+
if (ref === ownerRef || selectedRefs.has(ref) || supportRefs.some((existing) => existing.ref === ref))
|
|
345
|
+
continue;
|
|
346
|
+
const type = supportRefType(ref);
|
|
347
|
+
supportRefs.push({
|
|
348
|
+
ref,
|
|
349
|
+
...(type ? { type } : {}),
|
|
350
|
+
reason: `Declared link (${kind}) ${direction} this asset.`,
|
|
351
|
+
});
|
|
352
|
+
if (supportRefs.length >= MAX_CURATE_SUPPORT_REFS)
|
|
353
|
+
return supportRefs;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
338
356
|
}
|
|
339
357
|
return supportRefs;
|
|
340
358
|
}
|
|
359
|
+
/** The asset type a ref's conceptId names (`memories/x` → `memory`), when it names one. */
|
|
360
|
+
function supportRefType(ref) {
|
|
361
|
+
try {
|
|
362
|
+
return typeNameFromConceptId(parseBundleRef(ref).conceptId)?.type;
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
@@ -612,8 +612,9 @@ export async function writeMarkdownAsset(options) {
|
|
|
612
612
|
// no longer trigger reindexes, so keeping the index current is the writer's
|
|
613
613
|
// job. Demoted files reindex under their own containing root (usually the
|
|
614
614
|
// write target itself; the working stash when writing to a --target) so
|
|
615
|
-
// `--belief current` filtering
|
|
616
|
-
//
|
|
615
|
+
// `--belief current` filtering takes effect without waiting for the next
|
|
616
|
+
// full index. (alpha.4 removed belief weights from ranking; `--belief` is
|
|
617
|
+
// the only reader of `beliefState` today.)
|
|
617
618
|
const demotedInTargetRoot = demotedByRoot.get(source.path) ?? [];
|
|
618
619
|
demotedByRoot.delete(source.path);
|
|
619
620
|
await indexWrittenAssets(source.path, [result.path, ...demotedInTargetRoot], { bundleId: resolved.ref.origin });
|
|
@@ -24,7 +24,7 @@ import { makeBundleRef, parseBundleRef } from "../../core/asset/asset-ref.js";
|
|
|
24
24
|
import { parseFrontmatter } from "../../core/asset/frontmatter.js";
|
|
25
25
|
import { extractSection, markdownFragmentSlugs } from "../../core/asset/markdown.js";
|
|
26
26
|
import { buildMarkdownLeadContext, fragmentForSelector, MARKDOWN_FRAGMENT_CONTEXT_DEFAULT_MAX_CHARS, } from "../../core/asset/markdown-fragments.js";
|
|
27
|
-
import { displayRef, typeNameFromConceptId } from "../../core/asset/resolve-ref.js";
|
|
27
|
+
import { displayRef, displayRefForConceptId, typeNameFromConceptId } from "../../core/asset/resolve-ref.js";
|
|
28
28
|
import { META_DIR, parseMetaRef, readMetaFile } from "../../core/asset/stash-meta.js";
|
|
29
29
|
import { asNonEmptyString, isWithin } from "../../core/common.js";
|
|
30
30
|
import { loadConfig } from "../../core/config/config.js";
|
|
@@ -33,7 +33,6 @@ import { appendEvent } from "../../core/events.js";
|
|
|
33
33
|
import { SCRIPT_EXTENSIONS } from "../../core/recognition-util.js";
|
|
34
34
|
import { presentationFor } from "../../core/type-presentation.js";
|
|
35
35
|
import { warn, warnOnce } from "../../core/warn.js";
|
|
36
|
-
import { listRelatedPathsForFile } from "../../indexer/graph/graph-related.js";
|
|
37
36
|
import { lookupBundleRef, lookupBundleRefWithResolution } from "../../indexer/indexer.js";
|
|
38
37
|
import { projectMarkdownFragmentContent } from "../../indexer/passes/metadata.js";
|
|
39
38
|
import { ensurePrimaryIndexForRead, resolveReadSources } from "../../indexer/read-preflight.js";
|
|
@@ -43,6 +42,7 @@ import { buildFileContext, buildRenderContext, getRenderer, } from "../../indexe
|
|
|
43
42
|
import { resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
|
|
44
43
|
import { withIndexDb } from "../../storage/repositories/index-db.js";
|
|
45
44
|
import { getIndexedMarkdownFragment } from "../../storage/repositories/index-fts-repository.js";
|
|
45
|
+
import { readEntryLinks } from "../../storage/repositories/index-links-repository.js";
|
|
46
46
|
import { getCurrentWorkflowScopeKey } from "../../workflows/authoring/scope-key.js";
|
|
47
47
|
import { buildWorkflowAction } from "../../workflows/renderer.js";
|
|
48
48
|
import { getActiveWorkflowRun } from "../../workflows/runtime/runs.js";
|
|
@@ -318,12 +318,13 @@ export async function showLocal(input) {
|
|
|
318
318
|
response.type = indexedEntry.type;
|
|
319
319
|
response.name = indexedEntry.name;
|
|
320
320
|
const isPrimaryStash = source?.isDefault === true;
|
|
321
|
+
const displayDefaultBundle = config.defaultBundle ?? (isPrimaryStash ? indexedEntry.bundleId : undefined);
|
|
321
322
|
const canonicalRef = displayRef({
|
|
322
323
|
type: indexedEntry.type,
|
|
323
324
|
name: presentedName,
|
|
324
325
|
conceptId: indexedEntry.conceptId,
|
|
325
326
|
bundleId: indexedEntry.bundleId,
|
|
326
|
-
},
|
|
327
|
+
}, displayDefaultBundle);
|
|
327
328
|
if (parsed.fragment && indexedFragment) {
|
|
328
329
|
const selectedFragmentId = indexedFragment.fragments[indexedFragment.ordinal].fragmentId;
|
|
329
330
|
const selectedRef = `${canonicalRef}#${selectedFragmentId}`;
|
|
@@ -382,19 +383,7 @@ export async function showLocal(input) {
|
|
|
382
383
|
origin: source?.registryId ?? null,
|
|
383
384
|
editable,
|
|
384
385
|
...(!editable ? { editHint: buildEditHint(canonicalRef) } : {}),
|
|
385
|
-
|
|
386
|
-
try {
|
|
387
|
-
return withIndexDb((db) => {
|
|
388
|
-
const related = listRelatedPathsForFile(sourceStashDir, assetPath, 5, db);
|
|
389
|
-
return { total: related.length, hits: related };
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
catch (err) {
|
|
393
|
-
rethrowIfTestIsolationError(err);
|
|
394
|
-
rethrowIfDataDirUnreadable(err);
|
|
395
|
-
return { total: 0, hits: [] };
|
|
396
|
-
}
|
|
397
|
-
})(),
|
|
386
|
+
...showLinks(indexedEntry.itemRef, displayDefaultBundle),
|
|
398
387
|
};
|
|
399
388
|
const activeRun = await getActiveWorkflowRun(getCurrentWorkflowScopeKey());
|
|
400
389
|
if (activeRun) {
|
|
@@ -408,6 +397,56 @@ export async function showLocal(input) {
|
|
|
408
397
|
}
|
|
409
398
|
return fullResponse;
|
|
410
399
|
}
|
|
400
|
+
/** Refs listed per kind of declared link; `total` still counts them all (one memory is named by 1,437 others). */
|
|
401
|
+
const LINKS_PER_KIND = 10;
|
|
402
|
+
/**
|
|
403
|
+
* The declared links (#935) of an indexed asset, grouped by kind: outgoing in
|
|
404
|
+
* authored order, incoming by ref, and unresolved tokens as authored. Empty
|
|
405
|
+
* parts are omitted, and the field when nothing links either way.
|
|
406
|
+
*/
|
|
407
|
+
function showLinks(itemRef, defaultBundle) {
|
|
408
|
+
let rows;
|
|
409
|
+
try {
|
|
410
|
+
rows = withIndexDb((db) => readEntryLinks(db, itemRef));
|
|
411
|
+
}
|
|
412
|
+
catch (err) {
|
|
413
|
+
rethrowIfTestIsolationError(err);
|
|
414
|
+
rethrowIfDataDirUnreadable(err);
|
|
415
|
+
return {};
|
|
416
|
+
}
|
|
417
|
+
const outgoing = [];
|
|
418
|
+
const unresolved = [];
|
|
419
|
+
for (const row of rows.outgoing) {
|
|
420
|
+
if (row.conceptId === undefined)
|
|
421
|
+
unresolved.push({ kind: row.kind, ref: row.raw ?? "" });
|
|
422
|
+
else
|
|
423
|
+
outgoing.push({ kind: row.kind, ref: displayRefForConceptId(row.conceptId, row.bundleId, defaultBundle) });
|
|
424
|
+
}
|
|
425
|
+
const incoming = rows.incoming.map((row) => ({
|
|
426
|
+
kind: row.kind,
|
|
427
|
+
ref: displayRefForConceptId(row.conceptId ?? "", row.bundleId, defaultBundle),
|
|
428
|
+
}));
|
|
429
|
+
const links = {
|
|
430
|
+
...groupLinks("outgoing", outgoing),
|
|
431
|
+
...groupLinks("incoming", incoming),
|
|
432
|
+
...groupLinks("unresolved", unresolved),
|
|
433
|
+
};
|
|
434
|
+
return Object.keys(links).length > 0 ? { links } : {};
|
|
435
|
+
}
|
|
436
|
+
function groupLinks(part, rows) {
|
|
437
|
+
if (rows.length === 0)
|
|
438
|
+
return {};
|
|
439
|
+
const groups = {};
|
|
440
|
+
for (const kind of [...new Set(rows.map((row) => row.kind))].sort())
|
|
441
|
+
groups[kind] = { total: 0, refs: [] };
|
|
442
|
+
for (const { kind, ref } of rows) {
|
|
443
|
+
const group = groups[kind];
|
|
444
|
+
group.total++;
|
|
445
|
+
if (group.refs.length < LINKS_PER_KIND)
|
|
446
|
+
group.refs.push(ref);
|
|
447
|
+
}
|
|
448
|
+
return { [part]: groups };
|
|
449
|
+
}
|
|
411
450
|
/**
|
|
412
451
|
* Warn and ignore body fragments for namespaces whose authored bytes are
|
|
413
452
|
* sensitive. `warnOnce`-keyed on the exact ref: `akmShowUnified` calls this
|
|
@@ -10,6 +10,7 @@ import { formatRegistryUrl } from "../../core/registry-url.js";
|
|
|
10
10
|
import { error } from "../../core/warn.js";
|
|
11
11
|
import { closeDatabase, openExistingDatabase } from "../../storage/repositories/index-connection.js";
|
|
12
12
|
import { getEntryCount, getEntryCountByType } from "../../storage/repositories/index-entries-repository.js";
|
|
13
|
+
import { countLinksByKind } from "../../storage/repositories/index-links-repository.js";
|
|
13
14
|
import { getMeta } from "../../storage/repositories/index-meta-repository.js";
|
|
14
15
|
import { pkgVersion } from "../../version.js";
|
|
15
16
|
/**
|
|
@@ -99,9 +100,11 @@ function readIndexStats(resolvedPath) {
|
|
|
99
100
|
let db;
|
|
100
101
|
try {
|
|
101
102
|
db = openExistingDatabase(resolvedPath);
|
|
103
|
+
const links = countLinksByKind(db);
|
|
102
104
|
return {
|
|
103
105
|
entryCount: getEntryCount(db),
|
|
104
106
|
byType: getEntryCountByType(db),
|
|
107
|
+
...(Object.keys(links).length > 0 ? { links } : {}),
|
|
105
108
|
lastBuiltAt: getMeta(db, "builtAt") ?? null,
|
|
106
109
|
hasEmbeddings: getMeta(db, "hasEmbeddings") === "1",
|
|
107
110
|
};
|
|
@@ -83,10 +83,10 @@ export const indexCommand = defineCommand({
|
|
|
83
83
|
async run({ args }) {
|
|
84
84
|
await runWithJsonErrors(async () => {
|
|
85
85
|
if (getHyphenatedBoolean(args, "enrich") || getParsedInvocation().getFlagValue("--enrich") !== undefined) {
|
|
86
|
-
throw new UsageError("`akm index --enrich` has been removed.
|
|
86
|
+
throw new UsageError("`akm index --enrich` has been removed. Metadata enrichment during indexing is retired; it never runs.");
|
|
87
87
|
}
|
|
88
88
|
if (getHyphenatedBoolean(args, "re-enrich") || getParsedInvocation().getFlagValue("--re-enrich") !== undefined) {
|
|
89
|
-
throw new UsageError("`akm index --re-enrich` has been removed.
|
|
89
|
+
throw new UsageError("`akm index --re-enrich` has been removed. Metadata enrichment during indexing is retired; there is nothing to re-enrich.");
|
|
90
90
|
}
|
|
91
91
|
// #956: opt-in, non-blocking rebuild lock — never gates a human-typed
|
|
92
92
|
// `akm index` (it only warns and contends), but a scheduled/opportunistic
|
|
@@ -193,6 +193,8 @@ const DOCUMENT_JSON_CARRIED_FIELDS = [
|
|
|
193
193
|
"wikiRole",
|
|
194
194
|
"sources",
|
|
195
195
|
"evidenceSources",
|
|
196
|
+
// #935: a workflow's step targets and a task's target, read as declared links.
|
|
197
|
+
"uses",
|
|
196
198
|
// D2 (#730): the OKF v0.2 provenance `promoteProposal` stamps onto AKM-native
|
|
197
199
|
// writes (generated/verified/sources, namespaced — see `types.ts`'s
|
|
198
200
|
// `OkfProvenance` doc). Carried so the akm adapter rereads what it wrote and
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
* concern (Chunk 4/5), not recognition's. On the valid Chunk-0b fixture this
|
|
55
55
|
* distinction never triggers.
|
|
56
56
|
*/
|
|
57
|
+
import { parseBuiltinCommandAction } from "../../../commands/command/builtin-action.js";
|
|
57
58
|
import { scanEnvKeyNames } from "../../../commands/env/env.js";
|
|
58
59
|
import { parseTaskSource } from "../../../tasks/source/parse-task-source.js";
|
|
59
60
|
import { compileWorkflowSource, workflowStepInstructions } from "../../../workflows/compile.js";
|
|
@@ -125,6 +126,25 @@ function applyFrontmatterDescriptionAndTags(fm, out) {
|
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
}
|
|
129
|
+
/** The command a stored `akm/command` action runs; inline content names no asset. */
|
|
130
|
+
function storedCommandRef(action) {
|
|
131
|
+
return action?.kind === "stored" ? action.ref : undefined;
|
|
132
|
+
}
|
|
133
|
+
/** The asset a workflow step targets: its `uses:` ref, or the ref of a stored `akm/command`. Prose and `run:` steps target none. */
|
|
134
|
+
function workflowStepTarget(spec) {
|
|
135
|
+
if (!spec?.uses)
|
|
136
|
+
return undefined;
|
|
137
|
+
if (spec.uses !== "akm/command")
|
|
138
|
+
return spec.uses;
|
|
139
|
+
if (spec.commandMode !== "stored-ref")
|
|
140
|
+
return undefined;
|
|
141
|
+
try {
|
|
142
|
+
return storedCommandRef(parseBuiltinCommandAction(spec.with));
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
128
148
|
/** Collect + finalize a searchHints set the way every contributor does (`Array.from(hints).filter(Boolean)`, assigned only when non-empty). */
|
|
129
149
|
function finalizeHints(out, hints) {
|
|
130
150
|
if (hints.size > 0)
|
|
@@ -245,6 +265,9 @@ export function foldRecognizedMetadata(rendererName, file) {
|
|
|
245
265
|
hints.add(`prompt:${target.command.ref}`);
|
|
246
266
|
else
|
|
247
267
|
hints.add(`uses:${target.uses.ref}`);
|
|
268
|
+
const used = target.uses.kind !== "builtin-command" ? target.uses.ref : storedCommandRef(target.command);
|
|
269
|
+
if (used)
|
|
270
|
+
out.uses = [used];
|
|
248
271
|
}
|
|
249
272
|
else {
|
|
250
273
|
hints.add(`run:${target.run}`);
|
|
@@ -321,6 +344,7 @@ export function foldRecognizedMetadata(rendererName, file) {
|
|
|
321
344
|
return out;
|
|
322
345
|
const plan = result.plan;
|
|
323
346
|
const hints = new Set();
|
|
347
|
+
const uses = new Set();
|
|
324
348
|
if (plan.preamble)
|
|
325
349
|
hints.add(plan.preamble);
|
|
326
350
|
for (const step of plan.steps) {
|
|
@@ -328,8 +352,13 @@ export function foldRecognizedMetadata(rendererName, file) {
|
|
|
328
352
|
hints.add(workflowStepInstructions(step));
|
|
329
353
|
if (step.gate.criteria[0])
|
|
330
354
|
hints.add(step.gate.criteria[0]);
|
|
355
|
+
const used = workflowStepTarget(step.spec);
|
|
356
|
+
if (used)
|
|
357
|
+
uses.add(used);
|
|
331
358
|
}
|
|
332
359
|
out.searchHints = Array.from(hints).filter(Boolean);
|
|
360
|
+
if (uses.size > 0)
|
|
361
|
+
out.uses = [...uses];
|
|
333
362
|
if (plan.paramSchemas) {
|
|
334
363
|
const parameters = Object.entries(plan.paramSchemas).map(([name, schema]) => {
|
|
335
364
|
const description = schema.description;
|
|
@@ -395,4 +424,6 @@ export function applyFoldedMetadata(entry, folded) {
|
|
|
395
424
|
entry.toc = folded.toc;
|
|
396
425
|
if (folded.parameters)
|
|
397
426
|
entry.parameters = folded.parameters;
|
|
427
|
+
if (folded.uses)
|
|
428
|
+
entry.uses = folded.uses;
|
|
398
429
|
}
|
|
@@ -30,7 +30,6 @@ import fs from "node:fs";
|
|
|
30
30
|
import { readLockfile, renameLockEntry } from "../integrations/lockfile.js";
|
|
31
31
|
import { closeDatabase, openIndexDatabase, openReadonlyExistingDatabase, } from "../storage/repositories/index-connection.js";
|
|
32
32
|
import { getFilePathsByBundle, renameEntriesBundleId } from "../storage/repositories/index-entries-repository.js";
|
|
33
|
-
import { renameLlmCacheAssetRefs } from "../storage/repositories/index-llm-cache-repository.js";
|
|
34
33
|
import { countProposalsForBundleRename, renameProposalsBundleRef } from "../storage/repositories/proposals-repository.js";
|
|
35
34
|
import { countTaskHistoryTargetRefs, renameTaskHistoryTargetRefs, } from "../storage/repositories/task-history-repository.js";
|
|
36
35
|
import { selectBackend } from "../tasks/backends/index.js";
|
|
@@ -243,18 +242,13 @@ export async function renameBundle(oldId, newId, options = {}, deps) {
|
|
|
243
242
|
// e.g. a plain filesystem bundle).
|
|
244
243
|
await renameLockEntry(oldId, newId);
|
|
245
244
|
// Index: bundle_id/item_ref on every entry row (see index-entries-repository's
|
|
246
|
-
// renameEntriesBundleId docstring for why no FTS/vector rebuild is needed)
|
|
247
|
-
// and the metadata-enrichment LLM cache keyed by the same canonical
|
|
248
|
-
// item_ref — in the SAME write, so a rename can never land between the two
|
|
249
|
-
// and leave the cache stranded under the old prefix (the next `akm index`'s
|
|
250
|
-
// clearStaleCacheEntries would then delete it, forcing a full re-enrich).
|
|
245
|
+
// renameEntriesBundleId docstring for why no FTS/vector rebuild is needed).
|
|
251
246
|
const readIndexDb = openReadonlyExistingDatabase(getDbPath());
|
|
252
247
|
if (readIndexDb) {
|
|
253
248
|
closeDatabase(readIndexDb);
|
|
254
249
|
const writeIndexDb = openIndexDatabase(getDbPath());
|
|
255
250
|
try {
|
|
256
251
|
renameEntriesBundleId(writeIndexDb, oldId, newId);
|
|
257
|
-
renameLlmCacheAssetRefs(writeIndexDb, oldId, newId);
|
|
258
252
|
}
|
|
259
253
|
finally {
|
|
260
254
|
closeDatabase(writeIndexDb);
|
|
@@ -60,7 +60,7 @@ export { EngineConfigSchema, EnginesSchema, LlmConnectionConfigSchema, LlmProfil
|
|
|
60
60
|
export { ExperimentalConfigSchema } from "./schema/experimental.js";
|
|
61
61
|
export { FEEDBACK_FAILURE_MODES, FeedbackConfigSchema } from "./schema/feedback.js";
|
|
62
62
|
export { ImproveConfigSchema } from "./schema/improve.js";
|
|
63
|
-
export { ConsolidateProcessConfigSchema, DistillProcessConfigSchema, ExtractProcessConfigSchema,
|
|
63
|
+
export { ConsolidateProcessConfigSchema, DistillProcessConfigSchema, ExtractProcessConfigSchema, ImproveProcessConfigSchema, ImproveProfileConfigSchema, MemoryInferenceProcessConfigSchema, ProactiveMaintenanceProcessConfigSchema, ReflectProcessConfigSchema, TriageProcessConfigSchema, ValidationProcessConfigSchema, } from "./schema/improve-processes.js";
|
|
64
64
|
export { IndexConfigSchema, IndexPassConfigSchema } from "./schema/index-config.js";
|
|
65
65
|
export { OutputConfigSchema } from "./schema/output.js";
|
|
66
66
|
export { CURRENT_CONFIG_VERSION, LlmInvocationOverridesSchema } from "./schema/primitives.js";
|
|
@@ -240,6 +240,13 @@ export const AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) =>
|
|
|
240
240
|
}
|
|
241
241
|
const defaultStrategy = config.defaults?.improveStrategy;
|
|
242
242
|
if (defaultStrategy &&
|
|
243
|
+
// graph-refresh is exempt from this eager, config-load-time check: unlike
|
|
244
|
+
// a plain typo, it is a specific, known retirement, and refusing it here
|
|
245
|
+
// would fail every command's config load (including `akm migrate apply`,
|
|
246
|
+
// the one that fixes this). `resolveImproveStrategy`
|
|
247
|
+
// (src/commands/improve/improve-strategies.ts) refuses it lazily, at
|
|
248
|
+
// improve-invocation time, with the same message either way.
|
|
249
|
+
defaultStrategy !== "graph-refresh" &&
|
|
243
250
|
!BUILTIN_IMPROVE_STRATEGY_NAMES.includes(defaultStrategy) &&
|
|
244
251
|
!config.improve?.strategies?.[defaultStrategy]) {
|
|
245
252
|
ctx.addIssue({
|
|
@@ -27,36 +27,6 @@ export { VALID_HARNESS_IDS } from "./config-types.js";
|
|
|
27
27
|
// Canonical taxonomy lives in the schema/validator layer; re-exported here so
|
|
28
28
|
// existing `../core/config/config` import sites keep working.
|
|
29
29
|
export { FEEDBACK_FAILURE_MODES } from "./config-schema.js";
|
|
30
|
-
/**
|
|
31
|
-
* Default value for {@link IndexPassConfig.graphExtractionBatchSize}. Chosen
|
|
32
|
-
* empirically: 4 amortises the per-call HTTP overhead 4× while keeping the
|
|
33
|
-
* combined prompt size well under common 8K/16K context windows (each body is
|
|
34
|
-
* sliced to ~500 chars in the graph-extract prompt builder).
|
|
35
|
-
*/
|
|
36
|
-
const DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE = 4;
|
|
37
|
-
/**
|
|
38
|
-
* Approximate character budget per asset body inside a batched
|
|
39
|
-
* graph-extraction prompt — used by {@link resolveBatchSize} to derive a
|
|
40
|
-
* context-window ceiling when `llm.contextLength` is configured. This accounts
|
|
41
|
-
* for the actual `MAX_BODY_CHARS` (500) in graph-extract.ts plus the system
|
|
42
|
-
* prompt, user prompt wrapper, and expected JSON response overhead.
|
|
43
|
-
*/
|
|
44
|
-
const GRAPH_EXTRACTION_CHARS_PER_BODY = 1500;
|
|
45
|
-
/**
|
|
46
|
-
* Clamp a configured batch size against the model's known context window.
|
|
47
|
-
*
|
|
48
|
-
* `configured` defaults to {@link DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE} when
|
|
49
|
-
* `undefined`. When `contextLength` is provided, the result is the smaller of
|
|
50
|
-
* `configured` and `floor(contextLength / GRAPH_EXTRACTION_CHARS_PER_BODY)`,
|
|
51
|
-
* with a floor of 1 so the batched path always processes at least one body.
|
|
52
|
-
*/
|
|
53
|
-
export function resolveBatchSize(configured, contextLength) {
|
|
54
|
-
const base = configured && configured > 0 ? configured : DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE;
|
|
55
|
-
if (!contextLength || contextLength <= 0)
|
|
56
|
-
return base;
|
|
57
|
-
const ceiling = Math.max(1, Math.floor(contextLength / GRAPH_EXTRACTION_CHARS_PER_BODY));
|
|
58
|
-
return Math.max(1, Math.min(base, ceiling));
|
|
59
|
-
}
|
|
60
30
|
// ── Defaults ────────────────────────────────────────────────────────────────
|
|
61
31
|
export const DEFAULT_CONFIG = {
|
|
62
32
|
configVersion: "0.9.0",
|
|
@@ -210,6 +180,18 @@ function buildEffectiveConfig(liftedLocalRaw, sourcePath) {
|
|
|
210
180
|
assertUniquePhysicalBundleRoots(finalResult.data, sourcePath);
|
|
211
181
|
return finalResult.data;
|
|
212
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Retired `index.<passName>` keys that still validate against the generic
|
|
185
|
+
* per-pass catchall schema (`IndexPassConfigSchema`), so `resolveSchemaAt`
|
|
186
|
+
* below never returns `undefined` for them and the walk would otherwise
|
|
187
|
+
* treat them as a live, ordinary pass. Named here so the same three
|
|
188
|
+
* guarantees apply as any other retired config key (AGENTS.md "Reading
|
|
189
|
+
* persisted data"): a config setting one keeps loading, is named once by
|
|
190
|
+
* the unknown-key warning, and is dropped only by `akm migrate apply`.
|
|
191
|
+
* Both were retired in 0.9.17-alpha.9: `index.graph` (the LLM entity-graph
|
|
192
|
+
* extraction pass) and `index.metadataEnhance` (LLM metadata enrichment).
|
|
193
|
+
*/
|
|
194
|
+
const RETIRED_CATCHALL_KEY_PATHS = new Set(["index.graph", "index.metadataEnhance"]);
|
|
213
195
|
/**
|
|
214
196
|
* Every dotted key in `raw` the schema does not know, at any depth (arrays
|
|
215
197
|
* are not descended). Unknown keys are never an error: they are a typo, or a
|
|
@@ -221,7 +203,7 @@ export function unknownConfigKeyPaths(root, node = root, prefix = []) {
|
|
|
221
203
|
const found = [];
|
|
222
204
|
for (const key of Object.keys(node).sort()) {
|
|
223
205
|
const keyPath = [...prefix, key];
|
|
224
|
-
if (resolveSchemaAt(keyPath, root) === undefined) {
|
|
206
|
+
if (RETIRED_CATCHALL_KEY_PATHS.has(keyPath.join(".")) || resolveSchemaAt(keyPath, root) === undefined) {
|
|
225
207
|
found.push(keyPath);
|
|
226
208
|
continue;
|
|
227
209
|
}
|
|
@@ -695,6 +677,16 @@ export function normalizeConfigFile(configPath, options) {
|
|
|
695
677
|
const body = withSchedulerOnDisk(configWriteBody(localRaw, current, next), next);
|
|
696
678
|
for (const keyPath of unknownConfigKeyPaths(body))
|
|
697
679
|
deleteConfigPath(body, keyPath);
|
|
680
|
+
// `improve.strategies["graph-refresh"]` is schema-valid (any name is a
|
|
681
|
+
// legal custom-strategy key), so it never reaches the unknown-key sweep
|
|
682
|
+
// above. It can only be a leftover override of the deleted graph-refresh
|
|
683
|
+
// built-in (0.9.17-alpha.9) — resolveImproveStrategy now refuses that
|
|
684
|
+
// name unconditionally, so the override can never apply again. Drop it
|
|
685
|
+
// the same way any other retired key is dropped: only by `akm migrate
|
|
686
|
+
// apply`, never by an ordinary write.
|
|
687
|
+
const strategies = body.improve?.strategies;
|
|
688
|
+
if (strategies && Object.hasOwn(strategies, "graph-refresh"))
|
|
689
|
+
delete strategies["graph-refresh"];
|
|
698
690
|
const keys = [...new Set([...Object.keys(raw), ...Object.keys(body)])]
|
|
699
691
|
.filter((key) => JSON.stringify(raw[key]) !== JSON.stringify(body[key]))
|
|
700
692
|
.sort();
|
|
@@ -928,23 +920,6 @@ export function resolveSecret(value, resolveFromStore) {
|
|
|
928
920
|
return resolved ?? "";
|
|
929
921
|
});
|
|
930
922
|
}
|
|
931
|
-
/**
|
|
932
|
-
* Read a per-pass {@link IndexPassConfig} entry from {@link IndexConfig},
|
|
933
|
-
* filtering out the reserved feature-section keys so callers don't mistake
|
|
934
|
-
* `metadataEnhance` for a pass.
|
|
935
|
-
*/
|
|
936
|
-
/** Reserved well-known keys on IndexConfig that are NOT per-pass entries. */
|
|
937
|
-
const INDEX_RESERVED_KEYS = new Set(["metadataEnhance"]);
|
|
938
|
-
export function getIndexPassConfig(config, passName) {
|
|
939
|
-
if (!config)
|
|
940
|
-
return undefined;
|
|
941
|
-
if (INDEX_RESERVED_KEYS.has(passName))
|
|
942
|
-
return undefined;
|
|
943
|
-
const entry = config[passName];
|
|
944
|
-
if (!entry || typeof entry !== "object")
|
|
945
|
-
return undefined;
|
|
946
|
-
return entry;
|
|
947
|
-
}
|
|
948
923
|
// Re-export source runtime helpers — implementation lives in config-sources.ts.
|
|
949
924
|
export { bundleComponentConfig, bundleContentRoot, bundleContentRoots, bundleEntryToSourceEntry, bundleKeyForContentRoot, bundlePhysicalContentRoot, bundleSourceId, bundlesToSourceEntries, installedSourceDescriptor, isBundleEnabled, parseSourceSpec, primaryBundlePath, resolveActiveConfiguredSources, resolveConfiguredSources, } from "./config-sources.js";
|
|
950
925
|
/**
|
|
@@ -6,7 +6,6 @@ export const BUILTIN_IMPROVE_STRATEGY_NAMES = [
|
|
|
6
6
|
"default",
|
|
7
7
|
"quick",
|
|
8
8
|
"thorough",
|
|
9
|
-
"graph-refresh",
|
|
10
9
|
"consolidate",
|
|
11
10
|
"catchup",
|
|
12
11
|
"reflect-distill",
|
|
@@ -18,7 +17,6 @@ export const IMPROVE_PROCESS_ENGINE_CAPABILITIES = {
|
|
|
18
17
|
distill: "llm",
|
|
19
18
|
consolidate: "llm",
|
|
20
19
|
memoryInference: "llm",
|
|
21
|
-
graphExtraction: "llm",
|
|
22
20
|
extract: "llm",
|
|
23
21
|
validation: "llm",
|
|
24
22
|
triage: "runner",
|
|
@@ -10,13 +10,14 @@ import { IMPROVE_PROCESS_ENGINE_CAPABILITIES } from "../engine-semantics.js";
|
|
|
10
10
|
import { engineName, LlmInvocationOverridesSchema, nonEmptyString, positiveInt } from "./primitives.js";
|
|
11
11
|
// ── Improve profile / process ──────────────────────────────────────────────
|
|
12
12
|
//
|
|
13
|
-
// WI-9.6 (§4.2/§10.2): each of the
|
|
14
|
-
// consolidate, memoryInference,
|
|
15
|
-
// proactiveMaintenance
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
13
|
+
// WI-9.6 (§4.2/§10.2): each of the improve processes (reflect, distill,
|
|
14
|
+
// consolidate, memoryInference, extract, validation, triage,
|
|
15
|
+
// proactiveMaintenance — graphExtraction had one too, until the LLM
|
|
16
|
+
// entity-graph it ran was retired in 0.9.17-alpha.9) gets its OWN schema
|
|
17
|
+
// below — a shared base (engine, model, llm, enabled, timeoutMs) extended
|
|
18
|
+
// with only the fields meaningful on that process — replacing the prior
|
|
19
|
+
// single ImproveProcessConfigSchema reused via `.optional()` for all of them
|
|
20
|
+
// (which accepted, and silently ignored, any field on any process). Field→process assignment is derived from each
|
|
20
21
|
// field's original "only meaningful on X" doc comment, cross-checked against
|
|
21
22
|
// its actual runtime consumers and the built-in strategy assets
|
|
22
23
|
// (src/assets/improve-strategies/*.json).
|
|
@@ -164,12 +165,6 @@ const CONSOLIDATE_PROCESS_FIELDS = {
|
|
|
164
165
|
// entirely (emits `pool_below_min_size`). 0 disables the guard. Default 500.
|
|
165
166
|
minPoolSize: z.number().int().min(0).optional(),
|
|
166
167
|
maxChunkSize: z.number().int().min(1).max(50).optional(),
|
|
167
|
-
// Narrow candidate pool to memories modified within this duration window
|
|
168
|
-
// plus their graph neighbours. Absent = full-pool sweep.
|
|
169
|
-
incrementalSince: z.string().optional(),
|
|
170
|
-
// Graph neighbours per changed memory during incremental consolidation.
|
|
171
|
-
// Default 5. Only meaningful with incrementalSince.
|
|
172
|
-
neighborsPerChanged: z.number().int().min(1).optional(),
|
|
173
168
|
// Fallback p90 wall-clock time per consolidation chunk in seconds, used for
|
|
174
169
|
// cold-start budget estimation when no telemetry history exists. The actual
|
|
175
170
|
// p90 is derived from observed run durations once sufficient history
|
|
@@ -182,29 +177,6 @@ const MEMORY_INFERENCE_PROCESS_FIELDS = {
|
|
|
182
177
|
minPendingCount: z.number().int().min(0).optional(),
|
|
183
178
|
cls: clsField,
|
|
184
179
|
};
|
|
185
|
-
/**
|
|
186
|
-
* GraphExtraction process fields: one strategy's graph extraction scope and
|
|
187
|
-
* batching. `includeTypes` and `batchSize` override `index.graph`'s
|
|
188
|
-
* `graphExtractionIncludeTypes` and `graphExtractionBatchSize`; unset, the
|
|
189
|
-
* pass reads those.
|
|
190
|
-
*/
|
|
191
|
-
const GRAPH_EXTRACTION_PROCESS_FIELDS = {
|
|
192
|
-
// #624 P2: when set, rank eligible files by utility_scores DESC and process
|
|
193
|
-
// only the top-N per run (incremental high-signal-first sweep). Unset =
|
|
194
|
-
// process all eligible (current behavior).
|
|
195
|
-
topN: positiveInt.optional(),
|
|
196
|
-
includeTypes: z.array(z.string().min(1)).min(1).optional(),
|
|
197
|
-
batchSize: positiveInt.optional(),
|
|
198
|
-
// Full-corpus scan. When true, graph extraction runs on ALL stash files
|
|
199
|
-
// instead of only files touched by actionable refs in the current run.
|
|
200
|
-
// Used by the `graph-refresh` built-in profile / a scheduled weekly task.
|
|
201
|
-
fullScan: z.boolean().optional(),
|
|
202
|
-
// R12b + R20: cap on chunks processed per asset. A body chunked beyond this
|
|
203
|
-
// is truncated to the first N chunks instead of paying for unbounded
|
|
204
|
-
// per-asset LLM calls; the coverage loss is recorded as truncatedChunks.
|
|
205
|
-
// Absent = default 8 (src/llm/graph-extract.ts DEFAULT_MAX_CHUNKS_PER_ASSET).
|
|
206
|
-
maxChunksPerAsset: positiveInt.optional(),
|
|
207
|
-
};
|
|
208
180
|
const EXTRACT_PROCESS_FIELDS = {
|
|
209
181
|
defaultSince: z.string().min(1).optional(),
|
|
210
182
|
maxTotalChars: positiveInt.optional(),
|
|
@@ -264,7 +236,6 @@ export const ImproveProcessConfigSchema = z
|
|
|
264
236
|
...DISTILL_PROCESS_FIELDS,
|
|
265
237
|
...CONSOLIDATE_PROCESS_FIELDS,
|
|
266
238
|
...MEMORY_INFERENCE_PROCESS_FIELDS,
|
|
267
|
-
...GRAPH_EXTRACTION_PROCESS_FIELDS,
|
|
268
239
|
...EXTRACT_PROCESS_FIELDS,
|
|
269
240
|
...TRIAGE_PROCESS_FIELDS,
|
|
270
241
|
...PROACTIVE_MAINTENANCE_PROCESS_FIELDS,
|
|
@@ -288,10 +259,6 @@ export const ConsolidateProcessConfigSchema = z
|
|
|
288
259
|
export const MemoryInferenceProcessConfigSchema = z
|
|
289
260
|
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...MEMORY_INFERENCE_PROCESS_FIELDS })
|
|
290
261
|
.passthrough();
|
|
291
|
-
/** `processes.graphExtraction` — narrow per-process schema (WI-9.6). */
|
|
292
|
-
export const GraphExtractionProcessConfigSchema = z
|
|
293
|
-
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...GRAPH_EXTRACTION_PROCESS_FIELDS })
|
|
294
|
-
.passthrough();
|
|
295
262
|
/** `processes.extract` — narrow per-process schema (WI-9.6). */
|
|
296
263
|
export const ExtractProcessConfigSchema = z
|
|
297
264
|
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...EXTRACT_PROCESS_FIELDS })
|
|
@@ -306,13 +273,20 @@ export const TriageProcessConfigSchema = z
|
|
|
306
273
|
export const ProactiveMaintenanceProcessConfigSchema = z
|
|
307
274
|
.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...PROACTIVE_MAINTENANCE_PROCESS_FIELDS })
|
|
308
275
|
.passthrough();
|
|
276
|
+
/**
|
|
277
|
+
* Process names that once had a dedicated schema and are now gone. Setting
|
|
278
|
+
* one, even with `enabled: true`, is tolerated rather than rejected by the
|
|
279
|
+
* "unknown enabled process" check below — an old config must keep loading
|
|
280
|
+
* (AGENTS.md "Reading persisted data"). `graphExtraction`: the LLM
|
|
281
|
+
* entity-graph extraction it ran was retired in 0.9.17-alpha.9.
|
|
282
|
+
*/
|
|
283
|
+
const RETIRED_PROCESS_NAMES = new Set(["graphExtraction"]);
|
|
309
284
|
const ImproveProfileProcessesSchema = z
|
|
310
285
|
.object({
|
|
311
286
|
reflect: ReflectProcessConfigSchema.optional(),
|
|
312
287
|
distill: DistillProcessConfigSchema.optional(),
|
|
313
288
|
consolidate: ConsolidateProcessConfigSchema.optional(),
|
|
314
289
|
memoryInference: MemoryInferenceProcessConfigSchema.optional(),
|
|
315
|
-
graphExtraction: GraphExtractionProcessConfigSchema.optional(),
|
|
316
290
|
extract: ExtractProcessConfigSchema.optional(),
|
|
317
291
|
validation: ValidationProcessConfigSchema.optional(),
|
|
318
292
|
triage: TriageProcessConfigSchema.optional(),
|
|
@@ -335,6 +309,7 @@ const ImproveProfileProcessesSchema = z
|
|
|
335
309
|
}
|
|
336
310
|
for (const [name, process] of Object.entries(val)) {
|
|
337
311
|
if (!(name in IMPROVE_PROCESS_ENGINE_CAPABILITIES) &&
|
|
312
|
+
!RETIRED_PROCESS_NAMES.has(name) &&
|
|
338
313
|
process !== null &&
|
|
339
314
|
typeof process === "object" &&
|
|
340
315
|
process.enabled === true) {
|