@nurix/etna 0.19.66 → 0.19.68

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 (234) hide show
  1. package/bin/etna.js +10 -1
  2. package/data/harness-index.json +1 -5
  3. package/data/harnesses/code/CLAUDE.md +2 -0
  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/awareness.mjs +69 -0
  7. package/data/harnesses/code/hooks/compliance.mjs +2 -14
  8. package/data/harnesses/code/hooks/lib/approved.mjs +30 -0
  9. package/data/harnesses/code/hooks/lib/frozen.mjs +3 -0
  10. package/data/harnesses/code/hooks/lib/ownership.mjs +3 -1
  11. package/data/harnesses/code/skills/documentation/references/frontmatter.md +1 -1
  12. package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +1 -1
  13. package/data/harnesses/code/skills/documentation/templates/Readme.md +2 -0
  14. package/data/harnesses/code/skills/documentation/templates/structure.md +1 -0
  15. package/data/harnesses/delivery/agents/maintenance.md +4 -1
  16. package/data/harnesses/delivery/harness.json +2 -2
  17. package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +1 -1
  18. package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +1 -1
  19. package/data/harnesses/delivery/skills/documentation/templates/Readme.md +2 -0
  20. package/data/harnesses/delivery/skills/documentation/templates/structure.md +1 -0
  21. package/data/harnesses/etna/agents/maintenance.md +4 -1
  22. package/data/harnesses/etna/harness.json +2 -2
  23. package/data/harnesses/etna/skills/documentation/references/frontmatter.md +1 -1
  24. package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +1 -1
  25. package/data/harnesses/etna/skills/documentation/templates/Readme.md +2 -0
  26. package/data/harnesses/etna/skills/documentation/templates/structure.md +1 -0
  27. package/lib/install/materialize.mjs +51 -57
  28. package/package.json +2 -2
  29. package/data/harnesses/apollo/.mcp.json +0 -8
  30. package/data/harnesses/apollo/.prettierignore +0 -29
  31. package/data/harnesses/apollo/.prettierrc.json +0 -3
  32. package/data/harnesses/apollo/.vscode/settings.json +0 -19
  33. package/data/harnesses/apollo/CLAUDE.md +0 -162
  34. package/data/harnesses/apollo/agents/bookkeeper.md +0 -28
  35. package/data/harnesses/apollo/agents/brainstorm.md +0 -144
  36. package/data/harnesses/apollo/agents/change-review.md +0 -251
  37. package/data/harnesses/apollo/agents/lld-mode.md +0 -58
  38. package/data/harnesses/apollo/agents/maintenance.md +0 -234
  39. package/data/harnesses/apollo/agents/performance-review.md +0 -223
  40. package/data/harnesses/apollo/agents/retro.md +0 -46
  41. package/data/harnesses/apollo/codex/agents/bookkeeper.toml +0 -26
  42. package/data/harnesses/apollo/codex/agents/brainstorm.toml +0 -142
  43. package/data/harnesses/apollo/codex/agents/change-review.toml +0 -249
  44. package/data/harnesses/apollo/codex/agents/lld-mode.toml +0 -52
  45. package/data/harnesses/apollo/codex/agents/maintenance.toml +0 -228
  46. package/data/harnesses/apollo/codex/agents/performance-review.toml +0 -222
  47. package/data/harnesses/apollo/codex/agents/retro.toml +0 -45
  48. package/data/harnesses/apollo/harness.json +0 -19
  49. package/data/harnesses/apollo/hooks/approved-packages.md +0 -44
  50. package/data/harnesses/apollo/hooks/awareness.mjs +0 -405
  51. package/data/harnesses/apollo/hooks/check-bookkeeping-clean.mjs +0 -19
  52. package/data/harnesses/apollo/hooks/check-changelog-presence.mjs +0 -57
  53. package/data/harnesses/apollo/hooks/check-completion-integrity.mjs +0 -71
  54. package/data/harnesses/apollo/hooks/check-ownership.mjs +0 -22
  55. package/data/harnesses/apollo/hooks/compliance.mjs +0 -457
  56. package/data/harnesses/apollo/hooks/hooks.json +0 -23
  57. package/data/harnesses/apollo/hooks/lib/frozen.mjs +0 -58
  58. package/data/harnesses/apollo/hooks/lib/ownership.mjs +0 -242
  59. package/data/harnesses/apollo/hooks/lib/state.mjs +0 -170
  60. package/data/harnesses/apollo/rules/changelog.md +0 -27
  61. package/data/harnesses/apollo/rules/database.md +0 -34
  62. package/data/harnesses/apollo/rules/frontend.md +0 -30
  63. package/data/harnesses/apollo/rules/general.md +0 -40
  64. package/data/harnesses/apollo/rules/nomenclature.md +0 -30
  65. package/data/harnesses/apollo/rules/pnpm.md +0 -57
  66. package/data/harnesses/apollo/rules/testing.md +0 -64
  67. package/data/harnesses/apollo/skills/boundary/SKILL.md +0 -75
  68. package/data/harnesses/apollo/skills/boundary/references/index.md +0 -16
  69. package/data/harnesses/apollo/skills/boundary/references/mechanisms.md +0 -99
  70. package/data/harnesses/apollo/skills/boundary/references/packs/async-messaging.md +0 -81
  71. package/data/harnesses/apollo/skills/boundary/references/packs/auth.md +0 -93
  72. package/data/harnesses/apollo/skills/boundary/references/packs/build-config-runtime.md +0 -93
  73. package/data/harnesses/apollo/skills/boundary/references/packs/cloudflare.md +0 -93
  74. package/data/harnesses/apollo/skills/boundary/references/packs/frontend.md +0 -93
  75. package/data/harnesses/apollo/skills/boundary/references/packs/generic-tail.md +0 -55
  76. package/data/harnesses/apollo/skills/boundary/references/packs/persistence.md +0 -93
  77. package/data/harnesses/apollo/skills/boundary/references/packs/wire-api.md +0 -87
  78. package/data/harnesses/apollo/skills/brainstorm/README.md +0 -56
  79. package/data/harnesses/apollo/skills/brainstorm/SKILL.md +0 -173
  80. package/data/harnesses/apollo/skills/brainstorm/references/doctrine.md +0 -98
  81. package/data/harnesses/apollo/skills/brainstorm/references/harvest.md +0 -86
  82. package/data/harnesses/apollo/skills/brainstorm/references/session-schema.md +0 -186
  83. package/data/harnesses/apollo/skills/brainstorm/scripts/detector.mjs +0 -460
  84. package/data/harnesses/apollo/skills/design/SKILL.md +0 -121
  85. package/data/harnesses/apollo/skills/design/components/charts.md +0 -76
  86. package/data/harnesses/apollo/skills/design/components/collections.md +0 -132
  87. package/data/harnesses/apollo/skills/design/components/feedback.md +0 -47
  88. package/data/harnesses/apollo/skills/design/components/hooks.md +0 -35
  89. package/data/harnesses/apollo/skills/design/components/index.md +0 -143
  90. package/data/harnesses/apollo/skills/design/components/inputs.md +0 -327
  91. package/data/harnesses/apollo/skills/design/components/layout.md +0 -52
  92. package/data/harnesses/apollo/skills/design/components/media.md +0 -66
  93. package/data/harnesses/apollo/skills/design/components/motion.md +0 -82
  94. package/data/harnesses/apollo/skills/design/components/navigation.md +0 -29
  95. package/data/harnesses/apollo/skills/design/components/overlays.md +0 -72
  96. package/data/harnesses/apollo/skills/design/components/setup.md +0 -40
  97. package/data/harnesses/apollo/skills/design/components/typography.md +0 -46
  98. package/data/harnesses/apollo/skills/design/components/utils.md +0 -37
  99. package/data/harnesses/apollo/skills/design/data/blueprints/browse.md +0 -38
  100. package/data/harnesses/apollo/skills/design/data/blueprints/creation-flow.md +0 -38
  101. package/data/harnesses/apollo/skills/design/data/blueprints/dashboard.md +0 -38
  102. package/data/harnesses/apollo/skills/design/data/blueprints/grid.md +0 -38
  103. package/data/harnesses/apollo/skills/design/data/blueprints/queue.md +0 -38
  104. package/data/harnesses/apollo/skills/design/data/blueprints/record-detail.md +0 -38
  105. package/data/harnesses/apollo/skills/design/data/blueprints/settings.md +0 -38
  106. package/data/harnesses/apollo/skills/design/data/charts/census.csv +0 -58
  107. package/data/harnesses/apollo/skills/design/data/checklists/browse.md +0 -21
  108. package/data/harnesses/apollo/skills/design/data/checklists/creation-flow.md +0 -20
  109. package/data/harnesses/apollo/skills/design/data/checklists/dashboard.md +0 -21
  110. package/data/harnesses/apollo/skills/design/data/checklists/grid.md +0 -21
  111. package/data/harnesses/apollo/skills/design/data/checklists/queue.md +0 -21
  112. package/data/harnesses/apollo/skills/design/data/checklists/record-detail.md +0 -21
  113. package/data/harnesses/apollo/skills/design/data/checklists/settings.md +0 -21
  114. package/data/harnesses/apollo/skills/design/data/chrome/board-column.md +0 -68
  115. package/data/harnesses/apollo/skills/design/data/chrome/data-table.md +0 -63
  116. package/data/harnesses/apollo/skills/design/data/chrome/side-panel.md +0 -60
  117. package/data/harnesses/apollo/skills/design/data/chrome/sidebar.md +0 -78
  118. package/data/harnesses/apollo/skills/design/data/chrome/stat-cards.md +0 -62
  119. package/data/harnesses/apollo/skills/design/data/chrome/topbar.md +0 -65
  120. package/data/harnesses/apollo/skills/design/data/elevation/ant-design-directional-shadow.md +0 -19
  121. package/data/harnesses/apollo/skills/design/data/elevation/apple-liquid-glass-material.md +0 -18
  122. package/data/harnesses/apollo/skills/design/data/elevation/atlassian-surface-shadow-pairing.md +0 -20
  123. package/data/harnesses/apollo/skills/design/data/elevation/fluent-2-key-ambient-ramp.md +0 -20
  124. package/data/harnesses/apollo/skills/design/data/elevation/github-primer-sparing-shadow.md +0 -19
  125. package/data/harnesses/apollo/skills/design/data/elevation/ibm-carbon-layer-and-border.md +0 -19
  126. package/data/harnesses/apollo/skills/design/data/elevation/linear-dark-surface-ladder.md +0 -17
  127. package/data/harnesses/apollo/skills/design/data/elevation/material-2-key-ambient-dp-ramp.md +0 -19
  128. package/data/harnesses/apollo/skills/design/data/elevation/material-3-tonal-elevation.md +0 -21
  129. package/data/harnesses/apollo/skills/design/data/elevation/neobrutalist-hard-offset.md +0 -19
  130. package/data/harnesses/apollo/skills/design/data/elevation/neumorphic-soft-dual-shadow.md +0 -18
  131. package/data/harnesses/apollo/skills/design/data/elevation/notion-warm-minimal-hairline.md +0 -17
  132. package/data/harnesses/apollo/skills/design/data/elevation/polaris-elevation-inset-bevel.md +0 -21
  133. package/data/harnesses/apollo/skills/design/data/elevation/radix-themes-alpha-ring-scale.md +0 -19
  134. package/data/harnesses/apollo/skills/design/data/elevation/shadcn-neutral-derived-radius.md +0 -19
  135. package/data/harnesses/apollo/skills/design/data/elevation/stripe-brand-tinted-dual-shadow.md +0 -18
  136. package/data/harnesses/apollo/skills/design/data/elevation/tailwind-default-utility-scale.md +0 -19
  137. package/data/harnesses/apollo/skills/design/data/elevation/vercel-geist-shadow-as-border.md +0 -20
  138. package/data/harnesses/apollo/skills/design/data/iconography.md +0 -199
  139. package/data/harnesses/apollo/skills/design/data/motion/accordion-expand.md +0 -18
  140. package/data/harnesses/apollo/skills/design/data/motion/destructive-hold-confirm.md +0 -18
  141. package/data/harnesses/apollo/skills/design/data/motion/drag-dismiss-momentum.md +0 -18
  142. package/data/harnesses/apollo/skills/design/data/motion/empty-state-arrive.md +0 -18
  143. package/data/harnesses/apollo/skills/design/data/motion/hover-lift.md +0 -18
  144. package/data/harnesses/apollo/skills/design/data/motion/modal-center-arrive.md +0 -18
  145. package/data/harnesses/apollo/skills/design/data/motion/number-ticker-roll.md +0 -18
  146. package/data/harnesses/apollo/skills/design/data/motion/onboarding-bounce.md +0 -18
  147. package/data/harnesses/apollo/skills/design/data/motion/panel-slide.md +0 -18
  148. package/data/harnesses/apollo/skills/design/data/motion/press-feedback.md +0 -18
  149. package/data/harnesses/apollo/skills/design/data/motion/progress-linear-loop.md +0 -18
  150. package/data/harnesses/apollo/skills/design/data/motion/route-crossfade.md +0 -18
  151. package/data/harnesses/apollo/skills/design/data/motion/rubber-band-overscroll.md +0 -18
  152. package/data/harnesses/apollo/skills/design/data/motion/skeleton-shimmer.md +0 -18
  153. package/data/harnesses/apollo/skills/design/data/motion/stagger-arrive.md +0 -18
  154. package/data/harnesses/apollo/skills/design/data/motion/toast-enter-stack.md +0 -18
  155. package/data/harnesses/apollo/skills/design/data/motion/tooltip-chain-instant.md +0 -18
  156. package/data/harnesses/apollo/skills/design/data/motion/trigger-anchored-reveal.md +0 -18
  157. package/data/harnesses/apollo/skills/design/data/tells.csv +0 -34
  158. package/data/harnesses/apollo/skills/design/data/voices/bright-collaborator.md +0 -29
  159. package/data/harnesses/apollo/skills/design/data/voices/direct-operator.md +0 -29
  160. package/data/harnesses/apollo/skills/design/data/voices/earnest-helper.md +0 -29
  161. package/data/harnesses/apollo/skills/design/data/voices/editorial-composed.md +0 -29
  162. package/data/harnesses/apollo/skills/design/data/voices/quiet-concierge.md +0 -29
  163. package/data/harnesses/apollo/skills/design/data/voices/warm-guide.md +0 -29
  164. package/data/harnesses/apollo/skills/design/references/compose.md +0 -23
  165. package/data/harnesses/apollo/skills/design/references/content.md +0 -28
  166. package/data/harnesses/apollo/skills/design/references/emission.md +0 -21
  167. package/data/harnesses/apollo/skills/design/references/existing-apps.md +0 -27
  168. package/data/harnesses/apollo/skills/design/references/foundations.md +0 -57
  169. package/data/harnesses/apollo/skills/design/references/intake.md +0 -40
  170. package/data/harnesses/apollo/skills/design/references/object-pass.md +0 -24
  171. package/data/harnesses/apollo/skills/design/references/ship-gate.md +0 -29
  172. package/data/harnesses/apollo/skills/design/references/ux-patterns/Readme.md +0 -195
  173. package/data/harnesses/apollo/skills/design/references/ux-patterns/ai-layer.md +0 -49
  174. package/data/harnesses/apollo/skills/design/references/ux-patterns/attributes-lifecycle.md +0 -43
  175. package/data/harnesses/apollo/skills/design/references/ux-patterns/container-choice.md +0 -44
  176. package/data/harnesses/apollo/skills/design/references/ux-patterns/creation-paths.md +0 -46
  177. package/data/harnesses/apollo/skills/design/references/ux-patterns/dashboards.md +0 -42
  178. package/data/harnesses/apollo/skills/design/references/ux-patterns/modes.md +0 -42
  179. package/data/harnesses/apollo/skills/design/references/ux-patterns/object-model.md +0 -46
  180. package/data/harnesses/apollo/skills/design/references/ux-patterns/page-archetype.md +0 -48
  181. package/data/harnesses/apollo/skills/design/references/ux-patterns/promotion-demotion.md +0 -37
  182. package/data/harnesses/apollo/skills/design/references/ux-patterns/settings.md +0 -42
  183. package/data/harnesses/apollo/skills/design/references/ux-patterns/standard-pages.md +0 -46
  184. package/data/harnesses/apollo/skills/design/references/ux-patterns/state-matrix.md +0 -41
  185. package/data/harnesses/apollo/skills/design/references/ux-patterns/table-mechanics.md +0 -48
  186. package/data/harnesses/apollo/skills/design/references/ux-patterns/verbs.md +0 -45
  187. package/data/harnesses/apollo/skills/design/references/ux-patterns/viewer-context.md +0 -40
  188. package/data/harnesses/apollo/skills/design/scripts/README-validator.md +0 -27
  189. package/data/harnesses/apollo/skills/design/scripts/select-chart.mjs +0 -622
  190. package/data/harnesses/apollo/skills/design/scripts/validate-design-md.mjs +0 -1198
  191. package/data/harnesses/apollo/skills/documentation/SKILL.md +0 -135
  192. package/data/harnesses/apollo/skills/documentation/references/examples.md +0 -279
  193. package/data/harnesses/apollo/skills/documentation/references/frontmatter.md +0 -44
  194. package/data/harnesses/apollo/skills/documentation/references/instruction-style.md +0 -50
  195. package/data/harnesses/apollo/skills/documentation/references/style-guide.md +0 -384
  196. package/data/harnesses/apollo/skills/documentation/references/untemplated.md +0 -38
  197. package/data/harnesses/apollo/skills/documentation/scripts/doc-lint.mjs +0 -140
  198. package/data/harnesses/apollo/skills/documentation/templates/Readme.md +0 -35
  199. package/data/harnesses/apollo/skills/documentation/templates/api-reference.md +0 -20
  200. package/data/harnesses/apollo/skills/documentation/templates/architecture-decision.md +0 -121
  201. package/data/harnesses/apollo/skills/documentation/templates/backlog.md +0 -33
  202. package/data/harnesses/apollo/skills/documentation/templates/behavioral-checklist.md +0 -81
  203. package/data/harnesses/apollo/skills/documentation/templates/bookkeeping.md +0 -18
  204. package/data/harnesses/apollo/skills/documentation/templates/changelog-entry.md +0 -57
  205. package/data/harnesses/apollo/skills/documentation/templates/changelog-index.md +0 -41
  206. package/data/harnesses/apollo/skills/documentation/templates/docs-readme.md +0 -72
  207. package/data/harnesses/apollo/skills/documentation/templates/domain-model.md +0 -30
  208. package/data/harnesses/apollo/skills/documentation/templates/environment-registry.md +0 -15
  209. package/data/harnesses/apollo/skills/documentation/templates/feature.md +0 -150
  210. package/data/harnesses/apollo/skills/documentation/templates/glossary.md +0 -11
  211. package/data/harnesses/apollo/skills/documentation/templates/implementation-map.md +0 -42
  212. package/data/harnesses/apollo/skills/documentation/templates/journal.md +0 -13
  213. package/data/harnesses/apollo/skills/documentation/templates/memory-main.md +0 -25
  214. package/data/harnesses/apollo/skills/documentation/templates/migration-runbook.md +0 -34
  215. package/data/harnesses/apollo/skills/documentation/templates/non-goals.md +0 -11
  216. package/data/harnesses/apollo/skills/documentation/templates/operations-procedure.md +0 -36
  217. package/data/harnesses/apollo/skills/documentation/templates/plan.md +0 -88
  218. package/data/harnesses/apollo/skills/documentation/templates/protected-files.md +0 -37
  219. package/data/harnesses/apollo/skills/documentation/templates/root-readme.md +0 -104
  220. package/data/harnesses/apollo/skills/documentation/templates/security-overview.md +0 -27
  221. package/data/harnesses/apollo/skills/documentation/templates/structure.md +0 -65
  222. package/data/harnesses/apollo/skills/documentation/templates/system-overview.md +0 -32
  223. package/data/harnesses/apollo/skills/documentation/templates/testing-strategy.md +0 -29
  224. package/data/harnesses/apollo/skills/schema-design/SKILL.md +0 -141
  225. package/data/harnesses/apollo/skills/test/SKILL.md +0 -104
  226. package/data/harnesses/apollo/skills/testing/SKILL.md +0 -166
  227. package/data/harnesses/apollo/skills/workflow-mapper/SKILL.md +0 -451
  228. package/data/harnesses/apollo/skills/workflow-mapper/references/patterns.md +0 -214
  229. /package/data/harnesses/{apollo → code}/docs/README.md +0 -0
  230. /package/data/harnesses/{apollo → code}/docs/history/CHANGELOG.md +0 -0
  231. /package/data/harnesses/{apollo → code}/docs/history/backlog.md +0 -0
  232. /package/data/harnesses/{apollo → code}/docs/memory/main.md +0 -0
  233. /package/data/harnesses/{apollo → code}/docs/structure.md +0 -0
  234. /package/data/harnesses/{apollo → code}/rules/cloudflare.md +0 -0
