akm-cli 0.9.11 → 0.9.12

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.
Files changed (127) hide show
  1. package/CHANGELOG.md +166 -0
  2. package/STABILITY.md +6 -1
  3. package/dist/assets/hints/cli-hints-full.md +1 -1
  4. package/dist/assets/improve-strategies/consolidate.json +1 -1
  5. package/dist/assets/improve-strategies/default.json +1 -1
  6. package/dist/assets/improve-strategies/thorough.json +1 -2
  7. package/dist/cli/shared.js +16 -4
  8. package/dist/cli.js +15 -13
  9. package/dist/commands/agent/agent-dispatch.js +8 -0
  10. package/dist/commands/command/execution-source-loader.js +25 -22
  11. package/dist/commands/command/portable-template.js +4 -26
  12. package/dist/commands/config-cli.js +10 -4
  13. package/dist/commands/env/env-binding.js +10 -3
  14. package/dist/commands/env/env-cli.js +7 -0
  15. package/dist/commands/env/secret-cli.js +15 -4
  16. package/dist/commands/health/checks.js +186 -71
  17. package/dist/commands/health.js +16 -4
  18. package/dist/commands/improve/distill/quality-gate.js +2 -2
  19. package/dist/commands/improve/distill.js +28 -12
  20. package/dist/commands/improve/execution.js +1 -2
  21. package/dist/commands/improve/extract.js +82 -56
  22. package/dist/commands/improve/improve-strategies.js +26 -8
  23. package/dist/commands/improve/improve.js +13 -0
  24. package/dist/commands/improve/preparation.js +9 -6
  25. package/dist/commands/improve/reflect.js +61 -77
  26. package/dist/commands/lint/index.js +3 -1
  27. package/dist/commands/migrate-cli.js +6 -4
  28. package/dist/commands/proposal/drain-policies.js +22 -2
  29. package/dist/commands/proposal/repository.js +4 -4
  30. package/dist/commands/proposal/validators/proposal-quality-validators.js +23 -2
  31. package/dist/commands/proposal/validators/proposals.js +10 -19
  32. package/dist/commands/read/show.js +42 -31
  33. package/dist/commands/registry-cli.js +4 -2
  34. package/dist/commands/sources/init.js +4 -8
  35. package/dist/commands/sources/self-update.js +2 -2
  36. package/dist/commands/sources/source-clone.js +5 -7
  37. package/dist/commands/sources/sources-cli.js +3 -5
  38. package/dist/commands/tasks/tasks-cli.js +4 -12
  39. package/dist/commands/tasks/tasks.js +38 -35
  40. package/dist/commands/workflow-cli.js +17 -15
  41. package/dist/core/activation-policy.js +31 -3
  42. package/dist/core/adapter/execution-source.js +39 -11
  43. package/dist/core/asset/stash-meta.js +7 -41
  44. package/dist/core/common.js +8 -17
  45. package/dist/core/config/config-schema.js +3 -23
  46. package/dist/core/config/config-walker.js +50 -4
  47. package/dist/core/config/config.js +21 -5
  48. package/dist/core/config/legacy-source-shape-shim.js +79 -0
  49. package/dist/core/config/schema/embedding.js +2 -2
  50. package/dist/core/config/schema/engines.js +2 -2
  51. package/dist/core/config/schema/index-config.js +19 -21
  52. package/dist/core/config/schema/primitives.js +21 -10
  53. package/dist/core/config/schema/sources-bundles.js +1 -6
  54. package/dist/core/errors.js +2 -3
  55. package/dist/core/improve-types.js +17 -0
  56. package/dist/core/json-schema.js +1 -11
  57. package/dist/core/maintenance-barrier.js +17 -2
  58. package/dist/core/paths.js +12 -15
  59. package/dist/core/state/migrations.js +28 -0
  60. package/dist/core/state-db.js +28 -1
  61. package/dist/core/write-source.js +6 -6
  62. package/dist/indexer/bundle-identity-guard.js +3 -0
  63. package/dist/indexer/ensure-index.js +5 -0
  64. package/dist/indexer/indexer.js +11 -3
  65. package/dist/indexer/lookup/adapter-concept-owner.js +14 -3
  66. package/dist/indexer/passes/metadata.js +16 -5
  67. package/dist/indexer/search/search-fields.js +1 -30
  68. package/dist/integrations/agent/engine-resolution.js +15 -1
  69. package/dist/integrations/agent/model-map.js +16 -10
  70. package/dist/integrations/agent/prompts.js +13 -6
  71. package/dist/integrations/lockfile.js +22 -7
  72. package/dist/llm/client.js +16 -0
  73. package/dist/llm/index-passes.js +3 -2
  74. package/dist/output/shapes/passthrough.js +9 -3
  75. package/dist/output/shapes.js +5 -3
  76. package/dist/output/text/workflow-format.js +8 -1
  77. package/dist/scripts/akm-migrate-node.js +1461 -1267
  78. package/dist/scripts/akm-migrate.js +1460 -1266
  79. package/dist/setup/setup.js +14 -21
  80. package/dist/sources/include.js +150 -20
  81. package/dist/sources/providers/git-install.js +14 -12
  82. package/dist/sources/providers/git-provider.js +3 -3
  83. package/dist/sources/snapshot-fetchers/website-ingest.js +54 -16
  84. package/dist/sources/website-url.js +12 -4
  85. package/dist/storage/engines/sqlite-migrations.js +40 -10
  86. package/dist/storage/like-pattern.js +7 -0
  87. package/dist/storage/repositories/extract-sessions-repository.js +23 -0
  88. package/dist/storage/repositories/index-connection.js +27 -10
  89. package/dist/storage/repositories/index-entry-schema.js +19 -2
  90. package/dist/storage/repositories/index-schema.js +30 -9
  91. package/dist/storage/repositories/proposals-repository.js +2 -1
  92. package/dist/storage/repositories/task-history-repository.js +14 -7
  93. package/dist/storage/repositories/workflow-runs-repository.js +15 -1
  94. package/dist/storage/sqlite-read-snapshot.js +11 -9
  95. package/dist/tasks/backends/cron.js +34 -5
  96. package/dist/tasks/backends/launchd.js +23 -26
  97. package/dist/tasks/backends/schtasks.js +50 -3
  98. package/dist/tasks/frozen-script.js +2 -0
  99. package/dist/tasks/prepare/prepare.js +2 -7
  100. package/dist/tasks/prepare/script-capture.js +38 -6
  101. package/dist/tasks/schedule.js +154 -13
  102. package/dist/tasks/source/task-source-v3-frozen.js +0 -1
  103. package/dist/tasks/source/task-source-v4.js +0 -1
  104. package/dist/workflows/exec/child-workflow.js +2 -3
  105. package/dist/workflows/exec/exec-unit.js +3 -4
  106. package/dist/workflows/exec/run-workflow.js +19 -10
  107. package/dist/workflows/exec/step-work.js +35 -56
  108. package/dist/workflows/freeze/resolve-steps.js +19 -11
  109. package/dist/workflows/freeze/source-freeze.js +7 -0
  110. package/dist/workflows/freeze/targets/child-workflow.js +12 -18
  111. package/dist/workflows/freeze/targets/command.js +14 -2
  112. package/dist/workflows/ir/environment-v4.js +4 -2
  113. package/dist/workflows/ir/freeze-v4.js +2 -5
  114. package/dist/workflows/ir/plan-hash.js +0 -3
  115. package/dist/workflows/ir/schema-v4.js +14 -9
  116. package/dist/workflows/ir/schema.js +1 -3
  117. package/dist/workflows/resource-limits.js +35 -48
  118. package/dist/workflows/runtime/plan-classifier.js +89 -41
  119. package/dist/workflows/runtime/run-outputs.js +1 -21
  120. package/dist/workflows/runtime/runs.js +76 -150
  121. package/dist/workflows/source-files.js +28 -54
  122. package/dist/workflows/source-ir/program.js +2 -2
  123. package/dist/workflows/source-ir/semantics.js +5 -23
  124. package/docs/migration/v0.9.1-to-v0.9.2.md +20 -0
  125. package/docs/reference/cli.md +74 -17
  126. package/package.json +1 -1
  127. package/schemas/akm-config.json +5 -10
