@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
@@ -5,56 +5,60 @@ description: "Use when scoring a single software project for production-readines
5
5
 
6
6
  # Evaluator
7
7
 
8
- Single-project evaluator. One project in → one per-project workspace out. The caller supplies the output directory; the skill writes `<out_dir>/<project>/{README.md, scorecard.yaml, raw/<sub-criterion>-<artifact>.ext}` and returns that path.
9
-
10
- This skill scores **exactly one project**. It does not rank, normalize across projects, weight sub-criteria differently, or know anything about a batcher, a cohort, or other projects. Every band it assigns is **absolute** — computed from per-signal thresholds in each recipe — so the scorecard for a project is identical whether the project is scored alone or as one of fifty. Cross-project weighting and comparison, if wanted, is a separate concern layered on top by whoever calls this skill; the skill itself stays unaware of it.
8
+ Scores exactly one project: one repo in, one workspace out at `<out_dir>/<project>/`, whose path you return. Every band is **absolute** — computed from the per-signal thresholds in each recipe — so a project's scorecard is identical whether it is scored alone or as one of fifty. The skill **never** ranks, normalizes across projects, weights sub-criteria unequally, or knows a batcher or cohort exists; cross-project comparison is a layer the caller adds on top.
11
9
 
12
10
  ## Preflight (run once per host, idempotent)
13
11
 
14
- This skill depends on external tools (`gitleaks`, `lizard`, `scc`, `semgrep`, `hadolint`, `ruff`, `biome`, `knip`, `deptry`, `shellcheck`, `golangci-lint`, `gh`, `jq`, `pip-audit`, `govulncheck`, `trivy`). Before scoring, run [`preflight.md`](preflight.md). It checks each tool, installs any that are missing (via `brew` / `npm -g` / `pipx` / `go install`), and fails loud if an install fails. **Do not silently fall back to grep-or-LLM-only substitutes** — that poisons the gate checks (VULN / SECRETS / AUTH / OBSERVABILITY) and makes the scorecard dishonest. If preflight exits non-zero, return a clear failure message naming the missing tools.
12
+ Run [`preflight.md`](preflight.md) before scoring — it checks the external tools the recipes call, installs any that are missing, and exits non-zero if an install fails. If it exits non-zero, stop and return a failure message naming the missing tools. **Never fall back to a grep-or-LLM-only substitute for a missing tool** — the banding thresholds and the `VULN` / `SECRETS` / `AUTH` / `OBSERVABILITY` gates are calibrated against real tool output, so a substitute yields a scorecard that looks complete and is wrong exactly where it matters.
15
13
 
16
14
  ## Hard rule: every slow command gets a timeout
17
15
 
18
- Every command the skill runs that can hang or burst must be wrapped in a bounded wall-clock guard. Unbounded retries are how a single project eats 20+ minutes. Apply one of:
16
+ Wrap every command that can hang or burst in a wall-clock bound, even where a recipe shows it naked — unbounded retries are how one project eats 20+ minutes.
19
17
 
20
- - `timeout 60 <cmd>` for any `gh api`, `semgrep`, `npm install`, `pip install`, `go build`, `go vet`, or `curl` — even when the recipe doesn't show it. If the recipe shows a naked command, wrap it yourself.
21
- - `--maxdepth N` and `-not -path '*/node_modules/*' -not -path '*/.venv/*' -not -path '*/.git/*'` on every `find`.
22
- - `git log -n 500` (or similar ceiling) instead of walking full history. Never `git log --all` without a limit.
23
- - `semgrep`: always pass `--timeout 30` (per-rule), `--disable-version-check`, `--metrics=off`. Avoid `--config p/code-quality` — that registry entry 404s in retry-storm; use per-language packs (`p/python`, `p/typescript`, `p/javascript`, `p/go`) or `p/default`.
24
- - Dep-vuln scans: `pip-audit --timeout 120`, `govulncheck` in a 180 s `timeout`, `trivy image --timeout 180s`. `npm audit --json` doesn't take a flag; wrap the whole call in `timeout 120`.
18
+ | Command | Bound |
19
+ | --- | --- |
20
+ | `gh api`, `semgrep`, `npm install`, `pip install`, `go build`, `go vet`, `curl` | `timeout 60 <cmd>` |
21
+ | every `find` | `-maxdepth N` and `-not -path '*/node_modules/*' -not -path '*/.venv/*' -not -path '*/.git/*'` |
22
+ | `git log` | a ceiling such as `-n 500`; **never** `git log --all` without a limit |
23
+ | `semgrep` | `--timeout 30` (per rule), `--disable-version-check`, `--metrics=off` |
24
+ | `pip-audit` | `--timeout 120` |
25
+ | `govulncheck`, `trivy fs` | inside `timeout 180` |
26
+ | `npm audit --json` | takes no timeout flag — wrap the call in `timeout 120` |
25
27
 
26
- If a single mechanical command still exceeds ~2 min, something is wrong with the project (giant `node_modules/`, generated bundle, vendored deps). Skip it with `_NOT_RUN: true, reason: "timeout on <cmd>"` rather than retrying — a sparse signal is tolerable; a hang is not.
28
+ **Never use `semgrep --config p/code-quality`** — that registry entry returns 404 in a retry storm. Use the per-language packs (`p/python`, `p/typescript`, `p/javascript`, `p/go`) or `p/default`.
27
29
 
28
- ## Input
30
+ If one mechanical command still exceeds ~2 min, the project carries something pathological (a giant `node_modules/`, a generated bundle, vendored deps). Skip it with `_NOT_RUN: true, reason: "timeout on <cmd>"` rather than retrying — a sparse signal is tolerable; a hang is not.
29
31
 
30
- A repo reference + an output directory:
32
+ ## Input
31
33
 
