@dzhechkov/harness-cli 0.8.10 → 0.8.15

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,11 +5,11 @@
5
5
  "files": [
6
6
  {
7
7
  "path": "LICENSE",
8
- "sha256": "3b93f7070f6843f37e0cae255f7caff22b466a4017fd2020d7d3216237e5a701"
8
+ "sha256": "ec1ddbebcf25c3eb0423b8d7d5ebcdf9adda31455ac7257b3d156978880866cf"
9
9
  },
10
10
  {
11
11
  "path": "README.md",
12
- "sha256": "db656fad1737e98dc639d06388a5f4ac00fa4024b195c673c3deef2ede3a40d5"
12
+ "sha256": "ce474e87118603123db01d0d6a15d922e874aa9eaa33229882d930dc7dde04d7"
13
13
  },
14
14
  {
15
15
  "path": "dist/bin.d.ts",
@@ -33,31 +33,47 @@
33
33
  },
34
34
  {
35
35
  "path": "dist/boolean-flags.d.ts.map",
36
- "sha256": "454794ad9738157ca422201aaedf99704a2c525e32d48ee2dac533d498bf1271"
36
+ "sha256": "a15e65e835e952abf9d93fba352c2c6f840ce37458e22b52e8be2b6bd87b99fd"
37
37
  },
38
38
  {
39
39
  "path": "dist/boolean-flags.js",
40
- "sha256": "cd2cfc484dd9d0bcb1063be0f55e12dbd6b49e2642568bd7ad2a5f045b83be5b"
40
+ "sha256": "a0168adf31a200eaf7891f99ba6609cb08b5a1960ef1aaeff678e976ebc1f458"
41
41
  },
42
42
  {
43
43
  "path": "dist/boolean-flags.js.map",
44
- "sha256": "ce07c1e9270067794d744c59cdacd083e22ff3a2e38f10b7b41e3397b3ad2ff5"
44
+ "sha256": "879fce0bcbe4d86f4c45920fb55696d674e4b13753c34223570e1ce4cc4845ab"
45
45
  },
46
46
  {
47
47
  "path": "dist/cli.d.ts",
48
- "sha256": "0969e281fe2684f4143a3bf4b8cfd42894809a29d0d7f59afe0b90447c1a0cd4"
48
+ "sha256": "ed6343630400b6607e3b2eaadd9d57e694da5e0465a5136e802e6937175de190"
49
49
  },
50
50
  {
51
51
  "path": "dist/cli.d.ts.map",
52
- "sha256": "21b330f7ea9942f8356ca69990a7324b9441ac1247f0d8b45aafdc71b70b1ed6"
52
+ "sha256": "15386e1db8287bd1345528d08ef719be9044d5eac621fce86ea6cb13d2866c45"
53
53
  },
54
54
  {
55
55
  "path": "dist/cli.js",
56
- "sha256": "dcf63e22be659557cc6be3f3d339da93d31dcd2e7ed14e653de7d254e1f151c5"
56
+ "sha256": "d717bdd37c4e8d04d3364dbe37b7a878eadf8d38a25f6ababec98017208cc506"
57
57
  },
58
58
  {
59
59
  "path": "dist/cli.js.map",
60
- "sha256": "e232d50c27c05c95d479db0d2b861a042355db56cb8f570d371b5f0a4766e05e"
60
+ "sha256": "649c6d2b02b478362d85882c5b01be755a2df4ccfe2f91474d5a418aae5f8b05"
61
+ },
62
+ {
63
+ "path": "dist/command-inventory.d.ts",
64
+ "sha256": "152bdaf3aabeed5d579432be6597f2a5866fb70a2cf1961c1756722b3fec827e"
65
+ },
66
+ {
67
+ "path": "dist/command-inventory.d.ts.map",
68
+ "sha256": "17a8834ab57b6727779312025b612ecca0e1ce4b48c4d111674cc8a633c112af"
69
+ },
70
+ {
71
+ "path": "dist/command-inventory.js",
72
+ "sha256": "cff82b1185024a68126dca6c52eae394bc4ac236785673e54ecbc7d5864c4bba"
73
+ },
74
+ {
75
+ "path": "dist/command-inventory.js.map",
76
+ "sha256": "1c77452f22d0bff37809a57c98e98de37b815879330dff5ce4b17b4afa42240c"
61
77
  },
62
78
  {
63
79
  "path": "dist/core-compat.d.ts",
@@ -77,19 +93,19 @@
77
93
  },
78
94
  {
79
95
  "path": "dist/index.d.ts",
80
- "sha256": "7f2301a59931e768865a58b7681882dc3b6d9b19b4d6ba2d6836e153c15c39f0"
96
+ "sha256": "0b1c9584afba354756cf063df029c851cd1ccf34f613b9d1a10ba8769a100821"
81
97
  },
82
98
  {
83
99
  "path": "dist/index.d.ts.map",
84
- "sha256": "f90807882ce10b96cb22af34d9a612a87f8e3869c338ebed666f9f7677bb651c"
100
+ "sha256": "9ae1bd30f3c96ce9f1eddcd6d1aca95ae9cae7341157b655c0b96417bec8024a"
85
101
  },
86
102
  {
87
103
  "path": "dist/index.js",
88
- "sha256": "d492db6c67df4c7d78cdf50bcfb55da9609e2891178d5fdd1fa91ef973d81a62"
104
+ "sha256": "100dff8ee9a0da5fd2e7118ea8bf95f44c2e217a884e4eada2f1e33f1348ade1"
89
105
  },
90
106
  {
91
107
  "path": "dist/index.js.map",
92
- "sha256": "6a5a693bc1035cc67ea572e609d4e2fb05580c9268821e25ba8d278e61635033"
108
+ "sha256": "c1b84b471f6f22fb2556073a8357e51d0ef53481a1e5be8e33541403f908776f"
93
109
  },
94
110
  {
95
111
  "path": "dist/install-spec.d.ts",
@@ -113,15 +129,15 @@
113
129
  },
114
130
  {
115
131
  "path": "dist/known-flags.d.ts.map",
116
- "sha256": "bcc70b16fc530e09a764852e6d57f4858161244555b0d270fca8335b0a800a49"
132
+ "sha256": "30ee87b379eddb4da7f497c7b5f330e803e15d667d875a77f36eea9a374b8949"
117
133
  },
118
134
  {
119
135
  "path": "dist/known-flags.js",
120
- "sha256": "dc11bc77b47cd80ca6f0efb0f4d991ddc6060fe59bd30824178cc9c8add6bcaf"
136
+ "sha256": "9d526ae74a6026c47e0fcbce5b5fd1e980fe1a5c9bd80a95d878f31b83c530cb"
121
137
  },
122
138
  {
123
139
  "path": "dist/known-flags.js.map",
124
- "sha256": "1b5a6a740581a5ba0aa26533648ffa603411ac0ba5d9c243bd5005593e7ce11c"
140
+ "sha256": "23c7e0e140989a4aa1225b6b0027cffdc69e38a0ab2a1842c6b17e85e0685eb3"
125
141
  },
126
142
  {
127
143
  "path": "keys/README.md",
@@ -133,7 +149,7 @@
133
149
  },
134
150
  {
135
151
  "path": "package.json",
136
- "sha256": "8c3f7e57b7bd8fc7534c60ca0de986466095b9c09d526077cf81c8010afe30ba"
152
+ "sha256": "18211ce5363b82fbaea0593609b687c3705a60dd559c80a96d198f19c3f82402"
137
153
  },
138
154
  {
139
155
  "path": "src/bin.ts",
@@ -141,11 +157,15 @@
141
157
  },
142
158
  {
143
159
  "path": "src/boolean-flags.ts",
144
- "sha256": "8d9fe5f91b143cbecafacf69489f284ab312f277b8f84da0558ee572e4203b41"
160
+ "sha256": "36af96b1f0d629d90edbceafa2ce94aee5d31b51cb9ce9dbb73163d3f6643121"
145
161
  },
146
162
  {
147
163
  "path": "src/cli.ts",
148
- "sha256": "d235206d3cc7989890de5f9b5374755bb0a729ed2bfb63050b51a7d11dad9a8c"
164
+ "sha256": "7f6d7dbd6216436ffc19888b167d05b77cf6407758d4805d793f8830da315260"
165
+ },
166
+ {
167
+ "path": "src/command-inventory.ts",
168
+ "sha256": "a20358964708e3b0911b6aca39eb116b96c2972e512ef04fb9538f45fb82f075"
149
169
  },
150
170
  {
151
171
  "path": "src/core-compat.ts",
@@ -153,7 +173,7 @@
153
173
  },
154
174
  {
155
175
  "path": "src/index.ts",
156
- "sha256": "ece9dc7be312c38212e72440493221dc816ea109d1ba8842d2ed3410445b65a1"
176
+ "sha256": "e1ae4d6fcbbe51dd8c2c618b13f2c3dcd2e143004ffcb858e94add64d4f426bc"
157
177
  },
158
178
  {
159
179
  "path": "src/install-spec.ts",
@@ -161,9 +181,9 @@
161
181
  },
162
182
  {
163
183
  "path": "src/known-flags.ts",
164
- "sha256": "6365829621a8f3b50381310f4c62ae5a5c4c1625587acf2b73d3f3486ecfc791"
184
+ "sha256": "a744b4f1ec364464ae63acbdba613eb7a389c14cf8f98c89b5d712877326966f"
165
185
  }
166
186
  ]
