@nurix/etna 0.20.36 → 0.20.38

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 (212) hide show
  1. package/data/catalog/rules/frontend.md +5 -5
  2. package/data/catalog/rules/pnpm.md +2 -2
  3. package/data/catalog/skills/nustack/SKILL.md +2 -2
  4. package/data/catalog/skills/nustack/references/cli-design.md +35 -35
  5. package/data/catalog/skills/nustack/references/monorepo-master-list.md +6 -6
  6. package/data/catalog/skills/nustack/references/monorepo-setup.md +13 -13
  7. package/data/catalog/skills/nustack/references/publishing.md +40 -39
  8. package/data/harness-index.json +1 -1
  9. package/data/harnesses/code/harness.json +2 -2
  10. package/data/harnesses/code/hooks/approved-packages.md +1 -2
  11. package/data/harnesses/code/rules/frontend.md +5 -5
  12. package/data/harnesses/code/rules/pnpm.md +2 -2
  13. package/data/harnesses/code/skills/boundary/SKILL.md +33 -22
  14. package/data/harnesses/code/skills/boundary/references/index.md +2 -4
  15. package/data/harnesses/code/skills/boundary/references/mechanisms.md +3 -10
  16. package/data/harnesses/code/skills/boundary/references/packs/build-config-runtime.md +1 -1
  17. package/data/harnesses/code/skills/boundary/references/packs/frontend.md +17 -17
  18. package/data/harnesses/code/skills/boundary/references/packs/generic-tail.md +1 -1
  19. package/data/harnesses/code/skills/brainstorm/README.md +11 -13
  20. package/data/harnesses/code/skills/brainstorm/SKILL.md +150 -132
  21. package/data/harnesses/code/skills/brainstorm/references/doctrine.md +48 -51
  22. package/data/harnesses/code/skills/brainstorm/references/harvest.md +51 -56
  23. package/data/harnesses/code/skills/brainstorm/references/session-schema.md +48 -42
  24. package/data/harnesses/code/skills/design/SKILL.md +31 -35
  25. package/data/harnesses/code/skills/design/components/charts.md +121 -43
  26. package/data/harnesses/code/skills/design/components/collections.md +209 -41
  27. package/data/harnesses/code/skills/design/components/feedback.md +86 -25
  28. package/data/harnesses/code/skills/design/components/hooks.md +198 -12
  29. package/data/harnesses/code/skills/design/components/index.md +93 -71
  30. package/data/harnesses/code/skills/design/components/inputs.md +249 -157
  31. package/data/harnesses/code/skills/design/components/layout.md +98 -38
  32. package/data/harnesses/code/skills/design/components/media.md +46 -25
  33. package/data/harnesses/code/skills/design/components/motion.md +56 -46
  34. package/data/harnesses/code/skills/design/components/navigation.md +54 -15
  35. package/data/harnesses/code/skills/design/components/overlays.md +51 -41
  36. package/data/harnesses/code/skills/design/components/setup.md +84 -5
  37. package/data/harnesses/code/skills/design/components/typography.md +72 -22
  38. package/data/harnesses/code/skills/design/components/utils.md +47 -13
  39. package/data/harnesses/code/skills/design/data/chrome/board-column.md +12 -12
  40. package/data/harnesses/code/skills/design/data/chrome/data-table.md +6 -6
  41. package/data/harnesses/code/skills/design/data/chrome/side-panel.md +15 -15
  42. package/data/harnesses/code/skills/design/data/chrome/sidebar.md +25 -25
  43. package/data/harnesses/code/skills/design/data/chrome/stat-cards.md +22 -22
  44. package/data/harnesses/code/skills/design/data/chrome/topbar.md +12 -12
  45. package/data/harnesses/code/skills/design/data/iconography.md +2 -2
  46. package/data/harnesses/code/skills/design/references/compose.md +14 -16
  47. package/data/harnesses/code/skills/design/references/emission.md +6 -6
  48. package/data/harnesses/code/skills/design/references/foundations.md +5 -5
  49. package/data/harnesses/code/skills/design/references/intake.md +6 -6
  50. package/data/harnesses/code/skills/design/references/object-pass.md +1 -1
  51. package/data/harnesses/code/skills/design/references/ship-gate.md +5 -5
  52. package/data/harnesses/code/skills/design/references/ux-patterns/Readme.md +4 -4
  53. package/data/harnesses/code/skills/design/references/ux-patterns/ai-layer.md +1 -1
  54. package/data/harnesses/code/skills/design/references/ux-patterns/container-choice.md +1 -1
  55. package/data/harnesses/code/skills/design/references/ux-patterns/dashboards.md +1 -1
  56. package/data/harnesses/code/skills/design/references/ux-patterns/modes.md +1 -1
  57. package/data/harnesses/code/skills/design/references/ux-patterns/object-model.md +2 -2
  58. package/data/harnesses/code/skills/design/references/ux-patterns/promotion-demotion.md +1 -1
  59. package/data/harnesses/code/skills/design/references/ux-patterns/settings.md +1 -1
  60. package/data/harnesses/code/skills/design/references/ux-patterns/standard-pages.md +1 -1
  61. package/data/harnesses/code/skills/design/scripts/README-validator.md +20 -8
  62. package/data/harnesses/code/skills/design/scripts/validate-design-md.mjs +15 -10
  63. package/data/harnesses/code/skills/documentation/SKILL.md +5 -5
  64. package/data/harnesses/code/skills/documentation/references/examples.md +22 -22
  65. package/data/harnesses/code/skills/documentation/references/frontmatter.md +3 -3
  66. package/data/harnesses/code/skills/documentation/references/instruction-style.md +3 -3
  67. package/data/harnesses/code/skills/documentation/references/source-comments.md +3 -3
  68. package/data/harnesses/code/skills/documentation/references/style-guide.md +5 -5
  69. package/data/harnesses/code/skills/documentation/references/untemplated.md +8 -8
  70. package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +3 -2
  71. package/data/harnesses/code/skills/documentation/templates/Readme.md +1 -1
  72. package/data/harnesses/code/skills/documentation/templates/acceptance-criteria.md +1 -1
  73. package/data/harnesses/code/skills/documentation/templates/api-reference.md +1 -1
  74. package/data/harnesses/code/skills/documentation/templates/architecture-decision.md +3 -7
  75. package/data/harnesses/code/skills/documentation/templates/behavioral-checklist.md +1 -1
  76. package/data/harnesses/code/skills/documentation/templates/changelog-entry.md +1 -1
  77. package/data/harnesses/code/skills/documentation/templates/changelog-index.md +1 -1
  78. package/data/harnesses/code/skills/documentation/templates/docs-readme.md +3 -3
  79. package/data/harnesses/code/skills/documentation/templates/doctrine.md +1 -1
  80. package/data/harnesses/code/skills/documentation/templates/domain-model.md +1 -1
  81. package/data/harnesses/code/skills/documentation/templates/environment-registry.md +1 -1
  82. package/data/harnesses/code/skills/documentation/templates/feature.md +3 -3
  83. package/data/harnesses/code/skills/documentation/templates/handover.md +2 -2
  84. package/data/harnesses/code/skills/documentation/templates/implementation-map.md +1 -1
  85. package/data/harnesses/code/skills/documentation/templates/migration-runbook.md +1 -1
  86. package/data/harnesses/code/skills/documentation/templates/non-goals.md +1 -1
  87. package/data/harnesses/code/skills/documentation/templates/operations-procedure.md +2 -2
  88. package/data/harnesses/code/skills/documentation/templates/package.md +1 -1
  89. package/data/harnesses/code/skills/documentation/templates/protected-files.md +1 -1
  90. package/data/harnesses/code/skills/documentation/templates/root-readme.md +1 -1
  91. package/data/harnesses/code/skills/documentation/templates/security-overview.md +1 -1
  92. package/data/harnesses/code/skills/documentation/templates/system-overview.md +1 -1
  93. package/data/harnesses/code/skills/documentation/templates/system.md +1 -1
  94. package/data/harnesses/code/skills/documentation/templates/testing-strategy.md +1 -1
  95. package/data/harnesses/code/skills/documentation/templates/ux-behavior.md +3 -5
  96. package/data/harnesses/code/skills/issue-bridge/SKILL.md +51 -16
  97. package/data/harnesses/code/skills/issue-bridge/references/trackers/github.md +5 -5
  98. package/data/harnesses/code/skills/issue-bridge/references/trackers/jira.md +11 -8
  99. package/data/harnesses/code/skills/issue-bridge/references/trackers/linear.md +16 -11
  100. package/data/harnesses/code/skills/nustack-graph/SKILL.md +38 -29
  101. package/data/harnesses/code/skills/polygraph/references/dispatch.md +31 -18
  102. package/data/harnesses/code/skills/polygraph/references/rows.md +11 -6
  103. package/data/harnesses/code/skills/schema-design/SKILL.md +39 -41
  104. package/data/harnesses/code/skills/test/SKILL.md +38 -42
  105. package/data/harnesses/code/skills/testing/SKILL.md +83 -73
  106. package/data/harnesses/code/skills/workflow-mapper/SKILL.md +156 -193
  107. package/data/harnesses/code/skills/workflow-mapper/references/patterns.md +15 -15
  108. package/data/harnesses/delivery/harness.json +2 -2
  109. package/data/harnesses/delivery/skills/brainstorm/README.md +11 -13
  110. package/data/harnesses/delivery/skills/brainstorm/SKILL.md +150 -132
  111. package/data/harnesses/delivery/skills/brainstorm/references/doctrine.md +48 -51
  112. package/data/harnesses/delivery/skills/brainstorm/references/harvest.md +51 -56
  113. package/data/harnesses/delivery/skills/brainstorm/references/session-schema.md +48 -42
  114. package/data/harnesses/delivery/skills/cost-report/SKILL.md +10 -10
  115. package/data/harnesses/delivery/skills/documentation/SKILL.md +5 -5
  116. package/data/harnesses/delivery/skills/documentation/references/examples.md +22 -22
  117. package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +3 -3
  118. package/data/harnesses/delivery/skills/documentation/references/instruction-style.md +3 -3
  119. package/data/harnesses/delivery/skills/documentation/references/source-comments.md +3 -3
  120. package/data/harnesses/delivery/skills/documentation/references/style-guide.md +5 -5
  121. package/data/harnesses/delivery/skills/documentation/references/untemplated.md +8 -8
  122. package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +3 -2
  123. package/data/harnesses/delivery/skills/documentation/templates/Readme.md +1 -1
  124. package/data/harnesses/delivery/skills/documentation/templates/acceptance-criteria.md +1 -1
  125. package/data/harnesses/delivery/skills/documentation/templates/api-reference.md +1 -1
  126. package/data/harnesses/delivery/skills/documentation/templates/architecture-decision.md +3 -7
  127. package/data/harnesses/delivery/skills/documentation/templates/behavioral-checklist.md +1 -1
  128. package/data/harnesses/delivery/skills/documentation/templates/changelog-entry.md +1 -1
  129. package/data/harnesses/delivery/skills/documentation/templates/changelog-index.md +1 -1
  130. package/data/harnesses/delivery/skills/documentation/templates/docs-readme.md +3 -3
  131. package/data/harnesses/delivery/skills/documentation/templates/doctrine.md +1 -1
  132. package/data/harnesses/delivery/skills/documentation/templates/domain-model.md +1 -1
  133. package/data/harnesses/delivery/skills/documentation/templates/environment-registry.md +1 -1
  134. package/data/harnesses/delivery/skills/documentation/templates/feature.md +3 -3
  135. package/data/harnesses/delivery/skills/documentation/templates/handover.md +2 -2
  136. package/data/harnesses/delivery/skills/documentation/templates/implementation-map.md +1 -1
  137. package/data/harnesses/delivery/skills/documentation/templates/migration-runbook.md +1 -1
  138. package/data/harnesses/delivery/skills/documentation/templates/non-goals.md +1 -1
  139. package/data/harnesses/delivery/skills/documentation/templates/operations-procedure.md +2 -2
  140. package/data/harnesses/delivery/skills/documentation/templates/package.md +1 -1
  141. package/data/harnesses/delivery/skills/documentation/templates/protected-files.md +1 -1
  142. package/data/harnesses/delivery/skills/documentation/templates/root-readme.md +1 -1
  143. package/data/harnesses/delivery/skills/documentation/templates/security-overview.md +1 -1
  144. package/data/harnesses/delivery/skills/documentation/templates/system-overview.md +1 -1
  145. package/data/harnesses/delivery/skills/documentation/templates/system.md +1 -1
  146. package/data/harnesses/delivery/skills/documentation/templates/testing-strategy.md +1 -1
  147. package/data/harnesses/delivery/skills/documentation/templates/ux-behavior.md +3 -5
  148. package/data/harnesses/delivery/skills/escalate/SKILL.md +11 -11
  149. package/data/harnesses/delivery/skills/prompt-eval/SKILL.md +8 -8
  150. package/data/harnesses/delivery/skills/prompt-library/SKILL.md +30 -9
  151. package/data/harnesses/delivery/skills/route/SKILL.md +8 -8
  152. package/data/harnesses/etna/harness.json +2 -2
  153. package/data/harnesses/etna/skills/boundary/SKILL.md +33 -22
  154. package/data/harnesses/etna/skills/boundary/references/index.md +2 -4
  155. package/data/harnesses/etna/skills/boundary/references/mechanisms.md +3 -10
  156. package/data/harnesses/etna/skills/boundary/references/packs/build-config-runtime.md +1 -1
  157. package/data/harnesses/etna/skills/boundary/references/packs/frontend.md +17 -17
  158. package/data/harnesses/etna/skills/boundary/references/packs/generic-tail.md +1 -1
  159. package/data/harnesses/etna/skills/brainstorm/README.md +11 -13
  160. package/data/harnesses/etna/skills/brainstorm/SKILL.md +150 -132
  161. package/data/harnesses/etna/skills/brainstorm/references/doctrine.md +48 -51
  162. package/data/harnesses/etna/skills/brainstorm/references/harvest.md +51 -56
  163. package/data/harnesses/etna/skills/brainstorm/references/session-schema.md +48 -42
  164. package/data/harnesses/etna/skills/documentation/SKILL.md +5 -5
  165. package/data/harnesses/etna/skills/documentation/references/examples.md +22 -22
  166. package/data/harnesses/etna/skills/documentation/references/frontmatter.md +3 -3
  167. package/data/harnesses/etna/skills/documentation/references/instruction-style.md +3 -3
  168. package/data/harnesses/etna/skills/documentation/references/source-comments.md +3 -3
  169. package/data/harnesses/etna/skills/documentation/references/style-guide.md +5 -5
  170. package/data/harnesses/etna/skills/documentation/references/untemplated.md +8 -8
  171. package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +3 -2
  172. package/data/harnesses/etna/skills/documentation/templates/Readme.md +1 -1
  173. package/data/harnesses/etna/skills/documentation/templates/acceptance-criteria.md +1 -1
  174. package/data/harnesses/etna/skills/documentation/templates/api-reference.md +1 -1
  175. package/data/harnesses/etna/skills/documentation/templates/architecture-decision.md +3 -7
  176. package/data/harnesses/etna/skills/documentation/templates/behavioral-checklist.md +1 -1
  177. package/data/harnesses/etna/skills/documentation/templates/changelog-entry.md +1 -1
  178. package/data/harnesses/etna/skills/documentation/templates/changelog-index.md +1 -1
  179. package/data/harnesses/etna/skills/documentation/templates/docs-readme.md +3 -3
  180. package/data/harnesses/etna/skills/documentation/templates/doctrine.md +1 -1
  181. package/data/harnesses/etna/skills/documentation/templates/domain-model.md +1 -1
  182. package/data/harnesses/etna/skills/documentation/templates/environment-registry.md +1 -1
  183. package/data/harnesses/etna/skills/documentation/templates/feature.md +3 -3
  184. package/data/harnesses/etna/skills/documentation/templates/handover.md +2 -2
  185. package/data/harnesses/etna/skills/documentation/templates/implementation-map.md +1 -1
  186. package/data/harnesses/etna/skills/documentation/templates/migration-runbook.md +1 -1
  187. package/data/harnesses/etna/skills/documentation/templates/non-goals.md +1 -1
  188. package/data/harnesses/etna/skills/documentation/templates/operations-procedure.md +2 -2
  189. package/data/harnesses/etna/skills/documentation/templates/package.md +1 -1
  190. package/data/harnesses/etna/skills/documentation/templates/protected-files.md +1 -1
  191. package/data/harnesses/etna/skills/documentation/templates/root-readme.md +1 -1
  192. package/data/harnesses/etna/skills/documentation/templates/security-overview.md +1 -1
  193. package/data/harnesses/etna/skills/documentation/templates/system-overview.md +1 -1
  194. package/data/harnesses/etna/skills/documentation/templates/system.md +1 -1
  195. package/data/harnesses/etna/skills/documentation/templates/testing-strategy.md +1 -1
  196. package/data/harnesses/etna/skills/documentation/templates/ux-behavior.md +3 -5
  197. package/data/harnesses/etna/skills/workflow-mapper/SKILL.md +156 -193
  198. package/data/harnesses/etna/skills/workflow-mapper/references/patterns.md +15 -15
  199. package/data/harnesses/hr/harness.json +2 -2
  200. package/data/harnesses/hr/skills/evaluator/SKILL.md +71 -73
  201. package/data/harnesses/hr/skills/evaluator/criteria/code-quality.md +28 -47
  202. package/data/harnesses/hr/skills/evaluator/criteria/deployment-readiness.md +33 -43
  203. package/data/harnesses/hr/skills/evaluator/criteria/maintainability.md +34 -46
  204. package/data/harnesses/hr/skills/evaluator/criteria/mechanical-ambition.md +13 -13
  205. package/data/harnesses/hr/skills/evaluator/criteria/problem-substantiveness.md +7 -7
  206. package/data/harnesses/hr/skills/evaluator/criteria/testing.md +36 -41
  207. package/data/harnesses/hr/skills/evaluator/criteria/ux-mechanics.md +25 -11
  208. package/data/harnesses/hr/skills/evaluator/criteria/value-articulation.md +7 -7
  209. package/data/harnesses/hr/skills/evaluator/preflight.md +27 -46
  210. package/data/harnesses/hr/skills/interview-eval/SKILL.md +37 -42
  211. package/data/harnesses/hr/skills/interview-eval/rubric.md +21 -23
  212. package/package.json +2 -2