32
- - **Local clone path** — e.g. `/path/to/project/`. Used by filesystem reads (Semgrep, grep, file sampling, git analytics). This is the primary input.
33
- - **GitHub ref** (optional) — e.g. `<org>/<repo>`. Used by `gh api` calls for PR / code-review history when the project is hosted on GitHub. Absence just means those signals are skipped, not a failure.
34
- - **`out_dir`** — caller-supplied base directory. The skill writes into `<out_dir>/<project>/` and returns that path. The skill creates the folder; `raw/` is flat — one file per signal named `<sub-criterion>-<artifact>.ext`, no subdirectories.
34
+ | Input | Required | Use |
35
+ | --- | --- | --- |
36
+ | Local clone path, e.g. `/path/to/project/` | yes — the primary input | Filesystem reads: Semgrep, grep, file sampling, git analytics |
37
+ | GitHub ref, e.g. `<org>/<repo>` | no | `gh api` calls for PR and code-review history; absent ⇒ those signals are skipped, not failed |
38
+ | `out_dir` | yes | Base directory; you create `<out_dir>/<project>/` under it |
35
39
 
36
- `<project>` is a stable slug for the project (its directory name is fine). Optional baseline stats (kLoC, commit count, contributor count) may be supplied to skip a pre-pass; otherwise derive them from the local clone.
40
+ `<project>` is a stable slug — the directory name is fine. Baseline stats (kLoC, commit count, contributor count) may be supplied to skip a pre-pass; otherwise derive them from the clone.
37
41
 
38
42
  ## Output — per-project workspace
39
43
 
40
- Every invocation writes a folder at `<out_dir>/<project>/` with two parts plus raw dumps:
41
-
42
- ```
43
- <out_dir>/<project>/
44
- ├── README.md # Human-readable narrative. Shape: § "README shape" below.
45
- ├── scorecard.yaml # Structured scorecard (below). Machine-readable.
46
- └── raw/ # Flat directory — every file named `<sub-criterion>-<artifact>.ext`
47
- ├── code-quality-* # llm-sample.jsonl, lint-{ruff,biome,eslint,golangci}.json, semgrep-quality.json, cr-comments.jsonl
48
- ├── testing-* # tests-inventory.jsonl, llm-sample.jsonl, semgrep-resilience.json, gha-runs.json, auth-scan-{http,ws,grpc,trpc}.json
49
- ├── deployment-readiness-* # artifacts.json, hadolint.json, localhost-refs.txt, observability-markers.json, llm-read.md
50
- ├── maintainability-* # gitleaks.json, lizard.csv, knip.json|deptry.json|gomod-diff.txt, file-sizes.txt, tech-debt.txt, dep-vuln-{pip-audit,npm-audit,govulncheck,trivy}.json, llm-read.md
51
- ├── problem-substantiveness-* # llm-read.md, proxies.json
52
- ├── ux-mechanics-* # path-detection.json + path-specific files (ux-heuristics, routes, cli-probes, shellcheck, openapi-quality, api-surrogate), llm-read.md
53
- ├── value-articulation-* # llm-read.md, proxies.json
54
- └── mechanical-ambition-* # scc.json, stubs.json, git-analytics.json, tier-a-build.log, llm-read.md
55
- ```
56
-
57
- `raw/` is a **flat directory** — no subfolders. Every file is named `<sub-criterion>-<artifact>.ext` (e.g. `code-quality-semgrep-quality.json`, `maintainability-deptry.json`). A signal that couldn't be extracted (tool absent, language not present, repo shape mismatch) produces **no file** — absence is the signal, and `scorecard.yaml` flags the gap. Per-recipe artifact lists are authoritative in each recipe's "Raw dumps" section.
44
+ | Path under `<out_dir>/<project>/` | Contents |
45
+ | --- | --- |
46
+ | `README.md` | Human-readable narrative — § README shape |
47
+ | `scorecard.yaml` | Machine-readable scorecard — § Scorecard shape |
48
+ | `raw/` | Raw tool output, one file per signal |
49
+
50
+ `raw/` is a **flat directory** — no subfolders; every file is named `<sub-criterion>-<artifact>.ext` (e.g. `code-quality-semgrep-quality.json`). A signal that cannot be extracted (tool absent, language not present, repo shape mismatch) writes **no file** — absence is the signal, and `scorecard.yaml` flags the gap. Each recipe's "Raw dumps" section is authoritative for its artifact list; in summary:
51
+
52
+ | Prefix | Artifacts |
53
+ | --- | --- |
54
+ | `code-quality-` | `llm-sample.jsonl`, `lint-{ruff,biome,eslint,golangci}.json`, `semgrep-quality.json`, `cr-comments.jsonl` |
55
+ | `testing-` | `tests-inventory.jsonl`, `llm-sample.jsonl`, `semgrep-resilience.json`, `gha-runs.json`, `auth-scan-{http,ws,grpc,trpc}.json` |
56
+ | `deployment-readiness-` | `artifacts.json`, `hadolint.json`, `localhost-refs.txt`, `observability-markers.json`, `llm-read.md` |
57
+ | `maintainability-` | `gitleaks.json`, `lizard.csv`, `knip.json` \| `deptry.json` \| `gomod-diff.txt`, `file-sizes.txt`, `tech-debt.txt`, `dep-vuln-{pip-audit,npm-audit,govulncheck,trivy}.json`, `llm-read.md` |
58
+ | `problem-substantiveness-` | `llm-read.md`, `proxies.json` |
59
+ | `ux-mechanics-` | `path-detection.json` + path-specific files (`ux-heuristics`, `routes`, `cli-probes`, `shellcheck`, `api-surrogate`), `llm-read.md` |
60
+ | `value-articulation-` | `llm-read.md`, `proxies.json` |
61
+ | `mechanical-ambition-` | `scc.json`, `stubs.json`, `git-analytics.json`, `tier-a-build.log`, `llm-read.md` |
58
62
 
59
63
  ### Scorecard shape
60
64
 
@@ -90,39 +94,37 @@ available: 100.0 # max points from currently-scored items (lower if any item is
90
94
  normalized: 66.25 # total ÷ available × 100