167
187
  },
168
- "signature": "8YsvP0BnmZosr5jWsex+6d5UvqzGxIxzM4qBpf+iOO/E3xEcOV/DANFrklGs3XpMN+Vcgz/ult9JnixhAlK9Cw=="
188
+ "signature": "QOlXcEGN7yGgepJKgYaeJDGUci1a64zn/AbYVSQkGEE/xOY9lEACQCx7A/DKPQlWrx2BvND/6XC7qJwX9p7+Aw=="
169
189
  }
package/LICENSE CHANGED
@@ -19,3 +19,16 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
+
23
+ ---
24
+
25
+ Third-party licenses
26
+
27
+ This package bundles the frontend-design skill template, which is licensed
28
+ under the Apache License, Version 2.0 (not MIT). The full Apache-2.0 license
29
+ text ships alongside the skill at:
30
+
31
+ templates/.claude/skills/frontend-design/LICENSE.txt
32
+
33
+ All other contents of this package are covered by the MIT license above.
34
+ The package's SPDX license expression is: MIT AND Apache-2.0
package/README.md CHANGED
@@ -279,7 +279,7 @@ you know exactly which file is at fault, and you know whose defect it is.
279
279
 
280
280
  ## User Journey — from install to mastery
281
281
 
282
- All 83 commands (MEASURED — reproducer: `node --input-type=module -e "import('./dist/index.js').then(m=>console.log(m.DZ_COMMANDS.length))"` from this package; rendered help documents 80 unique top-level names, pinned by `test/command-count.test.ts`) mapped to a real workflow:
282
+ All 87 commands (MEASURED — reproducer: `node --input-type=module -e "import('./dist/index.js').then(m=>console.log(m.DZ_COMMANDS.length))"` from this package; rendered help documents 88 unique top-level names — the 87 plus the built-in `help` — pinned NAME-FOR-NAME by `test/command-inventory-parity.test.ts`) mapped to a real workflow:
283
283
 
