@dzhechkov/harness-core 0.8.10 → 0.8.20

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 (251) hide show
  1. package/.dz-manifest.json +490 -170
  2. package/LICENSE +13 -0
  3. package/README.md +420 -6
  4. package/dist/agents-policy.d.ts +15 -1
  5. package/dist/agents-policy.d.ts.map +1 -1
  6. package/dist/agents-policy.js +27 -1
  7. package/dist/agents-policy.js.map +1 -1
  8. package/dist/amendment-trace.d.ts +72 -0
  9. package/dist/amendment-trace.d.ts.map +1 -1
  10. package/dist/amendment-trace.js +385 -17
  11. package/dist/amendment-trace.js.map +1 -1
  12. package/dist/backlog-public.d.ts +153 -0
  13. package/dist/backlog-public.d.ts.map +1 -0
  14. package/dist/backlog-public.js +415 -0
  15. package/dist/backlog-public.js.map +1 -0
  16. package/dist/backlog-transitions.d.ts +48 -0
  17. package/dist/backlog-transitions.d.ts.map +1 -0
  18. package/dist/backlog-transitions.js +64 -0
  19. package/dist/backlog-transitions.js.map +1 -0
  20. package/dist/backlog.d.ts.map +1 -1
  21. package/dist/backlog.js +13 -0
  22. package/dist/backlog.js.map +1 -1
  23. package/dist/claim-check.d.ts.map +1 -1
  24. package/dist/claim-check.js +24 -2
  25. package/dist/claim-check.js.map +1 -1
  26. package/dist/claude-hooks-assets.d.ts +93 -0
  27. package/dist/claude-hooks-assets.d.ts.map +1 -0
  28. package/dist/claude-hooks-assets.js +208 -0
  29. package/dist/claude-hooks-assets.js.map +1 -0
  30. package/dist/clean-room-smoke.d.ts +83 -0
  31. package/dist/clean-room-smoke.d.ts.map +1 -0
  32. package/dist/clean-room-smoke.js +138 -0
  33. package/dist/clean-room-smoke.js.map +1 -0
  34. package/dist/cmd-usage.d.ts.map +1 -1
  35. package/dist/cmd-usage.js +36 -6
  36. package/dist/cmd-usage.js.map +1 -1
  37. package/dist/codex-hooks-assets.d.ts +25 -7
  38. package/dist/codex-hooks-assets.d.ts.map +1 -1
  39. package/dist/codex-hooks-assets.js +138 -30
  40. package/dist/codex-hooks-assets.js.map +1 -1
  41. package/dist/codex-hooks.d.ts +21 -1
  42. package/dist/codex-hooks.d.ts.map +1 -1
  43. package/dist/codex-hooks.js +21 -1
  44. package/dist/codex-hooks.js.map +1 -1
  45. package/dist/codex-invoke.d.ts +73 -0
  46. package/dist/codex-invoke.d.ts.map +1 -0
  47. package/dist/codex-invoke.js +80 -0
  48. package/dist/codex-invoke.js.map +1 -0
  49. package/dist/course-staleness.d.ts +19 -0
  50. package/dist/course-staleness.d.ts.map +1 -0
  51. package/dist/course-staleness.js +95 -0
  52. package/dist/course-staleness.js.map +1 -0
  53. package/dist/destructive-guard-hook.d.ts +40 -0
  54. package/dist/destructive-guard-hook.d.ts.map +1 -0
  55. package/dist/destructive-guard-hook.js +109 -0
  56. package/dist/destructive-guard-hook.js.map +1 -0
  57. package/dist/destructive-guard.d.ts +27 -0
  58. package/dist/destructive-guard.d.ts.map +1 -0
  59. package/dist/destructive-guard.js +2808 -0
  60. package/dist/destructive-guard.js.map +1 -0
  61. package/dist/discrimination-gate.d.ts +88 -3
  62. package/dist/discrimination-gate.d.ts.map +1 -1
  63. package/dist/discrimination-gate.js +173 -16
  64. package/dist/discrimination-gate.js.map +1 -1
  65. package/dist/event-chain.d.ts +30 -0
  66. package/dist/event-chain.d.ts.map +1 -1
  67. package/dist/event-chain.js +24 -0
  68. package/dist/event-chain.js.map +1 -1
  69. package/dist/feature-adr-routing.d.ts +95 -1
  70. package/dist/feature-adr-routing.d.ts.map +1 -1
  71. package/dist/feature-adr-routing.js +193 -27
  72. package/dist/feature-adr-routing.js.map +1 -1
  73. package/dist/guard.d.ts +98 -0
  74. package/dist/guard.d.ts.map +1 -1
  75. package/dist/guard.js +308 -0
  76. package/dist/guard.js.map +1 -1
  77. package/dist/harness-core-location.d.ts +18 -0
  78. package/dist/harness-core-location.d.ts.map +1 -0
  79. package/dist/harness-core-location.js +42 -0
  80. package/dist/harness-core-location.js.map +1 -0
  81. package/dist/index.d.ts +32 -11
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +32 -7
  84. package/dist/index.js.map +1 -1
  85. package/dist/lead-shift-gate.d.ts +95 -0
  86. package/dist/lead-shift-gate.d.ts.map +1 -0
  87. package/dist/lead-shift-gate.js +100 -0
  88. package/dist/lead-shift-gate.js.map +1 -0
  89. package/dist/ledger-backfill.d.ts +11 -1
  90. package/dist/ledger-backfill.d.ts.map +1 -1
  91. package/dist/ledger-backfill.js +19 -0
  92. package/dist/ledger-backfill.js.map +1 -1
  93. package/dist/loop-blobs.generated.d.ts +1 -1
  94. package/dist/loop-blobs.generated.d.ts.map +1 -1
  95. package/dist/loop-blobs.generated.js +12 -3
  96. package/dist/loop-blobs.generated.js.map +1 -1
  97. package/dist/loop-lint.d.ts.map +1 -1
  98. package/dist/loop-lint.js +56 -7
  99. package/dist/loop-lint.js.map +1 -1
  100. package/dist/loop-plan-graph.d.ts +1 -3
  101. package/dist/loop-plan-graph.d.ts.map +1 -1
  102. package/dist/loop-plan-graph.js +70 -1
  103. package/dist/loop-plan-graph.js.map +1 -1
  104. package/dist/loop-trace.d.ts.map +1 -1
  105. package/dist/loop-trace.js +16 -2
  106. package/dist/loop-trace.js.map +1 -1
  107. package/dist/managed-hooks.d.ts +5 -6
  108. package/dist/managed-hooks.d.ts.map +1 -1
  109. package/dist/managed-hooks.js +2 -2
  110. package/dist/managed-hooks.js.map +1 -1
  111. package/dist/model-recommender.d.ts.map +1 -1
  112. package/dist/model-recommender.js +14 -3
  113. package/dist/model-recommender.js.map +1 -1
  114. package/dist/mutation-gate.d.ts +39 -36
  115. package/dist/mutation-gate.d.ts.map +1 -1
  116. package/dist/mutation-gate.js +111 -5
  117. package/dist/mutation-gate.js.map +1 -1
  118. package/dist/operations.d.ts.map +1 -1
  119. package/dist/operations.js +90 -5
  120. package/dist/operations.js.map +1 -1
  121. package/dist/patterns.d.ts +23 -0
  122. package/dist/patterns.d.ts.map +1 -1
  123. package/dist/patterns.js +10 -0
  124. package/dist/patterns.js.map +1 -1
  125. package/dist/plugin.d.ts.map +1 -1
  126. package/dist/plugin.js +27 -5
  127. package/dist/plugin.js.map +1 -1
  128. package/dist/publish.d.ts +11 -0
  129. package/dist/publish.d.ts.map +1 -1
  130. package/dist/publish.js +16 -2
  131. package/dist/publish.js.map +1 -1
  132. package/dist/recommend.d.ts +4 -5
  133. package/dist/recommend.d.ts.map +1 -1
  134. package/dist/recommend.js +110 -45
  135. package/dist/recommend.js.map +1 -1
  136. package/dist/registry.d.ts +32 -1
  137. package/dist/registry.d.ts.map +1 -1
  138. package/dist/registry.js +168 -11
  139. package/dist/registry.js.map +1 -1
  140. package/dist/run-records.d.ts +3 -0
  141. package/dist/run-records.d.ts.map +1 -1
  142. package/dist/run-records.js +18 -0
  143. package/dist/run-records.js.map +1 -1
  144. package/dist/score.d.ts +95 -0
  145. package/dist/score.d.ts.map +1 -1
  146. package/dist/score.js +289 -6
  147. package/dist/score.js.map +1 -1
  148. package/dist/session-retro.d.ts +121 -2
  149. package/dist/session-retro.d.ts.map +1 -1
  150. package/dist/session-retro.js +454 -11
  151. package/dist/session-retro.js.map +1 -1
  152. package/dist/setup.d.ts +28 -0
  153. package/dist/setup.d.ts.map +1 -1
  154. package/dist/setup.js +223 -6
  155. package/dist/setup.js.map +1 -1
  156. package/dist/sign.d.ts.map +1 -1
  157. package/dist/sign.js +18 -1
  158. package/dist/sign.js.map +1 -1
  159. package/dist/skill-selection.d.ts +72 -0
  160. package/dist/skill-selection.d.ts.map +1 -0
  161. package/dist/skill-selection.js +76 -0
  162. package/dist/skill-selection.js.map +1 -0
  163. package/dist/skills-verify.d.ts +34 -1
  164. package/dist/skills-verify.d.ts.map +1 -1
  165. package/dist/skills-verify.js +82 -0
  166. package/dist/skills-verify.js.map +1 -1
  167. package/dist/stage-line.d.ts +68 -0
  168. package/dist/stage-line.d.ts.map +1 -0
  169. package/dist/stage-line.js +129 -0
  170. package/dist/stage-line.js.map +1 -0
  171. package/dist/statusline.d.ts +99 -0
  172. package/dist/statusline.d.ts.map +1 -1
  173. package/dist/statusline.js +310 -44
  174. package/dist/statusline.js.map +1 -1
  175. package/dist/stem.d.ts +12 -0
  176. package/dist/stem.d.ts.map +1 -0
  177. package/dist/stem.js +89 -0
  178. package/dist/stem.js.map +1 -0
  179. package/dist/store-counts.d.ts +26 -0
  180. package/dist/store-counts.d.ts.map +1 -0
  181. package/dist/store-counts.js +125 -0
  182. package/dist/store-counts.js.map +1 -0
  183. package/dist/store-guard.d.ts +106 -0
  184. package/dist/store-guard.d.ts.map +1 -0
  185. package/dist/store-guard.js +294 -0
  186. package/dist/store-guard.js.map +1 -0
  187. package/dist/swarm-brief.d.ts +95 -0
  188. package/dist/swarm-brief.d.ts.map +1 -0
  189. package/dist/swarm-brief.js +660 -0
  190. package/dist/swarm-brief.js.map +1 -0
  191. package/dist/telemetry-vocabulary.d.ts +7 -0
  192. package/dist/telemetry-vocabulary.d.ts.map +1 -1
  193. package/dist/telemetry-vocabulary.js +29 -0
  194. package/dist/telemetry-vocabulary.js.map +1 -1
  195. package/dist/trace-bundle.d.ts +8 -0
  196. package/dist/trace-bundle.d.ts.map +1 -1
  197. package/dist/trace-bundle.js +11 -0
  198. package/dist/trace-bundle.js.map +1 -1
  199. package/package.json +10 -9
  200. package/sbom.json +1033 -233
  201. package/src/agents-policy.ts +46 -2
  202. package/src/amendment-trace.ts +441 -19
  203. package/src/backlog-public.ts +503 -0
  204. package/src/backlog-transitions.ts +77 -0
  205. package/src/backlog.ts +12 -0
  206. package/src/claim-check.ts +25 -2
  207. package/src/claude-hooks-assets.ts +227 -0
  208. package/src/clean-room-smoke.ts +195 -0
  209. package/src/cmd-usage.ts +29 -5
  210. package/src/codex-hooks-assets.ts +140 -30
  211. package/src/codex-hooks.ts +21 -1
  212. package/src/codex-invoke.ts +138 -0
  213. package/src/course-staleness.ts +125 -0
  214. package/src/destructive-guard-hook.ts +151 -0
  215. package/src/destructive-guard.ts +3027 -0
  216. package/src/discrimination-gate.ts +262 -19
  217. package/src/event-chain.ts +41 -0
  218. package/src/feature-adr-routing.ts +220 -22
  219. package/src/guard.ts +358 -0
  220. package/src/harness-core-location.ts +44 -0
  221. package/src/index.ts +121 -7
  222. package/src/lead-shift-gate.ts +145 -0
  223. package/src/ledger-backfill.ts +20 -1
  224. package/src/loop-blobs.generated.ts +12 -3
  225. package/src/loop-lint.ts +52 -7
  226. package/src/loop-plan-graph.ts +66 -1
  227. package/src/loop-trace.ts +13 -1
  228. package/src/managed-hooks.ts +5 -6
  229. package/src/model-recommender.ts +14 -3
  230. package/src/mutation-gate.ts +165 -5
  231. package/src/operations.ts +83 -5
  232. package/src/patterns.ts +33 -0
  233. package/src/plugin.ts +27 -5
  234. package/src/publish.ts +27 -2
  235. package/src/recommend.ts +116 -46
  236. package/src/registry.ts +147 -13
  237. package/src/run-records.ts +23 -0
  238. package/src/score.ts +377 -7
  239. package/src/session-retro.ts +466 -11
  240. package/src/setup.ts +246 -9
  241. package/src/sign.ts +18 -1
  242. package/src/skill-selection.ts +111 -0
  243. package/src/skills-verify.ts +99 -1
  244. package/src/stage-line.ts +151 -0
  245. package/src/statusline.ts +396 -47
  246. package/src/stem.ts +87 -0
  247. package/src/store-counts.ts +154 -0
  248. package/src/store-guard.ts +388 -0
  249. package/src/swarm-brief.ts +661 -0
  250. package/src/telemetry-vocabulary.ts +36 -0
  251. package/src/trace-bundle.ts +10 -0