@@ -9,14 +9,24 @@ import { createLockPayload, probeLock, reclaimStaleLock, releaseLock, tryAcquire
9
9
  import { acquireMaintenanceBarrier } from "../core/maintenance-barrier.js";
10
10
  import { classifyPathAccess, describeInaccessiblePath } from "../core/path-access.js";
11
11
  import { getDataDir, getLockfileLockPath, getLockfilePath } from "../core/paths.js";
12
+ import { warn } from "../core/warn.js";
12
13
  // ── Lock sentinel ────────────────────────────────────────────────────────────
13
- const LOCK_MAX_RETRIES = 3;
14
- const LOCK_RETRY_DELAY_MS = 100;
14
+ const LOCK_ACQUIRE_TIMEOUT_MS = 30_000;
15
+ const LOCK_RETRY_INITIAL_DELAY_MS = 50;
16
+ const LOCK_RETRY_MAX_DELAY_MS = 1_000;
17
+ let lockAcquireTimeoutMsForTests;
18
+ export function _setLockAcquireTimeoutMsForTests(ms) {
19
+ lockAcquireTimeoutMsForTests = ms;
20
+ }
15
21
  async function acquireLockSentinel() {
16
22
  const sentinelPath = getLockfileLockPath();
17
23
  // Ensure the directory exists before attempting to create the sentinel.
18
24
  fs.mkdirSync(path.dirname(sentinelPath), { recursive: true });
19
- for (let attempt = 0; attempt < LOCK_MAX_RETRIES; attempt++) {
25
+ const timeoutMs = lockAcquireTimeoutMsForTests ?? LOCK_ACQUIRE_TIMEOUT_MS;
26
+ const deadline = Date.now() + timeoutMs;
27
+ let delayMs = LOCK_RETRY_INITIAL_DELAY_MS;
28
+ let announced = false;
29
+ for (;;) {
20
30
  const releaseBarrier = acquireMaintenanceBarrier();
21
31
  try {
22
32
  const ownership = tryAcquireLockSync(sentinelPath, createLockPayload());
@@ -31,12 +41,17 @@ async function acquireLockSentinel() {
31
41
  finally {
32
42
  releaseBarrier();
33
43
  }
34
- // Another process holds the lock — wait briefly before retrying.
35
- if (attempt < LOCK_MAX_RETRIES - 1) {
36
- await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_DELAY_MS));
44
+ // Another process holds the lock.
45
+ if (Date.now() >= deadline) {
46
+ throw new ConfigError(`Could not acquire lockfile sentinel at ${sentinelPath} after ${(timeoutMs / 1000).toFixed(1)}s; refusing to write without exclusive ownership.`, "INVALID_CONFIG_FILE");
47
+ }
48
+ if (!announced) {
49
+ announced = true;
50
+ warn("[akm] Waiting for another akm process to release the lockfile...");
37
51
  }
52
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
53
+ delayMs = Math.min(delayMs * 2, LOCK_RETRY_MAX_DELAY_MS);
38
54
  }
39
- throw new ConfigError(`Could not acquire lockfile sentinel at ${sentinelPath}; refusing to write without exclusive ownership.`, "INVALID_CONFIG_FILE");
40
55
  }
41
56
  // ── Read / Write ────────────────────────────────────────────────────────────
42
57
  export function readLockfile() {
@@ -447,3 +447,19 @@ export async function probeLlmReachable(config) {
447
447
  return { reachable: false, error: err instanceof Error ? err.message : String(err) };
448
448
  }
449
449
  }
450
+ /**
451
+ * Reachability probe for `akm health` (#914): one GET against the
452
+ * OpenAI-compatible `/models` route, bounded by `timeoutMs`. Any HTTP
453
+ * response counts as reachable — the question is whether the endpoint
454
+ * answers, not whether the route exists or the credential is right — so a
455
+ * cold local server is never asked to load a model just to be checked.
456
+ */
457
+ export async function probeLlmEndpoint(config, timeoutMs = 3_000) {
458
+ try {
459
+ await fetch(`${config.endpoint.replace(/\/+$/, "")}/models`, { signal: AbortSignal.timeout(timeoutMs) });
460
+ return { reachable: true };
461
+ }
462
+ catch (err) {
463
+ return { reachable: false, error: err instanceof Error ? err.message : String(err) };
464
+ }
465
+ }
@@ -1,7 +1,7 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { ConfigError } from "../core/errors.js";
4
+ import { warn } from "../core/warn.js";
5
5
  import { cloneExecutionJsonObject } from "../execution/json.js";
6
6
  import { lowerResolvedExecutionRequest } from "../integrations/agent/execution-lowering.js";
7
7
  import { prepareInlineExecution } from "../integrations/agent/inline-execution.js";
@@ -48,7 +48,8 @@ export function resolveIndexPassExecution(passName, config) {
48
48
  });
49
49
  const lowered = lowerResolvedExecutionRequest(prepared.request, prepared.config);
50
50
  if (lowered.runner.kind !== "llm") {
51
- throw new ConfigError(`Index pass ${JSON.stringify(passName)} requires an LLM engine; ${JSON.stringify(selectedEngine)} is not one.`, "INVALID_CONFIG_FILE");
51
+ warn("[akm] Index pass %s requires an LLM engine; %s is not one. Skipping this pass.", passName, selectedEngine);
52
+ return Object.freeze({ runner: undefined, notices: NO_LOWERING_NOTICES });
52
53
  }
53
54
  return Object.freeze({ runner: lowered.runner, notices: lowered.notices });
54
55
  }
@@ -3,7 +3,11 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  // #484: stamp schemaVersion + shape discriminator on passthrough envelopes so
5
5
  // third-party consumers can pin a schema version and dispatch on shape uniformly.
6
- // Idempotent never overwrites an existing schemaVersion or shape field.
6
+ // #918: also stamp `ok: true` so a caller branching on `.ok` sees the same
7
+ // field on every success envelope that it sees on the `{ok:false,...}` error
8
+ // envelope. Never overwrites an existing `shape`, `schemaVersion`, or `ok`;
9
+ // a command whose exit code grades the outcome emits through
10
+ // `outputWithExitCode` (src/cli/shared.ts), which sets `ok` from that code.
7
11
  //
8
12
  // Builds a shallow copy rather than mutating `result` in place: several
9
13
  // command results (e.g. `akm task sync --dry-run`'s `SchedulerPlanPreview`,
@@ -20,9 +24,11 @@ function makeStampHandler(command) {
20
24
  if (typeof result !== "object" || Array.isArray(result))
21
25
  return result;
22
26
  const obj = result;
23
- if (obj.shape !== undefined && obj.schemaVersion !== undefined)
24
- return obj;
25
27
  return {
28
+ // `ok` first so it heads the printed envelope instead of trailing a
29
+ // (possibly large) dump — the spread below still wins with `obj`'s own
30
+ // `ok` value when present, only its position is fixed here.
31
+ ok: obj.ok ?? true,
26
32
  ...obj,
27
33
  shape: obj.shape ?? command,
28
34
  schemaVersion: obj.schemaVersion ?? 1,
@@ -17,7 +17,7 @@
17
17
  * and throws for unknown commands (v1 spec §9 — exhaustive registry, no silent
18
18
  * fallback).
19
19
  */
20
- import { UsageError } from "../core/errors.js";
20
+ import { warnOnce } from "../core/warn.js";
21
21
  import { curateShapes } from "./shapes/curate.js";
22
22
  import { envListShapes } from "./shapes/env-list.js";
23
23
  import { eventsShapes } from "./shapes/events.js";
@@ -67,12 +67,14 @@ registerOutputShapes(BUILT_IN_OUTPUT_SHAPES);
67
67
  */
68
68
  const SHAPE_SUMMARY_COMMANDS = new Set(["show"]);
69
69
  export function shapeForCommand(command, result, detail, shape = "human") {
70
+ let effectiveShape = shape;
70
71
  if (shape === "summary" && !SHAPE_SUMMARY_COMMANDS.has(command)) {
71
- throw new UsageError(`'--shape summary' is not supported for 'akm ${command}'. It is only available on 'akm show'.`, "INVALID_SHAPE_VALUE");
72
+ warnOnce(`shape-summary-unsupported:${command}`, `[output] '--shape summary' is not supported for 'akm ${command}' (only 'akm show' has a summary projection); falling back to 'agent'.`);
73
+ effectiveShape = "agent";
72
74
  }
73
75
  const handler = getOutputShapeHandler(command);
74
76
  if (handler) {
75
- return handler(result, detail, shape);
77
+ return handler(result, detail, effectiveShape);
76
78
  }
77
79
  // v1 spec §9 (output-shape registry exhaustive): no silent JSON.stringify
78
80
  // fallback. A missing case here is a registration bug — fail loudly so
@@ -172,7 +172,14 @@ export function formatWorkflowRunPlain(result) {
172
172
  const run = typeof result.run === "object" && result.run !== null ? result.run : undefined;
173
173
  if (!run)
174
174
  return null;
175
- const lines = [`run: ${String(run.id ?? "unknown")}`, `status: ${String(run.status ?? "unknown")}`];
175
+ const lines = [];
176
+ // #919: `workflow run <ref>` silently resuming an existing active run (the
177
+ // #485 concurrency guard) is now announced up front, with the escape hatch.
178
+ if (result.resumed === true) {
179
+ lines.push(`resuming existing run ${String(run.id ?? "unknown")} for ${String(run.workflowRef ?? "this ref")}; ` +
180
+ `pass --new to start a fresh run`);
181
+ }
182
+ lines.push(`run: ${String(run.id ?? "unknown")}`, `status: ${String(run.status ?? "unknown")}`);
176
183
  // Creation-time notices (e.g. the implicit engine fallback) must survive the
177
184
  // text renderer: JSON/YAML pass them through, and dropping them here would
178
185
  // hide the announcement from the DEFAULT output mode — where it matters most.