284
284
  ```
285
285
  DISCOVER → INSTALL → USE → CREATE → MAINTAIN → SHARE
@@ -379,6 +379,28 @@ dz setup --target claude-code --preset devops # pretrain + hooks + memory + ins
379
379
 
380
380
  # With AgentDB vector memory (semantic search + self-learning):
381
381
  dz setup --target claude-code --preset devops --memory agentdb # vector memory + agentdb MCP server
382
+ ```
383
+
384
+ `dz setup` also installs the **destructive-command guard** into your project: the hook body at
385
+ `.claude/hooks/destructive-guard.cjs` plus its `PreToolUse` entry on `^Bash$` in
386
+ `.claude/settings.json`. It refuses a deletion whose target is a LITERAL path into a protected store
387
+ (`.dz/`, `.agentic-qe/`, a `.db`/`.sqlite`/`.rvf` file) and prints, on every verdict it speaks about,
388
+ the four things it does NOT decide — a target held in a shell variable, a relative target after a
389
+ directory change, `git rm`, and quoted text under any head other than the delete verb or `sh -c`.
390
+ `dz hooks-sync --target codex` installs the same check on the Codex host. Both hook bodies resolve
391
+ `@dzhechkov/harness-core` by path, including the absolute path of the installation that emitted
392
+ them, so a global install (`npm i -g @dzhechkov/harness-cli`) guards a project that has no local
393
+ copy of the package. If the guard cannot load it says so on one line and lets the command through —
394
+ it never blocks on its own failure, and it is never silent about failing.
395
+
396
+ Setup is additive here too, and deliberately incurious: if `.claude/hooks/destructive-guard.cjs`
397
+ already exists WITHOUT dz's ownership marker, the file is yours. dz does not overwrite it, does not
398
+ touch your `settings.json` entry for it, and — since a hook can only be proven to work by running it
399
+ — does not RUN it either: a file a repository shipped is not something `dz setup` may execute on
400
+ your behalf. You get one line saying so, and `dz setup --force` replaces the file (keeping a
401
+ timestamped backup) if that is what you want.
402
+
403
+ ```bash
382
404
 
383
405
  # Or just install skills (no learning):
384
406
  dz init --target claude-code --preset devops # 30 DevOps skills
@@ -930,6 +952,39 @@ extracts you scope are what leaves the machine. RU: мост в обратную
930
952
  позвать независимого Claude-ревьюера и получить РАЗОБРАННЫЙ вердикт; пустой или безоценочный ответ —
931
953
  это названная ошибка, а не «чисто».
932
954
 
955
+ ### Строка объявления стадии — что за модель сейчас запустится
956
+
957
+ Каждый прогон `/feature-adr` печатает **перед каждым диспатчем стадии** одну строку — всегда, без
958
+ флага:
959
+
960
+ ```
961
+ ▸ router · session · routing not requested
962
+ ▸ adr · fable · budget table cell
963
+ ▸ code · codex:gpt-5.6-sol:high · coder knob = codex · landed barrier
964
+ ▸ qe · sonnet · cross-family QE (the coder never self-reviews)
965
+ ▸ qe · opus · codex refused before dispatching — nothing ran
966
+ ```
967
+
968
+ Последняя строка — про случай, который легко принять за отработавшую ступень: модель Codex ОТВЕТИЛА на
969
+ пробу, но ступень отказалась строить диспатч (непригодный ref области ревью, небезопасный id). Ни один
970
+ агент не запускался, и строка говорит именно это, а не «предыдущая ступень ничего не отдала» — та
971
+ формулировка утверждала бы запуск, которого не было.
972
+
973
+ Тот же разбор действует, когда рантайм вовсе не знает типа агента `codex:codex-rescue`: строка
974
+ скажет `codex unsupported at this dispatch — Claude`. И исход принадлежит своему вызову — дизайн-
975
+ стадии идут параллельно, поэтому соседняя стадия не может подменить твоей стадии причину.
976
+
977
+ Три поля: **стадия · модель · ветка, которая эту модель выбрала**. `session` означает, что маршрутизация
978
+ не запрашивалась и стадия наследует модель сессии. Хвост `landed barrier` появляется там, где стадия
979
+ резолвится на Codex И пишет артефакт вне процесса (`code`, `plan` и четыре стадии дизайна): конвейер
980
+ после диспатча ЖДЁТ, пока файл ляжет на диск, — если прогон замер, эта пометка говорит, почему.
981
+
982
+ Строка описывает **фактический** диспатч, а не намерение: возобновлённая из точки сохранения стадия не
983
+ печатает ничего (она не запускается); при `coder=codex-fallback` первая ступень объявляется как Claude,
984
+ вторая — как Codex в момент своего запуска; codex-строка несёт **пробированный** id модели, тот же, что
985
+ попадёт в итоговый `modelsUsed`. Модель и причина берутся из ОДНОГО возвращённого значения резолвера,
986
+ поэтому строка, диспатч и отчёт не могут разойтись.
987
+
933
988
  ### Пересмотр после аварийного само-ревью — `dz reqe`
934
989
 
935
990
  The feature-adr pipeline's cross-model guard says *the model that writes code must not review it*.
@@ -1360,6 +1415,7 @@ Each pack is an npm package — click through for the **full per-skill documenta
1360
1415
  | [@dzhechkov/skills-meta](https://www.npmjs.com/package/@dzhechkov/skills-meta) | 20 | Dev-process meta skills — explore, feature-adr, design-thinking, audit, skill-advisor, loop-plan-author, decision-mockups (vendored mirror of `@dzhechkov/skills-decision-mockups`) |
1361
1416
  | [@dzhechkov/skills-academic](https://www.npmjs.com/package/@dzhechkov/skills-academic) | 5 | Thesis-defense toolkit — dissertation review, questions, doc-check, defense eval |
1362
1417
  | [@dzhechkov/skills-news](https://www.npmjs.com/package/@dzhechkov/skills-news) | 3 | *dz-original* — news digests (`news-digest`) + delta watches (`news-monitor`) + bundled `goap-research-ed25519` verified-research backend (mandatory) |
1418
+ | [@dzhechkov/skills-demo-publisher](https://github.com/djd1m/dz-harness/tree/main/packages/%40dzhechkov/skills-demo-publisher) | 1 | *dz-original, staged* — scenario-driven product recording → budgeted static HTML5 video site with Russian captions and fail-closed Pages delivery checks |
1363
1419
  | [@dzhechkov/skills-idea2prd](https://www.npmjs.com/package/@dzhechkov/skills-idea2prd) | 1 | *dz-original* — `idea2prd-manual`: idea/problem → PRD+ADR+DDD+C4+Pseudocode+Tests+Completion (9 checkpoints); bundles the analyst trio as a sources.json-tracked vendor ([ADR-0001](https://github.com/djd1m/dz-harness-hub/blob/main/docs/adr/0001-skill-canonicalization-and-dependency-model.md)) |
1364
1420
  | [@dzhechkov/skills-reverse-engineering](https://www.npmjs.com/package/@dzhechkov/skills-reverse-engineering) | 1 | *dz-original* — `reverse-engineering-unicorn`: company → launch playbook (+CJM) via 6-module QUICK/DEEP/VERIFIED pipeline; canonical home that resolved the keysarium↔p-replicator drift ([ADR-0001](https://github.com/djd1m/dz-harness-hub/blob/main/docs/adr/0001-skill-canonicalization-and-dependency-model.md)) |
1365
1421
  | [@dzhechkov/skills-presentation-storyteller](https://www.npmjs.com/package/@dzhechkov/skills-presentation-storyteller) | 1 | *dz-original* — `presentation-storyteller`: selling deck + verified sources + slide-by-slide speaker script; referenced (not vendored) by reverse-engineering-unicorn's Post-M6 step ([ADR-0001](https://github.com/djd1m/dz-harness-hub/blob/main/docs/adr/0001-skill-canonicalization-and-dependency-model.md)) |
@@ -1882,10 +1938,13 @@ runs a command that MEASURES the declared artifacts itself. It refuses a null re
1882
1938
  never recorded as done), an absent or partially-present artifact set, and a stage that declares nothing
1883
1939
  to witness — so a stage that did not happen can no longer be recorded, which the old mechanism allowed.
1884
1940
 
1885
- ## All Commands (85)
1941
+ ## All Commands (87)
1886
1942
 
1887
- *(84 MEASURED from the bounded command inventory below; rendered `dz --help` exposes 81 unique
1888
- top-level names, pinned by `test/command-count.test.ts`.)*
1943
+ *(87 MEASURED from the bounded command inventory below; rendered `dz --help` exposes 88 unique
1944
+ top-level names the 87 plus the built-in `help`, which prints USAGE before the dispatch switch and
1945
+ is therefore documented without being a command. Both numbers are COMPUTED, never typed: the name
1946
+ sets of this section, the root README, the docs site and `DZ_COMMANDS` are pinned to each other by
1947
+ `test/command-inventory-parity.test.ts`.)*
1889
1948
 
1890
1949
  ```
1891
1950
  dz setup --target <name> [--preset <name>] [--select id,id,...] [--skills-dir <dir>] [--memory agentdb] [--no-memory] [--no-hooks] [--install-driver] [--force]
@@ -1907,6 +1966,7 @@ dz vector import <file.rvf> [--project <dir>] [--json] # RVF import
1907
1966
  dz vector harmonize [--apply] [--threshold <0..1>] [--json] # SEMANTIC merge of near-dups (dry-run default; --apply after a restorable backup)
1908
1967
  dz teach --harmonize [--apply] [--threshold <0..1>] # alias of `dz vector harmonize`
1909
1968
  dz statusline [--json] [--install] # compact Claude Code statusline: live self-learning pattern count + brain sources
1969
+ dz store-guard [--status|--reset] [--yes] [--project <dir>] # inspect the monotonic external high-water mark; --reset is the only lowering path and requires confirmation or --yes
1910
1970
  dz usage [--json] [--project <dir>] | --calibrate --session <pct> --weekly <pct> [--model fable=<pct>] # ESTIMATE Claude usage from fixed reset windows; optional per-model weekly binding; exit 0 ALWAYS
1911
1971
  --by-stage [--run <id> | --slug <s>] [--epsilon <0..1>] [--write <file.jsonl>] [--json] # per-stage cost ledger for ONE feature-adr run + reconciliation invariant (BALANCED | DEFECT | INSUFFICIENT_DATA)
1912
1972
  dz chain [--project <dir>] [--json] # verify EVERY hash-chained journal in one command; coverage is DERIVED from the CHAINED_JOURNALS registry, so a journal cannot be chained and checked by nobody; an ABSENT journal is NAMED, never omitted; exit 1 on broken/unreadable
