@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.
- package/bin/etna.js +10 -1
- package/data/harness-index.json +1 -5
- package/data/harnesses/code/CLAUDE.md +2 -0
- package/data/harnesses/code/agents/maintenance.md +4 -1
- package/data/harnesses/code/harness.json +7 -2
- package/data/harnesses/code/hooks/awareness.mjs +69 -0
- package/data/harnesses/code/hooks/compliance.mjs +2 -14
- package/data/harnesses/code/hooks/lib/approved.mjs +30 -0
- package/data/harnesses/code/hooks/lib/frozen.mjs +3 -0
- package/data/harnesses/code/hooks/lib/ownership.mjs +3 -1
- package/data/harnesses/code/skills/documentation/references/frontmatter.md +1 -1
- package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +1 -1
- package/data/harnesses/code/skills/documentation/templates/Readme.md +2 -0
- package/data/harnesses/code/skills/documentation/templates/structure.md +1 -0
- package/data/harnesses/delivery/agents/maintenance.md +4 -1
- package/data/harnesses/delivery/harness.json +2 -2
- package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +1 -1
- package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +1 -1
- package/data/harnesses/delivery/skills/documentation/templates/Readme.md +2 -0
- package/data/harnesses/delivery/skills/documentation/templates/structure.md +1 -0
- package/data/harnesses/etna/agents/maintenance.md +4 -1
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/skills/documentation/references/frontmatter.md +1 -1
- package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +1 -1
- package/data/harnesses/etna/skills/documentation/templates/Readme.md +2 -0
- package/data/harnesses/etna/skills/documentation/templates/structure.md +1 -0
- package/lib/install/materialize.mjs +51 -57
- package/package.json +2 -2
- package/data/harnesses/apollo/.mcp.json +0 -8
- package/data/harnesses/apollo/.prettierignore +0 -29
- package/data/harnesses/apollo/.prettierrc.json +0 -3
- package/data/harnesses/apollo/.vscode/settings.json +0 -19
- package/data/harnesses/apollo/CLAUDE.md +0 -162
- package/data/harnesses/apollo/agents/bookkeeper.md +0 -28
- package/data/harnesses/apollo/agents/brainstorm.md +0 -144
- package/data/harnesses/apollo/agents/change-review.md +0 -251
- package/data/harnesses/apollo/agents/lld-mode.md +0 -58
- package/data/harnesses/apollo/agents/maintenance.md +0 -234
- package/data/harnesses/apollo/agents/performance-review.md +0 -223
- package/data/harnesses/apollo/agents/retro.md +0 -46
- package/data/harnesses/apollo/codex/agents/bookkeeper.toml +0 -26
- package/data/harnesses/apollo/codex/agents/brainstorm.toml +0 -142
- package/data/harnesses/apollo/codex/agents/change-review.toml +0 -249
- package/data/harnesses/apollo/codex/agents/lld-mode.toml +0 -52
- package/data/harnesses/apollo/codex/agents/maintenance.toml +0 -228
- package/data/harnesses/apollo/codex/agents/performance-review.toml +0 -222
- package/data/harnesses/apollo/codex/agents/retro.toml +0 -45
- package/data/harnesses/apollo/harness.json +0 -19
- package/data/harnesses/apollo/hooks/approved-packages.md +0 -44
- package/data/harnesses/apollo/hooks/awareness.mjs +0 -405
- package/data/harnesses/apollo/hooks/check-bookkeeping-clean.mjs +0 -19
- package/data/harnesses/apollo/hooks/check-changelog-presence.mjs +0 -57
- package/data/harnesses/apollo/hooks/check-completion-integrity.mjs +0 -71
- package/data/harnesses/apollo/hooks/check-ownership.mjs +0 -22
- package/data/harnesses/apollo/hooks/compliance.mjs +0 -457
- package/data/harnesses/apollo/hooks/hooks.json +0 -23
- package/data/harnesses/apollo/hooks/lib/frozen.mjs +0 -58
- package/data/harnesses/apollo/hooks/lib/ownership.mjs +0 -242
- package/data/harnesses/apollo/hooks/lib/state.mjs +0 -170
- package/data/harnesses/apollo/rules/changelog.md +0 -27
- package/data/harnesses/apollo/rules/database.md +0 -34
- package/data/harnesses/apollo/rules/frontend.md +0 -30
- package/data/harnesses/apollo/rules/general.md +0 -40
- package/data/harnesses/apollo/rules/nomenclature.md +0 -30
- package/data/harnesses/apollo/rules/pnpm.md +0 -57
- package/data/harnesses/apollo/rules/testing.md +0 -64
- package/data/harnesses/apollo/skills/boundary/SKILL.md +0 -75
- package/data/harnesses/apollo/skills/boundary/references/index.md +0 -16
- package/data/harnesses/apollo/skills/boundary/references/mechanisms.md +0 -99
- package/data/harnesses/apollo/skills/boundary/references/packs/async-messaging.md +0 -81
- package/data/harnesses/apollo/skills/boundary/references/packs/auth.md +0 -93
- package/data/harnesses/apollo/skills/boundary/references/packs/build-config-runtime.md +0 -93
- package/data/harnesses/apollo/skills/boundary/references/packs/cloudflare.md +0 -93
- package/data/harnesses/apollo/skills/boundary/references/packs/frontend.md +0 -93
- package/data/harnesses/apollo/skills/boundary/references/packs/generic-tail.md +0 -55
- package/data/harnesses/apollo/skills/boundary/references/packs/persistence.md +0 -93
- package/data/harnesses/apollo/skills/boundary/references/packs/wire-api.md +0 -87
- package/data/harnesses/apollo/skills/brainstorm/README.md +0 -56
- package/data/harnesses/apollo/skills/brainstorm/SKILL.md +0 -173
- package/data/harnesses/apollo/skills/brainstorm/references/doctrine.md +0 -98
- package/data/harnesses/apollo/skills/brainstorm/references/harvest.md +0 -86
- package/data/harnesses/apollo/skills/brainstorm/references/session-schema.md +0 -186
- package/data/harnesses/apollo/skills/brainstorm/scripts/detector.mjs +0 -460
- package/data/harnesses/apollo/skills/design/SKILL.md +0 -121
- package/data/harnesses/apollo/skills/design/components/charts.md +0 -76
- package/data/harnesses/apollo/skills/design/components/collections.md +0 -132
- package/data/harnesses/apollo/skills/design/components/feedback.md +0 -47
- package/data/harnesses/apollo/skills/design/components/hooks.md +0 -35
- package/data/harnesses/apollo/skills/design/components/index.md +0 -143
- package/data/harnesses/apollo/skills/design/components/inputs.md +0 -327
- package/data/harnesses/apollo/skills/design/components/layout.md +0 -52
- package/data/harnesses/apollo/skills/design/components/media.md +0 -66
- package/data/harnesses/apollo/skills/design/components/motion.md +0 -82
- package/data/harnesses/apollo/skills/design/components/navigation.md +0 -29
- package/data/harnesses/apollo/skills/design/components/overlays.md +0 -72
- package/data/harnesses/apollo/skills/design/components/setup.md +0 -40
- package/data/harnesses/apollo/skills/design/components/typography.md +0 -46
- package/data/harnesses/apollo/skills/design/components/utils.md +0 -37
- package/data/harnesses/apollo/skills/design/data/blueprints/browse.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/creation-flow.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/dashboard.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/grid.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/queue.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/record-detail.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/settings.md +0 -38
- package/data/harnesses/apollo/skills/design/data/charts/census.csv +0 -58
- package/data/harnesses/apollo/skills/design/data/checklists/browse.md +0 -21
- package/data/harnesses/apollo/skills/design/data/checklists/creation-flow.md +0 -20
- package/data/harnesses/apollo/skills/design/data/checklists/dashboard.md +0 -21
- package/data/harnesses/apollo/skills/design/data/checklists/grid.md +0 -21
- package/data/harnesses/apollo/skills/design/data/checklists/queue.md +0 -21
- package/data/harnesses/apollo/skills/design/data/checklists/record-detail.md +0 -21
- package/data/harnesses/apollo/skills/design/data/checklists/settings.md +0 -21
- package/data/harnesses/apollo/skills/design/data/chrome/board-column.md +0 -68
- package/data/harnesses/apollo/skills/design/data/chrome/data-table.md +0 -63
- package/data/harnesses/apollo/skills/design/data/chrome/side-panel.md +0 -60
- package/data/harnesses/apollo/skills/design/data/chrome/sidebar.md +0 -78
- package/data/harnesses/apollo/skills/design/data/chrome/stat-cards.md +0 -62
- package/data/harnesses/apollo/skills/design/data/chrome/topbar.md +0 -65
- package/data/harnesses/apollo/skills/design/data/elevation/ant-design-directional-shadow.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/apple-liquid-glass-material.md +0 -18
- package/data/harnesses/apollo/skills/design/data/elevation/atlassian-surface-shadow-pairing.md +0 -20
- package/data/harnesses/apollo/skills/design/data/elevation/fluent-2-key-ambient-ramp.md +0 -20
- package/data/harnesses/apollo/skills/design/data/elevation/github-primer-sparing-shadow.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/ibm-carbon-layer-and-border.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/linear-dark-surface-ladder.md +0 -17
- package/data/harnesses/apollo/skills/design/data/elevation/material-2-key-ambient-dp-ramp.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/material-3-tonal-elevation.md +0 -21
- package/data/harnesses/apollo/skills/design/data/elevation/neobrutalist-hard-offset.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/neumorphic-soft-dual-shadow.md +0 -18
- package/data/harnesses/apollo/skills/design/data/elevation/notion-warm-minimal-hairline.md +0 -17
- package/data/harnesses/apollo/skills/design/data/elevation/polaris-elevation-inset-bevel.md +0 -21
- package/data/harnesses/apollo/skills/design/data/elevation/radix-themes-alpha-ring-scale.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/shadcn-neutral-derived-radius.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/stripe-brand-tinted-dual-shadow.md +0 -18
- package/data/harnesses/apollo/skills/design/data/elevation/tailwind-default-utility-scale.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/vercel-geist-shadow-as-border.md +0 -20
- package/data/harnesses/apollo/skills/design/data/iconography.md +0 -199
- package/data/harnesses/apollo/skills/design/data/motion/accordion-expand.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/destructive-hold-confirm.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/drag-dismiss-momentum.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/empty-state-arrive.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/hover-lift.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/modal-center-arrive.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/number-ticker-roll.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/onboarding-bounce.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/panel-slide.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/press-feedback.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/progress-linear-loop.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/route-crossfade.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/rubber-band-overscroll.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/skeleton-shimmer.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/stagger-arrive.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/toast-enter-stack.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/tooltip-chain-instant.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/trigger-anchored-reveal.md +0 -18
- package/data/harnesses/apollo/skills/design/data/tells.csv +0 -34
- package/data/harnesses/apollo/skills/design/data/voices/bright-collaborator.md +0 -29
- package/data/harnesses/apollo/skills/design/data/voices/direct-operator.md +0 -29
- package/data/harnesses/apollo/skills/design/data/voices/earnest-helper.md +0 -29
- package/data/harnesses/apollo/skills/design/data/voices/editorial-composed.md +0 -29
- package/data/harnesses/apollo/skills/design/data/voices/quiet-concierge.md +0 -29
- package/data/harnesses/apollo/skills/design/data/voices/warm-guide.md +0 -29
- package/data/harnesses/apollo/skills/design/references/compose.md +0 -23
- package/data/harnesses/apollo/skills/design/references/content.md +0 -28
- package/data/harnesses/apollo/skills/design/references/emission.md +0 -21
- package/data/harnesses/apollo/skills/design/references/existing-apps.md +0 -27
- package/data/harnesses/apollo/skills/design/references/foundations.md +0 -57
- package/data/harnesses/apollo/skills/design/references/intake.md +0 -40
- package/data/harnesses/apollo/skills/design/references/object-pass.md +0 -24
- package/data/harnesses/apollo/skills/design/references/ship-gate.md +0 -29
- package/data/harnesses/apollo/skills/design/references/ux-patterns/Readme.md +0 -195
- package/data/harnesses/apollo/skills/design/references/ux-patterns/ai-layer.md +0 -49
- package/data/harnesses/apollo/skills/design/references/ux-patterns/attributes-lifecycle.md +0 -43
- package/data/harnesses/apollo/skills/design/references/ux-patterns/container-choice.md +0 -44
- package/data/harnesses/apollo/skills/design/references/ux-patterns/creation-paths.md +0 -46
- package/data/harnesses/apollo/skills/design/references/ux-patterns/dashboards.md +0 -42
- package/data/harnesses/apollo/skills/design/references/ux-patterns/modes.md +0 -42
- package/data/harnesses/apollo/skills/design/references/ux-patterns/object-model.md +0 -46
- package/data/harnesses/apollo/skills/design/references/ux-patterns/page-archetype.md +0 -48
- package/data/harnesses/apollo/skills/design/references/ux-patterns/promotion-demotion.md +0 -37
- package/data/harnesses/apollo/skills/design/references/ux-patterns/settings.md +0 -42
- package/data/harnesses/apollo/skills/design/references/ux-patterns/standard-pages.md +0 -46
- package/data/harnesses/apollo/skills/design/references/ux-patterns/state-matrix.md +0 -41
- package/data/harnesses/apollo/skills/design/references/ux-patterns/table-mechanics.md +0 -48
- package/data/harnesses/apollo/skills/design/references/ux-patterns/verbs.md +0 -45
- package/data/harnesses/apollo/skills/design/references/ux-patterns/viewer-context.md +0 -40
- package/data/harnesses/apollo/skills/design/scripts/README-validator.md +0 -27
- package/data/harnesses/apollo/skills/design/scripts/select-chart.mjs +0 -622
- package/data/harnesses/apollo/skills/design/scripts/validate-design-md.mjs +0 -1198
- package/data/harnesses/apollo/skills/documentation/SKILL.md +0 -135
- package/data/harnesses/apollo/skills/documentation/references/examples.md +0 -279
- package/data/harnesses/apollo/skills/documentation/references/frontmatter.md +0 -44
- package/data/harnesses/apollo/skills/documentation/references/instruction-style.md +0 -50
- package/data/harnesses/apollo/skills/documentation/references/style-guide.md +0 -384
- package/data/harnesses/apollo/skills/documentation/references/untemplated.md +0 -38
- package/data/harnesses/apollo/skills/documentation/scripts/doc-lint.mjs +0 -140
- package/data/harnesses/apollo/skills/documentation/templates/Readme.md +0 -35
- package/data/harnesses/apollo/skills/documentation/templates/api-reference.md +0 -20
- package/data/harnesses/apollo/skills/documentation/templates/architecture-decision.md +0 -121
- package/data/harnesses/apollo/skills/documentation/templates/backlog.md +0 -33
- package/data/harnesses/apollo/skills/documentation/templates/behavioral-checklist.md +0 -81
- package/data/harnesses/apollo/skills/documentation/templates/bookkeeping.md +0 -18
- package/data/harnesses/apollo/skills/documentation/templates/changelog-entry.md +0 -57
- package/data/harnesses/apollo/skills/documentation/templates/changelog-index.md +0 -41
- package/data/harnesses/apollo/skills/documentation/templates/docs-readme.md +0 -72
- package/data/harnesses/apollo/skills/documentation/templates/domain-model.md +0 -30
- package/data/harnesses/apollo/skills/documentation/templates/environment-registry.md +0 -15
- package/data/harnesses/apollo/skills/documentation/templates/feature.md +0 -150
- package/data/harnesses/apollo/skills/documentation/templates/glossary.md +0 -11
- package/data/harnesses/apollo/skills/documentation/templates/implementation-map.md +0 -42
- package/data/harnesses/apollo/skills/documentation/templates/journal.md +0 -13
- package/data/harnesses/apollo/skills/documentation/templates/memory-main.md +0 -25
- package/data/harnesses/apollo/skills/documentation/templates/migration-runbook.md +0 -34
- package/data/harnesses/apollo/skills/documentation/templates/non-goals.md +0 -11
- package/data/harnesses/apollo/skills/documentation/templates/operations-procedure.md +0 -36
- package/data/harnesses/apollo/skills/documentation/templates/plan.md +0 -88
- package/data/harnesses/apollo/skills/documentation/templates/protected-files.md +0 -37
- package/data/harnesses/apollo/skills/documentation/templates/root-readme.md +0 -104
- package/data/harnesses/apollo/skills/documentation/templates/security-overview.md +0 -27
- package/data/harnesses/apollo/skills/documentation/templates/structure.md +0 -65
- package/data/harnesses/apollo/skills/documentation/templates/system-overview.md +0 -32
- package/data/harnesses/apollo/skills/documentation/templates/testing-strategy.md +0 -29
- package/data/harnesses/apollo/skills/schema-design/SKILL.md +0 -141
- package/data/harnesses/apollo/skills/test/SKILL.md +0 -104
- package/data/harnesses/apollo/skills/testing/SKILL.md +0 -166
- package/data/harnesses/apollo/skills/workflow-mapper/SKILL.md +0 -451
- package/data/harnesses/apollo/skills/workflow-mapper/references/patterns.md +0 -214
- /package/data/harnesses/{apollo → code}/docs/README.md +0 -0
- /package/data/harnesses/{apollo → code}/docs/history/CHANGELOG.md +0 -0
- /package/data/harnesses/{apollo → code}/docs/history/backlog.md +0 -0
- /package/data/harnesses/{apollo → code}/docs/memory/main.md +0 -0
- /package/data/harnesses/{apollo → code}/docs/structure.md +0 -0
- /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
|
-
|
|
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);
|
package/data/harness-index.json
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"fingerprint": "
|
|
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
|
|
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.
|
|
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": "
|
|
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
|
-
|
|
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
|
|
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
|
+
"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": "
|
|
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
|
|
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
|
|
@@ -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 |
|