@nurix/etna 0.19.65 → 0.19.67

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 (250) hide show
  1. package/bin/etna.js +10 -1
  2. package/data/harness-index.json +1 -5
  3. package/data/harnesses/code/CLAUDE.md +3 -1
  4. package/data/harnesses/code/agents/maintenance.md +4 -1
  5. package/data/harnesses/code/harness.json +7 -2
  6. package/data/harnesses/code/hooks/check-completion-integrity.mjs +8 -0
  7. package/data/harnesses/code/hooks/compliance.mjs +139 -27
  8. package/data/harnesses/code/hooks/lib/frozen.mjs +3 -0
  9. package/data/harnesses/code/hooks/lib/ledger.mjs +31 -0
  10. package/data/harnesses/code/hooks/lib/ownership.mjs +3 -1
  11. package/data/harnesses/code/hooks/lib/session-log.mjs +75 -0
  12. package/data/harnesses/code/rules/changelog.md +2 -0
  13. package/data/harnesses/code/skills/documentation/SKILL.md +1 -0
  14. package/data/harnesses/code/skills/documentation/references/frontmatter.md +1 -1
  15. package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +2 -2
  16. package/data/harnesses/code/skills/documentation/templates/Readme.md +1 -0
  17. package/data/harnesses/code/skills/documentation/templates/behavioral-checklist.md +2 -0
  18. package/data/harnesses/code/skills/documentation/templates/changelog-entry.md +2 -2
  19. package/data/harnesses/code/skills/documentation/templates/feature.md +1 -0
  20. package/data/harnesses/code/skills/documentation/templates/implementation-map.md +42 -0
  21. package/data/harnesses/code/skills/testing/SKILL.md +5 -5
  22. package/data/harnesses/delivery/agents/maintenance.md +4 -1
  23. package/data/harnesses/delivery/harness.json +2 -2
  24. package/data/harnesses/delivery/rules/changelog.md +2 -0
  25. package/data/harnesses/delivery/skills/documentation/SKILL.md +1 -0
  26. package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +1 -1
  27. package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +2 -2
  28. package/data/harnesses/delivery/skills/documentation/templates/Readme.md +1 -0
  29. package/data/harnesses/delivery/skills/documentation/templates/behavioral-checklist.md +2 -0
  30. package/data/harnesses/delivery/skills/documentation/templates/changelog-entry.md +2 -2
  31. package/data/harnesses/delivery/skills/documentation/templates/feature.md +1 -0
  32. package/data/harnesses/delivery/skills/documentation/templates/implementation-map.md +42 -0
  33. package/data/harnesses/etna/agents/maintenance.md +4 -1
  34. package/data/harnesses/etna/harness.json +2 -2
  35. package/data/harnesses/etna/rules/changelog.md +2 -0
  36. package/data/harnesses/etna/skills/documentation/SKILL.md +1 -0
  37. package/data/harnesses/etna/skills/documentation/references/frontmatter.md +1 -1
  38. package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +2 -2
  39. package/data/harnesses/etna/skills/documentation/templates/Readme.md +1 -0
  40. package/data/harnesses/etna/skills/documentation/templates/behavioral-checklist.md +2 -0
  41. package/data/harnesses/etna/skills/documentation/templates/changelog-entry.md +2 -2
  42. package/data/harnesses/etna/skills/documentation/templates/feature.md +1 -0
  43. package/data/harnesses/etna/skills/documentation/templates/implementation-map.md +42 -0
  44. package/lib/install/materialize.mjs +51 -57
  45. package/package.json +2 -2
  46. package/data/harnesses/apollo/.mcp.json +0 -8
  47. package/data/harnesses/apollo/.prettierignore +0 -29
  48. package/data/harnesses/apollo/.prettierrc.json +0 -3
  49. package/data/harnesses/apollo/.vscode/settings.json +0 -19
  50. package/data/harnesses/apollo/CLAUDE.md +0 -162
  51. package/data/harnesses/apollo/agents/bookkeeper.md +0 -28
  52. package/data/harnesses/apollo/agents/brainstorm.md +0 -144
  53. package/data/harnesses/apollo/agents/change-review.md +0 -251
  54. package/data/harnesses/apollo/agents/lld-mode.md +0 -58
  55. package/data/harnesses/apollo/agents/maintenance.md +0 -233
  56. package/data/harnesses/apollo/agents/performance-review.md +0 -223
  57. package/data/harnesses/apollo/agents/retro.md +0 -46
  58. package/data/harnesses/apollo/codex/agents/bookkeeper.toml +0 -26
  59. package/data/harnesses/apollo/codex/agents/brainstorm.toml +0 -142
  60. package/data/harnesses/apollo/codex/agents/change-review.toml +0 -249
  61. package/data/harnesses/apollo/codex/agents/lld-mode.toml +0 -52
  62. package/data/harnesses/apollo/codex/agents/maintenance.toml +0 -228
  63. package/data/harnesses/apollo/codex/agents/performance-review.toml +0 -222
  64. package/data/harnesses/apollo/codex/agents/retro.toml +0 -45
  65. package/data/harnesses/apollo/harness.json +0 -19
  66. package/data/harnesses/apollo/hooks/approved-packages.md +0 -44
  67. package/data/harnesses/apollo/hooks/awareness.mjs +0 -405
  68. package/data/harnesses/apollo/hooks/check-bookkeeping-clean.mjs +0 -19
  69. package/data/harnesses/apollo/hooks/check-changelog-presence.mjs +0 -57
  70. package/data/harnesses/apollo/hooks/check-completion-integrity.mjs +0 -71
  71. package/data/harnesses/apollo/hooks/check-ownership.mjs +0 -22
  72. package/data/harnesses/apollo/hooks/compliance.mjs +0 -457
  73. package/data/harnesses/apollo/hooks/hooks.json +0 -23
  74. package/data/harnesses/apollo/hooks/lib/frozen.mjs +0 -58
  75. package/data/harnesses/apollo/hooks/lib/ownership.mjs +0 -242
  76. package/data/harnesses/apollo/hooks/lib/state.mjs +0 -170
  77. package/data/harnesses/apollo/rules/changelog.md +0 -25
  78. package/data/harnesses/apollo/rules/database.md +0 -34
  79. package/data/harnesses/apollo/rules/frontend.md +0 -30
  80. package/data/harnesses/apollo/rules/general.md +0 -40
  81. package/data/harnesses/apollo/rules/nomenclature.md +0 -30
  82. package/data/harnesses/apollo/rules/pnpm.md +0 -57
  83. package/data/harnesses/apollo/rules/testing.md +0 -64
  84. package/data/harnesses/apollo/skills/boundary/SKILL.md +0 -75
  85. package/data/harnesses/apollo/skills/boundary/references/index.md +0 -16
  86. package/data/harnesses/apollo/skills/boundary/references/mechanisms.md +0 -99
  87. package/data/harnesses/apollo/skills/boundary/references/packs/async-messaging.md +0 -81
  88. package/data/harnesses/apollo/skills/boundary/references/packs/auth.md +0 -93
  89. package/data/harnesses/apollo/skills/boundary/references/packs/build-config-runtime.md +0 -93
  90. package/data/harnesses/apollo/skills/boundary/references/packs/cloudflare.md +0 -93
  91. package/data/harnesses/apollo/skills/boundary/references/packs/frontend.md +0 -93
  92. package/data/harnesses/apollo/skills/boundary/references/packs/generic-tail.md +0 -55
  93. package/data/harnesses/apollo/skills/boundary/references/packs/persistence.md +0 -93
  94. package/data/harnesses/apollo/skills/boundary/references/packs/wire-api.md +0 -87
  95. package/data/harnesses/apollo/skills/brainstorm/README.md +0 -56
  96. package/data/harnesses/apollo/skills/brainstorm/SKILL.md +0 -173
  97. package/data/harnesses/apollo/skills/brainstorm/references/doctrine.md +0 -98
  98. package/data/harnesses/apollo/skills/brainstorm/references/harvest.md +0 -86
  99. package/data/harnesses/apollo/skills/brainstorm/references/session-schema.md +0 -186
  100. package/data/harnesses/apollo/skills/brainstorm/scripts/detector.mjs +0 -460
  101. package/data/harnesses/apollo/skills/design/SKILL.md +0 -121
  102. package/data/harnesses/apollo/skills/design/components/charts.md +0 -76
  103. package/data/harnesses/apollo/skills/design/components/collections.md +0 -132
  104. package/data/harnesses/apollo/skills/design/components/feedback.md +0 -47
  105. package/data/harnesses/apollo/skills/design/components/hooks.md +0 -35
  106. package/data/harnesses/apollo/skills/design/components/index.md +0 -143
  107. package/data/harnesses/apollo/skills/design/components/inputs.md +0 -327
  108. package/data/harnesses/apollo/skills/design/components/layout.md +0 -52
  109. package/data/harnesses/apollo/skills/design/components/media.md +0 -66
  110. package/data/harnesses/apollo/skills/design/components/motion.md +0 -82
  111. package/data/harnesses/apollo/skills/design/components/navigation.md +0 -29
  112. package/data/harnesses/apollo/skills/design/components/overlays.md +0 -72
  113. package/data/harnesses/apollo/skills/design/components/setup.md +0 -40
  114. package/data/harnesses/apollo/skills/design/components/typography.md +0 -46
  115. package/data/harnesses/apollo/skills/design/components/utils.md +0 -37
  116. package/data/harnesses/apollo/skills/design/data/blueprints/browse.md +0 -38
  117. package/data/harnesses/apollo/skills/design/data/blueprints/creation-flow.md +0 -38
  118. package/data/harnesses/apollo/skills/design/data/blueprints/dashboard.md +0 -38
  119. package/data/harnesses/apollo/skills/design/data/blueprints/grid.md +0 -38
  120. package/data/harnesses/apollo/skills/design/data/blueprints/queue.md +0 -38
  121. package/data/harnesses/apollo/skills/design/data/blueprints/record-detail.md +0 -38
  122. package/data/harnesses/apollo/skills/design/data/blueprints/settings.md +0 -38
  123. package/data/harnesses/apollo/skills/design/data/charts/census.csv +0 -58
  124. package/data/harnesses/apollo/skills/design/data/checklists/browse.md +0 -21
  125. package/data/harnesses/apollo/skills/design/data/checklists/creation-flow.md +0 -20
  126. package/data/harnesses/apollo/skills/design/data/checklists/dashboard.md +0 -21
  127. package/data/harnesses/apollo/skills/design/data/checklists/grid.md +0 -21
  128. package/data/harnesses/apollo/skills/design/data/checklists/queue.md +0 -21
  129. package/data/harnesses/apollo/skills/design/data/checklists/record-detail.md +0 -21
  130. package/data/harnesses/apollo/skills/design/data/checklists/settings.md +0 -21
  131. package/data/harnesses/apollo/skills/design/data/chrome/board-column.md +0 -68
  132. package/data/harnesses/apollo/skills/design/data/chrome/data-table.md +0 -63
  133. package/data/harnesses/apollo/skills/design/data/chrome/side-panel.md +0 -60
  134. package/data/harnesses/apollo/skills/design/data/chrome/sidebar.md +0 -78
  135. package/data/harnesses/apollo/skills/design/data/chrome/stat-cards.md +0 -62
  136. package/data/harnesses/apollo/skills/design/data/chrome/topbar.md +0 -65
  137. package/data/harnesses/apollo/skills/design/data/elevation/ant-design-directional-shadow.md +0 -19
  138. package/data/harnesses/apollo/skills/design/data/elevation/apple-liquid-glass-material.md +0 -18
  139. package/data/harnesses/apollo/skills/design/data/elevation/atlassian-surface-shadow-pairing.md +0 -20
  140. package/data/harnesses/apollo/skills/design/data/elevation/fluent-2-key-ambient-ramp.md +0 -20
  141. package/data/harnesses/apollo/skills/design/data/elevation/github-primer-sparing-shadow.md +0 -19
  142. package/data/harnesses/apollo/skills/design/data/elevation/ibm-carbon-layer-and-border.md +0 -19
  143. package/data/harnesses/apollo/skills/design/data/elevation/linear-dark-surface-ladder.md +0 -17
  144. package/data/harnesses/apollo/skills/design/data/elevation/material-2-key-ambient-dp-ramp.md +0 -19
  145. package/data/harnesses/apollo/skills/design/data/elevation/material-3-tonal-elevation.md +0 -21
  146. package/data/harnesses/apollo/skills/design/data/elevation/neobrutalist-hard-offset.md +0 -19
  147. package/data/harnesses/apollo/skills/design/data/elevation/neumorphic-soft-dual-shadow.md +0 -18
  148. package/data/harnesses/apollo/skills/design/data/elevation/notion-warm-minimal-hairline.md +0 -17
  149. package/data/harnesses/apollo/skills/design/data/elevation/polaris-elevation-inset-bevel.md +0 -21
  150. package/data/harnesses/apollo/skills/design/data/elevation/radix-themes-alpha-ring-scale.md +0 -19
  151. package/data/harnesses/apollo/skills/design/data/elevation/shadcn-neutral-derived-radius.md +0 -19
  152. package/data/harnesses/apollo/skills/design/data/elevation/stripe-brand-tinted-dual-shadow.md +0 -18
  153. package/data/harnesses/apollo/skills/design/data/elevation/tailwind-default-utility-scale.md +0 -19
  154. package/data/harnesses/apollo/skills/design/data/elevation/vercel-geist-shadow-as-border.md +0 -20
  155. package/data/harnesses/apollo/skills/design/data/iconography.md +0 -199
  156. package/data/harnesses/apollo/skills/design/data/motion/accordion-expand.md +0 -18
  157. package/data/harnesses/apollo/skills/design/data/motion/destructive-hold-confirm.md +0 -18
  158. package/data/harnesses/apollo/skills/design/data/motion/drag-dismiss-momentum.md +0 -18
  159. package/data/harnesses/apollo/skills/design/data/motion/empty-state-arrive.md +0 -18
  160. package/data/harnesses/apollo/skills/design/data/motion/hover-lift.md +0 -18
  161. package/data/harnesses/apollo/skills/design/data/motion/modal-center-arrive.md +0 -18
  162. package/data/harnesses/apollo/skills/design/data/motion/number-ticker-roll.md +0 -18
  163. package/data/harnesses/apollo/skills/design/data/motion/onboarding-bounce.md +0 -18
  164. package/data/harnesses/apollo/skills/design/data/motion/panel-slide.md +0 -18
  165. package/data/harnesses/apollo/skills/design/data/motion/press-feedback.md +0 -18
  166. package/data/harnesses/apollo/skills/design/data/motion/progress-linear-loop.md +0 -18
  167. package/data/harnesses/apollo/skills/design/data/motion/route-crossfade.md +0 -18
  168. package/data/harnesses/apollo/skills/design/data/motion/rubber-band-overscroll.md +0 -18
  169. package/data/harnesses/apollo/skills/design/data/motion/skeleton-shimmer.md +0 -18
  170. package/data/harnesses/apollo/skills/design/data/motion/stagger-arrive.md +0 -18
  171. package/data/harnesses/apollo/skills/design/data/motion/toast-enter-stack.md +0 -18
  172. package/data/harnesses/apollo/skills/design/data/motion/tooltip-chain-instant.md +0 -18
  173. package/data/harnesses/apollo/skills/design/data/motion/trigger-anchored-reveal.md +0 -18
  174. package/data/harnesses/apollo/skills/design/data/tells.csv +0 -34
  175. package/data/harnesses/apollo/skills/design/data/voices/bright-collaborator.md +0 -29
  176. package/data/harnesses/apollo/skills/design/data/voices/direct-operator.md +0 -29
  177. package/data/harnesses/apollo/skills/design/data/voices/earnest-helper.md +0 -29
  178. package/data/harnesses/apollo/skills/design/data/voices/editorial-composed.md +0 -29
  179. package/data/harnesses/apollo/skills/design/data/voices/quiet-concierge.md +0 -29
  180. package/data/harnesses/apollo/skills/design/data/voices/warm-guide.md +0 -29
  181. package/data/harnesses/apollo/skills/design/references/compose.md +0 -23
  182. package/data/harnesses/apollo/skills/design/references/content.md +0 -28
  183. package/data/harnesses/apollo/skills/design/references/emission.md +0 -21
  184. package/data/harnesses/apollo/skills/design/references/existing-apps.md +0 -27
  185. package/data/harnesses/apollo/skills/design/references/foundations.md +0 -57
  186. package/data/harnesses/apollo/skills/design/references/intake.md +0 -40
  187. package/data/harnesses/apollo/skills/design/references/object-pass.md +0 -24
  188. package/data/harnesses/apollo/skills/design/references/ship-gate.md +0 -29
  189. package/data/harnesses/apollo/skills/design/references/ux-patterns/Readme.md +0 -195
  190. package/data/harnesses/apollo/skills/design/references/ux-patterns/ai-layer.md +0 -49
  191. package/data/harnesses/apollo/skills/design/references/ux-patterns/attributes-lifecycle.md +0 -43
  192. package/data/harnesses/apollo/skills/design/references/ux-patterns/container-choice.md +0 -44
  193. package/data/harnesses/apollo/skills/design/references/ux-patterns/creation-paths.md +0 -46
  194. package/data/harnesses/apollo/skills/design/references/ux-patterns/dashboards.md +0 -42
  195. package/data/harnesses/apollo/skills/design/references/ux-patterns/modes.md +0 -42
  196. package/data/harnesses/apollo/skills/design/references/ux-patterns/object-model.md +0 -46
  197. package/data/harnesses/apollo/skills/design/references/ux-patterns/page-archetype.md +0 -48
  198. package/data/harnesses/apollo/skills/design/references/ux-patterns/promotion-demotion.md +0 -37
  199. package/data/harnesses/apollo/skills/design/references/ux-patterns/settings.md +0 -42
  200. package/data/harnesses/apollo/skills/design/references/ux-patterns/standard-pages.md +0 -46
  201. package/data/harnesses/apollo/skills/design/references/ux-patterns/state-matrix.md +0 -41
  202. package/data/harnesses/apollo/skills/design/references/ux-patterns/table-mechanics.md +0 -48
  203. package/data/harnesses/apollo/skills/design/references/ux-patterns/verbs.md +0 -45
  204. package/data/harnesses/apollo/skills/design/references/ux-patterns/viewer-context.md +0 -40
  205. package/data/harnesses/apollo/skills/design/scripts/README-validator.md +0 -27
  206. package/data/harnesses/apollo/skills/design/scripts/select-chart.mjs +0 -622
  207. package/data/harnesses/apollo/skills/design/scripts/validate-design-md.mjs +0 -1198
  208. package/data/harnesses/apollo/skills/documentation/SKILL.md +0 -134
  209. package/data/harnesses/apollo/skills/documentation/references/examples.md +0 -279
  210. package/data/harnesses/apollo/skills/documentation/references/frontmatter.md +0 -44
  211. package/data/harnesses/apollo/skills/documentation/references/instruction-style.md +0 -50
  212. package/data/harnesses/apollo/skills/documentation/references/style-guide.md +0 -384
  213. package/data/harnesses/apollo/skills/documentation/references/untemplated.md +0 -38
  214. package/data/harnesses/apollo/skills/documentation/scripts/doc-lint.mjs +0 -140
  215. package/data/harnesses/apollo/skills/documentation/templates/Readme.md +0 -34
  216. package/data/harnesses/apollo/skills/documentation/templates/api-reference.md +0 -20
  217. package/data/harnesses/apollo/skills/documentation/templates/architecture-decision.md +0 -121
  218. package/data/harnesses/apollo/skills/documentation/templates/backlog.md +0 -33
  219. package/data/harnesses/apollo/skills/documentation/templates/behavioral-checklist.md +0 -79
  220. package/data/harnesses/apollo/skills/documentation/templates/bookkeeping.md +0 -18
  221. package/data/harnesses/apollo/skills/documentation/templates/changelog-entry.md +0 -57
  222. package/data/harnesses/apollo/skills/documentation/templates/changelog-index.md +0 -41
  223. package/data/harnesses/apollo/skills/documentation/templates/docs-readme.md +0 -72
  224. package/data/harnesses/apollo/skills/documentation/templates/domain-model.md +0 -30
  225. package/data/harnesses/apollo/skills/documentation/templates/environment-registry.md +0 -15
  226. package/data/harnesses/apollo/skills/documentation/templates/feature.md +0 -149
  227. package/data/harnesses/apollo/skills/documentation/templates/glossary.md +0 -11
  228. package/data/harnesses/apollo/skills/documentation/templates/journal.md +0 -13
  229. package/data/harnesses/apollo/skills/documentation/templates/memory-main.md +0 -25
  230. package/data/harnesses/apollo/skills/documentation/templates/migration-runbook.md +0 -34
  231. package/data/harnesses/apollo/skills/documentation/templates/non-goals.md +0 -11
  232. package/data/harnesses/apollo/skills/documentation/templates/operations-procedure.md +0 -36
  233. package/data/harnesses/apollo/skills/documentation/templates/plan.md +0 -88
  234. package/data/harnesses/apollo/skills/documentation/templates/protected-files.md +0 -37
  235. package/data/harnesses/apollo/skills/documentation/templates/root-readme.md +0 -104
  236. package/data/harnesses/apollo/skills/documentation/templates/security-overview.md +0 -27
  237. package/data/harnesses/apollo/skills/documentation/templates/structure.md +0 -65
  238. package/data/harnesses/apollo/skills/documentation/templates/system-overview.md +0 -32
  239. package/data/harnesses/apollo/skills/documentation/templates/testing-strategy.md +0 -29
  240. package/data/harnesses/apollo/skills/schema-design/SKILL.md +0 -141
  241. package/data/harnesses/apollo/skills/test/SKILL.md +0 -104
  242. package/data/harnesses/apollo/skills/testing/SKILL.md +0 -166
  243. package/data/harnesses/apollo/skills/workflow-mapper/SKILL.md +0 -451
  244. package/data/harnesses/apollo/skills/workflow-mapper/references/patterns.md +0 -214
  245. /package/data/harnesses/{apollo → code}/docs/README.md +0 -0
  246. /package/data/harnesses/{apollo → code}/docs/history/CHANGELOG.md +0 -0
  247. /package/data/harnesses/{apollo → code}/docs/history/backlog.md +0 -0
  248. /package/data/harnesses/{apollo → code}/docs/memory/main.md +0 -0
  249. /package/data/harnesses/{apollo → code}/docs/structure.md +0 -0
  250. /package/data/harnesses/{apollo → code}/rules/cloudflare.md +0 -0