91
95
  ```
92
96
 
93
- **Each item scored 0–5** → points = `score × 2.5` (every item is weighted 12.5 pts, so the step is 2.5). `total` is the sum over scored items; `available` is the max points those scored items could have reached (12.5 × count); `normalized = total ÷ available × 100`. With all 8 items scored, `available == 100.0` and `total == normalized`. If a sub-criterion is genuinely unscoreable (`score: null`), it drops out of both `total` and `available` so the percentage stays honest.
94
-
95
- The `total` here is an **equal-weight** convenience score for reading one project on its own. The skill does not apply per-sub-criterion weights — it has no opinion on relative importance. A caller that wants weighted, cross-project-comparable scores reads the raw 0–5 `score` fields and applies its own weighting; that logic lives entirely outside this skill.
97
+ The totals arithmetic is § Scoring model.
96
98
 
97
99
  ### Workspace-writing order
98
100
 
99
- Write the outputs in this order — each depends on the prior:
101
+ Write the outputs in this order — each depends on the one before:
100
102
 
101
- 1. **`raw/<sub-criterion>-<artifact>.ext`** — run each recipe (see table below), dump raw tool output verbatim to the flat `raw/` directory with per-recipe filename prefixes. This is the extraction pass.
102
- 2. **`scorecard.yaml`** — fold each recipe's aggregates into the sub-criterion block, apply gates, compute `total` / `available` / `normalized`. Pin `commit_sha_pinned` (audit metadata) and `rubric_version`.
103
- 3. **`README.md`** — render the README shape below with values drawn from `scorecard.yaml` and pointers to `raw/` artifacts. The raw-dump section is a pointer index, not a re-embedded dump.
103
+ 1. **`raw/<sub-criterion>-<artifact>.ext`** — run each recipe and dump raw tool output verbatim to the flat `raw/` directory. This is the extraction pass.
104
+ 2. **`scorecard.yaml`** — fold each recipe's aggregates into its sub-criterion block, apply gates, compute `total` / `available` / `normalized`, and pin `commit_sha_pinned` and `rubric_version`.
105
+ 3. **`README.md`** — render § README shape from `scorecard.yaml`, pointing at `raw/` artifacts rather than re-embedding them.
104
106
 
105
107
  ### README shape
106
108
 
107
- `README.md` is a self-contained human narrative — no external template. Render these sections from `scorecard.yaml`:
109
+ `README.md` is a self-contained narrative with no external template. Render these sections from `scorecard.yaml`:
108
110
 
109
111
  1. **Title + verdict** — `# <project> — <normalized>/100` and a 2–3 sentence overall read.
110
112
  2. **Run metadata** — `rubric_version`, `scored_at`, `agent_model`, `commit_sha_pinned`, gates triggered, short-circuit flag.
111
113
  3. **Scorecard table** — one row per sub-criterion: `| Sub-criterion | Band (0–5) | Points / 12.5 | One-line evidence |`, split into a Code block and a Product block, with the `total / available / normalized` footer.
112
114
  4. **Per-sub-criterion detail** — for each item, the band, the full `evidence` string, and the key numbers from `data`.
113
- 5. **Raw artifact index** — a pointer list of the `raw/<sub-criterion>-*` files that were produced (and a note on any that were skipped and why).
115
+ 5. **Raw artifact index** — a pointer list of the `raw/<sub-criterion>-*` files produced, plus a note on any skipped and why. Every `_NOT_RUN` signal is flagged here.
114
116
 
115
117
  ### Rubric version
116
118
 
117
- `rubric_version` is a simple integer marker recorded on each scorecard. Bump it whenever a recipe adds/drops a signal, a gate threshold moves, a banding table changes, or the scorecard shape changes. It exists so a reader can tell which rubric produced a scorecard and so a caller can decide whether a cached workspace is stale. It is **not** a cohort cache key and carries no cross-project semantics — one project, one rubric version, decided at extraction time.
119
+ `rubric_version` is an integer marker on each scorecard. **Bump it whenever** a recipe adds or drops a signal, a gate threshold moves, a banding table changes, or the scorecard shape changes — a caller compares it to decide whether a cached workspace is stale. It is **not** a cohort cache key and carries no cross-project meaning.
118
120
 
119
121
  ## Scoring model
120
122
 
121
- - **100 points total, 50 per half:**
122
- - **1.x Production-Grade Code** — 4 sub-criteria × 12.5 pts each = **50 pts**
123
- - **2.x Product Thinking** — 4 sub-criteria × 12.5 pts each = **50 pts**
124
- - **Each item scored 0–5** → points = `score × 2.5`.
125
- - **Scorecard reports `total`, `available`, `normalized`.**
123
+ - **100 points, 50 per half:** 1.x Production-Grade Code and 2.x Product Thinking, each 4 sub-criteria × 12.5 pts.
124
+ - **Each item is scored 0–5**; points = `score × 2.5`.
125
+ - **`total`** is the sum of points over scored items; **`available`** is 12.5 × the count of scored items; **`normalized`** = `total ÷ available × 100`. With all 8 scored, `available == 100.0` and `total == normalized`.
126
+ - **A genuinely unscoreable item** (`score: null`) drops out of both `total` and `available`, so the percentage stays honest — a library with no UI is not punished for lacking one.
127
+ - **`total` is equal-weight by design** — the skill has no opinion on relative importance. A caller wanting weighted, comparable scores reads the raw 0–5 `score` fields and applies its own weights outside the skill.
126
128
 
127
129
  ### Bands (absolute)
128
130
 
@@ -135,7 +137,7 @@ Write the outputs in this order — each depends on the prior:
135
137
  | **1** | Token effort — minimal execution, most criteria absent |
136
138
  | **0** | Absent |
137
139
 
138
- Bands are **absolute, not relative to any other project**. Per-signal numeric thresholds live in each recipe's _Banding_ section. The rubric is single-project-invokable by design — there is no cohort pass, no quintile math, no re-banding step.
140
+ Per-signal numeric thresholds live in each recipe's _Banding_ section. There is no cohort pass, no quintile math, no re-banding step.
139
141
 
140
142
  ### Gates (cap specific items; stack additively)
141
143
 
@@ -146,34 +148,32 @@ Bands are **absolute, not relative to any other project**. Per-signal numeric th
146
148
  | `UNTESTED` (hard) | `test_file_count == 0` | `testing ≤ 1` |
147
149
  | `TESTS_TRIVIAL` (soft) | Tests exist but `assertion_density < 1.0` per test file OR `trivial_body_ratio > 0.8` | `testing ≤ 2` |
148
150
  | `SECRETS` | `gitleaks_findings ≥ 1` — any secret in git history, even rotated out of HEAD | `maintainability ≤ 2` |