package/bin/etna.js CHANGED
@@ -232,7 +232,16 @@ async function main(args) {
232
232
  await sleep(2000);
233
233
  boot.stop('Ready');
234
234
 
235
- const harnessName = await resolveHarnessName(name, harnesses);
235
+ // Transition alias: the `apollo` harness merged into `code` (the code harness is pre-baked —
236
+ // it ships the docs scaffold as seeds and auto-baselines on first contact). Scripts and docs
237
+ // that pin the old name keep working through the alias; it retires after one window.
238
+ let requested = name;
239
+ if (requested === 'apollo' && !harnesses.apollo) {
240
+ p.log.info('`apollo` merged into `code` — installing `code` (the pre-baked harness).');
241
+ requested = 'code';
242
+ }
243
+
244
+ const harnessName = await resolveHarnessName(requested, harnesses);
236
245
  if (!harnessName) return; // user cancelled the interactive pick
237
246
 
238
247
  await installHarness(harnessName, harnesses);
@@ -1,10 +1,6 @@
1
1
  {
2
- "fingerprint": "774efa3ae2da",
2
+ "fingerprint": "d5b676c55c3a",
3
3
  "harnesses": {
4
- "apollo": {
5
- "plugin": "apollo",
6
- "description": "the pre-baked `code` harness, built for Apollo Studio exports"
7
- },
8
4
  "code": {
9
5
  "plugin": "code",
10
6
  "description": "the foundation every Nurix project starts with"
@@ -6,6 +6,8 @@ How AI coding agents — any vendor, any runtime — work on this project. Rules
6
6
 
7
7
  ## Maintenance
8
8
 
9
+ **Baseline first**: if `docs/structure.md` lacks a `harness-version` frontmatter marker, or it is behind the `version` in `.claude/harness.json`, dispatch the `maintenance` agent **as a sub-agent** before taking up the user's first ask — baseline is bulky mechanical work, and dispatching it keeps this context clean for the ask. Tell the user what it will do; on a repo with existing docs or `.bkp` files, name what the fold will touch. No dispatch mechanism ⇒ run it inline.
10
+
9
11
  Invoke the `maintenance` agent when a mechanical condition holds: `docs/structure.md` is missing (the repo isn't reconciled — baseline first), the `harness-version` marker is behind the installed version, a doc contradicts code being touched, or source paths are unowned — not on prose that merely looks stale. Structural reconciliation is never done by hand — the agent auto-selects its mode (baseline when the marker is missing or behind, coherence audit otherwise) and hands back; if it returns a follow-up (typically the module proposal), re-invoke it to finish. Single-glob or single-line doc corrections are done inline, per § Documentation. Each component's internals live in the component, not here.
10
12
 
11
13
  ---
@@ -51,7 +51,7 @@ The ownership source of truth is the **union of every feature doc's `owns:` fron
51
51
  ### Step 1: Build the ownership map
52
52
 
53
53
  1. Read `docs/structure.md` for the authority map.
54
- 2. Glob `docs/features/**/*.md`; for each, parse the frontmatter `owns:` globs and `module:` label.
54
+ 2. Glob `docs/features/**/*.md`, ignoring `*.bkp.*` files (installer backups awaiting the fold); for each, parse the frontmatter `owns:` globs and `module:` label.
55
55
  3. Build a map: glob → owning doc + module. Narrower glob wins on overlap. **This IS the source of truth.**
56
56
 
57
57
  **Architecture-first fallback.** If no feature doc carries `owns:` yet (a fresh-baseline repo can carry thousands of LOC and zero feature docs), drive this pass's ownership/drift surface off `docs/architecture/**` file-references instead — they become the **primary** ownership map for Steps 2–5. The `owns:` map becomes primary the moment any feature doc declares ownership — this is a fallback, not a replacement.
@@ -149,6 +149,7 @@ docs/
149
149
  │ ├── plans/ # Implementation plans (Status field required)
150
150
  │ ├── migrations/ # One-shot migration/upgrade runbooks (YYYY-MM-DD-{slug}.md; outcome-stamped then frozen)
151
151
  │ ├── journal.md # Append-only mid-execution knowledge capture (one line per fact; resolves by landing in its owning doc) — author-created, never scaffolded
152
+ │ ├── sessions/ # Per-session gate logs (YYYY-MM-DD-{sid}.md) — machinery-written records, never drained, never edited down; created by the first gate event, never scaffolded
152
153
  │ ├── brainstorms/ # Harvested brainstorm sessions ({topic}/) — user decides kept (committed) or deleted; Readme.md is the index
153
154
  │ ├── research/ # Deep-research records ({topic}/ — README.md synthesis + findings.md + sources.md); frozen, cited, owns no code
154
155
  │ └── backlog.md ✱ # Tracked work items by priority (P0-P3)
@@ -186,6 +187,8 @@ This is what makes baseline more than a fresh scaffold. Detect old-shape artifac
186
187
  | `docs/architecture/overview.md` | split into `domain-model.md` / `glossary.md` / `non-goals.md` / `references.md` / `open-questions.md` |
187
188
  | `docs/architecture/adr/` (legacy folder name), or `ADR-NNN-*.md` records anywhere under `docs/architecture/` | **rename to the AD genre.** The folder becomes `docs/architecture/decisions/`; each record file `ADR-NNN-{slug}.md` becomes `AD-NNN-{slug}.md`, keeping its number and slug. Inside each record, update the retired vocabulary — "ADR", "Architecture Decision Record", and any supersession framing ("once accepted, an ADR is never edited; a later ADR supersedes it") — to the AD model: one AD per subject, **updated in place**, its journey confined to a `Decision Changelog` tail. A record's **reasoning is never rewritten** by a reconcile; only its genre vocabulary, its own title/id, and paths it cites. The folder's `Readme.md` is an **index, not a record** — reframe its genre description while preserving authored content such as a candidate-decision list verbatim. Repoint live references **inside `docs/`**, including one AD citing another; leave frozen records' links as point-in-time. A live reference **outside** your write scope — most often the root `README.md`, which you never overwrite — cannot be repointed: record it as a backlog item naming the file and line rather than leaving the residue silent |
188
189
  | a legacy `docs/brainstorm/{topic}/`, a singular `docs/history/brainstorm/`, or a root `brainstorm/`/`brainstorming/` folder | move each **active** record to `docs/research/{topic}-brainstorm/` and each **harvested** one to `docs/history/brainstorms/{topic}/` (dropping the suffix); create/refresh both `Readme.md` indexes; delete the emptied folder |
190
+ | `*.bkp.*` files under `docs/` (the installer's first-contact backups of the project's pre-existing files) | **fold the content, then delete the backup.** Classify each backup's content by nature and land it in the current shape — a backed-up changelog's rows into `docs/history/CHANGELOG.md` and per-entry files, a backed-up structure/readme's real claims into the scaffolded truth doc, a backed-up feature doc's content merged into its sibling (or adopted whole if the sibling is a pristine seed). Content is folded, never discarded silently; what cannot be classified goes to the backlog with the backup kept. When the fold lands, delete the `.bkp` file |
191
+ | `*.bkp.*` files at the repo root or in config (`CLAUDE.bkp.md`, `.prettierrc.bkp.json`, …) | **never merge these.** Top-level config is harness-owned by design; list each one to the user as their call, and leave the file in place |
189
192
  | no `harness-version` in `structure.md` | stamp it (Step B4) |
190
193
 
191
194
  ### Step B3 — Present the reconcile plan, then execute
@@ -1,14 +1,19 @@
1
1
  {
2
2
  "harness": "code",
3
3
  "name": "code",
4
- "version": "3.7.3",
4
+ "version": "3.8.2",
5
5
  "files": [
6
6
  ".prettierignore",
7
7
  ".prettierrc.json",
8
8
  ".vscode/settings.json"
9
9
  ],
10
10
  "seeds": [
11
+ "docs/README.md",
12
+ "docs/structure.md",
13
+ "docs/history/CHANGELOG.md",
14
+ "docs/history/backlog.md",
15
+ "docs/memory/main.md",
11
16
  ".mcp.json"
12
17
  ],
13
- "digest": "5e3c8dcf55ff"
18
+ "digest": "2dcea7420200"
14
19
  }
@@ -30,6 +30,8 @@ import {
30
30
  stateDir,
31
31
  recordTouched,
32
32
  } from "./lib/state.mjs";
33
+ import { frozenStatus } from "./lib/frozen.mjs";
34
+ import { approvedPackages } from "./lib/approved.mjs";
33
35
 
34
36
  const today = () => new Date().toISOString().slice(0, 10);
35
37
 
@@ -360,6 +362,68 @@ function detectRenames(projectDir, command, meta, rows) {
360
362
  }
361
363
  }
362
364
 
365
+ // Working-tree paths git sees as changed or untracked — the outcome detector's ground truth.
366
+ // Fails open: no git, or a git error, reads as an empty list.
367
+ function dirtyPaths(projectDir) {
368
+ const res = spawnSync("git", ["status", "--porcelain"], { cwd: projectDir, encoding: "utf8", timeout: 5000 });
369
+ if (res.status !== 0) return [];
370
+ return (res.stdout || "")
371
+ .split("\n")
372
+ .filter(Boolean)
373
+ .map((line) => {
374
+ const p = line.slice(3);
375
+ return p.includes(" -> ") ? p.split(" -> ")[1] : p; // a rename reports both sides; the new path is the live one
376
+ })
377
+ .map((p) => p.replace(/^"|"$/g, ""));
378
+ }
379
+
380
+ // OUTCOME RECOMPUTATION — the gates deny wrong actions, but an action can be routed around by
381
+ // any tool that writes bytes (a manifest written by a script, a frozen record touched by sed).
382
+ // State cannot be routed around: recompute the two outcomes the gates guard and raise what
383
+ // changed as rows. Dedupe against the queue so a retry loop raises one row, not ten.
384
+ function detectOutcomes(projectDir, meta, rows) {
385
+ const existing = readQueue(projectDir);
386
+ const raised = (needle) => existing.some((r) => r.body.includes(needle)) || rows.some((r) => r.includes(needle));
387
+ for (const rel of dirtyPaths(projectDir)) {
388
+ if (rel.includes("node_modules/") || rel.includes(".bkp.")) continue;
389
+ if (path.posix.basename(rel) === "package.json") {
390
+ const approved = approvedPackages(projectDir);
391
+ if (approved.size === 0) continue; // no table installed — nothing to enforce
392
+ let manifest;
393
+ try {
394
+ manifest = JSON.parse(readSafe(path.join(projectDir, rel)));
395
+ } catch (e) {
396
+ continue;
397
+ }
398
+ const names = [...Object.keys(manifest.dependencies || {}), ...Object.keys(manifest.devDependencies || {})];
399
+ for (const name of names) {
400
+ if (approved.has(name) || raised(`\`${name}\` (package-off-catalog`)) continue;
401
+ rows.push(
402
+ formatAutoRow({
403
+ ...meta,
404
+ kind: "package-off-catalog",
405
+ description: `${rel} declares \`${name}\` (package-off-catalog), absent from the approved table`,
406
+ action: "remove the dependency, or add it to .claude/hooks/approved-packages.md by explicit user decision",
407
+ })
408
+ );
409
+ }
410
+ }
411
+ if (rel.startsWith("docs/history/")) {
412
+ const frozen = frozenStatus(projectDir, rel);
413
+ if (frozen.frozen && !raised(`${rel} is a frozen record`)) {
414
+ rows.push(
415
+ formatAutoRow({
416
+ ...meta,
417
+ kind: "frozen-record-edited",
418
+ description: `${rel} is a frozen record and carries uncommitted modifications (${frozen.reason})`,
419
+ action: "revert the edit — a correction is a new dated entry that links back",
420
+ })
421
+ );
422
+ }
423
+ }
424
+ }
425
+ }
426
+
363
427
  function postToolUse(projectDir, payload) {
364
428
  const meta = {
365
429
  date: today(),
@@ -371,11 +435,16 @@ function postToolUse(projectDir, payload) {
371
435
  const rows = [];
372
436
  if (payload.tool_name === "Bash") {
373
437
  detectRenames(projectDir, input.command, meta, rows);
438
+ detectOutcomes(projectDir, meta, rows);
374
439
  } else {
375
440
  const rel = relIfInside(projectDir, input.file_path || input.notebook_path);
376
441
  if (rel) detectorForFile(projectDir, rel, meta, rows);
377
442
  // Editing a feature doc's frontmatter can orphan globs the same way a rename can.
378
443
  if (rel && rel.startsWith("docs/features/")) detectRenames(projectDir, "git mv", meta, rows);
444
+ // A manifest or history file written by a non-Bash tool is the same evasion surface.
445
+ if (rel && (path.posix.basename(rel) === "package.json" || rel.startsWith("docs/history/"))) {
446
+ detectOutcomes(projectDir, meta, rows);
447
+ }
379
448
  }
380
449
  appendRows(projectDir, rows);
381
450
  }
@@ -13,6 +13,7 @@ import { readQueue, countRows, askedThisSession, recordAsked } from "./lib/state
13
13
  import { frozenStatus } from "./lib/frozen.mjs";
14
14
  import { undischargedRows } from "./lib/ledger.mjs";
15
15
  import { appendEvent, unresolvedDenials, sessionLogPath } from "./lib/session-log.mjs";
16
+ import { approvedPackages } from "./lib/approved.mjs";
16
17
 
17
18
  function readSafe(file) {
18
19
  try {
@@ -192,6 +193,7 @@ function stagedExempt(files) {
192
193
  HARNESS_FILES.includes(f) ||
193
194
  f.startsWith("docs/history/changelog/") ||
194
195
  f.startsWith("docs/history/sessions/") ||
196
+ f.includes(".bkp.") ||
195
197
  f === "docs/history/CHANGELOG.md"
196
198
  );
197
199
  }
@@ -239,20 +241,6 @@ function commitGate(projectDir, sessionId) {
239
241
  return null;
240
242
  }
241
243
 
242
- // Package names approved in .claude/hooks/approved-packages.md (plus testing.md frameworks and general.md).
243
- function approvedPackages(projectDir) {
244
- const names = new Set();
245
- const sources = [
246
- path.join(projectDir, ".claude", "hooks", "approved-packages.md"),
247
- path.join(projectDir, ".claude", "rules", "general.md"),
248
- path.join(projectDir, ".claude", "rules", "testing.md"),
249
- ];
250
- for (const src of sources) {
251
- const text = readSafe(src);
252
- for (const m of text.matchAll(/`(@?[a-z0-9][\w./-]*)`/g)) names.add(m[1]);
253
- }
254
- return names;
255
- }
256
244
 
257
245
  // A token must parse as an npm package spec — name or @scope/name, optional @range tail —
258
246
  // before it may be judged against the table. Everything else on an install line (redirections
@@ -0,0 +1,30 @@
1
+ // harness/code/hooks/lib/approved.mjs — the approved-package set, one reader shared by the
2
+ // PreToolUse install gate (compliance) and the PostToolUse outcome detector (awareness), so
3
+ // "blocked at install" and "flagged in the manifest" can never disagree about the table.
4
+
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+
8
+ function readSafe(file) {
9
+ try {
10
+ return fs.readFileSync(file, "utf8");
11
+ } catch (e) {
12
+ return "";
13
+ }
14
+ }
15
+
16
+ // Package names approved in .claude/hooks/approved-packages.md (plus testing.md frameworks and
17
+ // general.md). Empty set ⇒ no rules installed ⇒ nothing to enforce.
18
+ export function approvedPackages(projectDir) {
19
+ const names = new Set();
20
+ const sources = [
21
+ path.join(projectDir, ".claude", "hooks", "approved-packages.md"),
22
+ path.join(projectDir, ".claude", "rules", "general.md"),
23
+ path.join(projectDir, ".claude", "rules", "testing.md"),
24
+ ];
25
+ for (const src of sources) {
26
+ const text = readSafe(src);
27
+ for (const m of text.matchAll(/`(@?[a-z0-9][\w./-]*)`/g)) names.add(m[1]);
28
+ }
29
+ return names;
30
+ }
@@ -29,6 +29,9 @@ function readSafe(projectDir, filePath) {
29
29
 
30
30
  // The predicate. Returns { frozen: boolean, reason?: string }.
31
31
  export function frozenStatus(projectDir, filePath) {
32
+ // *.bkp.* siblings are install-time backups, not records — the maintenance fold edits and
33
+ // deletes them, which a frozen verdict would forbid.
34
+ if (relPosix(projectDir, filePath).includes(".bkp.")) return { frozen: false };
32
35
  const rel = relPosix(projectDir, filePath);
33
36
  if (rel.startsWith("docs/history/changelog/") && rel.endsWith(".md")) {
34
37
  if (isCommitted(projectDir, rel)) {
@@ -117,7 +117,9 @@ export function asList(v) {
117
117
  // Shape: { doc (repo-relative, /-separated), owns[], module, keywords[], status }.
118
118
  export function scanFeatureDocs(projectDir) {
119
119
  const featuresDir = path.join(projectDir, "docs", "features");
120
- const files = listMarkdown(featuresDir);
120
+ // *.bkp.* files are install-time backups awaiting the maintenance fold — a backed-up feature
121
+ // doc still carries owns: frontmatter, and scanning it would double-own every path it names.
122
+ const files = listMarkdown(featuresDir).filter((f) => !f.includes(".bkp."));
121
123
  const docs = [];
122
124
  for (const file of files) {
123
125
  let text;
@@ -12,7 +12,7 @@ When creating or updating a feature doc, derive its **`owns:` frontmatter** —
12
12
 
13
13
  ## How to derive the frontmatter
14
14
 
15
- A feature doc's ownership frontmatter is `owns:` (required), `module:` (optional), `keywords:` (required), and `status:` (required). An optional `last-reviewed:` date (stamped whenever the doc is substantively reviewed or updated) gives the `maintenance` agent a staleness signal to rank its audits by — it is tooling metadata, never narrated in the body. `type:` (required — the genre, enum = the template names) and `rev:` (generator-written generation stamp) are the same class: external tooling reads them, sessions **preserve them on edits** and never narrate or inject them. The `maintenance` agent stamps `type:` on docs that predate the key.
15
+ A feature doc's ownership frontmatter is `owns:` (required), `module:` (optional), `keywords:` (required), and `status:` (required). An optional `last-reviewed:` date (stamped whenever the doc is substantively reviewed or updated) gives the `maintenance` agent a staleness signal to rank its audits by — it is tooling metadata, never narrated in the body. `type:` (required — the genre, enum = the template names) and `rev:` (generator-written generation stamp) are the same class: external tooling reads them, sessions **preserve them on edits** and never narrate or inject them. The `maintenance` agent stamps `type:` on docs that predate the key. `slug:` completes the set on generated docs: the identity key, minted once at creation and never re-derived from a display name — in the repo the filename is the slug, and the `maintenance` agent re-aligns the two when they diverge.
16
16
 
17
17
  **1. `owns:`** (the path scope)
18
18
 
@@ -23,7 +23,7 @@ const RULES = [
23
23
  // Sections inside a truth doc where dated history is sanctioned (the two bridges).
24
24
  const BRIDGE_HEADINGS = /^#{1,4}\s+(decision changelog|health log)\b/i;
25
25
  // Instruction files and generated trees are a different genre — out of this linter's scope.
26
- const SKIP = /(^|\/)(\.claude|node_modules|skills|rules|agents|harness|packages\/[^/]+\/data)\/|(^|\/)(CLAUDE|AGENTS)\.md$/;
26
+ const SKIP = /(^|\/)(\.claude|node_modules|skills|rules|agents|harness|packages\/[^/]+\/data)\/|(^|\/)(CLAUDE|AGENTS)\.md$|\.bkp\./;
27
27
  const RECORD = /(^|\/)docs\/(history|research|memory)\//;
28
28
 
29
29
  // Classify a path: skipped genre, record, or truth.
@@ -30,6 +30,8 @@ One file per template. Every template is either a **truth document** (states cur
30
30
  | Backlog | [backlog.md](backlog.md) | Record (append-only) |
31
31
  | Memory (main agent) | [memory-main.md](memory-main.md) | Record (append-only ledger) |
32
32
 
33
+ **The `type:` enum lives here.** A doc's `type:` frontmatter takes its value from this table — one genre per template (`feature`, `architecture-decision`, `non-goals`, …). External generators consume this list rather than defining their own; a type this table does not name defaults to `docs/architecture/` placement and is never added to the protected-files list.
34
+
33
35
  **Baseline scaffolds** — files that must exist after every baseline; the `maintenance` agent (baseline mode) creates any that are missing: [docs-readme.md](docs-readme.md), [structure.md](structure.md), [changelog-index.md](changelog-index.md), [backlog.md](backlog.md), [memory-main.md](memory-main.md), and [root-readme.md](root-readme.md) (never overwriting an existing root README).
34
36
 
35
37
  **Ownership.** A feature doc is the canonical reference for the code paths in its **`owns:` frontmatter** — the only ownership key. To find what a doc owns, read its `owns:` globs; to find the doc for a path, match the path against the injected ownership index (the union of every feature's `owns:` globs), narrower glob wins. See [`../references/frontmatter.md`](../references/frontmatter.md) for turning code into `owns:` globs.
@@ -31,6 +31,7 @@ Each topic has one canonical location. Read from here, not from plans or changel
31
31
  | Historical plans | `docs/history/plans/` | YYYY-MM-DD-name.md |
32
32
  | Change records | `docs/history/changelog/` | `YYYY-MM-DD-{three-words}.md` — one per unit of work, written at commit time |
33
33
  | Migration runbooks | `docs/history/migrations/` | YYYY-MM-DD-name.md |
34
+ | Session gate logs | `docs/history/sessions/` | `YYYY-MM-DD-{sid}.md` — machinery-written; denials and their resolutions, appended, never edited down |
34
35
  | Deep-research artifacts | `docs/history/research/{topic}/` | README.md + findings.md + sources.md |
35
36
  | Brainstorm design records | `docs/research/{topic}-brainstorm/` (active; legacy `-brainstorming/`) → `docs/history/brainstorms/{topic}/` (harvested; user deletes or commits) | thesis.md + forks.md + ledger.md + state.md |
36
37
  | Backlog | `docs/history/` | backlog.md |
@@ -51,7 +51,7 @@ The ownership source of truth is the **union of every feature doc's `owns:` fron
51
51
  ### Step 1: Build the ownership map
52
52
 
53
53
  1. Read `docs/structure.md` for the authority map.
54
- 2. Glob `docs/features/**/*.md`; for each, parse the frontmatter `owns:` globs and `module:` label.
54
+ 2. Glob `docs/features/**/*.md`, ignoring `*.bkp.*` files (installer backups awaiting the fold); for each, parse the frontmatter `owns:` globs and `module:` label.
55
55
  3. Build a map: glob → owning doc + module. Narrower glob wins on overlap. **This IS the source of truth.**
56
56
 
57
57
  **Architecture-first fallback.** If no feature doc carries `owns:` yet (a fresh-baseline repo can carry thousands of LOC and zero feature docs), drive this pass's ownership/drift surface off `docs/architecture/**` file-references instead — they become the **primary** ownership map for Steps 2–5. The `owns:` map becomes primary the moment any feature doc declares ownership — this is a fallback, not a replacement.
@@ -149,6 +149,7 @@ docs/
149
149
  │ ├── plans/ # Implementation plans (Status field required)
150
150
  │ ├── migrations/ # One-shot migration/upgrade runbooks (YYYY-MM-DD-{slug}.md; outcome-stamped then frozen)
151
151
  │ ├── journal.md # Append-only mid-execution knowledge capture (one line per fact; resolves by landing in its owning doc) — author-created, never scaffolded
152
+ │ ├── sessions/ # Per-session gate logs (YYYY-MM-DD-{sid}.md) — machinery-written records, never drained, never edited down; created by the first gate event, never scaffolded
152
153
  │ ├── brainstorms/ # Harvested brainstorm sessions ({topic}/) — user decides kept (committed) or deleted; Readme.md is the index
153
154
  │ ├── research/ # Deep-research records ({topic}/ — README.md synthesis + findings.md + sources.md); frozen, cited, owns no code
154
155
  │ └── backlog.md ✱ # Tracked work items by priority (P0-P3)
@@ -186,6 +187,8 @@ This is what makes baseline more than a fresh scaffold. Detect old-shape artifac
186
187
  | `docs/architecture/overview.md` | split into `domain-model.md` / `glossary.md` / `non-goals.md` / `references.md` / `open-questions.md` |
187
188
  | `docs/architecture/adr/` (legacy folder name), or `ADR-NNN-*.md` records anywhere under `docs/architecture/` | **rename to the AD genre.** The folder becomes `docs/architecture/decisions/`; each record file `ADR-NNN-{slug}.md` becomes `AD-NNN-{slug}.md`, keeping its number and slug. Inside each record, update the retired vocabulary — "ADR", "Architecture Decision Record", and any supersession framing ("once accepted, an ADR is never edited; a later ADR supersedes it") — to the AD model: one AD per subject, **updated in place**, its journey confined to a `Decision Changelog` tail. A record's **reasoning is never rewritten** by a reconcile; only its genre vocabulary, its own title/id, and paths it cites. The folder's `Readme.md` is an **index, not a record** — reframe its genre description while preserving authored content such as a candidate-decision list verbatim. Repoint live references **inside `docs/`**, including one AD citing another; leave frozen records' links as point-in-time. A live reference **outside** your write scope — most often the root `README.md`, which you never overwrite — cannot be repointed: record it as a backlog item naming the file and line rather than leaving the residue silent |
188
189
  | a legacy `docs/brainstorm/{topic}/`, a singular `docs/history/brainstorm/`, or a root `brainstorm/`/`brainstorming/` folder | move each **active** record to `docs/research/{topic}-brainstorm/` and each **harvested** one to `docs/history/brainstorms/{topic}/` (dropping the suffix); create/refresh both `Readme.md` indexes; delete the emptied folder |
190
+ | `*.bkp.*` files under `docs/` (the installer's first-contact backups of the project's pre-existing files) | **fold the content, then delete the backup.** Classify each backup's content by nature and land it in the current shape — a backed-up changelog's rows into `docs/history/CHANGELOG.md` and per-entry files, a backed-up structure/readme's real claims into the scaffolded truth doc, a backed-up feature doc's content merged into its sibling (or adopted whole if the sibling is a pristine seed). Content is folded, never discarded silently; what cannot be classified goes to the backlog with the backup kept. When the fold lands, delete the `.bkp` file |
191
+ | `*.bkp.*` files at the repo root or in config (`CLAUDE.bkp.md`, `.prettierrc.bkp.json`, …) | **never merge these.** Top-level config is harness-owned by design; list each one to the user as their call, and leave the file in place |
189
192
  | no `harness-version` in `structure.md` | stamp it (Step B4) |
190
193
 
191
194
  ### Step B3 — Present the reconcile plan, then execute
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "harness": "delivery",
3
3
  "name": "delivery",
4
- "version": "0.2.4",
4
+ "version": "0.2.6",
5
5
  "files": [
6
6
  ".prettierignore",
7
7
  ".prettierrc.json",
8
8
  ".vscode/settings.json"
9
9
  ],
10
10
  "seeds": [],
11
- "digest": "5384fce602a8"
11
+ "digest": "5f761b31c27a"
12
12
  }
@@ -12,7 +12,7 @@ When creating or updating a feature doc, derive its **`owns:` frontmatter** —
12
12
 
13
13
  ## How to derive the frontmatter
14
14
 
15
- A feature doc's ownership frontmatter is `owns:` (required), `module:` (optional), `keywords:` (required), and `status:` (required). An optional `last-reviewed:` date (stamped whenever the doc is substantively reviewed or updated) gives the `maintenance` agent a staleness signal to rank its audits by — it is tooling metadata, never narrated in the body. `type:` (required — the genre, enum = the template names) and `rev:` (generator-written generation stamp) are the same class: external tooling reads them, sessions **preserve them on edits** and never narrate or inject them. The `maintenance` agent stamps `type:` on docs that predate the key.
15
+ A feature doc's ownership frontmatter is `owns:` (required), `module:` (optional), `keywords:` (required), and `status:` (required). An optional `last-reviewed:` date (stamped whenever the doc is substantively reviewed or updated) gives the `maintenance` agent a staleness signal to rank its audits by — it is tooling metadata, never narrated in the body. `type:` (required — the genre, enum = the template names) and `rev:` (generator-written generation stamp) are the same class: external tooling reads them, sessions **preserve them on edits** and never narrate or inject them. The `maintenance` agent stamps `type:` on docs that predate the key. `slug:` completes the set on generated docs: the identity key, minted once at creation and never re-derived from a display name — in the repo the filename is the slug, and the `maintenance` agent re-aligns the two when they diverge.
16
16
 
17
17
  **1. `owns:`** (the path scope)
18
18
 
@@ -23,7 +23,7 @@ const RULES = [
23
23
  // Sections inside a truth doc where dated history is sanctioned (the two bridges).
24
24
  const BRIDGE_HEADINGS = /^#{1,4}\s+(decision changelog|health log)\b/i;
25
25
  // Instruction files and generated trees are a different genre — out of this linter's scope.
26
- const SKIP = /(^|\/)(\.claude|node_modules|skills|rules|agents|harness|packages\/[^/]+\/data)\/|(^|\/)(CLAUDE|AGENTS)\.md$/;
26
+ const SKIP = /(^|\/)(\.claude|node_modules|skills|rules|agents|harness|packages\/[^/]+\/data)\/|(^|\/)(CLAUDE|AGENTS)\.md$|\.bkp\./;
27
27
  const RECORD = /(^|\/)docs\/(history|research|memory)\//;
28
28
 
29
29
  // Classify a path: skipped genre, record, or truth.
@@ -30,6 +30,8 @@ One file per template. Every template is either a **truth document** (states cur
30
30
  | Backlog | [backlog.md](backlog.md) | Record (append-only) |
31
31
  | Memory (main agent) | [memory-main.md](memory-main.md) | Record (append-only ledger) |
32
32
 
33
+ **The `type:` enum lives here.** A doc's `type:` frontmatter takes its value from this table — one genre per template (`feature`, `architecture-decision`, `non-goals`, …). External generators consume this list rather than defining their own; a type this table does not name defaults to `docs/architecture/` placement and is never added to the protected-files list.
34
+
33
35
  **Baseline scaffolds** — files that must exist after every baseline; the `maintenance` agent (baseline mode) creates any that are missing: [docs-readme.md](docs-readme.md), [structure.md](structure.md), [changelog-index.md](changelog-index.md), [backlog.md](backlog.md), [memory-main.md](memory-main.md), and [root-readme.md](root-readme.md) (never overwriting an existing root README).
34
36
 
35
37
  **Ownership.** A feature doc is the canonical reference for the code paths in its **`owns:` frontmatter** — the only ownership key. To find what a doc owns, read its `owns:` globs; to find the doc for a path, match the path against the injected ownership index (the union of every feature's `owns:` globs), narrower glob wins. See [`../references/frontmatter.md`](../references/frontmatter.md) for turning code into `owns:` globs.
@@ -31,6 +31,7 @@ Each topic has one canonical location. Read from here, not from plans or changel
31
31
  | Historical plans | `docs/history/plans/` | YYYY-MM-DD-name.md |
32
32
  | Change records | `docs/history/changelog/` | `YYYY-MM-DD-{three-words}.md` — one per unit of work, written at commit time |
33
33
  | Migration runbooks | `docs/history/migrations/` | YYYY-MM-DD-name.md |
34
+ | Session gate logs | `docs/history/sessions/` | `YYYY-MM-DD-{sid}.md` — machinery-written; denials and their resolutions, appended, never edited down |
34
35
  | Deep-research artifacts | `docs/history/research/{topic}/` | README.md + findings.md + sources.md |
35
36
  | Brainstorm design records | `docs/research/{topic}-brainstorm/` (active; legacy `-brainstorming/`) → `docs/history/brainstorms/{topic}/` (harvested; user deletes or commits) | thesis.md + forks.md + ledger.md + state.md |
36
37
  | Backlog | `docs/history/` | backlog.md |
@@ -51,7 +51,7 @@ The ownership source of truth is the **union of every feature doc's `owns:` fron
51
51
  ### Step 1: Build the ownership map
52
52
 
53
53
  1. Read `docs/structure.md` for the authority map.
54
- 2. Glob `docs/features/**/*.md`; for each, parse the frontmatter `owns:` globs and `module:` label.
54
+ 2. Glob `docs/features/**/*.md`, ignoring `*.bkp.*` files (installer backups awaiting the fold); for each, parse the frontmatter `owns:` globs and `module:` label.
55
55
  3. Build a map: glob → owning doc + module. Narrower glob wins on overlap. **This IS the source of truth.**
56
56
 
57
57
  **Architecture-first fallback.** If no feature doc carries `owns:` yet (a fresh-baseline repo can carry thousands of LOC and zero feature docs), drive this pass's ownership/drift surface off `docs/architecture/**` file-references instead — they become the **primary** ownership map for Steps 2–5. The `owns:` map becomes primary the moment any feature doc declares ownership — this is a fallback, not a replacement.
@@ -149,6 +149,7 @@ docs/
149
149
  │ ├── plans/ # Implementation plans (Status field required)
150
150
  │ ├── migrations/ # One-shot migration/upgrade runbooks (YYYY-MM-DD-{slug}.md; outcome-stamped then frozen)
151
151
  │ ├── journal.md # Append-only mid-execution knowledge capture (one line per fact; resolves by landing in its owning doc) — author-created, never scaffolded
152
+ │ ├── sessions/ # Per-session gate logs (YYYY-MM-DD-{sid}.md) — machinery-written records, never drained, never edited down; created by the first gate event, never scaffolded
152
153
  │ ├── brainstorms/ # Harvested brainstorm sessions ({topic}/) — user decides kept (committed) or deleted; Readme.md is the index
153
154
  │ ├── research/ # Deep-research records ({topic}/ — README.md synthesis + findings.md + sources.md); frozen, cited, owns no code
154
155
  │ └── backlog.md ✱ # Tracked work items by priority (P0-P3)
@@ -186,6 +187,8 @@ This is what makes baseline more than a fresh scaffold. Detect old-shape artifac
186
187
  | `docs/architecture/overview.md` | split into `domain-model.md` / `glossary.md` / `non-goals.md` / `references.md` / `open-questions.md` |
187
188
  | `docs/architecture/adr/` (legacy folder name), or `ADR-NNN-*.md` records anywhere under `docs/architecture/` | **rename to the AD genre.** The folder becomes `docs/architecture/decisions/`; each record file `ADR-NNN-{slug}.md` becomes `AD-NNN-{slug}.md`, keeping its number and slug. Inside each record, update the retired vocabulary — "ADR", "Architecture Decision Record", and any supersession framing ("once accepted, an ADR is never edited; a later ADR supersedes it") — to the AD model: one AD per subject, **updated in place**, its journey confined to a `Decision Changelog` tail. A record's **reasoning is never rewritten** by a reconcile; only its genre vocabulary, its own title/id, and paths it cites. The folder's `Readme.md` is an **index, not a record** — reframe its genre description while preserving authored content such as a candidate-decision list verbatim. Repoint live references **inside `docs/`**, including one AD citing another; leave frozen records' links as point-in-time. A live reference **outside** your write scope — most often the root `README.md`, which you never overwrite — cannot be repointed: record it as a backlog item naming the file and line rather than leaving the residue silent |
188
189
  | a legacy `docs/brainstorm/{topic}/`, a singular `docs/history/brainstorm/`, or a root `brainstorm/`/`brainstorming/` folder | move each **active** record to `docs/research/{topic}-brainstorm/` and each **harvested** one to `docs/history/brainstorms/{topic}/` (dropping the suffix); create/refresh both `Readme.md` indexes; delete the emptied folder |
190
+ | `*.bkp.*` files under `docs/` (the installer's first-contact backups of the project's pre-existing files) | **fold the content, then delete the backup.** Classify each backup's content by nature and land it in the current shape — a backed-up changelog's rows into `docs/history/CHANGELOG.md` and per-entry files, a backed-up structure/readme's real claims into the scaffolded truth doc, a backed-up feature doc's content merged into its sibling (or adopted whole if the sibling is a pristine seed). Content is folded, never discarded silently; what cannot be classified goes to the backlog with the backup kept. When the fold lands, delete the `.bkp` file |
191
+ | `*.bkp.*` files at the repo root or in config (`CLAUDE.bkp.md`, `.prettierrc.bkp.json`, …) | **never merge these.** Top-level config is harness-owned by design; list each one to the user as their call, and leave the file in place |
189
192
  | no `harness-version` in `structure.md` | stamp it (Step B4) |
190
193
 
191
194
  ### Step B3 — Present the reconcile plan, then execute
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "harness": "etna",
3
3
  "name": "etna",
4
- "version": "1.4.3",
4
+ "version": "1.4.5",
5
5
  "files": [
6
6
  ".prettierignore",
7
7
  ".prettierrc.json",
8
8
  ".vscode/settings.json"
9
9
  ],
10
10
  "seeds": [],
11
- "digest": "1c440d72ea9f"
11
+ "digest": "e0669fcb3dcf"
12
12
  }
@@ -12,7 +12,7 @@ When creating or updating a feature doc, derive its **`owns:` frontmatter** —
12
12
 
13
13
  ## How to derive the frontmatter
14
14
 
15
- A feature doc's ownership frontmatter is `owns:` (required), `module:` (optional), `keywords:` (required), and `status:` (required). An optional `last-reviewed:` date (stamped whenever the doc is substantively reviewed or updated) gives the `maintenance` agent a staleness signal to rank its audits by — it is tooling metadata, never narrated in the body. `type:` (required — the genre, enum = the template names) and `rev:` (generator-written generation stamp) are the same class: external tooling reads them, sessions **preserve them on edits** and never narrate or inject them. The `maintenance` agent stamps `type:` on docs that predate the key.
15
+ A feature doc's ownership frontmatter is `owns:` (required), `module:` (optional), `keywords:` (required), and `status:` (required). An optional `last-reviewed:` date (stamped whenever the doc is substantively reviewed or updated) gives the `maintenance` agent a staleness signal to rank its audits by — it is tooling metadata, never narrated in the body. `type:` (required — the genre, enum = the template names) and `rev:` (generator-written generation stamp) are the same class: external tooling reads them, sessions **preserve them on edits** and never narrate or inject them. The `maintenance` agent stamps `type:` on docs that predate the key. `slug:` completes the set on generated docs: the identity key, minted once at creation and never re-derived from a display name — in the repo the filename is the slug, and the `maintenance` agent re-aligns the two when they diverge.
16
16
 
17
17
  **1. `owns:`** (the path scope)
18
18
 
@@ -23,7 +23,7 @@ const RULES = [
23
23
  // Sections inside a truth doc where dated history is sanctioned (the two bridges).
24
24
  const BRIDGE_HEADINGS = /^#{1,4}\s+(decision changelog|health log)\b/i;
25
25
  // Instruction files and generated trees are a different genre — out of this linter's scope.
26
- const SKIP = /(^|\/)(\.claude|node_modules|skills|rules|agents|harness|packages\/[^/]+\/data)\/|(^|\/)(CLAUDE|AGENTS)\.md$/;
26
+ const SKIP = /(^|\/)(\.claude|node_modules|skills|rules|agents|harness|packages\/[^/]+\/data)\/|(^|\/)(CLAUDE|AGENTS)\.md$|\.bkp\./;
27
27
  const RECORD = /(^|\/)docs\/(history|research|memory)\//;
28
28
 
29
29
  // Classify a path: skipped genre, record, or truth.
@@ -30,6 +30,8 @@ One file per template. Every template is either a **truth document** (states cur
30
30
  | Backlog | [backlog.md](backlog.md) | Record (append-only) |
31
31
  | Memory (main agent) | [memory-main.md](memory-main.md) | Record (append-only ledger) |
32
32
 
33
+ **The `type:` enum lives here.** A doc's `type:` frontmatter takes its value from this table — one genre per template (`feature`, `architecture-decision`, `non-goals`, …). External generators consume this list rather than defining their own; a type this table does not name defaults to `docs/architecture/` placement and is never added to the protected-files list.
34
+
33
35
  **Baseline scaffolds** — files that must exist after every baseline; the `maintenance` agent (baseline mode) creates any that are missing: [docs-readme.md](docs-readme.md), [structure.md](structure.md), [changelog-index.md](changelog-index.md), [backlog.md](backlog.md), [memory-main.md](memory-main.md), and [root-readme.md](root-readme.md) (never overwriting an existing root README).
34
36
 
35
37
  **Ownership.** A feature doc is the canonical reference for the code paths in its **`owns:` frontmatter** — the only ownership key. To find what a doc owns, read its `owns:` globs; to find the doc for a path, match the path against the injected ownership index (the union of every feature's `owns:` globs), narrower glob wins. See [`../references/frontmatter.md`](../references/frontmatter.md) for turning code into `owns:` globs.
@@ -31,6 +31,7 @@ Each topic has one canonical location. Read from here, not from plans or changel
31
31
  | Historical plans | `docs/history/plans/` | YYYY-MM-DD-name.md |
32
32
  | Change records | `docs/history/changelog/` | `YYYY-MM-DD-{three-words}.md` — one per unit of work, written at commit time |
33
33
  | Migration runbooks | `docs/history/migrations/` | YYYY-MM-DD-name.md |
34
+ | Session gate logs | `docs/history/sessions/` | `YYYY-MM-DD-{sid}.md` — machinery-written; denials and their resolutions, appended, never edited down |
34
35
  | Deep-research artifacts | `docs/history/research/{topic}/` | README.md + findings.md + sources.md |
35
36
  | Brainstorm design records | `docs/research/{topic}-brainstorm/` (active; legacy `-brainstorming/`) → `docs/history/brainstorms/{topic}/` (harvested; user deletes or commits) | thesis.md + forks.md + ledger.md + state.md |
36
37
  | Backlog | `docs/history/` | backlog.md |