@@ -1,87 +0,0 @@
1
- # Pack: HTTP wire / API
2
-
3
- Load when: the touch list exhibits Express routes/middleware (`app.use(`, `router.get(`), the response envelope (`res.json({ status`), zod request validation, axios clients/interceptors, CORS config, webhooks received, or rate limiting.
4
-
5
- ## express5-route-string-syntax — HIGH · rendezvous-string
6
- **Contract:** Express route strings are compiled by path-to-regexp v8 in Express 5; route authors and every URL caller meet on a path-string dialect that changed from Express 4.
7
- **Detect:** `app\.(get|post|put|patch|delete|all|use)\(['"]`, `['"]\*['"]`, `:[a-zA-Z]+\?`, `:\w+\(`, `/\*splat`, `\{/:`, `req\.params\[0\]`, `req\.params\.splat`
8
- **Ships green, breaks:** Old syntax `*`, `:id?`, `:id(\d+)` throws `TypeError: Missing parameter name` at boot — but the silent ones: `/*splat` no longer matches the mount root (`/files/*splat` misses `GET /files/`; only `/{*splat}` matches root); wildcard params are now ARRAYS of segments (`req.params.splat === ['a','b']`, not the string `'a/b'`; `req.params[0]` is gone → undefined); unmatched optional params are OMITTED from `req.params` instead of present-as-undefined; regex sub-patterns are unsupported, so numeric-only constraints once enforced by `(\d+)` silently stop filtering if approximated wrong.
9
- **Safe change:** Use `/{*splat}` when root must match; treat splat as array (`req.params.splat.join('/')` where a string was expected); `:p?` → `{/:p}`, `:file.:ext?` → `/:file{.:ext}`; move regex constraints into handler/zod validation; run the Express v5 migration codemod and re-test every wildcard/optional route with real URLs.
10
-
11
- ## express5-query-parser-flip — HIGH · serialized-shape
12
- **Contract:** Clients serialize query strings (qs brackets, axios `params`) and the server parses them per `app.set('query parser', ...)` — Express 5 flipped the default from `'extended'` to `'simple'`.
13
- **Detect:** `app.set('query parser'`, `req\.query`, `\[\w+\]=` in client URL builders, `qs.stringify`, `paramsSerializer`, `express.urlencoded()`
14
- **Ships green, breaks:** `?filter[status]=open` now parses to the flat key `"filter[status]"` instead of `{filter:{status:'open'}}` — loose schemas pass it through and filters silently no-op (endpoint returns unfiltered data); strict schemas start 400ing only for clients that send brackets. `req.query` is now a getter: sanitizer middleware doing `req.query = cleaned` silently no-ops (sloppy mode) or throws TypeError (strict). `express.urlencoded()` `extended` also now defaults to `false`.
15
- **Safe change:** Pin `app.set('query parser', 'extended')` on migration (or convert clients to flat params); mutate `req.query` properties in place, never reassign; validate `req.query` with a strict zod schema so shape drift fails loudly.
16
-
17
- ## express5-removed-response-apis — HIGH · rendezvous-string
18
- **Contract:** Handler code meets the Express request/response API by literal method name at runtime — nothing static links plain-JS call sites to Express 5's removed/changed methods.
19
- **Detect:** `res.sendfile(`, `app.del(`, `res.redirect('back')`, `res.location('back')`, `req.param(`, `res\.(send|json|jsonp)\([^)]+,\s*\d{3}\)`, `res\.send\(\d{3}\)`, `clearCookie\(.+maxAge|expires`
20
- **Ships green, breaks:** `res.redirect('back')` no longer resolves the Referrer — it redirects to the literal relative URL `back` (no error; users land on a 404). `res.clearCookie(name, {maxAge, expires})` silently ignores those options. `res.sendfile`, `app.del`, `req.param()`, `res.send(body, status)`, `res.send(404)` are removed → per-request TypeError → 500s only when the route is exercised. `res.status()` now throws for non-integers outside 100–999. `req.body` is `undefined` (not `{}`) when no parser ran, so `req.body.x` throws where v4 returned undefined.
21
- **Safe change:** Replace `'back'` with `req.get('Referrer') || '/'`; `res.sendStatus(n)` / `res.status(n).json(obj)`; guard trust edges with `req.body ?? {}`; grep the whole detect list before touching any Express-4-era file.
22
-
23
- ## express-error-handler-arity — HIGH · lifecycle-protocol
24
- **Contract:** Express identifies an error handler SOLELY by `fn.length === 4`; Express 5 additionally forwards every rejected async handler/middleware promise to that chain as `next(err)`.
25
- **Detect:** `app.use((err,`, `(err, req, res, next)`, `express-async-errors`, `.catch(next)`, `next(err)`
26
- **Ships green, breaks:** Deleting the "unused" fourth `next` param (a common lint autofix) silently turns the centralized error handler into ordinary middleware — it now runs on EVERY request and never on errors; errors fall through to Express's default handler, which emits HTML instead of the JSON envelope, and envelope-unwrapping clients break. With Express 5's native rejection forwarding, legacy `catch (e) { next(e) }` plus a rethrow (or a lingering `express-async-errors` shim) double-invokes the error chain → `Cannot set headers after they are sent`. Throws inside `setTimeout`/event callbacks are NOT forwarded and still crash the process.
27
- **Safe change:** Always declare 4 params on error middleware (void the unused one); one terminal error handler emitting the envelope; in async handlers throw OR `next(e)`, never both; keep non-request-path callbacks in their own try/catch.
28
-
29
- ## api-response-envelope — HIGH · serialized-shape
30
- **Contract:** Every response body is `{"status": 1, "message": "...", "data": {...}}` (errors: `{"status": 0, "message": "...", "data": null}`); axios interceptors unwrap `response.data.data` and branch on NUMERIC `status`.
31
- **Detect:** `status: 1`, `status: 0`, `"status": 1`, `.data.data`, `interceptors.response.use`, `res.json({ status`, `data: null`
32
- **Ships green, breaks:** Server emitting `status: true` breaks client `=== 1` / `=== 0` strict checks — responses classify as neither success nor error and fall through silently. A new endpoint returning a bare payload makes the unwrapper's `.data.data` yield `undefined` — spreads/destructures render empty state, no error thrown. If error envelopes move to non-2xx HTTP codes, axios's default `validateStatus` routes them into the REJECTED interceptor arm where the success unwrapper never runs — code must read `err.response.data.message`, not `res.data.message`. `data: null` on errors breaks optimistic `data.items.map`.
33
- **Safe change:** Emit the envelope only via one `sendSuccess`/`sendError` helper (no inline literals); unwrap in one axios interceptor handling BOTH fulfilled and rejected arms; zod-parse the envelope at the client edge (`z.union([z.literal(0), z.literal(1)])` for `status`) so drift throws instead of undefined-ing.
34
-
35
- ## http-status-code-convention — HIGH · rendezvous-string
36
- **Contract:** Server code choices and client interceptor branching meet on exact numeric codes: 200, 201 created, 400, 401 not-authenticated, 403 not-authorized, 404, 500 (plus 429/503 for backoff) — literals on both sides, no static link.
37
- **Detect:** `res.status(4`, `sendStatus(`, `err.response?.status`, `=== 401`, `=== 403`, `Retry-After`, `status === 429`
38
- **Ships green, breaks:** Returning 403 (or 200 + envelope `status: 0`) for an EXPIRED token means the client's 401→refresh-token interceptor never fires — sessions die silently or error-toast forever. Returning 401 for a pure permissions failure triggers refresh→retry loops that hammer the auth service and can force logouts. Backoff interceptors keyed to 429/503 don't engage if throttling ships as 400/500. 201-vs-200 breaks clients that branch on `status === 201` to read a created id.
39
- **Safe change:** 401 strictly = not authenticated (bad/expired credential), 403 strictly = authenticated but not allowed; auth failures always ride HTTP codes, never 200+envelope-0; grep client interceptors for the exact literal before changing any handler's code; include `Retry-After` with 429.
40
-
41
- ## middleware-mount-order — HIGH · lifecycle-protocol
42
- **Contract:** The `app.use` sequence is the contract: security/CORS → body parsers → auth/rate-limit middleware → routes → 404 → 4-arg error handler LAST.
43
- **Detect:** ordering in `server.js`/`app.js`/`index.js`, `app.use(express.json`, `app.use(router`, `app.use(errorHandler`, `express.json({ limit`
44
- **Ships green, breaks:** A router mounted above `express.json()` sees `req.body === undefined` in Express 5 → every POST 500s, or `req.body?.flag` goes falsy and the default branch runs for all users with no error. Routes registered AFTER the error handler still serve, but their errors bypass it → default HTML error responses that envelope clients can't parse. Auth or rate-limit mounted after routes is fail-open — unit tests that call handlers directly stay green. `express.json` only parses `Content-Type: application/json` — `navigator.sendBeacon` (text/plain) and pre-stringified axios posts arrive with `req.body` undefined.
45
- **Safe change:** Keep one composition file owning the order above; never register routes in two places; when adding a parser-dependent route, confirm it's below the parser; smoke-test one POST through real HTTP per deploy, not just handler units.
46
-
47
- ## webhook-hmac-raw-body — CRITICAL · trust-invariant
48
- **Contract:** The provider signs the exact raw request bytes; the server must verify the HMAC over those SAME bytes before trusting the event (often payment/provisioning events).
49
- **Detect:** `express.raw(`, `rawBody`, `createHmac`, `timingSafeEqual`, `verify: (req, res, buf`, headers `stripe-signature`/`x-hub-signature-256`/`x-signature`
50
- **Ships green, breaks:** Computing the HMAC over `JSON.stringify(req.body)` after `express.json()` produces different bytes (whitespace, unicode escaping, number formatting) → every signature mismatches → all deliveries rejected; the provider retries, then disables the endpoint — events silently lost. The common "fix" (skipping verification) fails OPEN to forged payment events. If `app.use(express.json())` runs globally, a route-level `express.raw()` gets an already-consumed stream → empty buffer → same permanent mismatch. `crypto.timingSafeEqual` THROWS RangeError on unequal lengths (length-check first), and `sig === expected` is a timing oracle. Providers redeliver on timeout/non-2xx → duplicate side effects.
51
- **Safe change:** Mount `express.raw({ type: 'application/json' })` for the webhook path (or global `express.json({ verify: (req, res, buf) => { req.rawBody = buf } })`); length-check then `timingSafeEqual` on hex-digest Buffers; respond 2xx fast and process async; dedupe on the provider's delivery-id header persisted atomically with the side effect.
52
-
53
- ## zod4-silent-semantics — HIGH · serialized-shape
54
- **Contract:** Request-validation schemas written with zod 3 idioms meet the zod 4 runtime, which silently ignores or re-interprets several idioms instead of erroring.
55
- **Detect:** `required_error`, `invalid_type_error`, `errorMap`, `z.record(` with one arg, `.default(`, `.errors`, `.flatten()`, `.format()`, `.strict()`, `.passthrough()`
56
- **Ships green, breaks:** `required_error`/`invalid_type_error` params were DROPPED — plain-JS call sites are silently ignored, custom messages vanish and clients string-matching them break (`errorMap` is renamed to the unified `error` param). Single-arg `z.record(z.string())` constructs fine and parses EMPTY objects fine, then throws on the first non-empty input; `z.record(z.enum([...]), v)` is now EXHAUSTIVE (missing enum keys fail — v3 was partial; use `z.partialRecord`). `.default(v)` now short-circuits on undefined and returns `v` as-is WITHOUT running transforms/coercions — use `.prefault()` for v3 behavior. `ZodError.errors` alias is removed → `err.errors.map` TypeErrors inside catch blocks (use `.issues`); `.format()`/`.flatten()` are deprecated for `z.treeifyError()`/`z.flattenError()`.
57
- **Safe change:** On any zod-touching edit, grep for dropped params and one-arg `z.record`; audit enum-keyed records for intended partiality; re-test every `.default()` whose value relied on transforms (switch to `.prefault()`); replace `.errors` with `.issues` in all error handlers.
58
-
59
- ## zod-query-param-coercion — HIGH · serialized-shape
60
- **Contract:** Query and path params arrive as strings (or string arrays); the schema's coercion layer is where wire strings become the types handlers assume.
61
- **Detect:** `safeParse(req.query`, `parse(req.query`, `z.coerce.`, `z.coerce.boolean`, `req.query.` feeding numeric/boolean logic
62
- **Ships green, breaks:** `z.coerce.boolean()` is `Boolean(x)` — `?active=false` and `?active=0` coerce to TRUE (any non-empty string is truthy). `z.coerce.number()` turns `?page=` (empty string) into `0`. Duplicate keys `?id=1&id=2` arrive as `string[]` and fail `z.string()` only for requests that actually send duplicates. Uncoerced `z.number()`/`z.boolean()` on query rejects every real request while handler unit tests (fed real numbers/booleans) stay green. Combined with Express 5's `'simple'` parser, nested-object query schemas never match at all.
63
- **Safe change:** Use `z.stringbool()` (zod 4) or an explicit `z.enum(['true','false']).transform(...)` for flags — never `z.coerce.boolean()` on query strings; wrap repeatable params in `z.union([T, z.array(T)])`; design query schemas so their INPUT type is string, and test through real URLs.
64
-
65
- ## axios-error-and-timeout-contract — HIGH · rendezvous-string
66
- **Contract:** Client catch-blocks and retry logic branch on axios 1.x's error taxonomy — `err.response` vs `err.request` vs config error, and literal `err.code` strings — plus its `validateStatus`/`timeout` defaults.
67
- **Detect:** `err.response`, `err.request`, `err.code ===`, `'ECONNABORTED'`, `'ETIMEDOUT'`, `validateStatus`, `timeout:`, `transitional`, `isAxiosError`
68
- **Ships green, breaks:** Default `timeout: 0` — axios NEVER times out; a hung upstream pins the request forever and retry logic never fires. When a timeout is set, it rejects with `code: 'ECONNABORTED'` (not ETIMEDOUT) unless `transitional: { clarifyTimeoutError: true }` flips it to `'ETIMEDOUT'` — retry code matching the other literal silently never retries. The timeout is socket-inactivity based, NOT a whole-request deadline: a slowly trickling response can run far past it. Default `validateStatus` rejects 3xx/304 as errors, and overriding it to `() => true` reroutes 4xx/5xx into the SUCCESS interceptor, bypassing envelope error handling. Response headers are lowercase-normalized: `err.response.headers['Retry-After']` is undefined; use `'retry-after'`.
69
- **Safe change:** Set an explicit `timeout` and decide the code literal via `transitional.clarifyTimeoutError`, matching retry logic to it; use `signal: AbortSignal.timeout(ms)` for a hard deadline; branch `err.response` → server replied, `err.request` → no reply, else config bug; never touch `validateStatus` without auditing both interceptor arms.
70
-
71
- ## cors-allowlist-mirror — HIGH · config-elsewhere
72
- **Contract:** `cors({ origin: process.env.FRONTEND_URL, credentials, allowedHeaders, exposedHeaders })` must mirror exactly what browser code sends and reads — enforcement happens only in the browser, never in server tests.
73
- **Detect:** `cors({`, `FRONTEND_URL`, `allowedHeaders`, `exposedHeaders`, `credentials: true`, `withCredentials`, `Access-Control-`
74
- **Ships green, breaks:** `FRONTEND_URL` unset → `origin: undefined` → the cors package falls back to `*`: silently allows EVERY origin AND breaks all credentialed requests (browsers reject `Access-Control-Allow-Origin: *` with credentials). A comma-joined multi-origin string matches nothing — must be an array or function. If `allowedHeaders` is omitted, cors reflects the request's headers (permissive); once it's explicitly set, adding a new client header without updating it fails ONLY the browser preflight — curl, Postman, and server-to-server all pass. Custom response headers are invisible to client JS without `exposedHeaders`. Errors thrown before the cors middleware produce responses without CORS headers — the browser shows "CORS error", masking the real 500. Cookies need BOTH server `credentials: true` and axios `withCredentials: true`; each alone ships green.
75
- **Safe change:** Fail boot if `FRONTEND_URL` is unset; origins as array/function; treat `allowedHeaders`/`exposedHeaders` as part of every header-adding change on either side; mount cors first; verify with a real browser preflight, not curl.
76
-
77
- ## rate-limit-trust-proxy — HIGH · trust-invariant
78
- **Contract:** express-rate-limit buckets by `req.ip`, which Express computes from `X-Forwarded-For` according to `app.set('trust proxy', ...)` — the limiter key is only as honest as the declared proxy-hop count.
79
- **Detect:** `app.set('trust proxy'`, `rateLimit(`, `keyGenerator`, `X-Forwarded-For`, `ipKeyGenerator`
80
- **Ships green, breaks:** `trust proxy: true` → `req.ip` is the LEFTMOST `X-Forwarded-For` entry, fully attacker-controlled — every request can present a fresh IP, bypassing the limiter (fail-open on login brute force); express-rate-limit v7 only console-logs `ERR_ERL_PERMISSIVE_TRUST_PROXY` and keeps serving. Unset behind nginx/Cloudflare → `req.ip` is the proxy's IP → the entire userbase shares ONE bucket → production-wide 429s that dev never reproduces (`ERR_ERL_UNEXPECTED_X_FORWARDED_FOR`). A custom `keyGenerator: (req) => req.ip` without IPv6 masking lets one user rotate a /64 for fresh buckets (use the exported `ipKeyGenerator` helper).
81
- **Safe change:** Set `app.set('trust proxy', 1)` with the exact hop count — never `true`; re-count hops whenever proxy topology changes; treat ERL console errors as failures, not noise; smoke-test `req.ip` from outside the proxy after deploy.
82
-
83
- ## route-path-client-rendezvous — MED · rendezvous-string
84
- **Contract:** axios/fetch URL strings in the client and Express mount + route strings on the server meet only at runtime — no compiler or test links them.
85
- **Detect:** `axios.(get|post|put|delete)('/`, `baseURL`, `fetch('/api`, `app.use('/api`, `router.(get|post)('/`, SPA catch-all `app.get('/{*splat}'`
86
- **Ships green, breaks:** Renaming a mount (`/api/v1` → `/api/v2`) or route segment 404s every call site — and when an envelope-unwrapping interceptor swallows instead of rethrowing, callers get `undefined` and render empty states with no error. An SPA catch-all serving index.html turns API-path typos into 200 `text/html` responses that fail JSON parsing far from the cause. Express defaults are case-insensitive and trailing-slash-tolerant — enabling `strict routing`/`case sensitive routing` changes which existing client strings still match.
87
- **Safe change:** Centralize client paths in one api module (no inline URL literals); grep both repos for the old path before any rename; mount an API-scoped 404 (JSON envelope) before the SPA catch-all so `/api/*` never falls into index.html; prefer additive versioned mounts over in-place renames.
@@ -1,56 +0,0 @@
1
- # Brainstorm — process, not archive
2
-
3
- A Claude Code skill that is a **thinking partner for designing large-scale software changes**.
4
- The session's product is the repo's living documentation: the conversation helps the user think
5
- correctly, the record stays readable at any pause, and the session ends with a harvest so
6
- complete that the session folder is useless — it moves to history and the user deletes or
7
- commits it.
8
-
9
- > Spec (single source of truth): `docs/architecture/skills/brainstorm/` in the etna repo. The etna
10
- > copy of this skill (`skills/brainstorm/`) is canonical; the user-level path
11
- > `~/.claude/skills/brainstorm/` is a symlink to it.
12
-
13
- ## The architecture — one capability, two seats
14
-
15
- Prose obligations decay in the conversing seat: the fleet audit behind v3 found the same rules
16
- dying in every real session, even the successful ones. So the capability is split:
17
-
18
- | Seat | Component | Owns |
19
- | --- | --- | --- |
20
- | Conversation (main loop) | `SKILL.md` — the facilitator | The dialogue, the basis gate, the moves, one write: appending everything to `ops/capture.md` |
21
- | Paper (dispatched agent) | `agents/brainstorm.md` — the twin, pinned strong tier | Every working-surface file: distilling ops into pillars, recomposing the thesis whole, the semantic audits, the harvest |
22
- | Integrity (script) | `scripts/detector.mjs` | Mechanical checks with stable rule IDs; blocks the manifest and the move while gates fail |
23
- | Quality (authoring-time) | `evals/` (never ships) | Session-replay scenarios, the two-agent audit, contrastive facilitation |
24
-
25
- Every twin dispatch is paired-logged in `ops/sync-log.md` — the facilitator writes the dispatch
26
- line, the twin writes the result — so reconciliation is observable, never asserted.
27
-
28
- ## The session lifecycle
29
-
30
- ```
31
- /brainstorm start
32
- → basis gate (a document, an old session folder of any format, or a brain dump)
33
- → bootstrap docs/research/{topic}-brainstorm/ (ops/ untracked; twin writes the surface)
34
- → converse: dump / interview / probe / blindspot / converge — steerable in plain language
35
- → "let me read" anytime: compose on demand, read the thesis, come back
36
- /brainstorm stop
37
- → converge → manifest → ONE user approval → apply → uselessness test
38
- → folder moves to docs/history/brainstorms/{topic}/ (the completion marker)
39
- → the user decides: delete or commit
40
- ```
41
-
42
- The working surface: `thesis.md` (claim → argument → what changed, recomposed whole, stamped),
43
- `forks.md` (open questions with close conditions — the only convergence currency), `ledger.md`
44
- (commitments: Decision / Why / How to apply / Resolves, declined options inline with re-evaluate
45
- conditions), `state.md` (anchor + the aspect map), `basis/`, `fragments/` (harvest-native,
46
- drafted in destination format), and untracked `ops/` (raw capture + sync log; deleted at stop).
47
-
48
- ## Files
49
-
50
- - `SKILL.md` — the facilitator hub
51
- - `references/doctrine.md` — thesis / forces / forks / commitments / consequences epistemics
52
- - `references/session-schema.md` — the single format authority (what the detector enforces)
53
- - `references/harvest.md` — the stop pipeline and routing map
54
- - `scripts/detector.mjs` — the rule registry (`node detector.mjs <folder> [--gate=…] [--json]`)
55
- - `scripts/fixtures/` — contrastive fixtures + runner (authoring-time; never ships)
56
- - `evals/` — session-replay + audit harness (authoring-time; never ships)
@@ -1,173 +0,0 @@
1
- ---
2
- name: brainstorm
3
- description: "Use when starting or stopping a large-scale design brainstorm via `/brainstorm start | stop` — never on phrases like 'let's plan' or 'let's design'. Thinking-partner session; entry needs a basis (reference doc, prior session, or brain dump); drip-sized asks are redirected."
4
- ---
5
-
6
- # Brainstorm
7
-
8
- Help the user think correctly about a large-scale change, in a record that reads well at any
9
- pause, and end with a harvest so complete the session folder is useless. You are the
10
- **facilitator** — the conversation seat of a capability split across two seats:
11
-
12
- - **You (this skill, main loop)** hold the conversation. Your only writes: append to
13
- `ops/capture.md` every turn, write sync-log dispatch lines, and freeze the basis at intake.
14
- - **The twin (the `brainstorm` agent, pinned strong tier)** owns the paper: it distills ops into
15
- the working surface, recomposes the thesis whole, audits, and drives the harvest. You dispatch
16
- it at gates and relay its reports. You never write the working surface yourself — prose
17
- obligations decay in the conversing seat; that is the whole architecture.
18
- - **The detector** (`scripts/detector.mjs`) owns mechanical integrity; the twin runs it.
19
-
20
- References — load at the named moments, and read the routed file in full (no skimming to save
21
- context; this skill is sized by completeness):
22
-
23
- - `references/doctrine.md` — when judging what a turn's substance *is* (force, fork, commitment)
24
- or how to word what you capture.
25
- - `references/session-schema.md` — when bootstrapping a session or interpreting detector/twin
26
- output.
27
- - `references/harvest.md` — at `stop`, before orchestrating the pipeline.
28
-
29
- ## The one habit that is yours: capture
30
-
31
- Append to `ops/capture.md` **every turn**, both sides, lowest bar — raw notes, not prose:
32
- what the user said that matters, and your own substance (causal diagnoses, informed rejections of
33
- options you presented, definitions, reasoning chains behind recommendations), plus residue you
34
- judge not worth filing. Turn-stamped per the schema (`### T# · <ISO datetime>`). Never distill
35
- here — distillation is the twin's. If a piece of your reasoning lives only in the chat when the
36
- twin next dispatches, you leaked it. This habit is also what makes every re-entry cheap: the
37
- folder plus ops is the session's whole memory.
38
-
39
- ## `start`
40
-
41
- Consult the indexes first — never scan folders: `docs/research/Readme.md` (active sessions) and
42
- `docs/history/brainstorms/Readme.md` (harvested). Topic matches an active session → resume it
43
- (re-entry, below). Harvested or prior-generation match → offer it **as a basis** for a fresh
44
- session. No match → new session.
45
-
46
- **1 · The entry gate.** A session needs substance: ask for a **basis** — a reference document
47
- (path or URL), a prior session folder of *any* format or generation, or a one-shot brain dump in
48
- prose, now. Information is information: an old v2 brainstorm folder is ingested exactly like a
49
- PRD — copied into `basis/`, frozen, distilled; never operated on in place, never migrated.
50
- Drip-sized input (a bug fix, one button) → say this skill is the wrong tool and don't open the
51
- session unless the user explicitly overrides. No basis, no session.
52
-
53
- **2 · Bootstrap.** Folder `docs/research/{topic}-brainstorm/` (kebab slug, confirm in one line).
54
- Create `ops/` with a `.gitignore` containing `*`, `ops/capture.md`, `ops/sync-log.md`; copy the
55
- basis into `basis/`; add the row to `docs/research/Readme.md`. Then write the sync-log dispatch
56
- line and dispatch the twin (gate: start) to write the initial surface — you don't scaffold
57
- `state.md`/`thesis.md`/`forks.md`/`ledger.md` yourself.
58
-
59
- **3 · Calibrate + frame.** Distill the basis first — it seeds everything. Calibrate from the
60
- living docs (the ownership index, recent decision records, any open-questions doc) so your
61
- questions match this repo, not a template. Then one `AskUserQuestion` batch: **sitting** (single
62
- sprint — the default and the shape that succeeds — or explicitly multi), **execution reality**
63
- (greenfield / brownfield / hybrid — migration gotchas discovered at plan time are discovered too
64
- late), and **where the idea is right now** (fully in their head → dump; half-formed → interview).
65
- Propose the **aspect map** — the thinking dimensions for *this* idea, derived from the basis,
66
- no fixed list; the user edits it; it lives in `state.md`.
67
-
68
- **4 · Orient.** 3–4 lines, assuming a first-time user: how the session works (you talk, the
69
- folder keeps everything), the steering verbs in plain words, "let me read" (pause and read the
70
- thesis anytime), and what `stop` does (converge → your approval → harvest → the folder moves and
71
- you choose delete or commit). Then begin — **always in dump or interview**; probe and converge
72
- are mid-session moves, never starting postures.
73
-
74
- ## The moves
75
-
76
- Five named, user-steerable interlocution moves — who drives, how much gets asked. No `MODE:`
77
- field, no switch ceremony, no sanctioned trigger words: **any phrasing that implies a move
78
- triggers it** ("I want to poke holes" → probe; "what am I missing?" → blindspot; "let's decide"
79
- → converge). The first time each
80
- move fires, name in one line what you're doing. Offer a switch when the signals say so (the user
81
- monologues mid-interview; every probe answer is "haven't thought about it") — one offer, never
82
- seized.
83
-
84
- - **dump** — user drives. No questions mid-stream. Reflect back the shape, contradictions, and
85
- implications as they land — that reflection *is* active listening; never sit silent.
86
- - **interview** — you drive. `AskUserQuestion` batches of 2–3, scoped to one aspect at a time.
87
- Questions derive from the basis and the current surface — never from a template inventory;
88
- never interview to fill empty files.
89
- - **probe** — you challenge: flaws, edge cases, conflicts with the tech fragment or domain
90
- fragment. Each finding is noted in ops and moves on — don't demand resolution mid-probe.
91
- - **blindspot** — hunt unknown unknowns. This move is dispatched, not conversed: you co-built
92
- the frame, so the outside view is structurally the twin's — dispatch it (gate: on demand,
93
- scope: blindspot) to cold-read the whole surface against the thesis's stated goal. Candidates
94
- die at the twin's quality gate (grounded in this folder, material to the design, new,
95
- answerable) so the user never over-replies to noise; at most five survivors arrive, each
96
- already filed as a fork. Relay them in prose — finding → why it's material here → what
97
- answering it would change — never as a question barrage: the user engages what matters and
98
- converge burns the rest down later. Don't wait to be asked — a user-only trigger makes
99
- coverage depend on the user remembering to ask: self-initiate a pass occasionally, at the
100
- moments the frame settles (an aspect closes, a converge burst lands, the thesis materially
101
- recomposes), by widening a reconcile dispatch's scope. Self-initiation needs no offer — it
102
- seizes nothing; survivors land as forks either way, and zero survivors is one relay line,
103
- never manufactured findings.
104
- - **converge** — burn forks down to commitments or explicit parks. `AskUserQuestion` for picks.
105
- Each resolution carries Why + How to apply (the twin files it; you capture it).
106
-
107
- ## Twin dispatches — the gates
108
-
109
- Dispatch at: **start** (bootstrap), **on demand** (below), **pause**, **stop**. One dispatch in
110
- flight at a time. For every dispatch *you* write the dispatch line to `ops/sync-log.md`
111
- (`S# | gate: <g> | dispatched: <ts> | scope: <s>`) — the twin appends the result; the pairing is
112
- how reconciliation stays observable instead of asserted. Relay the twin's one-line report at the
113
- next turn break ("4 edits · 2 new forks · 6 open · untouched: risks") — the only ambient
114
- convergence pressure this skill applies — plus what the recompose changed, so a rewrite of the
115
- user's thinking is never silent. A `failed` result: tell the user plainly and re-dispatch at the
116
- next gate.
117
-
118
- **On demand** means: the user asks ("let me read", "sync up", "what's open?"), or you judge the
119
- capture has accumulated enough that the surface has fallen meaningfully behind. **"Let me read"**
120
- is a recognized pause act: dispatch a compose (say honestly that it takes a couple of minutes),
121
- then point them at `thesis.md` — mandated shape, claim → argument → what changed, stamped — and
122
- pick the conversation back up when they return. Reading one's own thinking mid-session is a
123
- designed-for act, not an interruption.
124
-
125
- ## Re-entry — resume, or context loss
126
-
127
- Re-entry is a read, not a reconstruction: re-read this skill's hub, `state.md` (posture line
128
- first), and the tail of `ops/capture.md`; then dispatch the twin (gate: on demand) for a
129
- re-brief + freshness audit. This covers three triggers identically: resuming a parked session,
130
- a new sitting, and **loss of conversational context mid-session (compaction)** — if you find
131
- yourself mid-session without memory of it, this is the procedure; the folder was built so that
132
- nothing you "remembered" matters. While a session folder exists, read `state.md` at the start of
133
- every turn.
134
-
135
- ## `stop` — the fixed pipeline
136
-
137
- Read `references/harvest.md` first. The pipeline always runs — a stop *is* convergence plus
138
- harvest; you orchestrate, the twin executes each leg:
139
-
140
- 1. **Converge** — every open fork resolved now or explicitly parked with a destination
141
- (mini-converge in conversation; the scope-guard trio in `harvest.md` disambiguates parks).
142
- If no blindspot round has run this session, offer one first (one offer, never seized) — an
143
- unknown unknown found after commitments freeze is the expensive kind.
144
- 2. **Final sync + manifest** — dispatch the twin (gate: stop). It builds the manifest only when
145
- the detector's manifest gate is clean; relay anything blocking.
146
- 3. **One approval** — present the manifest via `AskUserQuestion`. Gap rounds later re-enter here:
147
- every write to canonical docs is user-approved, no exceptions.
148
- 4. **Apply → uselessness test → move** — the twin's legs; relay results. Harvest fails loud:
149
- a partial apply leaves the folder visibly unfinished in `docs/research/` and the user restarts
150
- the stop — never resume silently.
151
- 5. **The offer** — after the move to `docs/history/brainstorms/{topic}/`: **delete the folder, or
152
- commit it** — the user decides; the design assumes deletion. Relay via `AskUserQuestion`.
153
-
154
- ## Conduct — holds for the whole session
155
-
156
- 1. **Speak plain English; codes live in files.** Name every item by what it is; append the code
157
- in parentheses only when traceability needs it ("…the timeout question (F2)"). Never lead
158
- with a bare `F3`/`D7`.
159
- 2. **No production code outside the session folder while open.** Illustrative snippets live in
160
- the folder. Asked for production code: offer a sketch inside the folder, or `/brainstorm stop`
161
- first.
162
- 3. **`AskUserQuestion` at exactly four sites:** the intake frame batch, interview batches,
163
- converge picks, and the stop approvals (manifest; delete-or-commit). Everywhere else, prose.
164
- 4. **Suggested, never seized.** Moves, abstractions, probes — one offer each; accept refusal
165
- without re-litigating. Exemption: a self-initiated blindspot dispatch — it takes no
166
- conversational control; its findings arrive as forks the user may simply ignore.
167
- 5. **Nothing lives only in the transcript.** Ops is the floor: if it isn't in the folder or in
168
- ops, it doesn't exist. Flaws, gaps, and contradictions surface to the twin as capture — the
169
- twin turns them into forks; forks are the only convergence currency.
170
- 6. **The user decides when to converge and when to stop.** Distance-to-coherent is visible in
171
- every relayed twin report; you never say "let's decide now."
172
- 7. **Only `/brainstorm start` and `/brainstorm stop` enter or leave a session.** No
173
- auto-invocation, ever.
@@ -1,98 +0,0 @@
1
- # Doctrine — the epistemic core
2
-
3
- Load when: composing or auditing any working-surface file; deciding what a turn's substance *is*
4
- (a force, a fork, a commitment); judging whether a record is complete enough to harvest.
5
-
6
- The session's product is a defensible design position. Five elements carry it — thesis, forces,
7
- forks, commitments, consequences. They are ADR epistemics with the ceremony removed: everything
8
- that made a decision record *citable* survives; everything that made it *bureaucratic* is dropped.
9
-
10
- ## The five elements
11
-
12
- **Thesis** — the claim under construction. One composed document (`thesis.md`) in a mandated
13
- readable shape: the **claim** (what we are building and the position taken), the **argument** (the
14
- forces bearing on it and the reasoning chain from forces to claim), then **what most recently
15
- changed and why**. Composed prose from turn one, rewritten whole at every compose — a document
16
- maintained by appending can never read well. Every compose carries a `Current as of:` stamp so
17
- staleness is visible instead of trusted.
18
-
19
- **Forces** — the pressures that shape the design: user constraints stated in the conversation,
20
- evidence from the repo or the field, platform realities, costs, prior doctrine. Forces are not a
21
- file; they are the argument's raw material. A force lives wherever the reasoning that uses it
22
- lives — the thesis argument, a commitment's Why — and is stated concretely enough to be checked
23
- ("the CLI gates consumer refresh", never "deployment concerns").
24
-
25
- **Forks** — the open questions. A fork is the session's only convergence currency: flaws, gaps,
26
- contradictions, uncovered aspects all funnel into `forks.md` or they don't exist. Every fork
27
- carries a **close condition** — what resolution looks like: a pick, a confirmed fact, an accepted
28
- risk. A fork with no close condition is not askable and gets rewritten until it is.
29
-
30
- **Commitments** — the resolved calls, in `ledger.md`. Field set per entry:
31
-
32
- - **Decision** — the call, one sentence, present tense.
33
- - **Why** — the forces and reasoning that produced it. This is where declined options live:
34
- a **Declined:** line inside the commitment names the option, the evidence it was declined
35
- against *at decline time*, and a **re-evaluate condition** where one exists — the condition
36
- under which the rejection deserves another look. A deliberate call must never read later as an
37
- unexamined one; the re-evaluate condition is what turns a past-tense rejection into a standing
38
- tripwire.
39
- - **How to apply** — what acting on the decision looks like in this repo.
40
- - **Resolves** — the fork(s) this closes.
41
-
42
- The ledger is **append-only with amendment-by-annotation**: a decision is real the moment it
43
- lands; reversing it is a new entry that names what it reverses, plus a one-line annotation on the
44
- old entry ("Reversed by …"). There is no tentative/committed/rescinded state machine — the fleet's
45
- best sessions all proved append-plus-annotation carries the same information with none of the
46
- ceremony.
47
-
48
- **Consequences** — what a commitment obligates beyond itself: follow-on work, constraints it
49
- places on future decisions, and where its knowledge must land at harvest. Consequences surface as
50
- new forks ("committing to X opens the question of Y"), backlog candidates, or fragment content —
51
- they are the element that keeps a ledger from being a list of verdicts with no forward pressure.
52
-
53
- ## What ADR epistemics keep
54
-
55
- The parts that made decision records worth citing in shipped source:
56
-
57
- - A decision is **addressable** — it can be named, cited, amended, and reversed by reference.
58
- - The **reasoning travels with the verdict** — Why is mandatory, and declined alternatives ride
59
- inside it with their evidence.
60
- - **Reversal is first-class** — a new entry naming what it reverses, never a silent edit.
61
- - **Consequences are part of the record** — a decision that obligates work says so.
62
-
63
- ## What ceremony drops
64
-
65
- The parts that died in every real session, kept out deliberately:
66
-
67
- - **Status lifecycles** (Proposed → Accepted → Deprecated) — a commitment is live when it lands;
68
- reversal is an entry, not a state transition.
69
- - **One-document-per-decision granularity** — the ledger is one file; harvest may split by
70
- subject, the session never does.
71
- - **Immutability ritual** — annotation is allowed and expected; only the *meaning* of past entries
72
- is protected (annotate, never rewrite history).
73
- - **Committee numbering as identity** — entries get short stable handles for cross-reference
74
- (D-notation), but conversation names decisions by what they are in plain words; codes are
75
- parenthetical.
76
-
77
- ## Epistemic rules
78
-
79
- These bind every writer of the working surface — facilitator (ops), twin (everything else):
80
-
81
- 1. **Distilled, never verbatim.** Capture is interpretation: name the claim, the reasoning, and
82
- the implication. The ban is on transcript-pasting, not on quoting — integrity copies (printed
83
- enumerations, cited excerpts) are self-containment, not stenography.
84
- 2. **Examples are examples.** Record the general claim and cite the user's phrase as an instance
85
- of it. Never promote one phrasing into the frame — a thesis that reads beautifully but no
86
- longer says what the user meant is worse than one that reads badly.
87
- 3. **No naked pointers.** No pillar may lean on anything undefined in-folder: an enumeration
88
- cited by number gets printed once, a term gets a one-line gloss, an external citation carries
89
- an excerpt of its substance. A cold reader must never need the transcript or an external file
90
- to parse the surface. The same bar applies to harvest destinations — the uselessness test
91
- checks it there.
92
- 4. **Both sides are session knowledge.** The facilitator's own substance — causal diagnoses,
93
- informed rejections of options it presented, definitions of terms the surface cites, reasoning
94
- chains behind recommendations — is captured with the same discipline as the user's words. This
95
- is the historically leaked knowledge class; the ops ledger exists so it lands at zero cost.
96
- 5. **Directional steering is not feature truth.** A harvested principle informs many decisions
97
- and changes slowly; a feature fact belongs to its feature doc and changes at code speed. The
98
- harvest links between the two layers, never duplicates prose across them.
@@ -1,86 +0,0 @@
1
- # Harvest — the stop pipeline
2
-
3
- Load when: `/brainstorm stop` is invoked (facilitator), or executing any stop-gate dispatch
4
- (twin). The pipeline's mechanical gates live in the detector (`--gate=manifest`, `--gate=move`);
5
- this reference carries the routing judgment.
6
-
7
- The pipeline, end to end:
8
-
9
- ```
10
- converge → final sync/compose → manifest (Status: proposed)
11
- → ONE user approval (Status: approved)
12
- → apply, reading both sides of every destination (Status: applied)
13
- → uselessness test → gaps? new Round, back to approval
14
- → move to docs/history/brainstorms/{topic}/ ← the completion marker
15
- → offer: delete or commit — the user decides
16
- ```
17
-
18
- **Harvest fails loud, never silent.** The move happens only after the full apply passes the
19
- uselessness test. A partial apply — twin death, session kill, anything — leaves the folder
20
- visibly unfinished in `docs/research/` and the user restarts the stop. The pipeline never resumes
21
- silently from a half-applied state, and canonical docs are never written without an approved
22
- manifest (gap-round fixes included).
23
-
24
- ## The routing map
25
-
26
- Route each piece of the surface by scope. Format every artifact via the `documentation` skill;
27
- where it is unavailable, fall back to own formatting and record which path ran in the manifest.
28
- Read **both sides** of every destination before writing — the destination's current content is a
29
- contract, not a blank page.
30
-
31
- | What | Goes to | Shape |
32
- | --- | --- | --- |
33
- | **Source of truth** | The repo's canonical home for that knowledge: `docs/features/` for a feature, `docs/architecture/` for cross-cutting doctrine, else a topic `Readme.md` | One consolidated reader-first doc distilled from the whole surface: thesis → what it is; domain fragment → how it works; ledger → present-tense rationale **without entry codes** |
34
- | **Executable work** | `docs/history/plans/` | Split by deliverable, never by pillar |
35
- | **Decision records** | One record per decision *subject* | A decision revising an already-recorded subject updates that record in place (its changelog carries the journey) rather than minting a new one; declined alternatives ride along with their re-evaluate conditions |
36
- | **Domain-model changes** | The living domain-model doc | The information-architecture contract the `boundary` skill reads at the next plan check |
37
- | **Still-open (parked) forks** | The repo's open-questions home | Each with a *resolution-lands-in* pointer |
38
- | **Backlog items** | The repo backlog | See the scope-guard trio below |
39
- | **Fragments** | Their destinations — they were drafted in destination format precisely so this is a move, not a translation | Merge per the destination's existing structure |
40
-
41
- **The scope-guard trio** disambiguates everything that isn't a commitment:
42
-
43
- - *Will build later* → **backlog**.
44
- - *Deliberately not building* → **non-goals**.
45
- - *Weighed and chose another option* → a **Declined:** line inside the deciding ledger entry,
46
- with its evidence and re-evaluate condition — carried into the harvested decision record.
47
-
48
- **Directional steering is not feature truth.** A harvested principle informs many decisions and
49
- changes slowly; a feature fact belongs to its feature doc and changes at code speed. The harvest
50
- **links** between the steering layer and feature docs — it never duplicates prose across them,
51
- and it never invents a new top-level home for principles (they land in the *existing* living
52
- docs).
53
-
54
- Rejection rationale and reasoning chains must have explicit destinations — options-considered
55
- sections, decision changelogs — or the uselessness test fails: the folder may never be deleted
56
- into a knowledge loss.
57
-
58
- ## The uselessness test
59
-
60
- The deletion-safety gate: after the apply, the post-harvest living docs alone must be enough.
61
-
62
- - **The reader is always a freshly spawned, context-free agent** — a full-context reader cannot
63
- cold-read; it already knows every undefined term.
64
- - **Isolation is enforced, not instructed:** the cold reader's prompt contains an explicit
65
- allowed-path list (the manifest's destinations — never the session folder), and the detector
66
- independently verifies no harvested doc links back into the session folder (BS-HARVEST-01) — a
67
- link into scaffolding is itself a harvest defect.
68
- - **The task:** reconstruct the design — thesis, commitments, reasoning, declined branches — from
69
- the allowed paths only.
70
- - **Grading:** the twin diffs the reconstruction against the ledger and thesis and names every
71
- gap; the session-replay evals audit the grading itself. Anything unrecoverable is a named
72
- harvest gap → recorded in the manifest (`Result: fail`), fixes enter a new manifest `Round`,
73
- approved like the first. Iterate until the folder is redundant.
74
-
75
- ## The move, and the offer
76
-
77
- When the detector's move gate is clean: delete `ops/` entirely (transcript-grade residue never
78
- enters git), `git mv` the folder to `docs/history/brainstorms/{topic}/`, set
79
- `Status: harvested`, and update both indexes (row out of `docs/research/Readme.md`, row into
80
- `docs/history/brainstorms/Readme.md`). The move is the completion marker — a folder still under
81
- `docs/research/` is by definition unfinished, which is exactly what the maintenance census reads.
82
-
83
- Then the offer, relayed by the facilitator: **delete the moved folder, or commit it.** The user
84
- decides; the design assumes deletion — nothing anywhere may depend on the folder surviving.
85
- Committing is the explicit way to keep git-history forensics; an uncommitted folder deleted here
86
- is gone, and that residual is accepted by design.