149
- | `VULN` | Dep-scan reports ≥ 1 CVE at CRITICAL OR ≥ 3 at HIGH across any dep (direct or transitive). Tools: `pip-audit` / `npm audit --json` / `govulncheck` / `trivy image`. Skipped if no recognized package manifest. | `maintainability ≤ 2` |
151
+ | `VULN` | Dep-scan reports ≥ 1 CVE at CRITICAL OR ≥ 3 at HIGH across any dep (direct or transitive). Tools: `pip-audit` / `npm audit --json` / `govulncheck` / `trivy fs`. Skipped if no recognized package manifest. | `maintainability ≤ 2` |
150
152
  | `AUTH` | Network-routed handlers exist AND ≥ 1 mutating endpoint is not behind an auth middleware/dependency/decorator. Covers HTTP (FastAPI/Express/Flask/Gin/Django POST/PUT/PATCH/DELETE), WebSocket (ws/Socket.io/SignalR event handlers), gRPC (grpc/grpcio unary/streaming), tRPC (@trpc/server mutations). Skipped if no routed handlers detected. | `testing ≤ 2` |
151
- | `OBSERVABILITY` | Structured-logging library absent (no structlog / winston / pino / log-slog / zap AND no JSON log format detected in code) **AND** metrics/tracing library absent (no OpenTelemetry, Prometheus client, Datadog agent, statsd client, or custom `/metrics` endpoint). Both must be absent for the gate to fire. | `deployment_readiness ≤ 3` |
153
+ | `OBSERVABILITY` | Structured-logging library absent (no structlog / loguru / winston / pino / log-slog / zap AND no JSON log format detected in code) **AND** metrics/tracing library absent (no OpenTelemetry, Prometheus client, Datadog agent, statsd client, or custom `/metrics` endpoint). Both must be absent for the gate to fire. | `deployment_readiness ≤ 3` |
152
154
 
153
- Gates cap the **band** of the named sub-criterion. When multiple gates cap the same item, the lowest cap wins. Gates are recorded in `gates_triggered`; a reader (or a downstream caller) can see exactly which caps applied.
155
+ A gate caps the **band** of the named sub-criterion before totals are computed; when several cap one item, the lowest cap wins. Record every gate that fired in `gates_triggered`.
154
156
 
155
157
  ### Dead-project short-circuit
156
158
 
157
- If **3 or more gates** fire on one project, skip the interpretive LLM passes for all sub-criteria, emit a fixed floor scorecard, and set `short_circuited: true`:
159
+ If **3 or more gates** fire on one project, skip the interpretive LLM passes, emit a fixed floor scorecard, and set `short_circuited: true` — the interpretive pass on a dead project costs compute and returns generous hallucinations.
158
160
 
159
161
  - **Non-gate-capped items**: `score: 1, evidence: "Floor — 3+ gates triggered; interpretive pass skipped"`.
160
162
  - **Gate-capped items**: take the cap value (e.g. `deployment_readiness: 1` when DEMO fires, `testing: 1` when UNTESTED fires, `maintainability: 2` when SECRETS or VULN fires, `deployment_readiness: 3` when OBSERVABILITY fires). If multiple gates cap the same item, use the lowest cap.
161
163
  - **Totals**: `total`, `available`, `normalized` computed normally over the floored items.
162
164
 
163
- Rationale: a project that's undeployable + untested + broken is clearly dead. Running the expensive interpretive pass produces generous LLM hallucinations on dead code. Short-circuit saves compute and keeps the score honest.
164
-
165
165
  ### CodeRabbit — calibrating modifier with null-data semantics
166
166
 
167
- If the project's GitHub history includes CodeRabbit review comments, they act as a **calibrating modifier on 1.1 (Code Quality) and 1.2 (Testing)**, never a primary signal.
167
+ CodeRabbit (CR) review comments in the project's GitHub history are a **calibrating modifier on 1.1 (Code Quality) and 1.2 (Testing)**, never a primary signal.
168
168
 
169
- - When a project has CR data (`cr_pr_count > 0` **and** non-empty actionables): `cr_*_per_kloc` values feed the recipe's banding table as calibrating modifiers.
170
- - When a project has no CR data (no CR history, or walkthrough-only with `cr_actionable_total == 0`): every `cr_*_per_kloc` is emitted as `null`. The scorer treats `null` as a no-op; 1.1 / 1.2 bands are decided by the remaining signals.
169
+ - **CR data present** (`cr_pr_count > 0` **and** non-empty actionables): the `cr_*_per_kloc` values feed the recipe's banding table as modifiers.
170
+ - **No CR data** (no CR history, a project not on GitHub, or walkthrough-only with `cr_actionable_total == 0`): emit every `cr_*_per_kloc` as `null`; the modifier is a no-op and the remaining signals decide the band.
171
171
 
172
- Design principle: `null ≠ 0`. `null` means "no CR data, skip the modifier"; `0` means "CR reviewed the PR and found nothing" — a real signal pulling the band up. Projects not hosted on GitHub, or with no PRs, simply emit `null` and the modifier is a no-op.
172
+ **`null ≠ 0`.** `null` means no CR data, skip the modifier; `0` means CR reviewed and found nothing — a real signal that pulls the band up. Never coerce one into the other.
173
173
 
174
174
  ## Sub-criterion extraction recipes
175
175
 
176
- One recipe file per sub-criterion. All 8 are AI-scored from repo evidence.
176
+ One recipe per sub-criterion; all 8 are scored from repo evidence.
177
177
 
178
178
  | # | Item | Half | Contender | Recipe |
179
179
  | --- | --- | --- | --- | --- |
@@ -188,21 +188,19 @@ One recipe file per sub-criterion. All 8 are AI-scored from repo evidence.
188
188
 
189
189
  ## Workflow
190
190
 
191
- The skill scores one project end-to-end:
192
-
193
191
  1. **Preflight** — run [`preflight.md`](preflight.md). Halt with a clear error if it fails.