@@ -1938,13 +1998,13 @@ dz mcp-scan [path] [--json] (static agent-permission audit; exit 0/1/
1938
1998
  dz architecture [--json] [--revise] [--check --slug <s> --desc "<text>" [--cmd a,b] [--subsystem <id>]] # product map (subsystems = the README jobs + foundation/arsenal/ops); --revise = drift check (exit 1); --check = forward-looking сverka of a proposed feature vs map+vision (exit 2 on a hard-stop dup)
1939
1999
  dz project-skills [--json] [--stages-json] [--project <dir>] # polymorphic feature-adr: resolve architecture/project-skills.json (fixed roles product-vision/critic/brand/impl-bar + open extra[]) into per-stage guidance; absent = generic run (byte-identical); feature-adr Step 0 reads it
1940
2000
  dz mr-rakes [--json] [--candidate N --confirmed N] [--teach] [--gen-critic <path> [--apply]] # mine review artifacts (features' QE reports + REVIEW files) for RECURRING mistakes; anti-noise (≥2/≥3 distinct sources); close into dz teach + a project-critic skill (R2 critic role)
1941
- dz retro [transcript] [--json] [--threshold N] [--no-teach] [--install-hook] # per-session retro: mine the current session for recurring PROCESS rakes (claimed-done-without-verify, committed-without-verify, n-fix-cycles, ignored-correction), drill the user (socratic + checklist) AND teach the agent — co-learning via the dz teach store
2001
+ dz retro [transcript] [--json] [--threshold N] [--no-teach] [--install-hook] [--scan-tail [--transcript <path>]] # per-session retro: mine the current session for recurring PROCESS rakes (claimed-done-without-verify, committed-without-verify, n-fix-cycles, ignored-correction), drill the user (socratic + checklist) AND teach the agent — co-learning via the dz teach store
1942
2002
  dz feature-adr-setup [--plan] [--from-spec <f>] [--apply] # guided project onboarding engine (behind the `configure-feature-adr` skill): --plan shows which docs exist/missing; --from-spec scaffolds vision/map/testing/project-skills (propose; --apply writes; augment-never-clobber)
1943
2003
  dz challenge --plan <plan.md> [--json] [--context-only] [--author <model>] # adversarial plan-gate (behind the `challenge-panel` skill): assemble a WIDE context pack (plan + vision + testing + map + degradations) + the fixed C1-C8 "break it" brief for a FRESH adversary (≠ plan author); advisory, never blocks
1944
2004
  dz routing [--stage <s>] [--json] # inspect the learned cost-optimal routing store: what `args.models.<stage>='auto-cost'` believes per (stage, complexity-tier, model) — gated attempts/successes/rate (feeds feature-adr model selection)
1945
2005
  dz bto-optimize --split|--plan|--select|--scope-check|--diff [--json] # deterministic engine behind /bto-optimize: hold-out split + hard-capped budget + no-regress-on-holdout winner selection (defeats judge-gaming); prose-only, diff-confirmed, never auto-writes
1946
2006
  dz discrimination-check --test <f[,f]> [--base <ref>] [--name <filter>] [--runner <cmd>] [--timeout <ms>] [--json] # §42 test-discrimination gate for feature-adr Step-8: run the ADR's property test in an isolated git worktree at pre-feature base — it MUST go red without the fix. SEVEN verdicts, each gated on EXECUTION evidence: DISCRIMINATES · DISCRIMINATES_VIA_ERROR · NON_DISCRIMINATING (false green) · TEST_FILE_ABSENT · LOAD_ERROR_AT_BOTH_REVS · FAILS_AT_TIP · CANNOT_ISOLATE (+ typed reason). Advisory, never auto-aborts
1947
- dz amendment-check --slug <slug> | --feature-dir <dir> | --all [--json] (every AM-N amendment row must resolve to a test found INSIDE the file the row names; the PLAN is authoritative when it carries rows, and an ideation amendment the plan drops is a failure; --all is a census that always exits 0; exit 0 pass/skip, 1 fail, 3 NOT-ESTABLISHED — a section that parsed ZERO rows is never a pass)
2007
+ dz amendment-check --slug <slug> | --feature-dir <dir> | --all [--json] (every AM-N / AM-CP-N amendment row must resolve to a test found INSIDE the file the row names; the PLAN is authoritative when it carries rows, and an ideation amendment the plan drops is a failure; --all is a census that always exits 0; exit 0 pass/skip, 1 fail, 3 NOT-ESTABLISHED — ZERO parsed rows may skip only when the whole first paragraph or heading suffix is exactly "None"/"N/A"/"нет", optionally with a full stop; an optional CommonMark closing # sequence is heading furniture, qualified text is refused, and AM-like content beside the declaration is NOT-ESTABLISHED)
1948
2008
  dz contract-check --slug <s> [--json] (read-only retrospective feature contract gate: canonical AC-N + ADR Confirmation → CC-N; every item needs one artifact-anchored met|unmet|not-testable verdict; A/B with unmet is refused; exit 0 pass / 1 readable violation / 2 invalid invocation or unreadable/not-established artifacts)
1949
2009
  dz feature-adr-record --kind ledger|training-pair --stage <s> [--slug <s>] [--row|--pair <json>] [--mark <n>] [--once] [--json] (the witnessed writer: payload as an ARGUMENT never as shell, refused before any write, timestamp stamped before serialising, append verified by re-reading the tail; exit 0 written|duplicate|skipped, 2 refused, 3 not-verified, never blocking)
1950
2010
  dz mutation-gate [--package <dir>] [--registry <file>] [--test-cmd "<cmd>"] [--only <id[,id]>] [--timeout <ms>] [--rebaseline per-entry|final] [--keep-scratch] [--json] # the mutation gate: for each NAMED protection in a declarative registry, copy the package to a scratch dir (shadow-repo layout, node_modules symlinked, git-initialized), verify the baseline is green, apply the entry's exact {find, replace} mutation, run the suite, REQUIRE red, restore — and require the red to be ATTRIBUTABLE to the protection: a mutated file that no longer parses is MUTATION_UNPARSEABLE, a failing count far above the entry's bound (maxFailing, default from observed) is OVER_FAILING, and a restored tree that does not reproduce green makes the entry INCONCLUSIVE (flaky suite). A mutation that does not apply, a green suite, or an inconclusive run is a FAILURE — never a skip. exit 0 all proven / 1 gate failed / 2 setup error
@@ -1964,6 +2024,7 @@ dz qe-rounds (--slug <feature> | --feature-dir <abs>) [--ceiling <n>] [
1964
2024
  dz restart-advisor --slug <feature> [--threshold C|D] [--rounds <n>] [--json] # manual, read-only advice over this feature's QE history. Defaults: threshold D, rounds 2. Reads only features/<slug>/.fa-state/checkpoints.jsonl and .dz/fa-training/<slug>/qe.jsonl; when both carry QE rounds they must normalize identically and are never unioned. RESTART_CODE_STAGE is a recommendation for the operator, not an action: autoAction is always false, and every firing result includes an explicit decision-log line. exit 0 established recommendation/no-recommendation / 2 invalid or not established / 1 unexpected runtime failure
1965
2025
  dz provenance-check --manifest <sources.json> [--project <dir>] [--json] # nothing goes out citing a source that may not leave this machine. Checks PROVENANCE, not words: every claim in a draft names its source, and a source is cleared only when it is a KNOWN kind that resolves safely. Repo paths are classified by `git -C <root> check-ignore` over the RESOLVED path — so a symlink into an ignored directory is refused, not cleared (MEASURED: git classifies the string and never dereferences), and the verdict does not change with your working directory. Store records need naming in the git-TRACKED `provenance-public.json`, so declaring one public is a reviewable commit rather than a field inside an ignored store. Anything else is refused: an undeclared kind is never inferred from the path's shape. exit 0 allowed / 1 blocked / 3 NOT ESTABLISHED — an empty manifest, an unreadable one, or an oracle that did not run is never a pass. **What it cannot do, said on the passing path too:** it proves what was CITED. It cannot see a paraphrase with no citation, nor confidential text pasted by hand into an allowed file. Read the draft.
1966
2026
  dz name-check [--command <n>] [--module <basename>] [--export <a,b>] [--project <dir>] [--json] # is this name free, BEFORE a line of code? Twice in one day a collision broke the build outright — `dz retro` was already a command, `decideProvenance` already an export — and both were answerable in advance. Scans workspace SOURCE and never `dist`, because a stale build answers 'free' confidently (MEASURED: half an hour of convincing live runs against a previous build while tsc was red). Checks a command name against the dispatcher AND the help block, a module basename against every package's src/, and exported identifiers against every declaration — naming the DECLARING file, not the barrel. exit 0 all free / 1 at least one taken / 2 nothing asked or the scan read nothing — an empty sweep is never a clean bill. **Honest limit, printed on the passing path:** it reads declarations, so a re-export under a different name stays the build's job.
2027
+ dz brief-check <file> [--json] Swarm brief declares OUTPUT_DIR, UNITS, ASSEMBLY_UNIT? Parsed as data, refused by name. The verdict cannot be forged by the text it judges: declarations inside a fenced block or an HTML comment do not count (a closing fence must be at least as long as its opener, and a comment that tries to nest is refused rather than silently reopened); a decorated key still counts toward the duplicate check, so hiding one declaration behind bold or a quote yields an ambiguity refusal, not a quiet pick. The unit list is never silently truncated: a blank line or any non-item line with more items after it — including a masked fence or comment — is a refusal that NAMES the interrupting line, because `units` is the very list a directory is later compared against. Output dir is checked as a PATH (absolute, `..`, backslash, control bytes and non-name segments refused); `plan` is reserved because its file is the plan the swarm writes first; unit names are length-capped and the list is capped at 200 with a linear duplicate check. Every brief-supplied value that reaches the terminal is neutralised, so an ESC byte cannot repaint a REFUSED line as OK. exit 0 ok / 1 refused / 2 unreadable — and `--json` answers on ALL THREE branches, carrying `checked:false` when the tool could not check rather than when the brief was bad
1967
2028
  dz tg-post --draft <file.html> [--manifest <sources.json>] [--channel <@name>] [--send --yes] [--night] [--max-per-day <n>] [--json] # the sender for an APPROVED genai-tweets-channel post, held to the channel's own accepted ADRs: HTML mode only (never MarkdownV2 — 18 escapes against 3, one miss is a 400); link preview OFF by default (x.com previews in Telegram are broken since 2022); the 00:00-06:00 MSK quiet window refuses without an explicit --night. THE DEFAULT RUN IS A DRY-RUN: tag balance and allowed-tag checks, bare &/< detection, the 4096 visible-character limit with the overshoot counted — every issue named in one pass, not just the first. The provenance gate runs IN-PROCESS over --manifest, and a draft with no manifest is refused as unchecked when a send is asked. A real send needs --send AND --yes — ADR-004's standing order that publishing stays manual, stated out loud each time. Three autopublish guards run FAIL-CLOSED, in a fixed order: the **stop-cord** (`.dz/tg-post/HALT` exists ⇒ nothing publishes, checked FIRST so no bug in a later gate can route around it), **dedup** by the sha256 of the post's VISIBLE text (what the reader sees, not the bytes — a whitespace-different draft is the same post), and the **daily limit** (10 by default, `--max-per-day <n>` to change it), counted over the trailing 24h. The journal is two-phase: a `pending` row is written BEFORE the network call and a `sent` row after Telegram accepts, so a crash between the two is caught by dedup on the next run instead of double-publishing; only `sent` rows eat the daily ceiling. An UNREADABLE journal REFUSES — an unreadable counter does not prove the ceiling is unreached. The provenance gate also clears `kind: url`: a well-formed http(s) URL is public by construction so there is nothing local to protect, while a `file://`, a bare path or a non-URL is refused, never inferred. The bot token (TELEGRAM_BOT_TOKEN or telegram.tokenFile) is never printed, and the gates run BEFORE any secret is read. exit 0 sent or clean dry-run / 1 refused / 2 usage
1968
2029
  dz feature-adr-checkpoint (--slug <feature> | --feature-dir <abs>) --stage <s> --input-hash <h> --result <json> [--artifact a,b] [--json]
1969
2030
  dz reqe [--slug <feature> [--done --report <f>]] [--project <dir>] [--json] # the re-QE debt ledger: a usage-switched feature-adr run whose Step-8 QE ran on the coder's OWN family (cross-model guard suspended, FR-2.9) records a debt; list debts (also surfaced by dz usage), print the cross-family review brief, settle FAIL-CLOSED against an existing GRADED report (the run's own 08_qe_report.md — even hard-linked — can never settle its own debt); settlement lands in 08_qe_report.md, evidence rotates to reqe-settled.json
@@ -1971,6 +2032,7 @@ dz qe-bridge --family claude --slug <feature> [--coder-family codex|clau
1971
2032
  dz backlog <sub> add "<idea>" | list | show <id> | goals [--validate] | roulette [--seed n] [--commit <id>] | ship <id…> | drop <id…> | reopen <id…> | enrich <id> | jira <id> | harmonize [--apply] # brain-backed idea backlog: capture an idea → semantic dedup against past ideas/features via the REUSED agentdb vector engine (two-signal: bounded-excerpt cosine DUPLICATE≥0.92 corroborated by shared subject vocabulary — a register-only 0.94 is demoted to RELATED, a length-only re-capture is caught as a subset duplicate; absorbed texts kept in absorbed.jsonl) + GoalMap alignment ("map+compass") → weighted seeded roulette picks one to work on → enrich STAGES an idea2prd hand-off → jira writes an auditable outbox via a configurable MCP adapter seam (jira-mcp|copilot-mcp|none). No 2nd vector store; without agentdb it degrades to exact-text dedup (honest)
1972
2033
  dz sign --init --out <path> | --pack <dir> --key <path> # --init: generate the Ed25519 keypair (private OUTSIDE the repo, prints the public key for keys/dz.pub); else sign a pack's manifest + CycloneDX SBOM
1973
2034
  dz sbom --pack <dir> [--out <file>] # emit the CycloneDX 1.5 SBOM for a pack standalone (file-level bill of materials); print to stdout or write to a file
2035
+ dz verify-pack --pack <dir> [--pubkey <path>] # signature check of a pack: fail-closed, and the trust root comes from the repo, never from the pack it is verifying
1974
2036
  dz guard check --op <publish|teach|consolidate|reindex> [--text <s>] [--json] [--force <reason>] # declarative constraint layer before self-mutating ops: HARD violation → block (exit 1), SOFT → warn; zero-config defaults, .dz/guard.json to customise; dz guard --init | dz guard log (append-only audit). dz publish runs it automatically (--no-guard "<reason>" = logged escape hatch)
1975
2037
  dz guard promote [--dry-run | --apply] [--window-days <N>] [--periods <N>] [--json] # lesson → guard-rule promotion: ranks lessons by firings × cost, SHADOW-replays each candidate over real commits, and proposes a rule only after TWO consecutive wins AND two window-lengths of REAL elapsed time since first observation. Non-dry runs add bounded prospective funnel evidence to .dz/promotion-state.json without feeding the verdict; --dry-run remains write-free. --apply installs SOFT rules only; promotions/refusals remain under features/guard-promotion/promotions/
1976
2038
  dz feature-adr-setup --guards [--loc-cap <n>] [--apply] # P3: scaffold DETERMINISTIC guard tests into the project — guards.config.json + a zero-dependency check.mjs runner (LOC cap, secret scan, frozen-file sha256 pins, waivers-with-reasons); wire `node architecture/guards/check.mjs` into CI
@@ -1998,9 +2060,28 @@ dz dashboard
1998
2060
  dz doctor [--project <dir>]
1999
2061
  dz roam [--apply] [--slug <slug>]
2000
2062
  dz import-ecc [--local-path <dir>] [--select id,id,...] [--limit N] [--output <dir>] [--force]
2001
- dz help
2002
2063
  ```
2003
2064
 
2065
+ Built-in, not a command: `dz help` prints this same USAGE and is handled before the dispatch switch,
2066
+ so `dz --help` lists 88 names while the canonical inventory above holds 87 (ADR-001 of feature
2067
+ `command-count-triad`).
2068
+
2069
+ **Adding a command — the whole checklist, in order.** It replaces the seven-place folklore that used
2070
+ to pin three different numbers:
2071
+
2072
+ 0. `dz name-check --command <name>` — is the name free? (do this before writing a line)
2073
+ 1. add the `case '<name>':` branch to the main `switch (command)` in `src/cli.ts`;
2074
+ 2. add its ` dz <name> …` line to `USAGE` — a command absent from `--help` reads as non-existent;
2075
+ 3. add the name to `DZ_COMMANDS`;
2076
+ 4. run `npx vitest run test/command-inventory-parity.test.ts` from `packages/@dzhechkov/harness-cli` —
2077
+ it NAMES every place still missing the command (both README inventories, the docs-site table) and
2078
+ every count that has to move;
2079
+ 5. fix exactly what it named, and re-run.
2080
+
2081
+ A name may skip step 2 only by joining `INTERNAL_ENTRY_POINTS` in `src/command-inventory.ts` with a
2082
+ written reason and a date — empty today, and an entry without a reason fails the suite.
2083
+
2084
+
2004
2085
  ### Optional class form for a taught lesson
2005
2086
 
2006
2087
  `dz teach` can store the observed lesson and an explicitly proposed class template in the same
@@ -2128,11 +2209,14 @@ echo "how do I handle replication lag?" | dz brain ground --budget 2000 # eage
2128
2209
  `dz statusline` renders a compact Claude Code statusline that surfaces dz's learning at a glance:
2129
2210
 
2130
2211
  ```
2131
- 🎓 dz: 12 patterns · 🧠 3 sources
2212
+ 🎓 dz: 12 (9 актив · 3 карантин) · 🧠 3 sources
2132
2213
  ```
2133
2214
 
2134
- `N patterns` is the count of learned patterns in memory; `M sources` is how many brain sources
2135
- (book-KBs / grounding stores) are wired. Enable it once:
2215
+ The parenthesized split is read only from the primary lexical store. A row is quarantined exactly
2216
+ when parsed metadata has `qStatus: "quarantined"`; historical fields do not count. The quarantine
2217
+ fragment is omitted at zero, `⚠` appears at one third of the pool, and `⚠ тиры ΔN` reports a
2218
+ quarantine-label difference greater than five rows from the vector mirror. `M sources` is how many
2219
+ brain sources (book-KBs / grounding stores) are wired. Enable it once:
2136
2220
 
2137
2221
  ```bash
2138
2222
  dz statusline --install # wires it into .claude/settings.json → statusLine
@@ -2160,11 +2244,70 @@ dz statusline --fa-record --slug my-loop --step build --kind loop
2160
2244
  ```
2161
2245
 
2162
2246
  ```
2163
- 📐 feature-adr Step 7 Code · ⏱ ~25–47м (p25–p75 по n=5 ранам M; окно 2026-08-24–2026-08-29) · 🎓 224 pool · ↑7 used · +2 new · ↻0 reinforced · 🎓 dz: 224 patterns · 🧠 3 sources
2164
- 📐 feature-adr Step 8 QE · ETA: недостаточно истории (n=2 L; окно 2026-08-28–2026-08-29) · 🎓 224 pool · ↑7 used · +2 new · ↻0 reinforced · 🎓 dz: 224 patterns · 🧠 3 sources
2165
- 🔁 loop build · 🎓 dz: 224 patterns · 🧠 3 sources
2247
+ 📐 feature-adr Step 7 Code · ⏱ ~25–47м (p25–p75 по n=5 ранам M; окно 2026-08-24–2026-08-29) · 🎓 224 pool · ↑7 used · +2 new · ↻0 reinforced · 🎓 dz: 224 (200 актив · 24 карантин) · 🧠 3 sources
2248
+ 📐 feature-adr Step 8 QE · ETA: недостаточно истории (n=2 L; окно 2026-08-28–2026-08-29) · 🎓 224 pool · ↑7 used · +2 new · ↻0 reinforced · 🎓 dz: 224 (200 актив · 24 карантин) · 🧠 3 sources
2249
+ 🔁 loop build · 🎓 dz: 224 (224 актив) · 🧠 3 sources
2250
+ ```
2251
+
2252
+ ##### The 📐 panel is its OWN SECOND LINE (`--tier`, v0.8.11)
2253
+
2254
+ Claude Code renders **every** stdout line of a statusline command, so the phase panel no longer
2255
+ competes with the learning counts for one line: line 1 stays `🎓 dz: …`, line 2 is the panel in
2256
+ format `📐 <slug> [<tier>] <done>/<total> ▶ <label> · <N>м/—`. `<done>/<total>` is a LOOKUP, never a
2257
+ guess: `--tier <S|M|L|XL>` (validated; anything else exits 1 before a single byte is written) selects
2258
+ the tier's active-step list, and the label's `Step <n>` number is located in it. No tier, or a step
2259
+ number outside the list, renders `[?] ?/?` verbatim — the panel never invents a position. The tail
2260
+ is fixed-width `/—` until an ETA is available. The terminal label `done` drops the line entirely.
2261
+
2262
+ Reproduce it end to end (MEASURED 2026-09-06 on `harness-cli 0.8.11`):
2263
+
2264
+ ```bash
2265
+ D=$(mktemp -d)
2266
+ dz statusline --fa-record --slug add-user-auth --step "Step 7 Code" --tier M \
2267
+ --recalled 7 --stored 2 --mode full-qe-extended --project "$D"
2268
+ # → dz statusline: recorded /feature-adr learning state for "add-user-auth" (Step 7 Code) …
2269
+
2270
+ echo '{}' | dz statusline --project "$D"
2271
+ # → 🎓 dz: 0 patterns · 🧠 4 sources
2272
+ # → 📐 add-user-auth [M] 6/8 ▶ Step 7 Code · 0м/—
2273
+ ```
2274
+
2275
+ ##### The panel only moves FORWARD — and the ⛔ escape hatch
2276
+
2277
+ A plain `Step <n>` label whose number goes BACKWARDS against a slot younger than 90 minutes is
2278
+ ABSORBED as a stale duplicate: its counters, tier and mode land, but the step and the phase clock
2279
+ stand. This exists because the pipeline's own Step-0 fallback recorder fires *after* the router
2280
+ checkpoint; without the guard the panel rewound to `Step 0 recall` for the whole design fan and the
2281
+ design time was attributed to Step 0. A genuine regression has two escape hatches — a label
2282
+ prefixed with **⛔** or **⏸**, and a stale (>90 min) slot, so a crashed run never swallows a fresh
2283
+ restart. Continuing the session above:
2284
+
2285
+ ```bash
2286
+ dz statusline --fa-record --slug add-user-auth --step "Step 0 recall" --recalled 3 --project "$D"
2287
+ echo '{}' | dz statusline --project "$D"
2288
+ # → 📐 add-user-auth [M] 6/8 ▶ Step 7 Code · 0м/— # absorbed: the run is further along
2289
+
2290
+ dz statusline --fa-record --slug add-user-auth --step "⛔ K2 → Step 6" --project "$D"
2291
+ echo '{}' | dz statusline --project "$D"
2292
+ # → 📐 add-user-auth [M] 5/8 ⛔ K2 → Step 6 · 0м/— # a LEGITIMATE regression, recorded verbatim
2293
+ ```
2294
+
2295
+ ##### A refused write is LOUD, and never breaks your pipeline
2296
+
2297
+ The slot transition runs inside the `fa-phase-slot` named lock (it is a read-modify-write: two
2298
+ concurrent recorders would otherwise both read the same previous label). If the lock is held past
2299
+ the timeout, or `.dz` cannot be written, **nothing is written** — and the refusal is announced on
2300
+ **stderr**, naming the slug and the reason, while the exit code stays **0**:
2301
+
2302
+ ```
2303
+ fa-record: slot write refused (add-user-auth): the lock at …/.dz/locks/fa-phase-slot.lock stayed held for 250ms …
2166
2304
  ```
2167
2305
 
2306
+ Exit 0 is deliberate: the panel is advisory and rides a checkpoint agent's shell command, so it must
2307
+ never fail the run it is only reporting on. Silence would be worse than a failure — a caller reading
2308
+ nothing as success is how a stale panel becomes invisible. Argument errors (a bad `--tier`, a missing
2309
+ `--slug`) still exit 1: a malformed invocation is the caller's bug, not a refusal.
2310
+
2168
2311
  For a live `/feature-adr` run, the panel derives remaining-stage timing from timestamped
2169
2312
  `features/*/.fa-state/checkpoints.jsonl` runs of the **same tier**. Every estimate prints its
2170
2313
  evidence basis: distinct-run `n`, tier, and date window. A Codex-shaped `code` leg always renders
@@ -2186,6 +2329,44 @@ exits 1 rather than silently weakening panel arbitration. It is load-bearing in
2186
2329
  discovered newest-first, nothing older than 30 minutes is surfaced, and the write path prunes at
2187
2330
  24 h. Use `--project <dir>` to pin the panel to a specific project root.
2188
2331
 
2332
+ ### Learning-store evidence (`dz store-guard`)
2333
+
2334
+ The guard keeps a high-water mark outside the project, so deleting `<project>/.dz` does not delete
2335
+ the evidence that the learning store used to contain records. Inspect it without changing it:
2336
+
2337
+ ```bash
2338
+ dz store-guard --status --project ./my-project
2339
+ # dz store-guard: OK — row counts are within the recorded high-water bounds
2340
+ # mark: /home/alice/.dz-store-guard/<project-hash>.json
2341
+ # current rows: lexical=120, vector=118
2342
+ # lexical selected: /path/my-project/.dz/memory/patterns.sqlite (sqlite, 120 rows)
2343
+ # lexical ignored: /path/my-project/.dz/patterns.jsonl (17 rows) # only when both exist
2344
+ # recorded: {"lexicalSource":"sqlite","lexicalMax":120,...}
2345
+ ```
2346
+
2347
+ Ordinary writers and readers update `last` but can never lower either maximum. A lexical source
2348
+ change is reported as `SOURCE CHANGED`; one writer may proceed and records `sourceChangedAt` without
2349
+ erasing the previous maximum. Subsequent low-count writes are refused until the operator resets.
2350
+
2351
+ After restoring or deliberately replacing the store, an operator can accept the measured counts.
2352
+ This is destructive to the old evidence and therefore requires an interactive `yes`, or `--yes` for
2353
+ automation, before it writes an auditable receipt:
2354
+
2355
+ ```bash
2356
+ dz store-guard --reset --yes --project ./my-project
2357
+ # ⚠ dz store-guard --reset: manual operator decision required; this lowers the recorded high-water evidence
2358
+ # old maximum: lexical=1385, vector=1300
2359
+ # new observed: lexical=120 (sqlite), vector=118
2360
+ # dz store-guard: RESET — accepted lexical=120, vector=118
2361
+ # mark: /home/alice/.dz-store-guard/<project-hash>.json
2362
+ # receipt: <timestamp> — dz store-guard --reset: manual operator decision; before lexical=1385, vector=1300; after lexical=120, vector=118
2363
+ ```
2364
+
2365
+ Commands that intentionally remove records print the resulting counts, the unchanged maxima, and
2366
+ the exact `dz store-guard --reset --project '<dir>'` command. `--status` and guard warnings name the
2367
+ selected lexical source; when both SQLite and JSONL exist they also name the ignored JSONL row count.
2368
+ The snapshot helper supports both lexical formats.
2369
+
2189
2370
  ### Usage estimate (`dz usage`)
2190
2371
  > **Pin the weekly reset to an ABSOLUTE instant.** `weeklyResetAnchor: "Wed 08:59"` is
2191
2372
  > server-timezone-relative — measured: the same moment lands a week apart under UTC vs `+03:00`, so
@@ -3392,6 +3573,58 @@ retro: 2 recurring rake(s) to drill (from 6800 events):
3392
3573
  First-seen rakes accrue silently; only **recurring** ones get a drill (no nagging on a one-off). The user gets the
3393
3574
  drill, the agent gets the taught rule — from the same mistake, out of one shared `dz teach` store.
3394
3575
 
3576
+ #### `dz retro --scan-tail` — the per-turn debt scan (the Stop hook), settled by the teach RECEIPT
3577
+
3578
+ `dz retro` is the end-of-session pass. `--scan-tail` is the **per-turn** half: the Stop hook runs it after
3579
+ every assistant turn, it reads only the bytes added since the last scan, and it answers one question —
3580
+ *was an admitted mistake taught in the same turn?* An admission with no executed `dz teach` behind it
3581
+ arms `.dz/retro-pending.json`, and the recall hook turns that into a next-prompt directive.
3582
+
3583
+ ```bash
3584
+ dz retro --install-hook # print the opt-in hook set (Stop + PreCompact + SessionEnd)
3585
+ dz retro --scan-tail --transcript ~/.claude/projects/<enc>/<uuid>.jsonl # scan a NAMED transcript
3586
+ dz retro --scan-tail --json # what the hook itself runs; Claude Code pipes the payload on stdin
3587
+ ```
3588
+
3589
+ **The transcript is named, never guessed.** The Stop hook's stdin payload carries `transcript_path`, and
3590
+ that is what gets scanned; `--transcript <path>` (or a positional path) overrides it. With none of the
3591
+ three the scan REFUSES instead of picking the newest file on disk — on a machine running several
3592
+ sessions and their subagents at once, "the newest transcript" is routinely another session's, and
3593
+ scanning it advances the wrong session's bookmark while this turn's admission is never seen:
3594
+
3595
+ ```
3596
+ $ dz retro --scan-tail # no hook payload, no --transcript
3597
+ retro scan-tail: NOT-ESTABLISHED — no transcript_path on stdin and no --transcript/positional path —
3598
+ refusing to scan the newest transcript on disk, which on a machine running several sessions at once is
3599
+ routinely another session's. Wire the hook as `dz retro --scan-tail` (Claude Code pipes the payload on
3600
+ stdin) or pass `--transcript <path>`.
3601
+ ```
3602
+
3603
+ **What settles a debt is the RECEIPT, not the command text.** A `dz teach` that merely APPEARS at a shell
3604
+ command boundary proves nothing — `exit 0` on the line above it, and the command never runs. So a teach
3605
+ call carrying a `tool_use_id` is only *registered*; the debt is cleared when that call's own tool result
3606
+ carries a line `dz teach` prints on a real write (`Learned: "…"`, `Total patterns:`, `store (written):`,
3607
+ `↳ reinforced …`, `↳ mirrored to vector tier …`, `Imported N pattern(s) …`). Every teach still awaiting its
3608
+ result is retained, so two parallel teaches cannot cancel each other out.
3609
+
3610
+ ```
3611
+ $ dz retro --scan-tail --transcript <path> --json
3612
+ {"status":"pending","snippet":"Моя ошибка — гейт читал не тот стор…","scannedBytes":1841,"offset":204233,"source":"flag"}
3613
+
3614
+ # …the same turn, after a teach that actually wrote to the store:
3615
+ {"status":"cleared","scannedBytes":612,"offset":204845,"source":"stop-hook-stdin"}
3616
+ ```
3617
+
3618
+ `status` is one of `pending` · `cleared` · `none` · `no-transcript` · `contended` (another scan held the
3619
+ `retro-scan` lock — nothing advanced, the next turn re-reads the same bytes), plus `not-established` on
3620
+ the refusal above. It always exits 0: a Stop hook must never fail a turn.
3621
+
3622
+ **Honest limits, measured:** a genuine teach whose output was redirected away (`>/dev/null`, `| tail -1`)
3623
+ carries no receipt, so the debt stays armed — 41 of 329 real teach calls across 95 transcripts, most of
3624
+ them decoys the rule *should* arm. And a teach whose result lands in the NEXT scan chunk cannot be
3625
+ confirmed there, so it stays armed too. Both err toward one visible directive rather than a silently
3626
+ forgiven error.
3627
+
3395
3628
  ### `dz challenge` — when you have an implementation plan and want it broken BEFORE you code
3396
3629
 
3397
3630
  The cross-model QE at feature-adr Step 8 catches problems *after* the code is written. The most expensive plan
@@ -4012,7 +4245,7 @@ An unknown id exits `1` rather than reporting a successful removal of nothing. A
4012
4245
  the lessons ever read?* — and the answer is usually humbling. So the statusline reports both:
4013
4246
 
4014
4247
  ```
4015
- 🎓 dz: 103 patterns · 3 used · 🧠 2 sources
4248
+ 🎓 dz: 103 (103 актив) · 3 used · 🧠 2 sources
4016
4249
  ```
4017
4250
 
4018
4251
  ```bash
@@ -4417,7 +4650,24 @@ refusal as the honest answer.
4417
4650
 
4418
4651
  ## Status
4419
4652
 
4420
- `harness-core v0.8.10` · `harness-cli v0.8.10` — **staged, not published:** adds bounded
4653
+ `harness-core v0.8.12` · `harness-cli v0.8.12` — **staged, not published:** ONE definition of "a dz
4654
+ command" (ADR-001, feature `command-count-triad`). `src/command-inventory.ts` is the single pure
4655
+ parser every consumer derives from — the layer-1 parity test, `dz name-check`, and the new public
4656
+ exports (`commandInventory`, `declaredCommands`, `dispatchedCommands`, `documentedCommands`,
4657
+ `stripNonCode`, `validateExceptionList`, `INTERNAL_ENTRY_POINTS`, `PSEUDO_COMMANDS`) — instead of a
4658
+ fourth private regex and a fourth number. Four hidden commands (`mr-rakes`, `retro`,
4659
+ `feature-adr-setup`, `bto-optimize`) gained USAGE lines, so `--help` changed; `help` is a documented
4660
+ pseudo-command, not a `case` label. **87 canonical commands, 88 names in rendered `--help`** (the 87
4661
+ plus the built-in `help`) — both COMPUTED from `cli.ts`, neither typed into a test. Three cross-family QE rounds closed
4662
+ six parser defects the naive version had: four that INVENTED a command (regex literals with a lone
4663
+ `}`, `case` labels in comments or templates, sub-verb labels from nested switches, ` dz <name>` lines
4664
+ outside the USAGE literal), one that LOST one (an escaped newline destroyed a line and misaligned
4665
+ every later label), and one performance defect (a full-prefix rescan per slash made the parser
4666
+ quadratic — 4 000 division-heavy lines went from 10 366 ms to 53 ms).
4667
+
4668
+ `harness-core v0.8.11` · `harness-cli v0.8.10` — **published 2026-09-02** (core 0.8.11 also carries
4669
+ the Russian-catalogue stemming, the fixed `discrimination-check` / `mutation-gate` seams, `dz chain` and
4670
+ `dz score --all`; see the harness-core README status): adds bounded
4421
4671
  `volume-shadow/v1` publish observations with structured human/JSON/audit parity. All four remain
4422
4672
  SOFT-only; incomplete evidence is unknown, and source-comment justification is out of scope.
4423
4673
 
@@ -4533,7 +4783,7 @@ failed"; and a `--books` search that finds nothing says where it looked and, whe
4533
4783
  brain holds sources, names the command that searches them.
4534
4784
 
4535
4785
  `v0.6.1` — two commands that move checks off the model's judgement and onto the disk.
4536
- `dz amendment-check` resolves every `AM-N` amendment row to a test found INSIDE the file the row names
4786
+ `dz amendment-check` resolves every `AM-N` / `AM-CP-N` amendment row to a test found INSIDE the file the row names
4537
4787
  (the plan is authoritative; an amendment it drops or rewords under the same id is a failure; `--all` is
4538
4788
  a census that never blocks). `dz feature-adr-record` is the witnessed writer for the run-cost ledger
4539
4789
  and training pairs: the payload arrives as an ARGUMENT rather than baked into a shell pipeline, a
@@ -1 +1 @@
1
- {"version":3,"file":"boolean-flags.d.ts","sourceRoot":"","sources":["../src/boolean-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CA0FhD,CAAC;AAEH,gGAAgG;AAChG,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAAc,CAAC;AAElE,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAGpE"}
1
+ {"version":3,"file":"boolean-flags.d.ts","sourceRoot":"","sources":["../src/boolean-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CA6FhD,CAAC;AAEH,gGAAgG;AAChG,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAAc,CAAC;AAElE,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAGpE"}