@dzhechkov/keysarium 1.5.40 → 1.5.42

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/.dz-manifest.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "files": [
6
6
  {
7
7
  "path": "README.md",
8
- "sha256": "676f962e26cf674631c11f1593d533fa1e9c4cdee7e1d7786f7727fc1412366a"
8
+ "sha256": "7935edfd126b62acdb6f11962b194883ce0ff2369e17d034c8ca781d2369b043"
9
9
  },
10
10
  {
11
11
  "path": "README.ru.md",
@@ -17,7 +17,7 @@
17
17
  },
18
18
  {
19
19
  "path": "package.json",
20
- "sha256": "7b17d0b5b5a60c3ee74d7d93358040a1353c828a962df2530ba74dc982309089"
20
+ "sha256": "714af0158d54b6629e879b27f96ec7fc8d733f2e82a30a17432c1418b386c2ca"
21
21
  },
22
22
  {
23
23
  "path": "src/cli.js",
@@ -377,11 +377,11 @@
377
377
  },
378
378
  {
379
379
  "path": "templates/.claude/skills/feature-adr/modules/05-architecture.md",
380
- "sha256": "2ef7cf316903f0cbb1fabe1f0e1770c22b2cb3a11a4118cac0529c25074b5e8a"
380
+ "sha256": "4d20dbc85ea5bb93ca90fd8cd089255bab9c76a912ca3ad954f3a4bb670f3c45"
381
381
  },
382
382
  {
383
383
  "path": "templates/.claude/skills/feature-adr/modules/06-implementation-plan.md",
384
- "sha256": "3903e2694ad47782914b35869bbf19c5f0803b6dafdcfb629df343a5ff00d1b9"
384
+ "sha256": "b3efdfa1d44f4c51ff46551b5827066955c1f0bfee212d371ac1e2fb1c99980f"
385
385
  },
386
386
  {
387
387
  "path": "templates/.claude/skills/feature-adr/modules/07-code.md",
@@ -481,7 +481,7 @@
481
481
  },
482
482
  {
483
483
  "path": "templates/.claude/skills/feature-adr/scripts/check-plan-completeness.mjs",
484
- "sha256": "5cef77e68c58f163be64516013fb90866ef7201e415dc8888cc21a0f4d92b7d8"
484
+ "sha256": "eddf116620050e80b88497ace026fb8e0a12986f94f216181480c7daa0e08be4"
485
485
  },
486
486
  {
487
487
  "path": "templates/.claude/skills/frontend-design/LICENSE.txt",
@@ -985,5 +985,5 @@
985
985
  }
986
986
  ]
987
987
  },
988
- "signature": "HqvQFasiKkM8l4ksIkFcAGUHMtxvogzo9q7bO3Km4i2EQPoxwyWo6Z85GftW6HRLA+L75kTNPWpMU5avuxmJBA=="
988
+ "signature": "tqUAX98/iJ/i60v8VY10Q+L9vC+1P14cwe6z8Yg6dH8HzBux6tV2FlKoaVUjxzidn+dBKU775zMO2h1BUCuOBA=="
989
989
  }
package/README.md CHANGED
@@ -419,6 +419,16 @@ deliberately excluded — "skeleton first" is nonsense there.
419
419
 
420
420
  ## Status
421
421
 
422
+ `1.5.42` — refreshes the bundled `feature-adr` Step-5 module with the mandatory `Observability`
423
+ section. No keysarium behaviour changes. See `@dzhechkov/skills-feature-adr@1.5.4`.
424
+
425
+
426
+ `1.5.42` — refreshes the bundled `feature-adr` gate script with the C6 amendment-integrity fix (each
427
+ amendment scoped to its own block; closes a false refusal on markers below the old three-line window
428
+ AND a false pass where a testless amendment borrowed its neighbour's marker). No keysarium behaviour
429
+ changes. See `@dzhechkov/skills-feature-adr@1.5.3`.
430
+
431
+
422
432
  `1.5.38` — a fix to the bundled `feature-adr` gate script in `templates/`, no pipeline change.
423
433
 
424
434
  The bundled K2 plan-completeness gate now tells an **ABSENT** `00_complexity_assessment.md` from a
@@ -427,5 +437,5 @@ carrying no acid table is an honest SKIP. Both used to report as a clean skip, s
427
437
  silently switched itself off whenever Step 0 wrote nothing — MEASURED 2026-08-21, 66 of 199 features
428
438
  carried that file and the last four in a row did not.
429
439
 
430
- `1.5.40` — the bundled `feature-adr` Step-8 module now describes the amendment gate as the command
440
+ `1.5.42` — the bundled `feature-adr` Step-8 module now describes the amendment gate as the command
431
441
  `dz amendment-check` instead of a judgement the reviewer is asked to make. Text only; no pipeline change.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dzhechkov/keysarium",
3
- "version": "1.5.40",
3
+ "version": "1.5.42",
4
4
  "description": "AI Case Research Toolkit for Claude Code — full 7-phase pipeline with feature-adr, dream cycles, background workers, multi-platform support, reward learning, and Cloud.ru AI Factory mapping (--ai-factory flag)",
5
5
  "main": "src/cli.js",
6
6
  "bin": {
package/sbom.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "hashes": [
16
16
  {
17
17
  "alg": "SHA-256",
18
- "content": "676f962e26cf674631c11f1593d533fa1e9c4cdee7e1d7786f7727fc1412366a"
18
+ "content": "7935edfd126b62acdb6f11962b194883ce0ff2369e17d034c8ca781d2369b043"
19
19
  }
20
20
  ]
21
21
  },
@@ -45,7 +45,7 @@
45
45
  "hashes": [
46
46
  {
47
47
  "alg": "SHA-256",
48
- "content": "7b17d0b5b5a60c3ee74d7d93358040a1353c828a962df2530ba74dc982309089"
48
+ "content": "714af0158d54b6629e879b27f96ec7fc8d733f2e82a30a17432c1418b386c2ca"
49
49
  }
50
50
  ]
51
51
  },