194
- 2. **Mechanical extraction** — per recipe, run the shell commands under each recipe's "Extraction" section. Dump every tool output **verbatim** to the flat `<out_dir>/<project>/raw/` directory using the `<sub-criterion>-<artifact>.ext` naming convention. A signal that can't be extracted produces **no file** — absence is the signal.
195
- 3. **LLM interpretive passes** — per recipe, run the LLM reads (sample files, score axes, README parse, shipped-vs-promised diff). Write `raw/<slug>-llm-sample.jsonl` or `raw/<slug>-llm-read.md` per sub-criterion. These are the load-bearing interpretive judgments.
196
- 4. **Apply gates** — evaluate each gate (DEMO / BROKEN / UNTESTED / TESTS_TRIVIAL / SECRETS / VULN / AUTH / OBSERVABILITY) using the triggers above. If **≥3 gates** fire, emit the dead-project short-circuit floor scorecard (`short_circuited: true`) and skip remaining interpretive passes.
197
- 5. **Emit `scorecard.yaml`** — apply each recipe's absolute-threshold band table directly. Record the run-metadata block (`commit_sha_pinned`, `rubric_version`, `scored_at` via `date -u +"%Y-%m-%dT%H:%M:%SZ"`, `agent_model`, `approx_tokens`). Compute `total` / `available` / `normalized`.
198
- 6. **Render `README.md`** — fill the README shape above with values from `scorecard.yaml` and pointer references to `raw/` artifacts.
199
- 7. **Return the workspace path** — `<out_dir>/<project>/`. Write the files and leave them uncommitted; whoever invoked the skill decides whether to commit.
192
+ 2. **Mechanical extraction** — for each recipe, run the commands in its "Extraction" section and dump every tool output **verbatim** to the flat `<out_dir>/<project>/raw/` directory. A signal that cannot be extracted writes **no file**. Then evaluate the six gates decidable from mechanical signals alone (`UNTESTED`, `TESTS_TRIVIAL`, `SECRETS`, `VULN`, `BROKEN`, `OBSERVABILITY`); if **≥3** fire, skip step 3 and emit the dead-project short-circuit floor scorecard at step 5.
193
+ 3. **LLM interpretive passes** — for each recipe, run its LLM reads (file samples, score axes, README parse, shipped-vs-promised diff) and write `raw/<slug>-llm-sample.jsonl` or `raw/<slug>-llm-read.md`. These are the load-bearing interpretive judgments.
194
+ 4. **Apply gates** — evaluate all eight gates (DEMO / BROKEN / UNTESTED / TESTS_TRIVIAL / SECRETS / VULN / AUTH / OBSERVABILITY) against § Gates. If **≥3** fire, emit the dead-project short-circuit floor scorecard (`short_circuited: true`).
195
+ 5. **Emit `scorecard.yaml`** — apply each recipe's absolute band table directly. Record the run metadata (`commit_sha_pinned`, `rubric_version`, `scored_at` via `date -u +"%Y-%m-%dT%H:%M:%SZ"`, `agent_model`, `approx_tokens`) and compute `total` / `available` / `normalized`.
196
+ 6. **Render `README.md`** — fill § README shape from `scorecard.yaml`, with pointers to `raw/` artifacts.
197
+ 7. **Return the workspace path** — `<out_dir>/<project>/`. Leave the files uncommitted; the caller decides whether to commit.
200
198
 
201
199
  ### Scorecard schema validator
202
200
 
203
- [`validate_scorecard.py`](validate_scorecard.py) — a Python script that asserts a `scorecard.yaml` has every required top-level field (including `total` / `available` / `normalized`), all 8 sub-criterion blocks, and `score` + `evidence` + `data` on each. Exits 0 on valid; exits 1 on first failure with a specific error on stderr. Run it after emitting a scorecard to catch shape errors early. **Extending:** if a scorecard-shape bump introduces a new required field, append it to `REQUIRED_TOP` in the validator.
201
+ Run [`validate_scorecard.py`](validate_scorecard.py) on every emitted scorecard. It asserts every required top-level field (including `total` / `available` / `normalized`), all 8 sub-criterion blocks, and `score` + `evidence` + `data` on each; it exits 0 when valid and 1 on the first failure, with the error on stderr. When a scorecard-shape change adds a required top-level field, append it to `REQUIRED_TOP` in the validator.
204
202
 
205
203
  ## Not in scope
206
204
 
207
- - **Cross-project comparison, weighting, or ranking.** The skill emits raw 0–5 bands and an equal-weight `total`. Anything that compares projects, applies non-uniform weights, or normalizes a set against itself is a layer above this skill and must not leak into it.
208
- - **Runtime verification.** The skill reads the repo statically. Actually running `docker compose up` / `npm run dev` and clicking through the product is a separate manual pass a reviewer may add on top; the skill does not drive it.
205
+ - **Cross-project comparison, weighting, or ranking.** The skill emits raw 0–5 bands and an equal-weight `total`; anything that compares projects, applies non-uniform weights, or normalizes a set against itself is a layer above this skill and **must not** leak into it.
206
+ - **Runtime verification.** The skill reads the repo statically. Running `docker compose up` / `npm run dev` and clicking through the product is a separate manual pass a reviewer may add; the skill never drives it.
@@ -1,21 +1,19 @@
1
1
  # Code Quality — Extraction Plan
2
2
 
3
- - **Sub-criterion:** 1.1 (AI-only)
4
- - **Weight:** 12.5 pts (4 Code AI × 12.5 = 50 pts half)
3
+ - **Sub-criterion:** 1.1 (Production-Grade Code)
4
+ - **Weight:** 12.5 pts
5
5
  - **Contenders:** LLM interpretive read (primary, load-bearing) + lint (`ruff` / `biome` / `golangci-lint`) + `lizard` complexity (**per-language CCN**: Python 10 / JS-TS 10 / Java 12 / Go 15) + `semgrep` quality packs + CodeRabbit scrape (**calibrating modifier**).
6
6
  - **Source quote:** _"Readable, modular, well-structured. Good naming, clean APIs, no code smells."_
7
7
 
8
- Bands are **absolute** — the _Banding_ table in this recipe declares per-signal numeric thresholds. `lizard_god_per_kloc` is computed against **per-language CCN thresholds**: Python / JS / TS functions are "god" at CCN > 10; Java at CCN > 12; Go at CCN > 15 — a per-language lookup keyed on file extension. `_NOT_RUN: true` is supported for tool-missing cases but not for language-not-present (emit `null` aggregates instead). 1.1 has no gates of its own; secret/vuln signals are owned by `maintainability.md`.
8
+ Bands are **absolute** — the _Banding_ table declares per-signal numeric thresholds. Emit `_NOT_RUN: true` only for a missing tool; a language not present emits `null` aggregates instead. 1.1 owns no gates; secret and vuln signals belong to [maintainability.md](maintainability.md).
9
9
 
