akm-cli 0.9.17-alpha.6 → 0.9.17-alpha.8
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 +285 -0
- package/STABILITY.md +2 -2
- package/dist/akm +62 -29
- package/dist/akm-migrate +38 -19
- package/dist/assets/prompts/retrieval-relevance-judge.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +5 -3
- 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/loop-stages.js +4 -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 +41 -30
- package/dist/commands/read/show.js +55 -2
- package/dist/commands/sources/info.js +3 -0
- 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-adapter.js +2 -0
- package/dist/core/adapter/adapters/akm-metadata.js +31 -0
- 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/db/graph-db.js +0 -32
- package/dist/indexer/graph/graph-extraction.js +3 -1
- package/dist/indexer/indexer.js +1 -3
- package/dist/indexer/links/declared-links.js +90 -0
- package/dist/indexer/scan/doc-to-entry.js +1 -0
- package/dist/indexer/usage/usage-events.js +34 -0
- package/dist/llm/graph-extract.js +26 -37
- package/dist/output/shapes/helpers.js +3 -0
- package/dist/output/text/show-format.js +16 -0
- package/dist/scripts/akm-migrate-node.js +6377 -6437
- package/dist/scripts/akm-migrate.js +6860 -6920
- package/dist/storage/repositories/index-entries-repository.js +12 -6
- package/dist/storage/repositories/index-entry-schema.js +18 -1
- package/dist/storage/repositories/index-links-repository.js +143 -0
- package/dist/storage/repositories/index-schema.js +27 -0
- 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-v4.js +463 -87
- package/docs/migration/release-notes/0.9.17.md +7 -5
- package/docs/migration/v0.9.1-to-v0.9.2.md +7 -3
- package/docs/reference/cli.md +26 -10
- package/docs/reference/tasks.md +58 -40
- package/package.json +1 -1
- package/dist/tasks/source/task-to-v3.js +0 -507
|
@@ -5,59 +5,32 @@
|
|
|
5
5
|
* The task source version router.
|
|
6
6
|
*
|
|
7
7
|
* Runs the bounded YAML front end ONCE (`readBoundedTaskSourceYaml`), reads
|
|
8
|
-
* `root.version`, and
|
|
9
|
-
*
|
|
10
|
-
* grammar itself, no re-serialization back to disk, no synthetic document
|
|
11
|
-
* (the shim adds a pure bytes-in/bytes-out detour, never a disk write).
|
|
12
|
-
*
|
|
13
|
-
* The terminal routing table:
|
|
8
|
+
* `root.version`, and dispatches into `parseTaskSourceV4Document`. The
|
|
9
|
+
* runtime reads only task source v4 (#987):
|
|
14
10
|
*
|
|
15
11
|
* | root `version` | outcome |
|
|
16
12
|
* |------------------------|-----------------------------------------------------------------|
|
|
17
|
-
* | `4
|
|
18
|
-
* | `4`, some `schedule[]` entry carries `enabled`
|
|
19
|
-
* | `2` or `3` |
|
|
13
|
+
* | `4` | `parseTaskSourceV4Document` — the current grammar |
|
|
14
|
+
* | `4`, some `schedule[]` entry carries `enabled` (0.9.15's grammar) | `TASK_SOURCE_INVALID` naming `akm migrate apply`, which removes the key |
|
|
15
|
+
* | `2` or `3` | `TASK_SCHEMA_VERSION_UNSUPPORTED` naming `akm migrate apply`, which converts the file |
|
|
20
16
|
* | any other number | `TASK_SCHEMA_VERSION_UNSUPPORTED`, naming the migrator |
|
|
21
17
|
* | absent / not a number | `parseTaskSourceV4Document` — its own `TASK_SOURCE_INVALID` "version is required and must be 4" / "must be exactly 4" wording |
|
|
22
18
|
*
|
|
19
|
+
* `akm migrate apply` (`scripts/akm-migrate/`) is the one place a v2/v3
|
|
20
|
+
* document, or a v4 document carrying the retired `schedule[].enabled`, is
|
|
21
|
+
* converted: it rewrites the file once, under a backup. Nothing here converts
|
|
22
|
+
* in memory. Every caller reports the refusal for that one file — `akm task
|
|
23
|
+
* sync` keeps reconciling every other task (#867).
|
|
24
|
+
*
|
|
23
25
|
* A missing or non-numeric `version:` is a MALFORMED v4 document, not a
|
|
24
26
|
* legacy one — it routes into the v4 parser so the field error names the
|
|
25
|
-
* one grammar `src`
|
|
26
|
-
* message that would send the user to the migrator for a document that was
|
|
27
|
-
* never task v2 or v3 in the first place.
|
|
28
|
-
*
|
|
29
|
-
* task v2 and task v3 sources are no longer read as their own standing
|
|
30
|
-
* grammar anywhere else in `src` — the only readers of that grammar are the
|
|
31
|
-
* pure, byte-producing planners (`./task-to-v3.ts`, `./task-to-v4.ts`, and
|
|
32
|
-
* the frozen v3 reader `./task-source-v3-frozen.ts`), reached either through
|
|
33
|
-
* this shim (bytes in, bytes out, never touches disk) or through
|
|
34
|
-
* `akm migrate apply` / `akm-migrate` (`scripts/akm-migrate`, which
|
|
35
|
-
* additionally rewrites the file on disk once the user asks for that).
|
|
36
|
-
* Policy: a deterministic byte transform is the tool's job, not the user's —
|
|
37
|
-
* upgrading past a schema bump must not silently break a scheduled task, so
|
|
38
|
-
* v2/v3 files keep reading successfully at the cost of a one-line
|
|
39
|
-
* deprecation warning, and `akm migrate apply` remains available to rewrite
|
|
40
|
-
* the file and silence it. Activation itself is host-local (scheduler
|
|
41
|
-
* config, `src/core/activation-policy.ts`) and this shim never touches it:
|
|
42
|
-
* the v3->v4 planner never hoists the retired `akm.enabled` field to v4's
|
|
43
|
-
* top level and never carries a schedule entry's `enabled` key, so the
|
|
44
|
-
* document this shim hands back carries no enablement at all — the same
|
|
45
|
-
* shape a native v4 document has. A declared `version: 4` document that
|
|
46
|
-
* still carries a `schedule[].enabled` key (0.9.15's v4 grammar accepted
|
|
47
|
-
* it; this release's does not) gets the identical treatment: routed
|
|
48
|
-
* through `planTaskToV4File`'s own `version === 4` branch, which strips
|
|
49
|
-
* every `schedule[].enabled` key without reading its value and reports
|
|
50
|
-
* `source-enablement-removed`, then re-parsed and returned with the same
|
|
51
|
-
* one-line deprecation warning. The front end's own pre-version failures
|
|
27
|
+
* one grammar `src` accepts. The front end's own pre-version failures
|
|
52
28
|
* (source not a string, source too large, YAML parse/warning/expansion)
|
|
53
29
|
* render with the label `task source`.
|
|
54
30
|
*/
|
|
55
31
|
import { UsageError } from "../../core/errors.js";
|
|
56
|
-
import { warnOnce } from "../../core/warn.js";
|
|
57
32
|
import { readBoundedTaskSourceYaml } from "./bounded-document.js";
|
|
58
|
-
import {
|
|
59
|
-
import { planTaskToV3File } from "./task-to-v3.js";
|
|
60
|
-
import { planTaskToV4File } from "./task-to-v4.js";
|
|
33
|
+
import { parseTaskSourceV4Document, TASK_SOURCE_V4_VERSION } from "./task-source-v4.js";
|
|
61
34
|
/** Read the root `version` field without over-accepting non-number values (e.g. the string `"4"`). */
|
|
62
35
|
export function peekTaskSourceVersion(root) {
|
|
63
36
|
if (root === null || typeof root !== "object" || Array.isArray(root))
|
|
@@ -66,71 +39,19 @@ export function peekTaskSourceVersion(root) {
|
|
|
66
39
|
return typeof value === "number" ? value : undefined;
|
|
67
40
|
}
|
|
68
41
|
const TASK_MIGRATE_HINT = "Run `akm migrate apply --dry-run` to preview the task-v3 to task-source-v4 conversion, then run `akm migrate apply`.";
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
* behavior (e.g. an ambiguous shell command), not one the migrator can just
|
|
73
|
-
* be re-run to fix. `reason`/`detail` are the SAME blocked outcome
|
|
74
|
-
* `akm migrate status`/`apply` reports for this file, so the message names
|
|
75
|
-
* the actual decision instead of pointing at a command that will report the
|
|
76
|
-
* identical block.
|
|
77
|
-
*/
|
|
78
|
-
function unmigratableVersionError(filePath, version, reason, detail) {
|
|
79
|
-
return new UsageError(`TASK_SCHEMA_VERSION_UNSUPPORTED: Task at ${filePath} uses task schema version ${version} and needs a human decision before it can run — the deterministic migrator cannot convert it automatically (${reason}${detail ? `: ${detail}` : ""}).`, "TASK_SCHEMA_VERSION_UNSUPPORTED", "Review the file and resolve the ambiguity by hand, then it will convert normally; `akm migrate status` reports the same reason.");
|
|
42
|
+
/** A v2/v3 document: `akm migrate apply` converts it; this release reads only v4. */
|
|
43
|
+
function legacyVersionError(filePath, version) {
|
|
44
|
+
return new UsageError(`TASK_SCHEMA_VERSION_UNSUPPORTED: Task at ${filePath} uses task schema version ${version}; this release reads only version 4. Run \`akm migrate apply\` to convert it.`, "TASK_SCHEMA_VERSION_UNSUPPORTED", TASK_MIGRATE_HINT);
|
|
80
45
|
}
|
|
81
46
|
function unsupportedVersionError(filePath, version) {
|
|
82
47
|
return new UsageError(`TASK_SCHEMA_VERSION_UNSUPPORTED: Task at ${filePath} uses task schema version ${version}, which this release does not accept.`, "TASK_SCHEMA_VERSION_UNSUPPORTED", TASK_MIGRATE_HINT);
|
|
83
48
|
}
|
|
84
|
-
/**
|
|
85
|
-
* Plan the SAME bytes already in hand through the pure v3->v4 (and, for v2,
|
|
86
|
-
* chained v2->v3->v4) migration planner(s) — never touches disk, never
|
|
87
|
-
* writes the file, never re-reads it from disk. `version === 4` runs the
|
|
88
|
-
* identical bytes straight through `planTaskToV4File`'s own `version === 4`
|
|
89
|
-
* branch instead (the retired `schedule[].enabled` case, `./task-to-v4.ts`),
|
|
90
|
-
* so there is exactly one helper for every version this shim reads, not a
|
|
91
|
-
* second one for the v4-only case. Returns the produced v4 YAML text, or the
|
|
92
|
-
* blocked reason/detail when the deterministic conversion cannot proceed
|
|
93
|
-
* (an unmigratable v2/v3 shape, or a v4 document `planTaskToV4File` cannot
|
|
94
|
-
* revalidate once `schedule[].enabled` is stripped) — the caller falls back
|
|
95
|
-
* to the same hard error this gate threw before the shim existed, now
|
|
96
|
-
* naming that reason.
|
|
97
|
-
*/
|
|
98
|
-
function planInMemoryV4Bytes(version, yaml, filePath, workspaceRoot) {
|
|
99
|
-
const bytes = Buffer.from(yaml, "utf8");
|
|
100
|
-
// `writable`/`onDiskWritable` gate the DISK apply path's "don't touch a
|
|
101
|
-
// read-only file" check inside the planners; this shim never writes
|
|
102
|
-
// anything to disk, so that check does not apply here and must not block
|
|
103
|
-
// an otherwise-legal read of a task file that happens to be read-only.
|
|
104
|
-
const baseInput = {
|
|
105
|
-
filePath,
|
|
106
|
-
bytes,
|
|
107
|
-
mode: 0o644,
|
|
108
|
-
writable: true,
|
|
109
|
-
onDiskWritable: true,
|
|
110
|
-
...(workspaceRoot ? { containmentRoot: workspaceRoot } : {}),
|
|
111
|
-
};
|
|
112
|
-
let v3Bytes;
|
|
113
|
-
if (version === 3 || version === 4) {
|
|
114
|
-
v3Bytes = bytes;
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
const v3Outcome = planTaskToV3File(baseInput);
|
|
118
|
-
if (v3Outcome.status !== "changed")
|
|
119
|
-
return { reason: v3Outcome.reason, detail: v3Outcome.detail };
|
|
120
|
-
v3Bytes = v3Outcome.after;
|
|
121
|
-
}
|
|
122
|
-
const v4Outcome = planTaskToV4File({ ...baseInput, bytes: v3Bytes });
|
|
123
|
-
if (v4Outcome.status !== "changed")
|
|
124
|
-
return { reason: v4Outcome.reason, detail: v4Outcome.detail };
|
|
125
|
-
return v4Outcome.after.toString("utf8");
|
|
126
|
-
}
|
|
127
49
|
/**
|
|
128
50
|
* True when `root`'s `schedule:` is a sequence with at least one mapping
|
|
129
51
|
* entry that carries an `enabled` key, regardless of that key's value or
|
|
130
52
|
* type — the shape 0.9.15's v4 grammar accepted and this release's does
|
|
131
|
-
* not (`schedule[].enabled`).
|
|
132
|
-
*
|
|
133
|
-
* decides whether to route through the in-memory shim.
|
|
53
|
+
* not (`schedule[].enabled`). Activation is host-local `scheduler.enabled`,
|
|
54
|
+
* so the value is never read; `akm migrate apply` removes the key.
|
|
134
55
|
*/
|
|
135
56
|
export function v4ScheduleHasRetiredEnabledKey(root) {
|
|
136
57
|
if (root === null || typeof root !== "object" || Array.isArray(root))
|
|
@@ -140,42 +61,17 @@ export function v4ScheduleHasRetiredEnabledKey(root) {
|
|
|
140
61
|
return false;
|
|
141
62
|
return schedule.some((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry) && Object.hasOwn(entry, "enabled"));
|
|
142
63
|
}
|
|
143
|
-
/** Parse task source YAML, routing per the
|
|
64
|
+
/** Parse task source YAML, routing per the table above. */
|
|
144
65
|
export function parseTaskSource(input) {
|
|
145
66
|
const { root, lineAt } = readBoundedTaskSourceYaml(input, { sourceLabel: "task source" });
|
|
146
67
|
const version = peekTaskSourceVersion(root);
|
|
147
68
|
if (version !== undefined && version !== TASK_SOURCE_V4_VERSION) {
|
|
148
|
-
if (version === 2 || version === 3)
|
|
149
|
-
|
|
150
|
-
if (typeof shimmed === "string") {
|
|
151
|
-
const v4 = parseTaskSourceV4({
|
|
152
|
-
yaml: shimmed,
|
|
153
|
-
filePath: input.filePath,
|
|
154
|
-
...(input.workspaceRoot ? { workspaceRoot: input.workspaceRoot } : {}),
|
|
155
|
-
});
|
|
156
|
-
warnOnce(`task-source:v${version}-shim:${input.filePath}`, `akm: task ${input.filePath} uses schema v${version} — auto-read as v4; run \`akm migrate apply\` to rewrite it and silence this`);
|
|
157
|
-
return Object.freeze({ version: 4, v4 });
|
|
158
|
-
}
|
|
159
|
-
throw unmigratableVersionError(input.filePath, version, shimmed.reason, shimmed.detail);
|
|
160
|
-
}
|
|
69
|
+
if (version === 2 || version === 3)
|
|
70
|
+
throw legacyVersionError(input.filePath, version);
|
|
161
71
|
throw unsupportedVersionError(input.filePath, version);
|
|
162
72
|
}
|
|
163
73
|
if (version === TASK_SOURCE_V4_VERSION && v4ScheduleHasRetiredEnabledKey(root)) {
|
|
164
|
-
|
|
165
|
-
if (typeof shimmed === "string") {
|
|
166
|
-
const v4 = parseTaskSourceV4({
|
|
167
|
-
yaml: shimmed,
|
|
168
|
-
filePath: input.filePath,
|
|
169
|
-
...(input.workspaceRoot ? { workspaceRoot: input.workspaceRoot } : {}),
|
|
170
|
-
});
|
|
171
|
-
warnOnce(`task-source:v4-schedule-enabled-shim:${input.filePath}`, `akm: task ${input.filePath} uses the retired schedule[].enabled field — auto-read with it ignored; run \`akm migrate apply\` to rewrite it and silence this`);
|
|
172
|
-
return Object.freeze({ version: 4, v4 });
|
|
173
|
-
}
|
|
174
|
-
// Version 4 is supported; a blocked outcome here means the file itself
|
|
175
|
-
// is malformed (`generated-v4-validation-failed`), not that this
|
|
176
|
-
// version needs a human decision — throw the v4 grammar error, not
|
|
177
|
-
// `unmigratableVersionError`.
|
|
178
|
-
throw new UsageError(shimmed.detail ?? shimmed.reason, "TASK_SOURCE_INVALID");
|
|
74
|
+
throw new UsageError(`Invalid task source v4 at ${input.filePath}: schedule[].enabled was removed (scheduler activation is host-local config). Run \`akm migrate apply\` to rewrite it.`, "TASK_SOURCE_INVALID", TASK_MIGRATE_HINT);
|
|
179
75
|
}
|
|
180
76
|
const documentOptions = {
|
|
181
77
|
filePath: input.filePath,
|