@@ -1,24 +1,24 @@
1
1
  # Testing & Resilience — Extraction Plan
2
2
 
3
- - **Sub-criterion:** 1.2 (AI-only)
4
- - **Weight:** 12.5 pts (4 Code AI × 12.5 = 50 pts half)
3
+ - **Sub-criterion:** 1.2 (Production-Grade Code)
4
+ - **Weight:** 12.5 pts
5
5
  - **Contenders:** Semgrep + filesystem + GHA + LLM (joint load-bearing) + CodeRabbit resilience reuse (**calibrating modifier**) + **multi-protocol route-auth scan** (HTTP + WebSocket + gRPC + tRPC — feeds the `AUTH` gate).
6
6
  - **Source quote:** _"Unit/integration tests, error handling, input validation. It should survive more than the happy path."_
7
7
 
8
- Bands are **absolute** — thresholds in the _Banding_ section below are fixed numeric cutoffs. Gates this recipe owns: **`UNTESTED`** (hard, `testing ≤ 1` when `test_file_count == 0`), **`TESTS_TRIVIAL`** (soft, `testing ≤ 2` when `assertion_density < 1.0` OR `trivial_body_ratio > 0.8`), and **`AUTH`** (fires `testing ≤ 2` when network-routed handlers exist and ≥ 1 mutating endpoint isn't behind an auth middleware/dependency/decorator, detected across HTTP [FastAPI/Express/Flask/Gin/Django POST/PUT/PATCH/DELETE], WebSocket [ws/Socket.io/SignalR], gRPC [grpc/grpcio unary+streaming], tRPC [@trpc/server mutations]). Raw dumps: `raw/testing-auth-scan-{http,ws,grpc,trpc}.json`. Data fields: `routed_mutating_endpoints_total`, `routed_mutating_endpoints_unguarded`, `auth_by_protocol: {http: N, ws: N, grpc: N, trpc: N}`. AUTH gate is skipped if no routed handlers are detected.
8
+ Bands are **absolute** — the thresholds in _Aggregation_ are fixed numeric cutoffs. This recipe owns three gates — `UNTESTED`, `TESTS_TRIVIAL` and `AUTH` — defined in § Gates.
9
9
 
10
- > Four load-bearing signals + one calibrating modifier (CR), integrated by the scorer. No weighted-math internal split — the LLM emits a single 0–5 band and cites the most load-bearing signal.
10
+ Four load-bearing signals (1, 2, 4, 5) and one calibrating modifier (3, CodeRabbit) feed the band; Signal 6 feeds only the `AUTH` gate. There is no weighted internal split — the LLM emits a single 0–5 band and cites the most load-bearing signal.
11
11
 
12
12
  ---
13
13
 
14
14
  ## Preflight
15
15
 
16
- Before running this recipe, execute [`../../preflight.md`](../../preflight.md). Required:
16
+ Before running this recipe, execute [`../preflight.md`](../preflight.md). Required:
17
17
 
18
18
  - `semgrep` (polyglot static analysis — resilience rule-set)
19
19
  - `gh`, `jq` (CI workflow introspection + CR evidence scrape)
20
20
 
21
- If `semgrep` cannot be installed, emit `semgrep_resilience_findings: null, semgrep_NOT_RUN: true, reason: "..."` and flag loudly in `§6.1`. Do not substitute grep for it — the patterns Semgrep catches (`bare-except`, `empty-catch`, `unhandled-promise`) are structural, not lexical.
21
+ If `semgrep` cannot be installed, emit `semgrep_resilience_findings: null, semgrep_NOT_RUN: true, reason: "..."` and flag it in the workspace README's raw artifact index. **Never** substitute grep — the patterns Semgrep catches (`bare-except`, `empty-catch`, `unhandled-promise`) are structural, not lexical.
22
22
 
23
23
  ---
24
24
 
@@ -36,7 +36,7 @@ find <repo> -type f \
36
36
  -not -path '*/node_modules/*' -not -path '*/.venv/*' \
37
37
  | wc -l
38
38
 
39
- # Source file count (for ratio) — language-aware; see "Per-language thresholds" below
39
+ # Source file count (for ratio) — language-aware; see "Per-language test ratio thresholds" below
40
40
  find <repo> -type f \
41
41
  \( -name '*.py' -o -name '*.ts' -o -name '*.tsx' \
42
42
  -o -name '*.js' -o -name '*.jsx' -o -name '*.go' \) \
@@ -68,7 +68,7 @@ echo "$TEST_FILES" | xargs grep -cE \
68
68
 
69
69
  Capture: `test_file_count`, `src_file_count`, `test_ratio`, `framework_configured`, `assertion_density` (assertions per test file), `trivial_body_ratio` (trivial bodies ÷ total test bodies).
70
70
 
71
- **Primary language detection** (for thresholds — see Aggregation):
71
+ **Primary language detection** (selects the test-ratio threshold in _Aggregation_):
72
72
 
73
73
  ```bash
74
74
  find <repo> -type f \
@@ -98,7 +98,7 @@ Capture: `ci_has_test_job` (bool), `latest_test_conclusion` (SUCCESS/FAILURE/NON
98
98
 
99
99
  ### Signal 3 — CodeRabbit reuse (**calibrating modifier**)
100
100
 
101
- Reuse the CR scrape from 1.1 (see [code-quality.md](code-quality.md#signal-6--coderabbit-scrape-calibrating-modifier) Signal 6). Filter to resilience-relevant categories `[bug, warning]` — these are CR's signal for missing error handling, swallowed exceptions, or validation gaps on the PRs it reviewed.
101
+ Reuse the CR scrape from 1.1 ([code-quality.md Signal 6](code-quality.md#signal-6--coderabbit-scrape-calibrating-modifier)) — never re-scrape. Filter to the resilience categories `[bug, warning]`, CR's signal for missing error handling, swallowed exceptions and validation gaps.
102
102
 
103
103
  ```yaml
104
104
  categories_in_scope: [bug, warning]
@@ -108,21 +108,20 @@ Capture:
108
108
 
109
109
  - `cr_resilience_flags = by_category.bug + by_category.warning`
110
110
  - `cr_resilience_per_kloc = cr_resilience_flags ÷ (scc_code_loc ÷ 1000)` (lower-is-better; `null` when `cr_pr_count == 0` or `cr_resilience_flags == 0` on a zero-actionable walkthrough)
111
- - `cr_semgrep_overlap` — count of `file:line` flagged by both CR and Semgrep Signal 4. Prefer CR's context in evidence when they overlap; surface the overlap count for transparency.
111
+ - `cr_semgrep_overlap` — count of `file:line` flagged by both CR and Semgrep Signal 4. Prefer CR's context in evidence where they overlap.
112
112
 
113
- **Banding rule:** CR is a calibrating modifier — it pulls the band down when `cr_resilience_per_kloc` is high and (when non-null) participates in the aggregation table below alongside `semgrep_resilience_per_kloc`. When CR data is empty, `cr_resilience_per_kloc` is `null` and the modifier is a no-op. Full rationale + plan-upgrade escape hatch in [`SKILL.md → CodeRabbit — calibrating modifier with null-data semantics`](../SKILL.md#coderabbit--calibrating-modifier-with-null-data-semantics).
114
-
115
- **Semgrep remains the broadest resilience signal** (full-tree scan, not just reviewed diffs). Signal 4 below.
113
+ **Banding rule:** when non-null, `cr_resilience_per_kloc` sits in the _Aggregation_ table beside `semgrep_resilience_per_kloc` and pulls the band down when high; when CR data is empty it is `null` and a no-op ([`SKILL.md → CodeRabbit — calibrating modifier with null-data semantics`](../SKILL.md#coderabbit--calibrating-modifier-with-null-data-semantics)). Semgrep (Signal 4) is the broader resilience signal — it scans the full tree, not just reviewed diffs.
116
114
 
117
115
  ### Signal 4 — Semgrep scan
118
116
 
119
117
  ```bash
120
- semgrep --config p/python --config p/javascript --config p/typescript \
118
+ timeout 180 semgrep --config p/python --config p/javascript --config p/typescript \
121
119
  --config p/go \
122
- --json <repo> > /tmp/semgrep.json
120
+ --json --timeout 30 --disable-version-check --metrics=off \
121
+ <repo> > /tmp/semgrep.json
123
122
  ```
124
123
 
125
- **Filter to resilience-relevant rules only.** Tight pattern (catches the actual phenomena, drops noise):
124
+ **Filter to resilience-relevant rules only:**
126
125
 
127
126
  ```bash
128
127
  jq '[.results[] | select(
@@ -132,13 +131,13 @@ jq '[.results[] | select(
132
131
  )]' /tmp/semgrep.json
133
132
  ```
134
133
 
135
- **What the pattern deliberately excludes, and why:**
134
+ **Never widen the pattern with these** — each looks like a natural addition:
136
135
 
137
- - `error|exception` — matched every rule name containing those words (most security rules do), inflating findings ~10×.
138
- - `injection|deserial|unsafe` — security territory; belongs in 1.4 Maintainability / SECURITY gate to avoid double-counting.
139
- - `await|promise` (bare) — scoped to `unchecked-await` / `unhandled-promise` so async-correctness rules aren't indiscriminately matched.
136
+ - `error|exception` — matches every rule name containing those words (most security rules do), inflating findings ~10×.
137
+ - `injection|deserial|unsafe` — security territory, owned by 1.4 Maintainability; matching it here double-counts.
138
+ - bare `await|promise` — matches async-correctness rules indiscriminately; the pattern scopes them to `unchecked-await` / `unhandled-promise`.
140
139
 
141
- `p/security-audit` config is excluded — it produces security-skewed noise. Language packs alone carry the resilience rules we want.
140
+ **Never add `p/security-audit`** — it produces security-skewed noise; the language packs carry the resilience rules.
142
141
 
143
142
  Capture:
144
143
 
@@ -147,7 +146,7 @@ Capture:
147
146
  - `semgrep_resilience_by_severity` (ERROR / WARNING / INFO)
148
147
  - `semgrep_resilience_per_kloc`
149
148
 
150
- **Note:** Semgrep ERROR severity does **not** act as a hard score cap — signal only.
149
+ Semgrep ERROR severity is a signal only — **never** a hard score cap.
151
150
 
152
151
  ### Signal 5 — LLM sample (3 handler-or-resilience-dense files)
153
152
 
@@ -158,7 +157,7 @@ Tiered file selection — walk tiers until 3 files are picked:
158
157
  - Matches `*route*`, `*handler*`, `*controller*`, `*api*`, `*server*`, `*endpoint*`, `*view*`
159
158
  - Under `src/`, `app/`, `internal/`, `pkg/` or root
160
159
 
161
- **Tier 2 — resilience-dense files (for non-API repos: CLIs, agents, batch jobs):** Rank source files by `(try|catch|raise|throw|except|panic|recover) count ÷ LOC`; pick top 3. These are where resilience _matters_, regardless of repo shape.
160
+ **Tier 2 — resilience-dense files (non-API repos: CLIs, agents, batch jobs):** rank source files by `(try|catch|raise|throw|except|panic|recover) count ÷ LOC`; pick the top 3.
162
161
 
163
162
  ```bash
164
163
  for f in $(find <repo>/src <repo>/app <repo>/internal \
@@ -181,7 +180,7 @@ Capture: `llm_resilience_score` (0–5), `llm_notes` (one sentence), `llm_files_
181
180
 
182
181
  ### Signal 6 — Multi-protocol AUTH route-scan (AUTH gate trigger)
183
182
 
184
- Enterprise backends ship mutating endpoints. A POST/PUT/PATCH/DELETE (HTTP) — or a WebSocket message handler, gRPC unary/streaming method, or tRPC mutation — that doesn't run behind an auth middleware / dependency / decorator is an enterprise-grade resilience failure: anyone can mutate server state. This signal scans for routed mutating handlers across four protocols and checks each one for an auth guard. **Skipped (gate does not fire) if no routed handlers are detected** — a CLI or batch job isn't expected to carry auth.
183
+ A mutating handler — HTTP POST/PUT/PATCH/DELETE, a WebSocket message handler, a gRPC unary/streaming method, a tRPC mutation — not behind an auth middleware / dependency / decorator lets anyone mutate server state. Scan for routed mutating handlers across the four protocols and check each for an auth guard. **Skipped (the gate does not fire) when no routed handlers are detected** — a CLI or batch job carries no auth.
185
184
 
186
185
  ```bash
187
186
  # HTTP — FastAPI / Flask / Django / Express / Gin / Echo
@@ -232,7 +231,7 @@ semgrep --config=auto --timeout 30 --metrics=off --disable-version-check --json
232
231
  <repo> > /tmp/auth-trpc.json 2>/dev/null || true
233
232
  ```
234
233
 
235
- Parse each tool's output for the number of mutating handlers and, critically, whether each one is adjacent to or wrapped by an auth guard. A handler is "guarded" when any of these are present in the same scope:
234
+ Parse each output for the mutating handlers and whether each is adjacent to or wrapped by an auth guard. A handler is "guarded" when any of these is present in the same scope:
236
235
 
237
236
  - **Python/FastAPI**: `Depends(...)` call on the function signature that resolves to an auth dep, `@require_auth`/`@login_required` decorator, or a router prefix/dependency declaring auth
238
237
  - **Python/Django**: `@login_required` / `@permission_required` / DRF `permission_classes`
@@ -243,7 +242,7 @@ Parse each tool's output for the number of mutating handlers and, critically, wh
243
242
  - **WebSocket**: handshake-time auth in `connect` handler OR per-message token validation
244
243
  - **gRPC**: `ServerInterceptor` registered at `grpc.Server(interceptors=[...])` OR explicit `context.authenticate(...)` in the method
245
244
 
246
- The scan runs with a 30 s per-rule cap + 120 s wall-clock ceiling per protocol; tools that time out emit `<protocol>_NOT_RUN: true, reason: "semgrep timeout"` with no effect on the gate.
245
+ Run each protocol's scan under a 30 s per-rule cap and a 120 s wall-clock ceiling; a scan that times out emits `<protocol>_NOT_RUN: true, reason: "semgrep timeout"` and has no effect on the gate.
247
246
 
248
247
  Aggregate per protocol, then across all protocols:
249
248
 
@@ -268,7 +267,7 @@ Capture:
268
267
 
269
268
  ## Raw dumps (flat — files under `raw/` named `testing-*`)
270
269
 
271
- Each signal writes its raw output to the flat `raw/` directory at the workspace root. Absent files = not extracted. Aggregates go to `scorecard.yaml` under `data.`.
270
+ Each signal writes its raw output to the flat `raw/` directory; an absent file means not extracted. Aggregates go to `scorecard.yaml` under `data.`.
272
271
 
273
272
  | File | Source signal | Shape / note |
274
273
  | --- | --- | --- |
@@ -287,7 +286,7 @@ CodeRabbit comments are dumped once by 1.1 under `raw/code-quality-cr-comments.j
287
286
 
288
287
  ## Aggregation → 0–5 band
289
288
 
290
- Scorer integrates the 5 signals. Rough directionality:
289
+ Integrate Signals 1–5. Rough directionality:
291
290
 
292
291
  | Signal | Pulls score UP | Pulls score DOWN |
293
292
  | --- | --- | --- |
@@ -300,7 +299,7 @@ Scorer integrates the 5 signals. Rough directionality:
300
299
 
301
300
  ### Per-language test ratio thresholds
302
301
 
303
- Go colocates `foo_test.go` with `foo.go`; Python typically uses a separate `tests/` tree; TS varies. Fixed thresholds distort across stacks — use language-aware floors:
302
+ A single threshold distorts across stacks — Go colocates `foo_test.go` with `foo.go`, Python keeps a separate `tests/` tree, TS varies — so the floors are per language, keyed on `primary_language`:
304
303
 
305
304
  | Primary language | Top-band ratio | Floor (pulls band down) |
306
305
  | ----------------------- | -------------- | ----------------------- |
@@ -328,7 +327,7 @@ Go colocates `foo_test.go` with `foo.go`; Python typically uses a separate `test
328
327
  | `TESTS_TRIVIAL` (soft) | `test_file_count > 0` AND (`assertion_density < 1.0` per test file OR `trivial_body_ratio > 0.8`) | `testing` ≤ 2 |
329
328
  | `AUTH` | `routed_mutating_endpoints_total ≥ 1` AND `routed_mutating_endpoints_unguarded ≥ 1`. Covers HTTP (POST/PUT/PATCH/DELETE), WebSocket event handlers, gRPC unary+streaming, tRPC mutations. Skipped when `auth_NOT_RUN == true` (no routed handlers detected — CLI/batch/library). | `testing` ≤ 2 |
330
329
 
331
- All three can fire independently and stack. `AUTH` is the "enterprise-grade mutation without authentication" case — a POST endpoint that lets any unauthenticated caller mutate server state is a testing failure regardless of how clean the happy-path tests are. `TESTS_TRIVIAL` is the "tests exist but are meaningless" case (a single `def test(): pass` file passes `UNTESTED` but should not reach band 3+).
330
+ All three fire independently and stack. `AUTH` caps the band however clean the happy-path tests are — an endpoint any unauthenticated caller can use to mutate state is a resilience failure. `TESTS_TRIVIAL` catches meaningless tests: a single `def test(): pass` file passes `UNTESTED` but must not reach band 3+.
332
331
 
333
332
  ---
334
333
 
@@ -338,10 +337,10 @@ All three can fire independently and stack. `AUTH` is the "enterprise-grade muta
338
337
  - No CI workflows → drop signal 2, rely on 1, 4, 5.
339
338
  - `cr_pr_count == 0` OR CR empty (Free-plan walkthrough-only) → `cr_resilience_per_kloc: null`, Signal 3 modifier is a no-op; rely on 1, 2, 4, 5 for the band.
340
339
  - Semgrep doesn't support a repo's primary language → drop signal 4, rely on 1, 2, 5.
341
- - Semgrep not installed (preflight failed) → emit `semgrep_NOT_RUN: true`, rely on 1, 2, 5, flag in §6.1.
340
+ - Semgrep not installed (preflight failed) → emit `semgrep_NOT_RUN: true`, rely on 1, 2, 5, flag it in the README's raw artifact index.
342
341
  - LLM tier 1 & 2 yield nothing → use tier 3, annotate `llm_sample_tier: 3` (confidence is lower).
343
342
 
344
- Annotate evidence with `"Signals used: [...]"` so the audit trail is explicit.
343
+ Annotate evidence with `"Signals used: [...]"`.
345
344
 
346
345
  ---
347
346
 
@@ -384,16 +383,12 @@ cr_semgrep_overlap: 0
384
383
  signals_used: [filesystem, gha, semgrep, llm, coderabbit_empty]
385
384
  ```
386
385
 
387
- `null` signals the scorer to skip the CR modifier for this project.
388
-
389
386
  ---
390
387
 
391
388
  ## Caveats
392
389
 
393
- - Semgrep pre-built packs skew toward security. A tight regex keeps resilience focus; worth 3–5 custom rules if scoring reveals gaps.
394
- - CodeRabbit reuse is a calibrating modifier, not a primary axis; `null` on Free-plan walkthrough-only repos means no-op. Full rationale + plan-upgrade escape hatch in [`SKILL.md → CodeRabbit — calibrating modifier with null-data semantics`](../SKILL.md#coderabbit--calibrating-modifier-with-null-data-semantics).
395
- - `AI_AUTHORED_SUSPECTED` flag (from 1.1) remains informational — LLM reviewer should note AI-generated resilience patterns (e.g. copy-pasted try/except blocks with identical logging).
396
- - LLM sample size is 3. Diverse codebases may score unevenly. Evidence must name the files.
397
- - `trivial_body_ratio` heuristic may false-positive on pytest `parametrize` stubs where the real body lives in fixtures. Acceptable — over-triggering a soft gate is safer than under-triggering.
398
- - Per-language `test_ratio` thresholds are **absolute**. Each language's floor/top band is fixed in the table above.
399
- - AUTH scan's guard-detection is LLM-adjudicated — Semgrep surfaces the mutating handler; the scorer reads surrounding context to decide whether a guard is present. This is a deliberate trade-off: pattern-matching every auth idiom across 4+ protocols and 10+ frameworks is combinatorial, and an LLM with the source in front of it is more accurate than a brittle megapattern. When the LLM's confidence on guard-detection is low (unusual framework, ambiguous middleware chain), emit `auth_reason: "guard detection uncertain"` and let the gate fire conservatively — false-positive AUTH is cheaper than false-negative.
390
+ - Semgrep's pre-built packs skew toward security; the tight regex keeps the resilience focus. Prefer adding 3–5 custom rules when scoring reveals gaps.
391
+ - AI-authored code (`AI_AUTHORED_SUSPECTED`, defined in 1.1's Caveats) is informational — note AI-generated resilience patterns such as copy-pasted try/except blocks with identical logging.
392
+ - LLM sample size is 3, so diverse codebases may score unevenly. Evidence **must** name the files.
393
+ - `trivial_body_ratio` may false-positive on pytest `parametrize` stubs whose real body lives in fixtures. Accepted — over-triggering a soft gate is safer than under-triggering.
394
+ - AUTH guard detection is LLM-adjudicated: Semgrep surfaces the mutating handler and the scorer reads the surrounding source, because a pattern for every auth idiom across 4 protocols and 10+ frameworks is combinatorial and brittle. When confidence is low (unusual framework, ambiguous middleware chain), emit `auth_reason: "guard detection uncertain"` and let the gate fire — a false-positive AUTH is cheaper than a false negative.
@@ -5,7 +5,7 @@
5
5
  - **Contenders:** UX heuristic grep bundle (web) + clig.dev greps (CLI) + **enterprise API quality signals** (API-only path) + LLM read (layered, path-dependent)
6
6
  - **Source quote:** _"Clear user flows, thoughtful UX (even with minimal UI). Usability, not just features."_
7
7
 
8
- This recipe scores usability and user-flow quality across three surfaces (web UI / CLI / API-only). Bands are **absolute**. The **API-only path is not capped** — enterprise backends can score up to 5. API-only signal bundle: (a) OpenAPI/Swagger spec presence + completeness (all routes documented, examples present, error shapes declared), (b) route naming consistency (kebab / snake / camel singular-vs-plural coherence), (c) response envelope + error-handling consistency (uniform `{data, error}` or RFC 7807), (d) versioning strategy (`/v1/` prefix, `Accept-Version` header, or clearly no-version-needed), (e) idempotency on mutations (Idempotency-Key header support on POST/PUT/PATCH), (f) rate-limiting presence (middleware + headers), (g) input validation at boundaries (schema validation on incoming requests), (h) API documentation quality (written docs beyond autogen). Three-path detection (web / CLI / API-only) writes `raw/ux-mechanics-path-detection.json`. Gates: none owned by this recipe.
8
+ This recipe scores usability and user-flow quality on three surfaces — web UI (Path A), CLI (Path B), API-only (Path C). Bands are **absolute**, and the **API-only path is uncapped**: a polished enterprise backend scores up to 5, like an equally polished web UI. This recipe owns no gates.
9
9
 
10
10
  ---
11
11
 
@@ -34,7 +34,7 @@ grep -rlE 'Flask|FastAPI|express\(\)|gin\.Default|fiber\.New|@nestjs/core' \
34
34
  <local-repo-path>/src <local-repo-path>/app <local-repo-path>/internal 2>/dev/null
35
35
  ```
36
36
 
37
- Capture: `path` ∈ `web-ui` / `cli` / `backend-only` / `mixed` (run all relevant bundles).
37
+ Capture: `path` ∈ `web-ui` / `cli` / `backend-only` / `mixed` in `raw/ux-mechanics-path-detection.json`; in `scorecard.yaml` and evidence, record the path as its letter — `A` (web-ui), `B` (cli), `C` (backend-only). For `mixed`, run every relevant bundle.
38
38
 
39
39
  ---
40
40
 
@@ -129,7 +129,7 @@ grep -rlE 'logging\.|logger\.|log\.|pino|winston|zerolog|zap' \
129
129
  grep -cE '^\s*\$ |^\s*```(sh|bash|console|shell)' <local-repo-path>/README.md 2>/dev/null
130
130
  ````
131
131
 
132
- Capture 6 booleans + counts:
132
+ Capture the six conformance signals:
133
133
 
134
134
  - `cli_help_wired` (bool)
135
135
  - `cli_stderr_discipline` (bool)
@@ -137,12 +137,23 @@ Capture 6 booleans + counts:
137
137
  - `cli_common_flags_count`
138
138
  - `cli_logging_present` (bool)
139
139
  - `cli_readme_examples` (count of fenced cmd blocks)
140
- - `cli_clig_conformance_score` = count of the 6 booleans satisfied (0-6)
140
+ - `cli_clig_conformance_score` = count of the six signals satisfied (0-6)
141
141
 
142
142
  ---
143
143
 
144
144
  ## Path C — Backend-only (API-UX surrogate)
145
145
 
146
+ API quality is judged on eight axes; C1–C3 extract (a), (c) and (h) mechanically, and the Signal X read judges the rest:
147
+
148
+ - **(a) OpenAPI/Swagger** — spec present and complete (all routes documented, examples present, error shapes declared)
149
+ - **(b) Route naming** — consistent kebab / snake / camel, coherent singular-vs-plural
150
+ - **(c) Response envelope + errors** — uniform shape (`{data, error}` or RFC 7807)
151
+ - **(d) Versioning** — `/v1/` prefix, `Accept-Version` header, or clearly no version needed
152
+ - **(e) Idempotency on mutations** — `Idempotency-Key` header support on POST/PUT/PATCH
153
+ - **(f) Rate limiting** — middleware + headers
154
+ - **(g) Input validation** — schema validation on incoming requests at the boundary
155
+ - **(h) Documentation** — written API docs beyond autogen
156
+
146
157
  ### Signal C1 — OpenAPI / docs presence
147
158
 
148
159
  ```bash
@@ -188,7 +199,11 @@ Capture:
188
199
 
189
200
  ## Signal X (shared) — LLM read
190
201
 
191
- **Web-UI path:** read top 2 route files + main layout + 1 form component → score "thoughtful UX" **CLI path:** read main command file + 1 error-handling path → score "thoughtful CLI" **Backend-only path:** read 2 route handlers + error-response module → score "thoughtful API"
202
+ | Path | Read | Score |
203
+ | --- | --- | --- |
204
+ | Web-UI | top 2 route files + main layout + 1 form component | thoughtful UX |
205
+ | CLI | main command file + 1 error-handling path | thoughtful CLI |
206
+ | Backend-only | 2 route handlers + the error-response module | thoughtful API, across the Path C axes |
192
207
 
193
208
  Capture:
194
209
 
@@ -201,7 +216,7 @@ Capture:
201
216
 
202
217
  ## Raw dumps (flat — files under `raw/` named `ux-mechanics-*`)
203
218
 
204
- Each signal writes its raw output to the flat `raw/` directory at the workspace root. Absent files = not extracted or path not applicable. Aggregates go to `scorecard.yaml` under `data.`.
219
+ Each signal writes its raw output to the flat `raw/` directory; an absent file means not extracted or path not applicable. Aggregates go to `scorecard.yaml` under `data.`.
205
220
 
206
221
  | File | Source | Shape / note |
207
222
  | --- | --- | --- |
@@ -217,7 +232,7 @@ Each signal writes its raw output to the flat `raw/` directory at the workspace
217
232
 
218
233
  ## Aggregation → 0–5 band
219
234
 
220
- Scorer integrates the path-specific signals + LLM read.
235
+ Integrate the path-specific signals and the Signal X read.
221
236
 
222
237
  **Banding (absolute):**
223
238
 
@@ -276,8 +291,7 @@ data:
276
291
 
277
292
  ## Caveats
278
293
 
279
- - **UX heuristic grep is noisy.** Presence of `isLoading` ≠ loading UI is actually shown. LLM adjudicates when score conflicts with heuristic count.
294
+ - **The UX heuristic grep is noisy** — `isLoading` present ≠ a loading UI shown. The LLM adjudicates when its score conflicts with the heuristic count.
280
295
  - **Route-orphan detection is stack-specific** — reliable in Next.js file-based routing, weaker in hand-rolled React Router.
281
- - **Backend-only / API-only is uncapped.** Enterprise API design (OpenAPI quality + versioning + idempotency + rate-limiting + input validation) can score up to 5 on the strength of those signals, matching an equally polished web UI.
282
- - **CLI assessment via clig.dev** assumes conformance signals quality — some CLIs ship deliberately minimal with well-chosen defaults; LLM should adjudicate.
283
- - **Accessibility deliberately out of scope.** A11y lint and the `aria/role/htmlFor` heuristic are not part of this recipe because tool coverage is uneven and a11y is out of scope for this rubric. UX heuristics, clig.dev conformance, API-UX surrogates, and the LLM read remain.
296
+ - **clig.dev conformance is a proxy for quality** — some CLIs ship deliberately minimal with well-chosen defaults; the LLM adjudicates.
297
+ - **Accessibility is out of scope.** **Never** add a11y lint or an `aria/role/htmlFor` heuristic — tool coverage is uneven and a11y is outside this rubric.
@@ -4,23 +4,23 @@
4
4
  - **Weight:** 12.5 pts
5
5
  - **Source quote:** _"Does the README make a case for impact? Are claims quantified (time saved, cost, quality)?"_
6
6
 
7
- This recipe scores how well the README articulates value — whether it makes a clear case for impact with a named audience and quantified outcomes (time / cost / quality).
7
+ This recipe scores how well the README articulates value — a clear case for impact with a named audience and quantified outcomes (time / cost / quality).
8
8
 
9
9
  ---
10
10
 
11
11
  ## Extraction recipe
12
12
 
13
- README-centric. The evaluator parses the README for impact claims, audience, scope coverage, and quantified outcomes.
13
+ README-centric: parse the README for impact claims, audience, scope coverage, and quantified outcomes.
14
14
 
15
15
  ### Signal 1 — README impact read (LLM interpretive)
16
16
 
17
- Feed the LLM the full README (truncated to the first ~1000 lines) plus a list of shipped capabilities (extracted from the `mechanical_ambition` recipe's `shipped_*` fields in its `raw/mechanical-ambition-llm-read.md`, if that recipe has already run for this project):
17
+ Feed the LLM the README (first ~1000 lines) plus the shipped capabilities — the `shipped` list in `raw/mechanical-ambition-llm-read.md`, when that recipe has already run for this project:
18
18
 
19
19
  ```bash
20
20
  head -1000 "$REPO/README.md" > /tmp/val-art-readme.md
21
21
  ```
22
22
 
23
- Write the LLM read to `raw/value-articulation-llm-read.md`. The LLM emits:
23
+ Write the LLM read to `raw/value-articulation-llm-read.md`. It emits:
24
24
 
25
25
  ```yaml
26
26
  scope_breadth: N # number of distinct capabilities the README claims
@@ -59,7 +59,7 @@ Aggregate into `raw/value-articulation-proxies.json`:
59
59
  | **1** | No value claim, or README is an unmodified starter/template README. `value_articulation_score ≤ 1`. |
60
60
  | **0** | Empty README. |
61
61
 
62
- **Over-promise penalty:** if `completeness_ratio < 0.5` AND the README claims shipped functionality (not "WIP"), cap the band at **2** — the README is writing checks the code doesn't cash.
62
+ **Over-promise penalty:** if `completeness_ratio < 0.5` AND the README claims shipped functionality (not "WIP"), cap the band at **2** — the README promises what the code does not deliver.
63
63
 
64
64
  ---
65
65
 
@@ -72,5 +72,5 @@ Aggregate into `raw/value-articulation-proxies.json`:
72
72
 
73
73
  ## Not in scope
74
74
 
75
- - Judging whether the claimed impact is realistic needs real operational/runtime data — out of scope; this recipe scores how well the README *articulates* value, not whether the claimed magnitude holds up.
76
- - Measuring actual runtime behavior against claims — that's a separate runtime-verification pass, out of scope here.
75
+ - **Whether the claimed impact is realistic** — that needs operational data; this recipe scores how well the README *articulates* value, not whether the magnitude holds up.
76
+ - **Runtime behavior against claims** — a separate runtime-verification pass.
@@ -1,74 +1,55 @@
1
1
  # Evaluator — Preflight
2
2
 
3
- > **Run before scoring a project.** This skill depends on external tools that must exist on the host. If a tool is missing, **install it** — do not silently fall back to grep / LLM-only. A silent fallback poisons the gate checks (VULN / SECRETS / AUTH / OBSERVABILITY) and makes the scorecard dishonest.
3
+ > **Run before scoring a project.** If a tool is missing, **install it** — never fall back to grep or an LLM-only read. A silent fallback corrupts the scorecard twice: the absolute banding tables are calibrated against real tool output (`lizard` CCN, `semgrep` finding density), so an estimate lands in the wrong band; and `gitleaks` catches entropic tokens `grep` cannot while `pip-audit` / `trivy` catch CVEs no heuristic will, so a missed `SECRETS` or `VULN` hit becomes a dishonest pass.
4
4
 
5
- The evaluator is allowed to install its own tools via `brew` / `pipx` / `npm -g`. Installing is cheap (~1 minute total) and idempotent. Ignoring a missing tool is not.
5
+ The evaluator installs its own tools via `brew` / `pipx` / `npm -g` / `go install`. Installing is cheap (~1 minute total) and idempotent.
6
6
 
7
- ---
7
+ ## Invocation
8
+
9
+ Run `bash .claude/skills/evaluator/preflight.sh` — idempotent, so re-running no-ops when every tool is present. `preflight.sh` is the executable contract and holds the canonical install commands; edit there, then bring the table below to match.
8
10
 
9
11
  ## Required tools
10
12
 
11
13
  | Tool | Purpose | Recipes that use it | Install (macOS, primary) |
12
14
  | --- | --- | --- | --- |
13
15
  | `gh` | GitHub API (CR scrape, GHA runs, PR enumeration) | 1.1, 1.2, 2.4 | `brew install gh` |
14
- | `jq` | JSON parsing in shell pipelines | all | `brew install jq` |
15
16
  | `gitleaks` | committed-secret scan — fires `SECRETS` gate | 1.4 | `brew install gitleaks` |
16
- | `lizard` | polyglot complexity / god-function detection (per-language CCN: Py 10 / JS-TS 10 / Java 12 / Go 15) | 1.1, 1.4 | `brew install lizard` |
17
- | `scc` | LoC + cocomo estimate (replaces tokei/cloc) | 1.4, 2.4a | `brew install scc` |
18
- | `semgrep` | polyglot static analysis (quality + resilience + multi-protocol auth) | 1.1, 1.2, 2.4a | `brew install semgrep` |
17
+ | `lizard` | polyglot complexity / god-function detection (per-language CCN: Py 10 / JS-TS 10 / Java 12 / Go 15) | 1.1, 1.4 | `pipx install lizard` — **never** `brew install lizard`, which is an unrelated LZ5 compressor of the same name |
18
+ | `scc` | LoC + COCOMO estimate | 1.4, 2.4 | `brew install scc` |
19
+ | `semgrep` | polyglot static analysis (quality + resilience + multi-protocol auth) | 1.1, 1.2, 2.4 | `brew install semgrep` |
19
20
  | `hadolint` | Dockerfile lint | 1.3 | `brew install hadolint` |
20
- | `ruff` | Python lint + formatter | 1.1 (Python repos), 2.4a (tier-A) | `brew install ruff` |
21
- | `shellcheck` | shell-script lint | 2.2a (CLI path) | `brew install shellcheck` |
22
- | `tree` | folder-tree read for LLM context | 1.4, 2.2a, 2.4a | `brew install tree` |
21
+ | `ruff` | Python lint + formatter | 1.1 (Python repos), 2.4 (Tier-A) | `brew install ruff` |
22
+ | `shellcheck` | shell-script lint | 2.2 (CLI path) | `brew install shellcheck` |
23
+ | `tree` | folder-tree read for LLM context | 1.4, 2.1, 2.2, 2.4 | `brew install tree` |
23
24
  | `golangci-lint` | Go aggregate linter | 1.1 (Go repos) | `brew install golangci-lint` |
24
- | `biome` | TS/JS lint + format (preferred over eslint for speed) | 1.1 (TS/JS repos) | `npm i -g @biomejs/biome` |
25
+ | `pnpm` | installs and audits pnpm-locked JS repos | 1.4 | `brew install pnpm` |
26
+ | `yarn` | installs and audits yarn-locked JS repos | 1.4 | `brew install yarn` |
27
+ | `trivy` | filesystem dep-vuln scan (OS + language packages) — feeds `VULN` gate | 1.4 | `brew install trivy` |
28
+ | `biome` | TS/JS lint (preferred over eslint for speed) | 1.1 (TS/JS repos) | `npm i -g @biomejs/biome` |
25
29
  | `knip` | TS/JS dead-code + unused-deps | 1.4 | `npm i -g knip` |
26
- | `pipx` | isolated install for Python CLIs below | — | `brew install pipx && pipx ensurepath` |
30
+ | `pipx` | isolated install for the Python CLIs below | — | `brew install pipx && pipx ensurepath` |
27
31
  | `deptry` | Python unused-deps | 1.4 | `pipx install deptry` |
28
32
  | `pip-audit` | Python dep-vuln scan — feeds `VULN` gate | 1.4 (Python repos) | `pipx install pip-audit` |
29
- | `govulncheck` | Go dep-vuln scan — feeds `VULN` gate | 1.4 (Go repos) | `go install golang.org/x/vuln/cmd/govulncheck@latest` (conditional — skipped if go not on PATH) |
30
- | `trivy` | Container + JS dep-vuln scan — feeds `VULN` gate | 1.4 | `brew install trivy` |
33
+ | `govulncheck` | Go dep-vuln scan — feeds `VULN` gate | 1.4 (Go repos) | `go install golang.org/x/vuln/cmd/govulncheck@latest` — only when `go` is on PATH; otherwise skipped and Go vuln scans record `_NOT_RUN: true` with reason `"govulncheck unavailable (go not installed)"` |
31
34
 
32
- Host prerequisites that must already exist:
35
+ Host prerequisites — the script never installs these and exits 2 if any is missing:
33
36
 
34
- - `brew` (macOS) or `apt` (Linux)
37
+ - `brew`
38
+ - `jq`
35
39
  - `node` + `npm` (≥ 18)
36
40
  - `python3` (≥ 3.10) — `pipx` layers on top
37
41
 
38
- ---
39
-
40
- ## Invocation
41
-
42
- Run once per host: `bash .claude/skills/evaluator/preflight.sh`. Idempotent — re-running no-ops when every tool is already present. Canonical install commands live in `preflight.sh` (the executable contract); edit there, not here. Host prerequisites (`brew`, `node`/`npm`, `python3`) must already exist — the script halts loud if any are missing.
43
-
44
- ---
42
+ Each install runs under a 180 s cap from `timeout` or `gtimeout`; on a host with neither, the script warns and installs uncapped (`brew install coreutils` restores the cap). Preflight ends by checking that the `lizard` on PATH is the cyclomatic-complexity analyzer, and fails if brew's compressor shadows it.
45
43
 
46
44
  ## Required behaviour for scoring agents
47
45
 
48
- 1. **Run preflight first.** Before extracting any signal, execute the preflight script.
49
- 2. **If preflight exits non-zero, STOP.** Do not proceed to scoring with missing tools. Return a clear failure message to the caller naming which tools failed to install.
50
- 3. **No silent fallback.** A signal that requires a tool must either run the tool or emit `{signal}_NOT_RUN: true` with `reason: "preflight failed"` in the matching sub-criterion's `data` block in `scorecard.yaml`. This is a loud failure mode, not a graceful one.
51
- 4. **Re-running preflight is free.** Every invocation should run it — the first run installs; subsequent runs no-op.
52
-
53
- ---
46
+ 1. **Run preflight first** — before extracting any signal, on every invocation; the first run installs, later runs no-op.
47
+ 2. **If preflight exits non-zero, stop.** Never score with missing tools; return a failure message to the caller naming the tools that failed to install.
48
+ 3. **No silent fallback.** A signal that needs a tool either runs it or emits `{signal}_NOT_RUN: true` with a `reason` naming the cause in that sub-criterion's `data` block in `scorecard.yaml` — a loud failure, never a graceful substitute.
54
49
 
55
50
  ## When a tool does not apply
56
51
 
57
- Some tools apply only when a repo contains the target language (e.g. `ruff` on Python, `golangci-lint` on Go, `knip` on TS/JS). In that case:
58
-
59
- - The tool is **not** required to be installed for repos where the language is absent.
60
- - The signal is emitted as `{signal}: null, reason: "language_not_present"` — NOT as `_NOT_RUN`.
61
- - Preflight still installs all tools idempotently; language filtering happens at the recipe level, not preflight.
62
-
63
- This separates "tool missing from host" (a failure) from "tool not applicable here" (expected).
64
-
65
- ---
66
-
67
- ## Rationale
68
-
69
- Silent fallback to grep / LLM equivalents corrupts the scorecard in two ways:
70
-
71
- 1. **Wrong bands.** The absolute banding tables in each recipe are calibrated against real tool output (e.g. `lizard` CCN, `semgrep` finding density). A grep-estimated substitute lands the project in the wrong band.
72
- 2. **Under-reporting bias.** `gitleaks` catches entropic tokens `grep` cannot; `pip-audit` / `trivy` catch CVEs no heuristic will. Missing them turns a SECRETS- or VULN-gate hit into silence — a dishonest pass.
52
+ A language-specific tool (`ruff` on Python, `golangci-lint` on Go, `knip` on TS/JS) does not apply to a repo without that language:
73
53
 
74
- Installing tools is cheap and one-time. Skipping them silently produces a scorecard that looks complete but isn't.
54
+ - Emit the signal as `{signal}: null, reason: "language_not_present"` — **not** as `_NOT_RUN`, which means the tool was missing from the host (a failure), where `null` means not applicable here (expected).
55
+ - Preflight still installs every tool; language filtering happens in the recipes, not in preflight.