akm-cli 0.10.261011-beta → 0.10.261012-beta

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 CHANGED
@@ -6,6 +6,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.10.261012] - 2026-10-22
10
+
11
+ ### Changed
12
+
13
+ - Distill writes more useful lessons without writing wrong ones. The lesson
14
+ writer treats a tested or measured result about a change or method, stated
15
+ with the conditions and limits it held under, as a lesson. It answers NONE for
16
+ a dated status, for the report of one run or day whose cause is only suspected
17
+ with no fix verified, and for a recap or reminder list whose rules a related
18
+ asset already states. Lessons are shorter (about half the memory), in the
19
+ writer's own words, and keep the memory's numbers, names and terms. The lesson
20
+ judge's REUSABLE criterion credits such a tested result and scores a lesson
21
+ drawn from an unconfirmed one-run report as not reusable; judging an update
22
+ to an existing lesson keeps the original criterion.
23
+
24
+ ### Fixed
25
+
26
+ - A SIGINT or SIGTERM that reached akm just after it started an agent or harness
27
+ in its own process group could end akm with that group still running (#1230).
28
+ The signal guard is now in place before the child is spawned, so the group is
29
+ always terminated with akm.
30
+
9
31
  ## [0.10.261011] - 2026-10-22
10
32
 
11
33
  ### Changed
@@ -4,7 +4,10 @@ holds a lesson and, if it does, write the lesson.
4
4
 
5
5
  A memory holds a lesson when it states a cause and what to do about it: a
6
6
  failure or surprise with its cause and the fix that worked, or a rule with the
7
- reason it holds. It holds a lesson even when it is short and names one project,
7
+ reason it holds. A measured or tested result also holds a lesson when someone
8
+ could reuse it, even with no fix: what was found, under which conditions, and
9
+ the limits the memory states (what was not checked, not confirmed, or only
10
+ held in one place). It holds a lesson even when it is short and names one project,
8
11
  tool or incident, if the cause and the fix would help someone in a similar
9
12
  situation.
10
13
 
@@ -13,9 +16,15 @@ or decided, what is pending or planned, how a system is set up now, or the steps
13
16
  of a procedure, with no failure and cause behind it, or when its feedback says
14
17
  only that it is out of date or superseded. ANSWER NONE then: the single word and
15
18
  nothing else. A reply bound to a JSON schema answers NONE by
16
- setting `decision` to `none` and leaving the other fields empty. Answer NONE too
19
+ setting `decision` to `none` and leaving the other fields empty. A status on
20
+ a date (blocked, waiting on someone, pending approval, ready to ship) is not a
21
+ result, and neither is the report of one run or day (counts passed and failed,
22
+ durations, which items failed) whose cause is only suspected, with no fix
23
+ verified: answer NONE, even if a rule could be drawn from it. A result that holds a lesson is a finding about a change or a method (what
24
+ it did, under which conditions), not an account of how one run went. Answer NONE too
17
25
  when a related asset listed below the memory already states the rule the memory
18
- would give.
26
+ would give, including when the memory is a recap or a list of reminders whose
27
+ rules a related asset already states.
19
28
 
20
29
  When the memory holds a lesson, write it from what the memory and its feedback
21
30
  say, and nothing more:
@@ -23,7 +32,11 @@ say, and nothing more:
23
32
  - Keep the scope the memory has. A fix verified in one place is a fix for that
24
33
  place, and what was not checked stays unchecked. One case is not "always" or
25
34
  "never".
26
- - Be shorter than the memory.
35
+ - Be clearly shorter than the memory (about half its length; the description,
36
+ when_to_use and body together, not only the body), and write it in
37
+ your own words. Leave out the incident's
38
+ story; keep only the rule, its cause and its limits. Keep the memory's
39
+ numbers, names, versions and terms exactly as written.
27
40
 
28
41
  YOUR RESPONSE MUST START EXACTLY WITH `---` ON THE VERY FIRST LINE.
29
42
  DO NOT output any prose, explanation, or code fences before or after.
@@ -34,7 +47,7 @@ description: <one complete sentence (ending with `.`) summarising what the lesso
34
47
  when_to_use: <one complete sentence describing the concrete trigger condition>
35
48
  ---
36
49
 
37
- <lesson body — plain markdown, as short as the memory allows>
50
+ <lesson body — at most three sentences that add what the description lacks (the cause, the facts, the limits); never repeat the description>
38
51
 
39
52
  ## description field (MANDATORY)
40
53
  - A single complete sentence in present tense, 20–400 chars, NO markdown.
@@ -222,7 +222,9 @@ export function buildJudgePrompt(lessonContent, sourceContent, related, feedback
222
222
  "You are evaluating a lesson an agent wrote from a memory and the feedback about it, for an akm knowledge base.",
223
223
  "",
224
224
  "Score this lesson on each criterion from 1 (poor) to 5 (excellent):",
225
- "1. REUSABLE: Does the lesson state a rule an agent can use on another occasion, with the reason it holds? Score 1-2 when it only records what was done, shipped, decided, found or is pending, on a date or for one build, machine or project, or how a system is set up now, however it is phrased. Score 4-5 for a rule with its reason.",
225
+ extending !== undefined
226
+ ? "1. REUSABLE: Does the lesson state a rule an agent can use on another occasion, with the reason it holds? Score 1-2 when it only records what was done, shipped, decided, found or is pending, on a date or for one build, machine or project, or how a system is set up now, however it is phrased. Score 4-5 for a rule with its reason."
227
+ : "1. REUSABLE: Does the lesson state a rule or a result an agent can use on another occasion, with the reason or the conditions it holds under? Score 1-2 when it only records what was done, shipped, decided or is pending, on a date or for one build, machine or project, the counts or outcomes of one run, or how a system is set up now, however it is phrased. Score 1-2 also when the source memory is the report of one run, build or day (its date, counts, durations, which items passed or failed) whose cause is only suspected, with no fix verified, and the lesson turns that suspicion into a cause or a rule. Score 4-5 for a rule with its reason, or for a tested or measured result about a change or method, stated with the conditions and limits it held under (what was not checked stays a limit).",
226
228
  extending !== undefined
227
229
  ? "2. NON-REDUNDANCY: The proposed lesson is the existing lesson below with lines added. Compare each added line (a line the existing lesson does not have) only with the existing lesson, never with the source memory. Redundancy means the information is already in the existing lesson. Score 1-2 when an added line only says again what the existing lesson says: its rule or cause in other words, or the same rule applied to an example from the memory. Score 4-5 when every added line states a fact the existing lesson does not contain (a cause, number, version, limit, consequence or observation), however specific or tied to one incident it is: whether the lesson is general enough is REUSABLE's question, asked of the whole lesson, never of this criterion."
228
230
  : '2. NON-REDUNDANCY: Compare the lesson only with the assets listed under "Existing assets nearest the new lesson" (each starts with "Existing asset ref:"); never with the source memory. When that list is absent, score 5. Score 1-2 when a listed asset already states the same rule, or states most of what the lesson says in broader words. Score 4-5 when the lesson gives a rule none of the listed assets gives, or when they are on other subjects.',
@@ -135,9 +135,21 @@ function removeSignalGuard() {
135
135
  * else handles the signal. A command that handles it itself (`workflow run`,
136
136
  * `improve`, task runs) unwinds through its own cleanup, which already aborts
137
137
  * its children, and must not have its handling pre-empted by a re-raise.
138
+ *
139
+ * They go in BEFORE the spawn ({@link installSignalGuard}): a signal that lands
140
+ * between the spawn and the registration would otherwise meet the default
141
+ * disposition, end akm, and leave the new group running (#1230). The listener
142
+ * runs on the event loop, so it always sees the child registered here.
138
143
  */
139
144
  function registerLiveGroupChild(child) {
140
145
  liveGroupChildren.add(child);
146
+ return () => {
147
+ liveGroupChildren.delete(child);
148
+ if (liveGroupChildren.size === 0)
149
+ removeSignalGuard();
150
+ };
151
+ }
152
+ function installSignalGuard() {
141
153
  if (!signalGuardHandlers && process.listenerCount("SIGINT") === 0 && process.listenerCount("SIGTERM") === 0) {
142
154
  const handlers = [];
143
155
  for (const signal of ["SIGINT", "SIGTERM"]) {
@@ -155,11 +167,6 @@ function registerLiveGroupChild(child) {
155
167
  }
156
168
  signalGuardHandlers = handlers;
157
169
  }
158
- return () => {
159
- liveGroupChildren.delete(child);
160
- if (liveGroupChildren.size === 0)
161
- removeSignalGuard();
162
- };
163
170
  }
164
171
  /**
165
172
  * The joined, human-readable reason ONE managed run's capture is incomplete, or
@@ -383,11 +390,17 @@ export async function runManagedSubprocess(cmd, opts) {
383
390
  stderrRead: EMPTY_READ,
384
391
  };
385
392
  }
393
+ // A termination signal to this process takes the own-group child down too.
394
+ const guardsGroup = capture && spawnsOwnProcessGroup();
395
+ if (guardsGroup)
396
+ installSignalGuard();
386
397
  let proc;
387
398
  try {
388
399
  proc = spawnFn(cmd, buildSpawnOptions(opts));
389
400
  }
390
401
  catch (err) {
402
+ if (guardsGroup && liveGroupChildren.size === 0)
403
+ removeSignalGuard();
391
404
  return {
392
405
  exitCode: null,
393
406
  stdout: "",
@@ -446,8 +459,7 @@ export async function runManagedSubprocess(cmd, opts) {
446
459
  else
447
460
  abortSignal.addEventListener("abort", onAbort, { once: true });
448
461
  }
449
- // A termination signal to this process takes the own-group child down too.
450
- const unregisterLiveChild = capture && spawnsOwnProcessGroup() ? registerLiveGroupChild({ proc, terminate: onAbort }) : () => { };
462
+ const unregisterLiveChild = guardsGroup ? registerLiveGroupChild({ proc, terminate: onAbort }) : () => { };
451
463
  // Stream-drain timeout: a short grace once nothing living owns the pipe any
452
464
  // more, or a one-hour safety bound when execution itself is unbounded.
453
465
  //
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akm-cli",
3
- "version": "0.10.261011-beta",
3
+ "version": "0.10.261012-beta",
4
4
  "type": "module",
5
5
  "description": "akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cursor.",
6
6
  "keywords": [