10
- > **Why CR is a modifier, not primary.** Null-data semantics and the plan-upgrade escape hatch are spelled out once in [`SKILL.md → CodeRabbit — calibrating modifier with null-data semantics`](../SKILL.md#coderabbit--calibrating-modifier-with-null-data-semantics). Summary: CR joins lint / complexity / file-size / semgrep as a **calibrating modifier**; contributes when a project has non-empty CR data, no-op (`null`) when empty.
11
-
12
- > **Source-quote is semantic.** "Readable", "good naming", "clean APIs", "no code smells" are all reader-experience judgments. No single mechanical tool captures them — so the LLM read is the load-bearing signal, with lint / complexity / file-size / semgrep / CR acting as calibrating modifiers.
10
+ The source quote names reader-experience judgments no mechanical tool captures, so the LLM read is the load-bearing signal; lint, complexity, file size, semgrep and CodeRabbit (CR) are calibrating modifiers. CR's null-data semantics are [`SKILL.md → CodeRabbit — calibrating modifier with null-data semantics`](../SKILL.md#coderabbit--calibrating-modifier-with-null-data-semantics).
13
11
 
14
12
  ---
15
13
 
16
14
  ## Preflight
17
15
 
18
- Before running this recipe, execute [`../../preflight.md`](../../preflight.md). The recipe hard-requires:
16
+ Before running this recipe, execute [`../preflight.md`](../preflight.md). The recipe hard-requires:
19
17
 
20
18
  - `ruff` (Python repos)
21
19
  - `biome` (TS/JS repos) — preferred over eslint for speed; eslint is a per-project fallback if biome rejects the repo's config shape
@@ -24,9 +22,7 @@ Before running this recipe, execute [`../../preflight.md`](../../preflight.md).
24
22
  - `semgrep` (polyglot static analysis)
25
23
  - `gh`, `jq` (CR scrape + utilities)
26
24
 
27
- If any of the above is missing **and preflight cannot install it**, the recipe must emit `{signal}_NOT_RUN: true` + `reason` and flag the shortfall loudly in `§6.1` of the analysis file. No silent grep-estimation substitutes.
28
-
29
- Tools are called only for languages present in the repo (see each signal below).
25
+ If any of the above is missing **and preflight cannot install it**, emit `{signal}_NOT_RUN: true` + `reason` and flag the shortfall in the workspace README's raw artifact index. **Never** substitute a grep estimate. Call each tool only for languages present in the repo.
30
26
 
31
27
  ---
32
28
 
@@ -37,7 +33,7 @@ Tools are called only for languages present in the repo (see each signal below).
37
33
  Sample **6 source files** that give the reader a representative slice:
38
34
 
39
35
  1. **Largest source file** by LoC (one per primary language)
40
- 2. **Highest-churn file** from `git log --numstat --all --no-merges | awk ...` (top by lines touched)
36
+ 2. **Highest-churn file** from `git log -n 500 --numstat --no-merges | awk ...` (top by lines touched)
41
37
  3. **Entrypoint / handler**: matches `*/main.{py,ts,js,go}`, `*/app.{py,ts}`, `*/handlers/*`, `*/routes/*`, `*/api/*`
42
38
  4. **3 random** across distinct directories, excluding `tests/`, `__tests__/`, generated, vendored, lockfiles. Prefer files > 50 LoC.
43
39
 
@@ -76,12 +72,9 @@ if echo "$LANGS" | grep -q '^py$'; then
76
72
  ruff check <repo> --output-format json > /tmp/ruff.json || true
77
73
  fi
78
74
 
79
- # TS / JS — prefer biome. Use `biome lint` (not `biome ci` or `biome check`):
80
- # `ci` / `check` bundle lint + format + organizeImports as diagnostics, which
81
- # inflates `lint_findings_per_kloc` with stylistic `category: "format"` noise
82
- # that the scorer doesn't want (one observed project showed 11.4/kLoC with
83
- # format, 5.1/kLoC without — crossing the band-4 threshold of 10). `biome lint`
84
- # is pure lint and matches the intent of the signal.
75
+ # TS / JS — prefer biome. Use `biome lint`, never `biome ci` / `biome check`:
76
+ # those add format + organizeImports diagnostics, and the format noise alone
77
+ # can double `lint_findings_per_kloc` across the band-4 threshold of 10.
85
78
  if echo "$LANGS" | grep -qE '^(ts|tsx|js|jsx)$'; then
86
79
  cd <repo>
87
80
  biome lint . --reporter=json > /tmp/biome.json 2>/dev/null \
@@ -105,7 +98,7 @@ Parse (same shape across tools):
105
98
 
106
99
  ### Signal 3 — Complexity density (`lizard`; shared with 1.4)
107
100
 
108
- `lizard` is run once by 1.4 Maintainability — **read its output**, do not re-run. 1.4's Signal 2 applies per-language CCN thresholds (Python 10 / JS-TS 10 / Java 12 / Go 15 — see [maintainability.md](maintainability.md#signal-2--polyglot-complexity-lizard-per-language-ccn)); 1.1 reuses those aggregates verbatim.
101
+ `lizard` runs once, in 1.4 Maintainability — **read its output**, do not re-run. 1.4's [Signal 2](maintainability.md#signal-2--polyglot-complexity-lizard-per-language-ccn) applies the per-language CCN thresholds; 1.1 reuses its aggregates verbatim. If 1.4 has not run yet for this repo, run lizard now with the same command and CSV location, and share the output.
109
102
 
110
103
  Reuse:
111
104
 
@@ -116,8 +109,6 @@ Reuse:
116
109
  - `lizard_god_ratio` — `god_functions ÷ total_functions`
117
110
  - `lizard_thresholds_applied` — `{py: 10, js: 10, ts: 10, java: 12, go: 15, default: 15}` (audit constant)
118
111
 
119
- If 1.4 has not been run yet for this repo, run lizard now (same command, same CSV location) and share the output.
120
-
121
112
  ### Signal 4 — File-size distribution (filesystem)
122
113
 
123
114
  ```bash
@@ -136,14 +127,13 @@ Capture:
136
127
  - `largest_file_loc` — largest source file
137
128
  - `mean_source_file_loc` — mean over all source files
138
129
 
139
- Shared with 1.4; avoid duplicate computation.
130
+ Shared with 1.4 — compute once.
140
131
 
141
132
  ### Signal 5 — Semgrep quality rule-set
142
133
 
143
134
  ```bash
144
- # NOTE: `--config p/code-quality` is deprecated on Semgrep Registry and
145
- # returns HTTP 404 with retry-storm. Stick to the per-language packs that
146
- # resolve cleanly. If you need an umbrella, use `p/default` (lower signal).
135
+ # Never `--config p/code-quality` — it 404s in a retry storm. Use the
136
+ # per-language packs; `p/default` is the umbrella fallback (lower signal).
147
137
  timeout 180 semgrep --config p/python --config p/typescript \
148
138
  --config p/javascript --config p/go \
149
139
  --json --timeout 30 --disable-version-check --metrics=off \
@@ -160,13 +150,11 @@ Capture:
160
150
 
161
151
  ### Signal 6 — CodeRabbit scrape (**calibrating modifier**)
162
152
 
163
- Scrape CR comments from both endpoints CR posts to — inline review comments and issue-style walkthrough comments. Both are needed: walkthrough-only repos look empty on the pulls endpoint alone. CR's label text is authoritative; emoji is a fallback (CR has rotated emoji twice recently).
153
+ Scrape both endpoints CR posts to — inline review comments and issue-style walkthrough comments; a walkthrough-only repo looks empty on the pulls endpoint alone. CR's label text is authoritative; emoji drifts and is the fallback.
164
154
 
165
155
  ```bash
166
- # Cap each endpoint at 90s so a CR-heavy repo can't stall the run. The
167
- # `--paginate-limit` flag was removed in gh 2.89+, so we rely on `--paginate`
168
- # (fetches all pages) wrapped in `timeout` for the actual cap. Typical comment
169
- # counts fit easily inside the 90s window.
156
+ # Cap each endpoint at 90s so a CR-heavy repo can't stall the run. `gh api`
157
+ # has no page-limit flag: `--paginate` fetches every page and `timeout` is the cap.
170
158
  (
171
159
  timeout 90 gh api "repos/<org>/<repo>/pulls/comments?per_page=100" \
172
160
  --paginate \
@@ -188,13 +176,13 @@ Parse each CR comment; prefer label text, fall back to emoji:
188
176
  | `Security` | `🔒` | `security` |
189
177
  | `Performance` | `⚡` | `performance` |
190
178
 
191
- **Walkthrough detection (positive-match, not silence-inferred).** CR posts one issue-level walkthrough per PR it reviews, regardless of plan tier. Detect walkthroughs positively via any of these markers in the body (robust across CR template drift):
179
+ **Walkthrough detection (positive-match, never silence-inferred).** CR posts one issue-level walkthrough per PR it reviews, on every plan tier. Count a comment as a walkthrough when its body carries any of these markers:
192
180
 
193
- - HTML comment: `<!-- walkthrough_start -->` (current stable anchor)
181
+ - HTML comment: `<!-- walkthrough_start -->` (the stable anchor)
194
182
  - Section heading: `## Walkthrough`
195
183
  - Collapsible summary: `<summary>📝 Walkthrough</summary>`
196
184
 
197
- Any one match ⇒ count the comment as a walkthrough and record `cr_walkthrough_count`. This is separate from `cr_pr_count` (unique PRs with ≥1 CR comment of any kind).
185
+ Record the count as `cr_walkthrough_count` — distinct from `cr_pr_count` (unique PRs with ≥1 CR comment of any kind).
198
186
 
199
187
  **Actionable-count capture.** When CR has actionable inline feedback, the walkthrough summary carries a line of the form `Actionable comments posted: N` (optionally bold-wrapped). Match with a tolerant regex:
200
188
 
@@ -202,7 +190,7 @@ Any one match ⇒ count the comment as a walkthrough and record `cr_walkthrough_
202
190
  \*{0,2}Actionable comments posted:\s*(\d+)\*{0,2}
203
191
  ```
204
192
 
205
- Sum captured `N` across walkthroughs → `cr_actionable_total`. If no walkthrough contains this string **and** at least one walkthrough contains a Free-plan disclaimer (`Summarized by CodeRabbit Free` / `is on the Free plan`), set `cr_free_plan: true` — this distinguishes "zero actionables because Free-plan walkthrough-only" from "zero actionables because the regex is blind to a new template." Unmatched inline comments bucket to `uncategorized`; surface the count so loss is visible.
193
+ Sum captured `N` across walkthroughs → `cr_actionable_total`. If no walkthrough contains this string **and** at least one carries a Free-plan disclaimer (`Summarized by CodeRabbit Free` / `is on the Free plan`), set `cr_free_plan: true` — it separates a Free-plan zero from a regex blind to a new template. Unmatched inline comments bucket to `uncategorized`; surface that count so loss is visible.
206
194
 
207
195
  Capture:
208
196
 
@@ -215,23 +203,23 @@ Capture:
215
203
  - `cr_severe_count` — `by_category.bug + by_category.security + by_category.warning`
216
204
  - `cr_severe_per_kloc` — `cr_severe_count ÷ (scc_code_loc ÷ 1000)` (lower-is-better; `null` when `cr_pr_count == 0`)
217
205
 
218
- **Banding rule:** CR is one of several calibrating modifiers (see _Banding_ below). When `cr_pr_count > 0`, `cr_actionable_per_kloc` and `cr_severe_per_kloc` join lint/lizard/semgrep as density signals that cap the band. When `cr_pr_count == 0` or all walkthroughs are actionable-free (the Free-plan default for many projects), both fields are `null` and the modifier is a no-op — the LLM + remaining density signals decide the band. Scorer cites the top 3 CR comments in the evidence string when `cr_actionable_total > 0`.
206
+ **Banding rule:** when `cr_pr_count > 0`, `cr_actionable_per_kloc` and `cr_severe_per_kloc` join lint / lizard / semgrep as density caps in _Banding_. When `cr_pr_count == 0` or every walkthrough is actionable-free (the Free-plan default), both are `null` and the modifier is a no-op. When `cr_actionable_total > 0`, cite the top 3 CR comments in the evidence string.
219
207
 
220
208
  ---
221
209
 
222
210
  ## Raw dumps (flat — files under `raw/` named `code-quality-*`)
223
211
 
224
- Each signal writes its raw output verbatim to the flat `raw/` directory at the workspace root. Absent files = "not extracted" (tool missing / language not present). Aggregates land in `scorecard.yaml` under `data.`.
212
+ Each signal writes its raw output verbatim to the flat `raw/` directory; an absent file means not extracted (tool missing / language not present). Aggregates land in `scorecard.yaml` under `data.`.
225
213
 
226
214
  | File | Source signal | Shape / note |
227
215
  | --- | --- | --- |
228
216
  | `raw/code-quality-llm-sample.jsonl` | Signal 1 | 6 lines, one per sampled file: `{path, naming, api_shape, abstraction, modularity, smells, one_sentence}` |
229
217
  | `raw/code-quality-lint-ruff.json` | Signal 2 | Raw `ruff check --output-format json` (Python only) |
230
- | `raw/code-quality-lint-biome.json` | Signal 2 | Raw `biome ci --reporter json` (TS/JS preferred) |
218
+ | `raw/code-quality-lint-biome.json` | Signal 2 | Raw `biome lint --reporter=json` (TS/JS preferred) |
231
219
  | `raw/code-quality-lint-eslint.json` | Signal 2 | Raw `eslint --format json` (TS/JS fallback when biome rejects config) |
232
220
  | `raw/code-quality-lint-golangci.json` | Signal 2 | Raw `golangci-lint run --out-format json ./...` (Go only) |
233
221
  | `raw/code-quality-semgrep-quality.json` | Signal 5 | Post-filter semgrep output (resilience + security rules stripped) |
234
- | `raw/code-quality-cr-comments.jsonl` | Signal 6 | One line per CR comment: `{pr, file, line, category, label, body_excerpt}`. Empty file when `cr_pr_count == 0` — still emit it (absence of file would be ambiguous with "scrape not run"). |
222
+ | `raw/code-quality-cr-comments.jsonl` | Signal 6 | One line per CR comment: `{pr, file, line, category, label, body_excerpt}`. Empty file when `cr_pr_count == 0` — still emit it, since a missing file reads as "scrape not run". |
235
223
 
236
224
  `raw/maintainability-lizard.csv` and `raw/maintainability-file-sizes.txt` are shared with 1.4 — read, don't duplicate.
237
225
 
@@ -250,8 +238,6 @@ Each signal writes its raw output verbatim to the flat `raw/` directory at the w
250
238
  - `cr_actionable_per_kloc` _(participates only when `cr_pr_count > 0`; null = no-op)_
251
239
  - `cr_severe_per_kloc` _(participates only when `cr_pr_count > 0`; null = no-op)_
252
240
 
253
- Absolute, per-signal thresholds. CR caps apply only when `cr_pr_count > 0` (null = no-op).
254
-
255
241
  | Band | `llm_quality_score` | Density caps |
256
242
  | --- | --- | --- |
257
243
  | **5** | ≥ 4.5 | AND `lint_findings_per_kloc` ≤ 5 AND `lizard_god_per_kloc` ≤ 2 AND `files_over_500_loc` ≤ 1 AND (when non-null) `cr_severe_per_kloc` ≤ 0.5 |
@@ -313,7 +299,7 @@ data:
313
299
  scoring_method: llm_primary_with_mechanical_modifiers
314
300
  ```
315
301
 
316
- When `cr_pr_count == 0` or all walkthroughs are actionable-free (the Free-plan default for most projects), emit:
302
+ When `cr_pr_count == 0` or every walkthrough is actionable-free, emit:
317
303
 
318
304
  ```yaml
319
305
  cr_pr_count: 12
@@ -325,8 +311,6 @@ cr_by_category: {}
325
311
  signals_used: [llm, ruff, lizard, filesystem, semgrep, coderabbit_empty]
326
312
  ```
327
313
 
328
- `null` values signal the scorer to skip the CR modifier for this project — banding leans on the remaining density signals.
329
-
330
314
  If any required tool failed preflight:
331
315
 
332
316
  ```yaml
@@ -341,10 +325,7 @@ data:
341
325
 
342
326
  ## Caveats
343
327
 
344
- - **LLM sample size = 6 files.** Evidence must name every file sampled; the reader should be able to audit each axis score.
328
+ - **LLM sample size = 6 files.** Evidence **must** name every file sampled, so each axis score is auditable.
345
329
  - **Lint tool coverage varies.** A TS repo without a `biome.json` or `.eslintrc` will emit different default rules than one with either — `lint_has_config_in_repo` surfaces the difference.
346
330
  - **Mixed-language repos.** Sum findings across tools; normalise by `scc_code_loc` (not per-language LoC) to avoid double-normalising.
347
- - **`lizard` CCN thresholds are language-idiomatic** — handled by per-language lookup (Py/JS/TS 10, Java 12, Go 15, other 15). See [maintainability.md → Signal 2](maintainability.md#signal-2--polyglot-complexity-lizard-per-language-ccn).
348
- - **CodeRabbit Free plan** sparsity → `cr_*_per_kloc: null`, modifier 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).
349
- - **`AI_AUTHORED_SUSPECTED` signal** (>50% added lines in commits > 500 LoC) remains useful — LLM reviewer should weigh LLM-generated code patterns in `llm_notes` (repetitive scaffolding, over-engineered edge-case branches, inconsistent naming within a single file, etc.).
350
- - **No silent fallback.** If a tool is absent despite preflight, the signal is emitted as `_NOT_RUN` with `reason`. Grep-based substitutes break the absolute band thresholds and are banned.
331
+ - **AI-authored code** (`AI_AUTHORED_SUSPECTED`: >50% of added lines in commits > 500 LoC) — weigh LLM-generated patterns in `llm_notes`: repetitive scaffolding, over-engineered edge-case branches, inconsistent naming within one file.