package/dist/guard.d.ts CHANGED
@@ -27,12 +27,19 @@ export interface Violation {
27
27
  /** Present for promoted-template firings; ids alone do not prove equal effective rule content. */
28
28
  readonly contentAnchor?: string;
29
29
  }
30
+ /** A publish-secret waiver: exact repo-relative path, with a mandatory explanation. */
31
+ interface SecretWaiver {
32
+ readonly path?: string;
33
+ readonly reason?: string;
34
+ }
30
35
  export interface GuardResult {
31
36
  readonly op: GuardOp;
32
37
  readonly verdict: GuardVerdict;
33
38
  readonly violations: readonly Violation[];
34
39
  /** ids of the rules that ran for this op (so a report can show what was checked, not just what failed). */
35
40
  readonly checked: readonly string[];
41
+ /** ids of the rules that ran for this op but received no input to examine. */
42
+ readonly notEstablished: readonly string[];
36
43
  /**
37
44
  * Informational notes (FN-7): things a rule wants ON THE RECORD that are NOT violations and never
38
45
  * touch the verdict — e.g. "no-stubs: N changed scannable file(s) not scanned". A fail-open skip
@@ -53,13 +60,70 @@ export interface GuardFacts {
53
60
  readonly name: string;
54
61
  readonly deps: Readonly<Record<string, string>>;
55
62
  }[];
63
+ /**
64
+ * for sibling-dep-protocol: КАЖДАЯ зависимость на соседний пакет монорепозитория, как она
65
+ * записана НА ДИСКЕ (без подстановки версии), с полем, в котором она объявлена. Поле нужно:
66
+ * `dependencies` и `devDependencies` обязаны идти через workspace-протокол, а `peerDependencies`
67
+ * и `optionalDependencies` — НЕТ, и это не послабление, а разная семантика (см. правило).
68
+ */
69
+ /**
70
+ * for plugin-manifest-audit: каждый найденный `.claude-plugin/plugin.json` и объявленные им
71
+ * поля. `parseError` заполнен ⇒ манифест не разобрался; остальные поля тогда не смотрят.
72
+ */
73
+ readonly pluginManifests?: readonly {
74
+ readonly path: string;
75
+ readonly parseError?: string;
76
+ readonly name?: string;
77
+ readonly version?: string;
78
+ readonly description?: string;
79
+ /** Имена навыков, ОБЪЯВЛЕННЫЕ манифестом. */
80
+ readonly declaredSkills?: readonly string[];
81
+ /** Имена навыков, НАЙДЕННЫЕ на диске рядом с манифестом. */
82
+ readonly skillsOnDisk?: readonly string[];
83
+ }[];
84
+ readonly siblingDeps?: readonly {
85
+ readonly name: string;
86
+ readonly field: string;
87
+ readonly dep: string;
88
+ readonly spec: string;
89
+ }[];
90
+ /**
91
+ * for backlog-covers-features: каталоги фич, дата их ПЕРВОГО коммита, тексты записей бэклога и
92
+ * базовая дата. Базовая дата обязательна и делает правило зелёным на приходе: 336 существующих
93
+ * каталогов заведены до правила, и краснеть на них — значит учить себя игнорировать (ИЗМЕРЕНО
94
+ * 2026-09-03: без базы 236 нарушений, в окне 7 дней — 48). Отсутствие факта ⇒ правило молчит:
95
+ * страж без улик не выдумывает вердикт.
96
+ */
97
+ readonly featureBacklog?: {
98
+ readonly baseline: string;
99
+ readonly features: readonly {
100
+ readonly slug: string;
101
+ readonly createdIso: string;
102
+ readonly waiver?: string;
103
+ }[];
104
+ readonly backlogTexts: readonly string[];
105
+ };
56
106
  /** for no-skill-drift: the names that byte-drift between copies (from sweepSkillDrift). */
57
107
  readonly drift?: readonly string[];
108
+ /**
109
+ * for codex-wrapper-for-value-stage: workflow scripts to scan, as (path, text). Absent ⇒ the
110
+ * rule reports nothing: a guard with no evidence must stay silent rather than invent a verdict.
111
+ */
112
+ readonly workflowScripts?: readonly {
113
+ readonly path: string;
114
+ readonly text: string;
115
+ }[];
58
116
  /** for no-secrets: labelled blobs to scan (lesson text, staged files). */
59
117
  readonly secretTargets?: readonly {
60
118
  readonly label: string;
61
119
  readonly text: string;
62
120
  }[];
121
+ /** for no-secrets: exact path waivers; entries without a non-empty reason are ignored and noted. */
122
+ readonly secretWaivers?: readonly SecretWaiver[];
123
+ /** Publish secret-scan coverage gaps; skips are informational and never verdict inputs. */
124
+ readonly secretScan?: {
125
+ readonly skipped: number;
126
+ };
63
127
  /** for readme-consistency: labelled (a,b) count pairs that must be equal. */
64
128
  readonly counts?: readonly {
65
129
  readonly label: string;
@@ -243,6 +307,39 @@ export declare const SECRET_PATTERNS: readonly {
243
307
  export declare function scanSecrets(text: unknown): {
244
308
  readonly name: string;
245
309
  }[];
310
+ /** Per-rule pure checkers. Each returns the violations it found (empty ⇒ clean). Missing evidence ⇒ []. */
311
+ /**
312
+ * Какие каталоги фич заведены после базовой даты и НЕ названы ни одной записью бэклога.
313
+ *
314
+ * БАЗОВАЯ ДАТА — не украшение, а условие осмысленности. ИЗМЕРЕНО 2026-09-03: без неё правило даёт
315
+ * 236 нарушений из 336 каталогов, а в окне «последние 7 дней» — 48 из 85. Проверка, изобретающая
316
+ * полсотни нарушений в первый день, учит людей себя игнорировать, то есть хуже отсутствующей.
317
+ * База делает правило зелёным на приходе и красным ровно на новом.
318
+ *
319
+ * ДАТА ПЕРВОГО КОММИТА, А НЕ mtime. Время правки меняет любой посторонний процесс — пересборка,
320
+ * перенос, чтение с обновлением. Дата появления каталога в истории неподвижна. ЧЕСТНАЯ ГРАНИЦА:
321
+ * функция ДОВЕРЯЕТ переданной строке и происхождение её не подтверждает — обязанность подать
322
+ * именно git-дату лежит на вызывающем (сбор фактов в cli.ts). Здесь проверяется только то, что
323
+ * строка вообще разбирается в дату.
324
+ *
325
+ * ЧТО ИМЕННО ПРОВЕРЯЕТСЯ В ОГОВОРКЕ — сказано точно, потому что ревью 2026-09-03 поймало
326
+ * расхождение обещания с кодом. Машинно проверяется РОВНО одно: строка непуста после обрезки
327
+ * пробелов. Осмысленность причины машинно не проверяема, и оговорка `x` пройдёт. Это сознательная
328
+ * граница слоя: гейт заставляет РЕШЕНИЕ БЫТЬ ЗАПИСАННЫМ, а качество формулировки остаётся делом
329
+ * человека — ровно как у освобождений заставы секретов и списка исключений дрейфа.
330
+ *
331
+ * БАЗА ВКЛЮЧИТЕЛЬНА: каталог, заведённый В САМ день базы, правилом контролируется («не раньше
332
+ * базы», а не «после базы»).
333
+ *
334
+ * ЧЕГО ЭТА ПРОВЕРКА НЕ ЛОВИТ, названо честно: работу БЕЗ каталога фичи — разбор, ремонт, рой,
335
+ * обещание «вернёмся». Машинного следа у них нет, и они остаются на слое 2 (текст правила в
336
+ * CLAUDE.md). Утверждать, что правило покрыто целиком, было бы ложной гарантией.
337
+ */
338
+ export declare function backlogCoversFeatures(features: readonly {
339
+ readonly slug: string;
340
+ readonly createdIso: string;
341
+ readonly waiver?: string;
342
+ }[], backlogTexts: readonly string[], baseline: string): readonly string[];
246
343
  /**
247
344
  * Rules that may NEVER be promoted to HARD, whatever a config says. A rule whose evidence comes from a
248
345
  * deliberately tolerant parser must not be able to BLOCK an operation: the parser's own design admits it
@@ -294,4 +391,5 @@ export declare function auditRecord(result: GuardResult, ts: string, override?:
294
391
  }): GuardAuditRecord;
295
392
  /** The exit-code contract: a block is non-zero unless forced; a warn/pass is zero. */
296
393
  export declare function guardExitCode(result: GuardResult, forced: boolean): number;
394
+ export {};
297
395
  //# sourceMappingURL=guard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"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"}
package/dist/guard.js CHANGED
@@ -110,7 +110,10 @@ function unquoteYaml(s) {
110
110
  /** The built-in rule set (works with no config). Ops are the mutating operations each rule guards. */
111
111
  export const DEFAULT_RULES = [
112
112
  { id: 'no-workspace-star', severity: 'hard', ops: ['publish'], description: 'a published package.json must carry no workspace:* dep (npm ships it verbatim → the install breaks)' },
113
+ { id: 'plugin-manifest-audit', severity: 'hard', ops: ['publish'], description: 'every .claude-plugin/plugin.json parses and declares a non-empty name, description and a STRICT N.N.N version' },
114
+ { id: 'sibling-dep-protocol', severity: 'hard', ops: ['publish'], description: 'a dependencies/devDependencies entry on a sibling @dzhechkov package must use the workspace: protocol on disk (peer/optional deps are deliberately exempt — a range is their point)' },
113
115
  { id: 'no-skill-drift', severity: 'hard', ops: ['publish', 'consolidate'], description: 'no unexpected byte-drift between shared skill copies' },
116
+ { id: 'backlog-covers-features', severity: 'soft', ops: ['publish', 'consolidate'], description: 'каталог фичи, заведённый после базовой даты, назван записью бэклога — либо несёт именованную оговорку с причиной' },
114
117
  { id: 'no-secrets', severity: 'hard', ops: ['teach', 'publish'], description: 'no private key or API token in lesson text or a published file' },
115
118
  { id: 'readme-consistency', severity: 'soft', ops: ['publish'], description: 'README counts agree (CJM header vs All Commands, etc.)' },
116
119
  { id: 'skills-registrable', severity: 'soft', ops: ['publish'], description: 'every skill directory in a skill pack has a depth-1 SKILL.md (a buried or missing one ships un-registrable — the health-advisor 1.2.0 class)' },
@@ -122,6 +125,7 @@ export const DEFAULT_RULES = [
122
125
  { id: 'feature-artifact-diff-ratio', severity: 'soft', ops: ['publish'], description: 'observe feature artifact bytes against attributable unified-diff bytes, explicitly a proxy; advisory only' },
123
126
  { id: 'feature-tier-artifact-set', severity: 'soft', ops: ['publish'], description: 'observe artifacts due for the recorded feature tier, active steps, consumers, and lifecycle; advisory only' },
124
127
  { id: 'agents-md-policy-sync', severity: 'soft', ops: ['publish'], description: 'proves the AGENTS.md copy is in SYNC with its source — not that the runtime read or obeyed it; heal drift with dz agents-sync' },
128
+ { id: 'codex-wrapper-for-value-stage', severity: 'hard', ops: ['publish'], description: 'a workflow stage routed to the fire-and-forget codex wrapper must not have its return value consumed — the wrapper answers with a dispatch stub, never with the model' },
125
129
  { id: 'lockfile-in-sync', severity: 'soft', ops: ['publish'], description: 'every workspace @dzhechkov/* dependency spec matches the specifier pnpm-lock.yaml records for that importer (a dep bump without a lockfile refresh breaks CI with ERR_PNPM_OUTDATED_LOCKFILE). SOFT-ONLY — a config cannot promote it to HARD' },
126
130
  { id: 'store-bloat-cap', severity: 'soft', ops: ['teach', 'consolidate'], description: 'the learned store is within its size cap' },
127
131
  // Description ASSEMBLED from STUB_MARKERS so guard.ts itself stays clean under the scan it defines
@@ -155,7 +159,91 @@ export function scanSecrets(text) {
155
159
  hits.add(p.name);
156
160
  return [...hits].map((name) => ({ name }));
157
161
  }
162
+ function secretWaiverState(waivers) {
163
+ const waived = new Set();
164
+ let reasonless = 0;
165
+ for (const waiver of Array.isArray(waivers) ? waivers : []) {
166
+ if (!waiver || typeof waiver !== 'object' || typeof waiver.path !== 'string' || waiver.path.trim() === '')
167
+ continue;
168
+ const reason = typeof waiver.reason === 'string' ? waiver.reason.trim() : '';
169
+ if (reason.length > 0)
170
+ waived.add(waiver.path);
171
+ else
172
+ reasonless++;
173
+ }
174
+ return { waived, reasonless };
175
+ }
158
176
  /** Per-rule pure checkers. Each returns the violations it found (empty ⇒ clean). Missing evidence ⇒ []. */
177
+ /**
178
+ * Какие каталоги фич заведены после базовой даты и НЕ названы ни одной записью бэклога.
179
+ *
180
+ * БАЗОВАЯ ДАТА — не украшение, а условие осмысленности. ИЗМЕРЕНО 2026-09-03: без неё правило даёт
181
+ * 236 нарушений из 336 каталогов, а в окне «последние 7 дней» — 48 из 85. Проверка, изобретающая
182
+ * полсотни нарушений в первый день, учит людей себя игнорировать, то есть хуже отсутствующей.
183
+ * База делает правило зелёным на приходе и красным ровно на новом.
184
+ *
185
+ * ДАТА ПЕРВОГО КОММИТА, А НЕ mtime. Время правки меняет любой посторонний процесс — пересборка,
186
+ * перенос, чтение с обновлением. Дата появления каталога в истории неподвижна. ЧЕСТНАЯ ГРАНИЦА:
187
+ * функция ДОВЕРЯЕТ переданной строке и происхождение её не подтверждает — обязанность подать
188
+ * именно git-дату лежит на вызывающем (сбор фактов в cli.ts). Здесь проверяется только то, что
189
+ * строка вообще разбирается в дату.
190
+ *
191
+ * ЧТО ИМЕННО ПРОВЕРЯЕТСЯ В ОГОВОРКЕ — сказано точно, потому что ревью 2026-09-03 поймало
192
+ * расхождение обещания с кодом. Машинно проверяется РОВНО одно: строка непуста после обрезки
193
+ * пробелов. Осмысленность причины машинно не проверяема, и оговорка `x` пройдёт. Это сознательная
194
+ * граница слоя: гейт заставляет РЕШЕНИЕ БЫТЬ ЗАПИСАННЫМ, а качество формулировки остаётся делом
195
+ * человека — ровно как у освобождений заставы секретов и списка исключений дрейфа.
196
+ *
197
+ * БАЗА ВКЛЮЧИТЕЛЬНА: каталог, заведённый В САМ день базы, правилом контролируется («не раньше
198
+ * базы», а не «после базы»).
199
+ *
200
+ * ЧЕГО ЭТА ПРОВЕРКА НЕ ЛОВИТ, названо честно: работу БЕЗ каталога фичи — разбор, ремонт, рой,
201
+ * обещание «вернёмся». Машинного следа у них нет, и они остаются на слое 2 (текст правила в
202
+ * CLAUDE.md). Утверждать, что правило покрыто целиком, было бы ложной гарантией.
203
+ */
204
+ export function backlogCoversFeatures(features, backlogTexts, baseline) {
205
+ // ДАТЫ СРАВНИВАЮТСЯ ЧИСЛАМИ, А НЕ СТРОКАМИ. Кросс-семейное ревью 2026-09-03 (gpt-5.6-sol, Grade D)
206
+ // предъявило три входа, на которых строковое сравнение ISO даёт неверный ответ, и я воспроизвёл их
207
+ // прогоном: `" "` (пробелы лексикографически меньше любой даты — каталог освобождался),
208
+ // `"2026-09-02T23:30:00-02:00"` (фактически ПОЗЖЕ базы, строково раньше), и разные формы записи
209
+ // одной даты. Разбор в число снимает весь класс разом.
210
+ const baseMs = Date.parse(baseline);
211
+ const blob = backlogTexts.join('\n').toLowerCase();
212
+ const out = [];
213
+ for (const f of features) {
214
+ if (typeof f.slug !== 'string' || f.slug.trim() === '')
215
+ continue;
216
+ // НЕРАЗБИРАЕМАЯ ИЛИ ОТСУТСТВУЮЩАЯ ДАТА — НЕ ОСВОБОЖДЕНИЕ. Каталог, чью дату появления не удалось
217
+ // установить, считается новым: это отказ в сторону строгости. Обратный выбор превращал бы порчу
218
+ // входа в способ обойти правило.
219
+ const bornMs = typeof f.createdIso === 'string' ? Date.parse(f.createdIso.trim()) : Number.NaN;
220
+ const born = Number.isFinite(bornMs) ? bornMs : Number.POSITIVE_INFINITY;
221
+ if (Number.isFinite(baseMs) && born < baseMs)
222
+ continue;
223
+ if (typeof f.waiver === 'string' && f.waiver.trim() !== '')
224
+ continue;
225
+ if (mentionsSlug(blob, f.slug))
226
+ continue;
227
+ out.push(f.slug);
228
+ }
229
+ return out;
230
+ }
231
+ /**
232
+ * Назван ли slug в тексте КАК ОТДЕЛЬНОЕ СЛОВО.
233
+ *
234
+ * Голый `includes` засчитывал совпадение внутри чужого слова: slug `log` считался покрытым записью
235
+ * «обновить catalog schema», а `api` — записью «починить capitalization report» (примеры из
236
+ * кросс-семейного ревью 2026-09-03, воспроизведены прогоном). Ложное покрытие опаснее ложного
237
+ * срабатывания: оно ТИХО гасит правило ровно там, где оно нужно.
238
+ *
239
+ * Границей считается всё, кроме латинской буквы, цифры, подчёркивания и дефиса — дефис входит в
240
+ * слово, потому что сами slug'и кебабные и `date-layers` не должен совпасть внутри
241
+ * `dashboard-date-layers`.
242
+ */
243
+ function mentionsSlug(haystackLower, slug) {
244
+ const s = slug.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
245
+ return new RegExp(`(^|[^a-z0-9_-])${s}($|[^a-z0-9_-])`).test(haystackLower);
246
+ }
159
247
  const CHECKERS = {
160
248
  'no-workspace-star': (f, sev) => {
161
249
  const out = [];
@@ -168,13 +256,150 @@ const CHECKERS = {
168
256
  }
169
257
  return out;
170
258
  },
259
+ 'plugin-manifest-audit': (f, sev) => {
260
+ /**
261
+ * ЗНАЧЕНИЕ ЕСТЬ, ТОЛЬКО ЕСЛИ ОНО ВИДНО. `trim()` не убирает нулевой ширины пробел и его
262
+ * родню, поэтому описание из одного `\u200B` проходило как заполненное — назвал независимый
263
+ * ревьюер 2026-09-04. Считается видимым лишь то, что остаётся после удаления пробельных И
264
+ * невидимых символов.
265
+ */
266
+ const visible = (v) => typeof v === 'string' && v.replace(/[\s\u00a0\u180e\u200b-\u200f\u2028\u2029\u202a-\u202e\u2060-\u2064\ufeff]/g, '') !== '';
267
+ /** Путь состава в сравнимом виде: `./skills/a` и `skills/a` — один каталог, а не два. */
268
+ const normPath = (v) => typeof v === 'string'
269
+ ? v.normalize('NFC').replace(/^\.\//, '').replace(/\/+$/, '').replace(/\/{2,}/g, '/')
270
+ : null;
271
+ // ПРОВЕРКА ПАСПОРТА НА ВХОДЕ. Правило `marketplace-parity` отвечает на другой вопрос — совпадает
272
+ // ли витрина со свежей регенерацией. Если ГЕНЕРАТОР выдаст пустое описание или версию `1.0`,
273
+ // parity будет доволен: копия совпадает с оригиналом, оба неверны. Здесь проверяется САМО
274
+ // содержимое.
275
+ //
276
+ // ЧЕГО ЗДЕСЬ НЕТ И ПОЧЕМУ: приёма «имя манифеста равно имени каталога». ИЗМЕРЕНО 2026-09-04 на
277
+ // 10 манифестах дерева — расхождение ровно одно и оно НАМЕРЕННОЕ: пакет называется
278
+ // `loop-designer-plugin`, а плагин внутри него — `loop-designer`. Имя плагина есть
279
+ // опубликованная личность и законно отличается от имени каталога, поэтому такая проверка
280
+ // краснела бы на верном коде. Правило, изобретающее нарушения, учит людей себя игнорировать.
281
+ // Ведущие нули запрещены (`01.2.3` — не строгая форма), и значение НЕ обрезается: пробел
282
+ // вокруг версии в манифесте есть дефект манифеста, а не мелочь, которую следует простить.
283
+ const STRICT_SEMVER = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
284
+ const out = [];
285
+ for (const m of f.pluginManifests ?? []) {
286
+ if (m.parseError !== undefined) {
287
+ out.push({ rule: 'plugin-manifest-audit', severity: sev, detail: `${m.path}: манифест не разобрался — ${m.parseError}` });
288
+ continue; // остальные поля у неразобранного манифеста не существуют
289
+ }
290
+ for (const field of ['name', 'description', 'version']) {
291
+ // СОБСТВЕННОЕ свойство: манифест, чьи поля приходят из прототипа, ничего не объявил.
292
+ const value = Object.hasOwn(m, field) ? m[field] : undefined;
293
+ if (!visible(value)) {
294
+ out.push({ rule: 'plugin-manifest-audit', severity: sev, detail: `${m.path}: поле ${field} пусто или отсутствует` });
295
+ }
296
+ }
297
+ const rawVersion = Object.hasOwn(m, 'version') ? m['version'] : undefined;
298
+ if (visible(rawVersion) && !STRICT_SEMVER.test(rawVersion)) {
299
+ out.push({ rule: 'plugin-manifest-audit', severity: sev, detail: `${m.path}: version = ${JSON.stringify(rawVersion)} — нужна строгая форма N.N.N без ведущих нулей и без пробелов` });
300
+ }
301
+ // ИНВЕНТАРИЗАЦИЯ В ОБЕ СТОРОНЫ: всё, что записано в накладной, лежит на складе, И всё, что
302
+ // лежит на складе, вписано в накладную. Одна сторона ловит обещание без товара, другая —
303
+ // товар, о котором никто не узнает. Класс, который эта пара закрывает: «счётчики поправили,
304
+ // файлы не тронули».
305
+ //
306
+ // Обе стороны проверяются ТОЛЬКО когда обе улики есть: манифест без поля `skills` не
307
+ // объявляет состава вовсе, и требовать от него совпадения значило бы выдумать обязательство.
308
+ const declared = Array.isArray(m.declaredSkills) ? m.declaredSkills : undefined;
309
+ const onDisk = Array.isArray(m.skillsOnDisk) ? m.skillsOnDisk : undefined;
310
+ // ПОЛОВИНА УЛИК — НЕ УЛИКИ. Прежде состав, объявленный без осмотра диска, ТИХО пропускался,
311
+ // а правило продолжало числиться проверенным: то самое «успех из тишины», против которого
312
+ // оно и заведено (назвал независимый ревьюер 2026-09-04).
313
+ if ((declared === undefined) !== (onDisk === undefined)) {
314
+ out.push({
315
+ rule: 'plugin-manifest-audit', severity: sev,
316
+ detail: `${m.path}: есть только одна половина улик о составе (${declared !== undefined ? 'объявленное без осмотра диска' : 'осмотр диска без объявленного'}) — сверить нечем`,
317
+ });
318
+ }
319
+ else if (declared !== undefined && onDisk !== undefined) {
320
+ const normList = (xs) => xs.map(normPath).filter((x) => x !== null && x !== '');
321
+ // Элемент не-строка — не путь. Молча его пропустить значило бы сверять неполные списки.
322
+ const badDeclared = declared.filter((x) => normPath(x) === null).length;
323
+ const badOnDisk = onDisk.filter((x) => normPath(x) === null).length;
324
+ if (badDeclared > 0 || badOnDisk > 0) {
325
+ out.push({ rule: 'plugin-manifest-audit', severity: sev, detail: `${m.path}: в составе есть элементы, которые не являются путями (объявлено ${badDeclared}, на диске ${badOnDisk})` });
326
+ }
327
+ const have = new Set(normList(onDisk));
328
+ const said = new Set(normList(declared));
329
+ const missing = [...said].filter((n) => !have.has(n));
330
+ const undeclared = [...have].filter((n) => !said.has(n));
331
+ if (missing.length > 0) {
332
+ out.push({ rule: 'plugin-manifest-audit', severity: sev, detail: `${m.path}: объявлены, но НЕ найдены на диске: ${missing.join(', ')}` });
333
+ }
334
+ if (undeclared.length > 0) {
335
+ out.push({ rule: 'plugin-manifest-audit', severity: sev, detail: `${m.path}: лежат на диске, но НЕ объявлены: ${undeclared.join(', ')}` });
336
+ }
337
+ }
338
+ }
339
+ return out;
340
+ },
341
+ 'sibling-dep-protocol': (f, sev) => {
342
+ // ПАРА К `no-workspace-star`, а не противоречие ему: они говорят о РАЗНЫХ МОМЕНТАХ. На ДИСКЕ
343
+ // сиблинг-зависимость обязана быть `workspace:` — тогда pnpm подставит реальную версию при
344
+ // паковке. В ОПУБЛИКОВАННОМ манифесте `workspace:` быть не должно — npm отправляет его
345
+ // дословно и ломает установку. Одно правило охраняет вход, другое выход.
346
+ //
347
+ // ОБЪЁМ СУЖЕН ИЗМЕРЕНИЕМ, а не осторожностью. Запись бэклога требовала протокол для ЛЮБОЙ
348
+ // сиблинг-зависимости. Замер 2026-09-03 (56 пакетов, 60 сиблинг-зависимостей) показал 8
349
+ // исключений — и ВСЕ восемь оказались `peerDependencies` (7) и `optionalDependencies` (1), где
350
+ // диапазон и есть смысл записи: peer-зависимость объявляет, чему обязан удовлетворять
351
+ // ПОТРЕБИТЕЛЬ, а `workspace:` при паковке превращается в точный пин, враждебный потребителю.
352
+ // Одна из восьми — намеренная схема «dz как ОБНАРУЖИВАЕМАЯ необязательная зависимость».
353
+ // То есть правило в исходной формулировке сломало бы работающий замысел; здесь оно охраняет
354
+ // ровно те два поля, где протокол уместен, и на них нарушений сегодня НОЛЬ.
355
+ const out = [];
356
+ for (const d of f.siblingDeps ?? []) {
357
+ // Поля читаются как ПРИМИТИВНЫЕ строки. Объект с унаследованным `startsWith`, всегда
358
+ // возвращающим true, прежде проходил мимо правила — назвал независимый ревьюер 2026-09-04.
359
+ const field = typeof d?.field === 'string' ? d.field : '';
360
+ const spec = typeof d?.spec === 'string' ? d.spec : null;
361
+ if (field !== 'dependencies' && field !== 'devDependencies')
362
+ continue;
363
+ if (spec === null) {
364
+ out.push({ rule: 'sibling-dep-protocol', severity: sev, detail: `${String(d?.name)}: ${field}.${String(d?.dep)} — спецификатор не строка, сверить нечем` });
365
+ continue;
366
+ }
367
+ if (spec.startsWith('workspace:'))
368
+ continue;
369
+ out.push({
370
+ rule: 'sibling-dep-protocol',
371
+ severity: sev,
372
+ detail: `${d.name}: ${field}.${d.dep} = "${spec}" — a sibling package must be referenced through the workspace: protocol on disk, so pnpm substitutes the real version at pack time`,
373
+ });
374
+ }
375
+ return out;
376
+ },
171
377
  'no-skill-drift': (f, sev) => {
172
378
  const drifted = Array.isArray(f.drift) ? f.drift.filter((d) => typeof d === 'string') : [];
173
379
  return drifted.length === 0 ? [] : [{ rule: 'no-skill-drift', severity: sev, detail: `${drifted.length} skill(s) drift between copies: ${drifted.slice(0, 8).join(', ')}${drifted.length > 8 ? '…' : ''} — heal with dz sync-canonical` }];
174
380
  },
381
+ 'backlog-covers-features': (f, sev) => {
382
+ const ev = f.featureBacklog;
383
+ if (!ev)
384
+ return [];
385
+ const uncovered = backlogCoversFeatures(ev.features, ev.backlogTexts, ev.baseline);
386
+ if (uncovered.length === 0)
387
+ return [];
388
+ return [{
389
+ rule: 'backlog-covers-features',
390
+ severity: sev,
391
+ detail: `${uncovered.length} фич(и) заведены после ${ev.baseline} и не названы ни одной записью бэклога: `
392
+ + `${uncovered.slice(0, 8).join(', ')}${uncovered.length > 8 ? '…' : ''}`
393
+ + ` — заведи запись (dz backlog add) ЛИБО впиши оговорку в features/<slug>/README.md строкой`
394
+ + ` "Backlog: не заведено — <причина>". Оговорка без причины не считается.`,
395
+ }];
396
+ },
175
397
  'no-secrets': (f, sev) => {
176
398
  const out = [];
399
+ const waived = secretWaiverState(f.secretWaivers).waived;
177
400
  for (const t of f.secretTargets ?? []) {
401
+ if (waived.has(t.label))
402
+ continue;
178
403
  for (const hit of scanSecrets(t.text)) {
179
404
  out.push({ rule: 'no-secrets', severity: sev, detail: `${t.label}: looks like a ${hit.name} — do not teach/publish a credential` });
180
405
  }
@@ -332,6 +557,42 @@ const CHECKERS = {
332
557
  detail: `${drifted.length} AGENTS.md policy section(s) are out of sync: ${drifted.slice(0, 8).join(', ')}${drifted.length > 8 ? '…' : ''} — heal with: dz agents-sync`,
333
558
  }];
334
559
  },
560
+ /**
561
+ * The fire-and-forget wrapper returns a DISPATCH STUB, so a stage whose deliverable is its
562
+ * return value gets a receipt instead of an answer. MEASURED 2026-08-31: eight stages of one
563
+ * research swarm each returned "Codex Task started in the background as task-…", downstream
564
+ * agents built on those stubs, and no artifact was produced. The misuse is visible in the
565
+ * program text — the stage's result is assigned to a name that a later prompt interpolates —
566
+ * so it belongs on layer 1 rather than in a rule nobody re-reads.
567
+ */
568
+ 'codex-wrapper-for-value-stage': (f, sev) => {
569
+ const scripts = f.workflowScripts;
570
+ if (scripts === undefined || scripts.length === 0)
571
+ return [];
572
+ const out = [];
573
+ for (const s of scripts) {
574
+ const text = String(s.text ?? '');
575
+ // Find `const <name> = await agent(… codex:codex-rescue …)` and ask whether <name> is later
576
+ // interpolated into another prompt. Assignment alone is not the defect: a stage may keep its
577
+ // handle for logging. Consumption in a prompt is what proves the VALUE was the deliverable.
578
+ const re = /(?:const|let)\s+([A-Za-z_$][\w$]*)\s*=\s*await\s+agent\(([\s\S]{0,4000}?)\)\s*(?:\n|;)/g;
579
+ for (const m of text.matchAll(re)) {
580
+ const name = String(m[1]);
581
+ const call = String(m[2]);
582
+ if (!/codex:codex-rescue/.test(call))
583
+ continue;
584
+ const consumed = new RegExp('\\$\\{\\s*(?:String\\()?' + name.replace(/[.*+?^{}()|[\]\\]/g, '\\$&') + '\\b');
585
+ if (consumed.test(text)) {
586
+ out.push({
587
+ rule: 'codex-wrapper-for-value-stage',
588
+ severity: sev,
589
+ detail: `${s.path}: stage "${name}" is routed to codex:codex-rescue AND its result is interpolated into another prompt — the wrapper returns a dispatch stub, so that prompt would receive a receipt, not an answer. Invoke codex synchronously (dz codex / codex exec) for a stage whose deliverable is its return value.`,
590
+ });
591
+ }
592
+ }
593
+ }
594
+ return out;
595
+ },
335
596
  'lockfile-in-sync': (f, _sev) => {
336
597
  // The 2026-07-28 CI break, mechanized: an overnight dep bump edited package.json and left
337
598
  // pnpm-lock.yaml stale, so `pnpm install --frozen-lockfile` died with ERR_PNPM_OUTDATED_LOCKFILE.
@@ -431,6 +692,19 @@ const CHECKERS = {
431
692
  return out;
432
693
  },
433
694
  };
695
+ /** Per-rule evidence predicates. No entry preserves the rule's existing checked behaviour exactly. */
696
+ const HAS_INPUT = {
697
+ // `!== undefined` пропускал `null`: правило объявлялось проверенным и возвращало чисто по
698
+ // ветке «улик нет». Это буквально отсутствие улик, отчитанное как проверка (назвал независимый
699
+ // ревьюер 2026-09-04).
700
+ 'backlog-covers-features': (f) => typeof f.featureBacklog === 'object' && f.featureBacklog !== null,
701
+ // Страж без улик не выдумывает вердикт: в дереве без сиблинг-зависимостей правилу нечего
702
+ // сказать, и «прошло» тут значило бы «не смотрели».
703
+ 'sibling-dep-protocol': (f) => Array.isArray(f.siblingDeps) && f.siblingDeps.length > 0,
704
+ // Дерево без плагин-манифестов правилу нечего сказать: «прошло» тут значило бы «не смотрели».
705
+ 'plugin-manifest-audit': (f) => Array.isArray(f.pluginManifests) && f.pluginManifests.length > 0,
706
+ 'no-secrets': (f) => Array.isArray(f.secretTargets) && f.secretTargets.length > 0,
707
+ };
434
708
  /**
435
709
  * Rules that may NEVER be promoted to HARD, whatever a config says. A rule whose evidence comes from a
436
710
  * deliberately tolerant parser must not be able to BLOCK an operation: the parser's own design admits it
@@ -530,6 +804,7 @@ export function evaluateGuard(facts, rules = DEFAULT_RULES) {
530
804
  const active = (Array.isArray(rules) ? rules : []).filter((r) => !!r && typeof r === 'object' && typeof r.id === 'string' && r.enabled !== false && Array.isArray(r.ops) && r.ops.includes(op));
531
805
  const violations = [];
532
806
  const checked = [];
807
+ const notEstablished = [];
533
808
  const observations = [];
534
809
  let volumeResult;
535
810
  let volumeEvaluated = false;
@@ -546,6 +821,28 @@ export function evaluateGuard(facts, rules = DEFAULT_RULES) {
546
821
  return volumeResult;
547
822
  };
548
823
  for (const r of active) {
824
+ const hasInput = HAS_INPUT[r.id];
825
+ // ПРЕДИКАТ УЛИК ИСПОЛНЯЕТСЯ ПОД ЗАЩИТОЙ. Прежде он стоял вне `try`, и факт с бросающим
826
+ // геттером ронял весь страж вместо того, чтобы стать отказом (назвал независимый ревьюер
827
+ // 2026-09-04). Гейт, падающий на враждебном входе, не даёт вердикта вообще.
828
+ let inputPresent;
829
+ try {
830
+ inputPresent = hasInput === undefined ? true : hasInput(facts);
831
+ }
832
+ catch (error) {
833
+ violations.push({
834
+ rule: r.id, severity: r.severity,
835
+ detail: `улики правила нечитаемы (${error instanceof Error ? error.message : String(error)}) — правило считается НАРУШЕННЫМ, а не пройденным`,
836
+ });
837
+ checked.push(r.id);
838
+ continue;
839
+ }
840
+ if (!inputPresent) {
841
+ // A rule with nothing to measure cannot produce a positive receipt. Keep the verdict unchanged,
842
+ // but record the missing input explicitly instead of calling the rule checked.
843
+ notEstablished.push(r.id);
844
+ continue;
845
+ }
549
846
  checked.push(r.id);
550
847
  if (VOLUME_SHADOW_RULE_IDS.includes(r.id)) {
551
848
  const emission = volume();
@@ -585,6 +882,16 @@ export function evaluateGuard(facts, rules = DEFAULT_RULES) {
585
882
  notes.push(`no-stubs: ${skipped} changed scannable file(s) not scanned (deleted/oversize/unreadable/beyond the file cap) — the stub scan is fail-open, so this is a coverage gap on the record, not a violation`);
586
883
  }
587
884
  }
885
+ if (checked.includes('no-secrets') || notEstablished.includes('no-secrets')) {
886
+ const reasonless = secretWaiverState(facts.secretWaivers).reasonless;
887
+ if (reasonless > 0) {
888
+ notes.push(`no-secrets: ${reasonless} reasonless secret waiver(s) ignored — add a non-empty reason or remove the entry`);
889
+ }
890
+ const skipped = facts.secretScan?.skipped;
891
+ if (typeof skipped === 'number' && Number.isFinite(skipped) && skipped > 0) {
892
+ notes.push(`no-secrets: ${skipped} packed inventory item(s) not scanned (oversize/unreadable/binary) — the secret scan is fail-open, so this is a coverage gap on the record, not a violation`);
893
+ }
894
+ }
588
895
  if (checked.includes('review-round') && facts.reviewRound?.gathered === false) {
589
896
  // A HARD gate that passes SILENTLY when it could not gather its evidence is a gate you cannot
590
897
  // tell from one that checked and approved (raised by cross-family review). It still does not
@@ -613,6 +920,7 @@ export function evaluateGuard(facts, rules = DEFAULT_RULES) {
613
920
  verdict,
614
921
  violations,
615
922
  checked,
923
+ notEstablished,
616
924
  ...(notes.length > 0 ? { notes } : {}),
617
925
  ...(observations.length > 0 ? { observations } : {}),
618
926
  };