@@ -945,7 +945,7 @@
945
945
  "hashes": [
946
946
  {
947
947
  "alg": "SHA-256",
948
- "content": "2ef7cf316903f0cbb1fabe1f0e1770c22b2cb3a11a4118cac0529c25074b5e8a"
948
+ "content": "4d20dbc85ea5bb93ca90fd8cd089255bab9c76a912ca3ad954f3a4bb670f3c45"
949
949
  }
950
950
  ]
951
951
  },
@@ -955,7 +955,7 @@
955
955
  "hashes": [
956
956
  {
957
957
  "alg": "SHA-256",
958
- "content": "3903e2694ad47782914b35869bbf19c5f0803b6dafdcfb629df343a5ff00d1b9"
958
+ "content": "b3efdfa1d44f4c51ff46551b5827066955c1f0bfee212d371ac1e2fb1c99980f"
959
959
  }
960
960
  ]
961
961
  },
@@ -1205,7 +1205,7 @@
1205
1205
  "hashes": [
1206
1206
  {
1207
1207
  "alg": "SHA-256",
1208
- "content": "5cef77e68c58f163be64516013fb90866ef7201e415dc8888cc21a0f4d92b7d8"
1208
+ "content": "eddf116620050e80b88497ace026fb8e0a12986f94f216181480c7daa0e08be4"
1209
1209
  }
1210
1210
  ]
1211
1211
  },
@@ -118,6 +118,32 @@ GET /api/v1/{resource}/:id
118
118
  Errors: 401, 404
119
119
  ```
120
120
 
121
+ ## Observability — a MANDATORY section of `05_architecture.md`
122
+
123
+ The artifact must carry a section headed exactly **`Observability`**, answering how anyone would
124
+ know this feature is working once it ships:
125
+
126
+ - what it **logs**, and at what level;
127
+ - what it **counts** — the one or two numbers that would move if it broke;
128
+ - what a **failure looks like from outside** — the symptom, not the stack trace;
129
+ - **who would notice**, and how.
130
+
131
+ If the feature genuinely emits nothing at runtime — a pure refactor, a doc change, a gate that only
132
+ runs in CI — write **"nothing to observe"** and say why. That is a complete answer, not a gap. What
133
+ is not acceptable is leaving the question unanswered.
134
+
135
+ The heading is read by a machine (`dz score` reports it as a discipline), so it is spelled exactly
136
+ `Observability` — the prompt above and the check derive that word from one shared constant, because
137
+ a prompt asking for one heading while a check greps another produces a gate that fails every honest
138
+ run.
139
+
140
+ **Why this section exists.** MEASURED 2026-08-25: across 107 existing `05_architecture.md` files,
141
+ ZERO carried such a section, and the word `observability` appeared nowhere in the pipeline's own
142
+ prompts. The pipeline kept five telemetry stores about itself and asked for none about what it
143
+ built. The two capable skills — `observability` (818 lines) and `observability-testing-patterns`
144
+ (946 lines) — were fully written and unreachable, because nothing called them. This section is the
145
+ call site.
146
+
121
147
  ## Write discipline (the 180-second rule)
122
148
 
123
149
  An executor that returns from a tool call and then thinks in silence past **180 seconds** is killed by the
@@ -185,6 +185,11 @@ Create `features/<slug>/06_implementation_plan.md` with:
185
185
  - `## Amendments` — every correction folded into this plan (a Step-3.5 CONDITIONAL condition, a
186
186
  challenge-panel confirmed finding, a user checkpoint steer) as a fixed-shape row:
187
187
  `AM-N (source): <change>. Confirmation: <property> → test `test_name` (fails if reverted).`
188
+ The row is MACHINE-READ by the K2 C6 gate: the `→ test \`name\`` marker (or `superseded by AM-N`)
189
+ must sit inside that amendment's OWN block — anywhere between its `AM-N` line and the line where
190
+ the NEXT `AM-N` begins. Multi-line amendments are fine; what is NOT fine is putting a marker after
191
+ the following amendment has already started, because it then belongs to that one. A bare range
192
+ like `AM-1..AM-4` never opens a row.
188
193
  A safeguard amendment's named test must prove it TRIGGERS on a real input, not merely that its code
189
194
  path exists. Step 8 verifies every named test exists and is non-vacuous (`dz discrimination-check`).
190
195
 
@@ -327,13 +327,36 @@ else for (const t of acidTokens) if (!new RegExp(`\\b${t.replace(/[.*+?^${}()|[\
327
327
  }
328
328
  }
329
329
  if (sectionStart >= 0) {
330
- for (const lnRaw of amSection.split('\n')) {
331
- const ln = lnRaw.trim();
332
- const am = /^(?:[-*|]\s*)?\*{0,2}(AM-(?:CP-)?\d+)\*{0,2}\b/.exec(ln);
333
- if (!am) continue;
334
- const hasTest = /\u2192\s*test\b|->\s*test\b/.test(ln) || /\u2192\s*test\b|->\s*test\b/.test(amSection.slice(amSection.indexOf(lnRaw)).split('\n').slice(0, 3).join('\n'));
335
- const superseded = /superseded by AM-(?:CP-)?\d+/i.test(ln);
336
- if (!hasTest && !superseded) failures.push(`C6: ${am[1]} carries neither \`\u2192 test <name>\` nor \`superseded by AM-N\` — an amendment without a confirmation is a wish, and a retracted one must say its successor`);
330
+ // Each amendment's confirmation is looked for in ITS OWN BLOCK: from its definition line to the
331
+ // line where the NEXT amendment begins. Three defects die with the old three-line window
332
+ // (MEASURED 2026-08-25 against the 142-plan corpus — 292 C6 failures before, 33 after, and ZERO
333
+ // rows newly caught that pass today):
334
+ // • FALSE REFUSAL — a marker on the `Confirmation:` line 4+ lines down was invisible, so plans
335
+ // that DID name their test were rejected (7 per run, twice in one day, on a user's machine).
336
+ // • FALSE PASS — the window is three LINES, not one amendment, so `- AM-1 testless` followed by
337
+ // `- AM-2 … -> test x` PASSED: AM-1 borrowed its neighbour's marker. That is the safety half,
338
+ // and it is why the boundary is the next DEFINITION rather than a blank line — a blank line
339
+ // does not separate adjacent bullet rows.
340
+ // • A substring seek (`amSection.indexOf(lnRaw)`) let a duplicated line read someone else's
341
+ // window. Indices remove that hazard for free.
342
+ // The boundary is not invented: parseAmendments() in harness-core/src/amendment-trace.ts has used
343
+ // the same next-definition bound all along, so this also ends a divergence between two checkers.
344
+ const secLines = amSection.split('\n');
345
+ // The bullet stays OPTIONAL: requiring it drops 104 of the corpus's 347 real AM rows out of the
346
+ // check entirely (MEASURED). The `(?!\s*\.)` guard is what refuses a wrapped `AM-1..AM-4;`
347
+ // range preamble, which used to open a phantom amendment and double-count AM-1 — it costs 0 rows.
348
+ const DEF = /^(?:[-*|]\s*)?\*{0,2}(AM-(?:CP-)?\d+)\*{0,2}\b(?!\s*\.)/;
349
+ // `tests?` — the two-id form `-> tests \`a\` and \`b\`` is corpus-canonical and is what
350
+ // amendment-trace.ts parses; matching only the singular turned two currently-green rows red.
351
+ const MARK = /\u2192\s*tests?\b|->\s*tests?\b/;
352
+ const defs = [];
353
+ secLines.forEach((l, i) => { const m = DEF.exec(l.trim()); if (m) defs.push({ i, id: m[1] }); });
354
+ for (let k = 0; k < defs.length; k++) {
355
+ const to = k + 1 < defs.length ? defs[k + 1].i : secLines.length;
356
+ const block = secLines.slice(defs[k].i, to).join('\n');
357
+ const hasTest = MARK.test(block);
358
+ const superseded = /superseded by AM-(?:CP-)?\d+/i.test(block);
359
+ if (!hasTest && !superseded) failures.push(`C6: ${defs[k].id} carries neither \`\u2192 test <name>\` nor \`superseded by AM-N\` — an amendment without a confirmation is a wish, and a retracted one must say its successor`);
337
360
  }
338
361
  }
339
362
  }