akm-cli 0.9.0-beta.58 → 0.9.0-beta.59
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/dist/commands/improve/consolidate/eligibility.js +0 -17
- package/dist/commands/improve/consolidate.js +2 -8
- package/dist/commands/improve/preparation.js +2 -5
- package/dist/commands/improve/recombine.js +2 -11
- package/dist/commands/tasks/default-tasks.js +3 -2
- package/dist/indexer/graph/graph-extraction.js +1 -13
- package/package.json +1 -1
- package/dist/assets/tasks/core/update-stashes.yml +0 -4
|
@@ -9,23 +9,6 @@ import { hasHotCaptureMode } from "../../proposal/validators/proposal-quality-va
|
|
|
9
9
|
export function isConsolidationEligibleMemoryName(name) {
|
|
10
10
|
return !name.endsWith(".derived");
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
13
|
-
* #632 — AKM session-capture telemetry memories: auto-generated session-end
|
|
14
|
-
* checkpoints named `<harness>-session-<YYYYMMDD>-<id>` or
|
|
15
|
-
* `<harness>-checkpoint-<YYYYMMDD…>-<id>`, carrying an embedded
|
|
16
|
-
* `akm_memory_kind: session_checkpoint` metadata block. Their bodies are
|
|
17
|
-
* pipeline bookkeeping, not durable knowledge, so the improve passes exclude
|
|
18
|
-
* them from their pools (recombine, consolidate). The `\d{8}` datestamp anchor
|
|
19
|
-
* is what distinguishes a capture name from a durable memory that merely
|
|
20
|
-
* MENTIONS session/checkpoint (e.g. `akm-plugins-session-end-extract-hook`,
|
|
21
|
-
* `session-checkpoint-lint-skips`), which stay in the pool.
|
|
22
|
-
*
|
|
23
|
-
* Lives here (the eligibility module) rather than in recombine so both
|
|
24
|
-
* recombine and consolidate can reuse it without a circular import.
|
|
25
|
-
*/
|
|
26
|
-
export function isSessionCaptureMemoryName(name) {
|
|
27
|
-
return /-(session|checkpoint)-\d{8}/.test(name);
|
|
28
|
-
}
|
|
29
12
|
/**
|
|
30
13
|
* Returns true when the memory file has `captureMode: hot` in its frontmatter.
|
|
31
14
|
*
|
|
@@ -45,8 +45,8 @@ import { normalizeUpdatedField, sanitizeMergedContent } from "./consolidate/sani
|
|
|
45
45
|
export { normalizeUpdatedField, sanitizeMergedContent, stripOuterCodeFence } from "./consolidate/sanitize.js";
|
|
46
46
|
// Eligibility / safety predicates live in ./consolidate/eligibility. Imported
|
|
47
47
|
// for internal guard use; the two public predicates are re-exported.
|
|
48
|
-
import { consolidateGuardStatus, isConsolidationEligibleMemoryName, isHotCapturedMemory,
|
|
49
|
-
export { isConsolidationEligibleMemoryName, isHotCapturedMemory
|
|
48
|
+
import { consolidateGuardStatus, isConsolidationEligibleMemoryName, isHotCapturedMemory, } from "./consolidate/eligibility.js";
|
|
49
|
+
export { isConsolidationEligibleMemoryName, isHotCapturedMemory } from "./consolidate/eligibility.js";
|
|
50
50
|
// Plan parsing / merging (pure op-reconciliation algebra) lives in
|
|
51
51
|
// ./consolidate/merge. Imported for internal use; mergePlans re-exported.
|
|
52
52
|
import { isValidOp, mergePlans } from "./consolidate/merge.js";
|
|
@@ -2105,10 +2105,6 @@ function loadMemoriesForSource(source, stashDir, warnings) {
|
|
|
2105
2105
|
return path.resolve(e.stashDir) === path.resolve(source);
|
|
2106
2106
|
})
|
|
2107
2107
|
.filter((e) => isConsolidationEligibleMemoryName(e.entry.name))
|
|
2108
|
-
// #632 — exclude session-capture telemetry (checkpoints) from the
|
|
2109
|
-
// consolidation pool, mirroring recombine. Their bodies are pipeline
|
|
2110
|
-
// bookkeeping, so consolidating them burns LLM calls on pure noise.
|
|
2111
|
-
.filter((e) => !isSessionCaptureMemoryName(e.entry.name))
|
|
2112
2108
|
// Skip stale DB entries whose file was deleted by a prior run but not yet
|
|
2113
2109
|
// re-indexed. Without this guard the deleted file's ref appears in chunks
|
|
2114
2110
|
// sent to the LLM, which then proposes a second delete → delete_failed
|
|
@@ -2142,8 +2138,6 @@ function loadMemoriesForSource(source, stashDir, warnings) {
|
|
|
2142
2138
|
const name = fname.replace(/\.md$/, "");
|
|
2143
2139
|
if (!isConsolidationEligibleMemoryName(name))
|
|
2144
2140
|
continue;
|
|
2145
|
-
if (isSessionCaptureMemoryName(name))
|
|
2146
|
-
continue; // #632 — skip telemetry checkpoints
|
|
2147
2141
|
memories.push({ name, filePath, description: "", tags: [], stashDir: fsStashDir });
|
|
2148
2142
|
}
|
|
2149
2143
|
}
|
|
@@ -21,7 +21,7 @@ import { akmLint } from "../lint/index.js";
|
|
|
21
21
|
import { getProposal, listProposals } from "../proposal/repository.js";
|
|
22
22
|
import { runSchemaRepairPass } from "../sources/schema-repair.js";
|
|
23
23
|
import { computeThresholdAutoTune, gateDecisionsToSamples, summarizeCalibration, } from "./calibration.js";
|
|
24
|
-
import { akmConsolidate
|
|
24
|
+
import { akmConsolidate } from "./consolidate.js";
|
|
25
25
|
// Eligibility / candidate-selection predicates live in ./eligibility.
|
|
26
26
|
import { buildLatestFeedbackTsMap, buildLatestProposalTsMap, buildUtilityMap, dedupeRefs, findAssetFilePath, isDistillCandidateRef, isLessonCandidate, isSignalDeltaEligible, } from "./eligibility.js";
|
|
27
27
|
import { akmExtract, countNewExtractCandidates } from "./extract.js";
|
|
@@ -1156,10 +1156,7 @@ export async function runImprovePreparationStage(args) {
|
|
|
1156
1156
|
// collapse the lane to exactly 1 ref via the bare `?? 10` fallback.
|
|
1157
1157
|
const effectiveLimit = options.limit ?? improveProfile?.processes?.reflect?.limit ?? improveProfile.limit ?? 10;
|
|
1158
1158
|
const highSalienceCap = Math.max(1, Math.floor(effectiveLimit * 0.1));
|
|
1159
|
-
|
|
1160
|
-
// the scarce high-salience budget. Even with a content-scored row, these
|
|
1161
|
-
// are pipeline bookkeeping, not assets worth reflecting/rewriting.
|
|
1162
|
-
const candidates = noFeedbackCandidates.filter((r) => !proactiveAndRetrievalSet.has(r.ref) && !isSessionCaptureMemoryName(parseAssetRef(r.ref).name));
|
|
1159
|
+
const candidates = noFeedbackCandidates.filter((r) => !proactiveAndRetrievalSet.has(r.ref));
|
|
1163
1160
|
// Collect ALL qualifying candidates, then take the top-N BY SCORE — the
|
|
1164
1161
|
// previous first-N-in-scan-order break meant a higher-salience candidate
|
|
1165
1162
|
// found later in the scan lost its slot to an earlier lower-scoring one.
|
|
@@ -52,7 +52,7 @@ import { closeDatabase, getAllEntries, getEntitiesByEntryIds, openExistingDataba
|
|
|
52
52
|
import { decayUnseenRecombineHypotheses, findMatchingRecombineHypothesis, getRecombineHypothesis, markRecombineHypothesisPromoted, recordRecombineInduction, } from "../../storage/repositories/recombine-repository.js";
|
|
53
53
|
import { archiveProposal, createProposal, isProposalSkipped, listProposals } from "../proposal/repository.js";
|
|
54
54
|
import { isValidDescription, isValidWhenToUse, validateProposalFrontmatter, } from "../proposal/validators/proposal-quality-validators.js";
|
|
55
|
-
import { isConsolidationEligibleMemoryName
|
|
55
|
+
import { isConsolidationEligibleMemoryName } from "./consolidate.js";
|
|
56
56
|
import { resolveImproveLlmFn } from "./shared.js";
|
|
57
57
|
const RECOMBINE_SYSTEM_PROMPT = recombineSystemPrompt;
|
|
58
58
|
const DEFAULT_MIN_CLUSTER_SIZE = 3;
|
|
@@ -174,10 +174,6 @@ const JUNK_ENTITY_NORMS = new Set([
|
|
|
174
174
|
"metadata",
|
|
175
175
|
"status",
|
|
176
176
|
]);
|
|
177
|
-
// #632 — `isSessionCaptureMemoryName` now lives in ./consolidate/eligibility so
|
|
178
|
-
// both recombine and consolidate can reuse it without a circular import. It is
|
|
179
|
-
// re-exported here for back-compat (existing importers + tests).
|
|
180
|
-
export { isSessionCaptureMemoryName };
|
|
181
177
|
/**
|
|
182
178
|
* #632 — an entity carries no clustering signal (and must be skipped) when it is
|
|
183
179
|
* a generic extraction artefact (session / structured-log bookkeeping), a raw
|
|
@@ -229,12 +225,7 @@ export function isJunkEntity(entity) {
|
|
|
229
225
|
*/
|
|
230
226
|
export function buildRelatednessClusters(entries, opts) {
|
|
231
227
|
// Only consolidation-eligible memories participate (exclude `.derived`).
|
|
232
|
-
|
|
233
|
-
// `isConsolidationEligibleMemoryName`) AND session-capture telemetry dumps
|
|
234
|
-
// whose embedded metadata pollutes both tag and entity clustering.
|
|
235
|
-
const memories = entries.filter((e) => e.entry.type === "memory" &&
|
|
236
|
-
isConsolidationEligibleMemoryName(e.entry.name) &&
|
|
237
|
-
!isSessionCaptureMemoryName(e.entry.name));
|
|
228
|
+
const memories = entries.filter((e) => e.entry.type === "memory" && isConsolidationEligibleMemoryName(e.entry.name));
|
|
238
229
|
// signal -> member entries
|
|
239
230
|
const groups = new Map();
|
|
240
231
|
const add = (signal, entry) => {
|
|
@@ -20,8 +20,9 @@ import fs from "node:fs";
|
|
|
20
20
|
import os from "node:os";
|
|
21
21
|
import { akmTasksAdd, akmTasksList } from "./tasks.js";
|
|
22
22
|
/**
|
|
23
|
-
* The canonical default improve task set. `update-stashes`
|
|
24
|
-
*
|
|
23
|
+
* The canonical default improve task set. The `update-stashes` embedded core
|
|
24
|
+
* template (nightly `akm update --all`) was retired in meta-review 06-M2:
|
|
25
|
+
* third-party stash pulls are on-demand only now, not a scheduled cron.
|
|
25
26
|
*/
|
|
26
27
|
export const DEFAULT_IMPROVE_TASKS = [
|
|
27
28
|
{
|
|
@@ -838,14 +838,10 @@ export function rankCandidatesByUtility(db, candidates, _stashRoot) {
|
|
|
838
838
|
*
|
|
839
839
|
* Inferred-child memories (frontmatter `inferred: true`) are skipped — they
|
|
840
840
|
* are already derived summaries, with no additional internal graph structure worth
|
|
841
|
-
* extracting.
|
|
841
|
+
* extracting.
|
|
842
842
|
*
|
|
843
843
|
* Exported for direct unit testing.
|
|
844
844
|
*/
|
|
845
|
-
// #632 — canonical session-capture name shape, mirrored from
|
|
846
|
-
// isSessionCaptureMemoryName (src/commands/improve/consolidate/eligibility.ts).
|
|
847
|
-
// Inlined to avoid an improve-layer import from the indexer layer.
|
|
848
|
-
const SESSION_CAPTURE_NAME_RE = /-(session|checkpoint)-\d{8}/;
|
|
849
845
|
export function collectEligibleFiles(stashRoot, includeTypes = [...DEFAULT_GRAPH_EXTRACTION_INCLUDE_TYPES]) {
|
|
850
846
|
const out = [];
|
|
851
847
|
for (const rawType of includeTypes) {
|
|
@@ -871,14 +867,6 @@ export function collectEligibleFiles(stashRoot, includeTypes = [...DEFAULT_GRAPH
|
|
|
871
867
|
// graph to extract from a single-fact body.
|
|
872
868
|
if (type === "memory" && parsed.data.inferred === true)
|
|
873
869
|
continue;
|
|
874
|
-
// #632 — skip session-capture telemetry checkpoints (named
|
|
875
|
-
// `<harness>-(session|checkpoint)-<YYYYMMDD>-<id>`). Their bodies are
|
|
876
|
-
// pipeline bookkeeping; graph-extracting them lifts metadata fields as
|
|
877
|
-
// entities that then dominate clustering as bland stash-wide buckets.
|
|
878
|
-
// Mirrors isSessionCaptureMemoryName (consolidate/eligibility.ts); inlined
|
|
879
|
-
// here to keep the indexer layer free of an improve-layer import.
|
|
880
|
-
if (type === "memory" && SESSION_CAPTURE_NAME_RE.test(path.basename(filePath, ".md")))
|
|
881
|
-
continue;
|
|
882
870
|
const body = parsed.content.trim();
|
|
883
871
|
if (!body)
|
|
884
872
|
continue;
|
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.59",
|
|
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": [
|