akm-cli 0.9.17-alpha.6 → 0.9.17-alpha.7
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 +146 -0
- package/STABILITY.md +2 -2
- package/dist/akm +7 -7
- package/dist/assets/prompts/retrieval-relevance-judge.md +6 -0
- package/dist/commands/improve/consolidate.js +11 -0
- package/dist/commands/improve/improve-cli.js +27 -7
- package/dist/commands/improve/ledger.js +7 -3
- package/dist/commands/improve/preparation.js +40 -10
- package/dist/commands/improve/reflect.js +46 -22
- package/dist/commands/improve/retrieval-gate.js +127 -0
- package/dist/commands/improve/retrieval-scope.js +77 -0
- package/dist/commands/read/curate.js +1 -17
- package/dist/commands/tasks/tasks-cli.js +10 -12
- package/dist/commands/tasks/tasks.js +57 -56
- package/dist/commands/tasks/validate.js +27 -46
- package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
- package/dist/core/improve-result.js +4 -1
- package/dist/core/non-task-input.js +20 -0
- package/dist/core/paths.js +0 -4
- package/dist/indexer/indexer.js +1 -3
- package/dist/indexer/usage/usage-events.js +34 -0
- package/dist/scripts/akm-migrate-node.js +5822 -5833
- package/dist/scripts/akm-migrate.js +6301 -6312
- package/dist/storage/repositories/proposals-repository.js +4 -0
- package/dist/tasks/backends/cron.js +80 -43
- package/dist/tasks/backends/launchd.js +28 -15
- package/dist/tasks/backends/schtasks.js +25 -10
- package/dist/tasks/run/load-task.js +1 -1
- package/dist/tasks/scheduler-binding.js +4 -2
- package/dist/tasks/scheduler-invocation.js +127 -235
- package/dist/tasks/scheduler-sync.js +13 -8
- package/dist/tasks/source/parse-task-source.js +22 -126
- package/dist/tasks/source/task-to-v3.js +1 -55
- package/dist/tasks/source/task-to-v4.js +1 -13
- package/docs/migration/v0.9.1-to-v0.9.2.md +7 -3
- package/docs/reference/cli.md +4 -3
- package/docs/reference/tasks.md +58 -40
- package/package.json +1 -1
|
@@ -17,11 +17,9 @@
|
|
|
17
17
|
* ── validate (spec §6 task validation column) ──
|
|
18
18
|
*
|
|
19
19
|
* Validation enters the canonical task source parser (`parseTaskSource`,
|
|
20
|
-
* task source v4
|
|
21
|
-
*
|
|
22
|
-
* `
|
|
23
|
-
* cannot convert, or any other unsupported number, fails closed with
|
|
24
|
-
* `TASK_SCHEMA_VERSION_UNSUPPORTED`). That parser owns the closed key sets,
|
|
20
|
+
* which reads only task source v4 — a `version: 2` or `version: 3`
|
|
21
|
+
* document fails closed with `TASK_SCHEMA_VERSION_UNSUPPORTED`, naming
|
|
22
|
+
* `akm migrate apply`, which converts it). That parser owns the closed key sets,
|
|
25
23
|
* the executable-selector XOR, hostile YAML policy, the `akm/command`
|
|
26
24
|
* builtin, bounds, and physical `working-directory` containment. The
|
|
27
25
|
* adapter only translates a parser failure into the format-family
|
|
@@ -33,7 +31,8 @@
|
|
|
33
31
|
*/
|
|
34
32
|
import fs from "node:fs";
|
|
35
33
|
import path from "node:path";
|
|
36
|
-
import {
|
|
34
|
+
import { readBoundedTaskSourceYaml } from "../../../tasks/source/bounded-document.js";
|
|
35
|
+
import { parseTaskSource, peekTaskSourceVersion } from "../../../tasks/source/parse-task-source.js";
|
|
37
36
|
import { TASK_EXTENSION, TASK_NEAR_MISS_EXTENSION, taskExtensionDetail, taskSourceErrorDetail, } from "../../../tasks/source-v3.js";
|
|
38
37
|
import { toPosix } from "../../common.js";
|
|
39
38
|
import { hashContent } from "./shared.js";
|
|
@@ -125,8 +124,11 @@ export const akmTaskAdapter = {
|
|
|
125
124
|
return ["."];
|
|
126
125
|
},
|
|
127
126
|
/**
|
|
128
|
-
* Install-time probe (§1.2): a root holding a top-level, valid task
|
|
129
|
-
* `.yml` file
|
|
127
|
+
* Install-time probe (§1.2): a root holding a top-level, valid task source
|
|
128
|
+
* v4 `.yml` file, or a task v2/v3 file that `akm migrate apply` has yet to
|
|
129
|
+
* convert (the runtime refuses those, so without this the migrator and
|
|
130
|
+
* `akm task sync` would not find them in a bundle whose adapter config does
|
|
131
|
+
* not record). The full parser keeps this disjoint from unrelated YAML and
|
|
130
132
|
* prevents probe semantics from drifting from validation semantics.
|
|
131
133
|
*/
|
|
132
134
|
looksLikeRoot(root) {
|
|
@@ -152,9 +154,28 @@ export const akmTaskAdapter = {
|
|
|
152
154
|
return true;
|
|
153
155
|
}
|
|
154
156
|
catch {
|
|
157
|
+
if (isLegacyTaskDocument(raw, entry.name))
|
|
158
|
+
return true;
|
|
155
159
|
// Continue probing the remaining top-level .yml files.
|
|
156
160
|
}
|
|
157
161
|
}
|
|
158
162
|
return false;
|
|
159
163
|
},
|
|
160
164
|
};
|
|
165
|
+
/** The executable keys each retired task schema version required one of. */
|
|
166
|
+
const LEGACY_TASK_TARGET_KEYS = {
|
|
167
|
+
2: ["workflow", "prompt", "command"],
|
|
168
|
+
3: ["uses", "run"],
|
|
169
|
+
};
|
|
170
|
+
/** A task v2/v3 document: its schema version, plus a target key that version used. */
|
|
171
|
+
function isLegacyTaskDocument(yaml, filePath) {
|
|
172
|
+
let root;
|
|
173
|
+
try {
|
|
174
|
+
root = readBoundedTaskSourceYaml({ yaml, filePath }, { sourceLabel: "task source" }).root;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
const keys = LEGACY_TASK_TARGET_KEYS[peekTaskSourceVersion(root) ?? 0];
|
|
180
|
+
return keys !== undefined && keys.some((key) => Object.hasOwn(root, key));
|
|
181
|
+
}
|
|
@@ -306,6 +306,8 @@ function validateImprovePlan(value, dryRun, plannedRefNames) {
|
|
|
306
306
|
fail("plan.limits.totalCeiling must equal plan.limits.effective + plan.limits.additiveReplayAllowance");
|
|
307
307
|
}
|
|
308
308
|
const gateNames = new Set(["profile", "cleanup", "validation", "signal", "disk", "limit"]);
|
|
309
|
+
// Plans stored before 0.9.17-alpha.7 (#986) have no retrieval gate.
|
|
310
|
+
const optionalGateNames = new Set(["retrieval"]);
|
|
309
311
|
if (!Array.isArray(value.gates))
|
|
310
312
|
fail("plan.gates must be an array");
|
|
311
313
|
const gateRemovedByName = new Map();
|
|
@@ -313,8 +315,9 @@ function validateImprovePlan(value, dryRun, plannedRefNames) {
|
|
|
313
315
|
if (!isRecord(gate))
|
|
314
316
|
fail("plan.gates entries must be objects");
|
|
315
317
|
requireExactFields(gate, new Set(["name", "removed", "reason"]));
|
|
316
|
-
if (typeof gate.name !== "string" || !gateNames.has(gate.name))
|
|
318
|
+
if (typeof gate.name !== "string" || !(gateNames.has(gate.name) || optionalGateNames.has(gate.name))) {
|
|
317
319
|
fail("plan.gates.name is invalid");
|
|
320
|
+
}
|
|
318
321
|
requireCount(gate, "removed", "plan.gates entry");
|
|
319
322
|
if (typeof gate.reason !== "string")
|
|
320
323
|
fail("plan.gates.reason must be a string");
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/** The line of `src/assets/stash-skeleton/README.md` that reaches curate verbatim as a query. */
|
|
5
|
+
const STASH_README_LINE = "This is an **AKM stash** — a structured knowledge repository that stores reusable";
|
|
6
|
+
/**
|
|
7
|
+
* What the (trimmed) curate input is when it is not a task, else undefined.
|
|
8
|
+
* Harness and tool envelopes (`<task-notification>…`, `<system-reminder>…`,
|
|
9
|
+
* `<cross-session-message …>…`) start with a tag and close one, and the stash
|
|
10
|
+
* README line arrives verbatim; on the retrieval suite neither shape occurs in
|
|
11
|
+
* a real query. Length is not a signal: prompts over 2,000 characters found
|
|
12
|
+
* relevant assets at about the rate of shorter long prompts.
|
|
13
|
+
*/
|
|
14
|
+
export function nonTaskInput(query) {
|
|
15
|
+
if (query.startsWith("<") && query.includes("</"))
|
|
16
|
+
return "a harness or tool envelope";
|
|
17
|
+
if (query === STASH_README_LINE)
|
|
18
|
+
return "the akm stash README boilerplate";
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
package/dist/core/paths.js
CHANGED
|
@@ -249,10 +249,6 @@ export function getIndexRebuildLockPath() {
|
|
|
249
249
|
export function getStateDbPathInDataDir() {
|
|
250
250
|
return path.join(getDataDir(), "state.db");
|
|
251
251
|
}
|
|
252
|
-
/** Content-addressed scheduler runtime descriptors. */
|
|
253
|
-
export function getTaskContextDir(env = process.env) {
|
|
254
|
-
return path.join(getDataDir(env), "tasks", "context");
|
|
255
|
-
}
|
|
256
252
|
/** Path to the akm.lock file in $DATA. */
|
|
257
253
|
export function getLockfilePath() {
|
|
258
254
|
return path.join(getDataDir(), "akm.lock");
|
package/dist/indexer/indexer.js
CHANGED
|
@@ -35,7 +35,7 @@ import { generateEmbeddingsForDb } from "./materialize-embeddings.js";
|
|
|
35
35
|
import { canUseIncrementalSkip, computeDirFingerprint, getCachedDirState, getDirIndexState, inferZeroRowReason, } from "./passes/dir-staleness.js";
|
|
36
36
|
import { isEnrichmentComplete, isWorkflowSkipWarning, withFileSize, } from "./passes/metadata.js";
|
|
37
37
|
import { drainDirDocuments } from "./scan/drain-dir.js";
|
|
38
|
-
import { purgeOldUsageEvents } from "./usage/usage-events.js";
|
|
38
|
+
import { purgeOldUsageEvents, USAGE_EVENT_RETENTION_DAYS } from "./usage/usage-events.js";
|
|
39
39
|
import { walkStashFlatWithStatus } from "./walk/walker.js";
|
|
40
40
|
function collectLoweringNotices(target, notices) {
|
|
41
41
|
const keys = new Set(target.map((notice) => JSON.stringify(notice)));
|
|
@@ -1624,8 +1624,6 @@ export async function lookup(ref) {
|
|
|
1624
1624
|
return lookupBundleRef({ bundle: ref.origin, conceptId: conceptIdFromTypeName(ref.type, ref.name) });
|
|
1625
1625
|
}
|
|
1626
1626
|
// ── Utility score recomputation ──────────────────────────────────────────────
|
|
1627
|
-
/** Retention window for usage events: events older than this are purged. */
|
|
1628
|
-
const USAGE_EVENT_RETENTION_DAYS = 90;
|
|
1629
1627
|
/**
|
|
1630
1628
|
* Recompute utility scores for all entries based on usage_events data.
|
|
1631
1629
|
*
|
|
@@ -91,6 +91,40 @@ export function countUsageEventsByType(db, eventType) {
|
|
|
91
91
|
return db.prepare("SELECT COUNT(*) AS cnt FROM usage_events WHERE event_type = ?").get(eventType)
|
|
92
92
|
.cnt;
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Durable refs a user-attributed `search`, `curate` or `show` returned, or a
|
|
96
|
+
* user `feedback` named, at or after `sinceIso`. Machine traffic (`improve`,
|
|
97
|
+
* `task`, `audit`, `unknown`) is not demand, as in {@link countFeedbackSignals}.
|
|
98
|
+
*/
|
|
99
|
+
export function listUsedEntryRefs(db, sinceIso) {
|
|
100
|
+
const rows = db
|
|
101
|
+
.prepare(`SELECT DISTINCT entry_ref FROM usage_events
|
|
102
|
+
WHERE event_type IN ('search', 'curate', 'show', 'feedback')
|
|
103
|
+
AND source = 'user'
|
|
104
|
+
AND entry_ref IS NOT NULL
|
|
105
|
+
AND julianday(created_at) >= julianday(?)`)
|
|
106
|
+
.all(sinceIso);
|
|
107
|
+
return rows.map((row) => row.entry_ref);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The distinct query texts of user `search` and `curate` events that returned
|
|
111
|
+
* `conceptId` (any bundle prefix), most recent first.
|
|
112
|
+
*/
|
|
113
|
+
export function listRetrievalQueries(db, conceptId) {
|
|
114
|
+
const rows = db
|
|
115
|
+
.prepare(`SELECT query, MAX(created_at) AS last_at FROM usage_events
|
|
116
|
+
WHERE event_type IN ('search', 'curate')
|
|
117
|
+
AND source = 'user'
|
|
118
|
+
AND query IS NOT NULL AND trim(query) != ''
|
|
119
|
+
AND instr(entry_ref, '//') > 0
|
|
120
|
+
AND substr(entry_ref, instr(entry_ref, '//') + 2) = ?
|
|
121
|
+
GROUP BY query
|
|
122
|
+
ORDER BY last_at DESC`)
|
|
123
|
+
.all(conceptId);
|
|
124
|
+
return rows.map((row) => row.query);
|
|
125
|
+
}
|
|
126
|
+
/** Usage events older than this many days are purged on every `akm index`. */
|
|
127
|
+
export const USAGE_EVENT_RETENTION_DAYS = 90;
|
|
94
128
|
/**
|
|
95
129
|
* Delete usage events older than the given number of days.
|
|
96
130
|
*/
|