@nurix/etna 0.16.0 → 0.17.1
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 +148 -67
- package/data/harness-index.json +1 -1
- package/data/harnesses/code/.prettierignore +12 -0
- package/data/harnesses/code/.prettierrc.json +3 -0
- package/data/harnesses/code/.vscode/settings.json +10 -0
- package/data/harnesses/code/CLAUDE.md +5 -8
- package/data/harnesses/code/agents/change-review.md +13 -14
- package/data/harnesses/code/agents/harness-manager.md +14 -26
- package/data/harnesses/code/agents/maintenance.md +10 -18
- package/data/harnesses/code/harness.json +8 -3
- package/data/harnesses/code/hooks/hooks.json +2 -2
- package/data/harnesses/code/hooks/lib/{redact.js → redact.mjs} +2 -4
- package/data/harnesses/{code-fable/hooks/prompt-recall.js → code/hooks/prompt-recall.mjs} +5 -7
- package/data/harnesses/{code-fable/hooks/session-reflect.js → code/hooks/session-reflect.mjs} +9 -7
- package/data/harnesses/code/rules/general.md +23 -40
- package/data/harnesses/code/rules/nomenclature.md +0 -4
- package/data/harnesses/code/rules/typescript.md +19 -0
- package/data/harnesses/code/skills/boundary/SKILL.md +53 -239
- package/data/harnesses/code/skills/brainstorm/harvest.md +2 -2
- package/data/harnesses/code/skills/documentation/SKILL.md +2 -4
- package/data/harnesses/code/skills/documentation/references/templates.md +12 -89
- package/data/harnesses/code-fable/.prettierignore +12 -0
- package/data/harnesses/code-fable/.prettierrc.json +3 -0
- package/data/harnesses/code-fable/.vscode/settings.json +10 -0
- package/data/harnesses/code-fable/CLAUDE.md +5 -8
- package/data/harnesses/code-fable/agents/change-review.md +13 -14
- package/data/harnesses/code-fable/agents/harness-manager.md +14 -26
- package/data/harnesses/code-fable/agents/maintenance.md +10 -18
- package/data/harnesses/code-fable/harness.json +8 -3
- package/data/harnesses/code-fable/hooks/hooks.json +2 -2
- package/data/harnesses/code-fable/hooks/lib/{redact.js → redact.mjs} +2 -4
- package/data/harnesses/{code/hooks/prompt-recall.js → code-fable/hooks/prompt-recall.mjs} +5 -7
- package/data/harnesses/{code/hooks/session-reflect.js → code-fable/hooks/session-reflect.mjs} +9 -7
- package/data/harnesses/code-fable/rules/general.md +23 -40
- package/data/harnesses/code-fable/rules/nomenclature.md +0 -4
- package/data/harnesses/code-fable/rules/typescript.md +19 -0
- package/data/harnesses/code-fable/skills/boundary/SKILL.md +53 -239
- package/data/harnesses/code-fable/skills/brainstorm/harvest.md +2 -2
- package/data/harnesses/code-fable/skills/documentation/SKILL.md +2 -4
- package/data/harnesses/code-fable/skills/documentation/references/templates.md +12 -89
- package/data/harnesses/discover/.prettierignore +12 -0
- package/data/harnesses/discover/.prettierrc.json +3 -0
- package/data/harnesses/discover/.vscode/settings.json +10 -0
- package/data/harnesses/discover/harness.json +6 -1
- package/data/harnesses/discover/rules/evaluation.md +13 -1
- package/data/harnesses/discover/rules/ingestion.md +15 -0
- package/data/harnesses/discover/rules/tradecraft.md +13 -0
- package/data/harnesses/hr/.prettierignore +12 -0
- package/data/harnesses/hr/.prettierrc.json +3 -0
- package/data/harnesses/hr/.vscode/settings.json +10 -0
- package/data/harnesses/hr/harness.json +6 -1
- package/data/harnesses/kb-agi/.prettierignore +12 -0
- package/data/harnesses/kb-agi/.prettierrc.json +3 -0
- package/data/harnesses/kb-agi/.vscode/settings.json +10 -0
- package/data/harnesses/kb-agi/harness.json +6 -1
- package/package.json +4 -1
|
@@ -4,12 +4,12 @@ Harvest is **optional and offered, never assumed**. By default the session folde
|
|
|
4
4
|
|
|
5
5
|
## Routing
|
|
6
6
|
|
|
7
|
-
The harvest is a structured diff between the session pillars and the live docs, routed by scope: module-local findings → `docs/modules/{m}/pillars/`, cross-module
|
|
7
|
+
The harvest is a structured diff between the session pillars and the live docs, routed by scope: module-local findings → `docs/modules/{m}/pillars/`, cross-module + IA/contract changes → `docs/architecture/`, backlog → `docs/history/`.
|
|
8
8
|
|
|
9
9
|
| Session source | Destination |
|
|
10
10
|
|---|---|
|
|
11
11
|
| `thesis.md` narrative | `docs/history/plans/YYYY-MM-DD-{slug}.md` (Status: Draft, `documentation` skill §8 Plan template) |
|
|
12
|
-
| `domain-model.md` | `docs/architecture/domain-model.md`; if it changes the IA or a cross-cutting contract,
|
|
12
|
+
| `domain-model.md` | `docs/architecture/domain-model.md`; if it changes the IA or a cross-cutting contract, note the contract change there — the `boundary` skill will pick it up from source at the next plan check |
|
|
13
13
|
| Decisions spanning 2+ modules | one ADR per cohesive theme → `docs/architecture/adr/ADR-NNN-{slug}.md`, authored to the **`documentation` skill §10 ADR template** (frontmatter `status:` is the lifecycle source of truth — no body Status line; required sections Decision/Context/Consequences); rejected alternatives → the ADR's **Options Considered** table |
|
|
14
14
|
| Module-local decisions / doctrine / glossary / rejected | `docs/modules/{m}/pillars/{decisions,doctrine,glossary,rejected}.md` |
|
|
15
15
|
| Cross-module doctrine / glossary | `docs/architecture/domain-model.md` / `docs/architecture/glossary.md` |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: documentation
|
|
3
|
-
description: Template & generator library for technical docs — the skill agents call to produce a doc from a template. Use to (1) document a feature or module, (2) create or update a changelog entry, (3) document data flows or Redux state, (4) add to protected files, (5)
|
|
3
|
+
description: Template & generator library for technical docs — the skill agents call to produce a doc from a template. Use to (1) document a feature or module, (2) create or update a changelog entry, (3) document data flows or Redux state, (4) add to protected files, (5) record an architecture decision (ADR), (6) create or update the project root README, (7) create or update a plan, (8) derive ownership frontmatter (`owns`/`touches`/`depends_on`) from code, (9) scaffold a standard doc (README, structure.md, CHANGELOG, backlog, memory) from its template, or (10) co-author any technical doc. Baselining / reconciling a repo's docs to the installed harness version is the **`harness-manager` agent** (which calls this skill for each template) — this skill does not orchestrate baseline. Triggers on "document this", "create docs", "update changelog", "add to protected files", "ADR", "architecture decision", "root README", "plan", "feature doc".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Technical Documentation Skill
|
|
@@ -30,8 +30,6 @@ User request
|
|
|
30
30
|
│
|
|
31
31
|
├─ "Add to protected files" ───────▶ Protected Files Template
|
|
32
32
|
│
|
|
33
|
-
├─ "Create/update a boundary" ─────▶ boundary skill (this skill holds only the boundary-file template)
|
|
34
|
-
│
|
|
35
33
|
├─ "Record architecture decision" ─▶ ADR Template
|
|
36
34
|
│
|
|
37
35
|
├─ "Create/update root README" ────▶ Project Root README Template
|
|
@@ -122,6 +120,6 @@ For docs that don't match templates:
|
|
|
122
120
|
|
|
123
121
|
| File | Use For |
|
|
124
122
|
|------|---------|
|
|
125
|
-
| `references/templates.md` | docs/README.md, structure.md, frontmatter, scaffolds (CHANGELOG, backlog, memory),
|
|
123
|
+
| `references/templates.md` | docs/README.md, structure.md, frontmatter, scaffolds (CHANGELOG, backlog, memory), feature, changelog, plan, protected files, ADR, project root README templates |
|
|
126
124
|
| `references/style-guide.md` | Writing rules, formatting conventions |
|
|
127
125
|
| `references/examples.md` | Good vs bad documentation examples |
|
|
@@ -93,7 +93,6 @@ Each topic has one canonical location. Read from here, not from plans or changel
|
|
|
93
93
|
| ----- | --------- | --------- |
|
|
94
94
|
| System architecture + steering | `docs/architecture/` | domain-model, glossary, non-goals, references, adr/ |
|
|
95
95
|
| Feature behavior | `docs/features/` (or `docs/modules/{m}/features/`) | {key files} |
|
|
96
|
-
| Cross-module contracts | `docs/boundaries/` | one file per boundary (maintained by the `boundary` skill) |
|
|
97
96
|
| Declared modules (bounded contexts) | `docs/modules/{m}/` | `features/` + `pillars/` |
|
|
98
97
|
| Setup & development | `docs/operations/` | {key files} |
|
|
99
98
|
| Historical plans | `docs/history/plans/` | YYYY-MM-DD-name.md |
|
|
@@ -112,7 +111,6 @@ Plan (Status: Draft) → Implementation → Feature Doc or Architecture Update
|
|
|
112
111
|
|
|
113
112
|
- `docs/features/`: Living reference for implemented features. Each spec includes YAML frontmatter with `owns`, `touches`, `depends_on` fields declaring code ownership.
|
|
114
113
|
- `docs/architecture/`: System-wide patterns and the cross-module steering layer (domain model, glossary, non-goals, references, ADRs). Update when cross-cutting concerns change.
|
|
115
|
-
- `docs/boundaries/`: Horizontal typed application boundaries — one file per cross-module contract. Generated/maintained by the `boundary` skill; read before touching a shape it defines.
|
|
116
114
|
- `docs/modules/{m}/`: Vertical bounded contexts, **declared** (not inferred from layout) and tied to code by their `owns` globs. Each owns `features/` + module-local `pillars/` (doctrine, lazy). There is no repo-wide `docs/pillars/`. Worth declaring at ≥2 genuine bounded contexts; a single-context app stays flat under `docs/features/`.
|
|
117
115
|
- `docs/operations/`: How-to procedures for setup, development, and deployment. Update when workflows change.
|
|
118
116
|
- `docs/history/plans/`: Historical. Must have `Status:` field. Never modify after completion.
|
|
@@ -150,7 +148,7 @@ anchors:
|
|
|
150
148
|
- `owns`: Glob patterns for files this feature doc is the canonical reference for
|
|
151
149
|
- `touches`: Files this feature interacts with but doesn't own
|
|
152
150
|
- `depends_on`: Other docs that must be read for full context
|
|
153
|
-
- `anchors` (optional): A list of qmd queries (or `#docid`s) that re-resolve to the code/facts this doc abstracts as they move; anchors are retrieval context plus a drift tripwire, never a contract — an anchor that returns nothing IS the drift signal, nothing auto-rewrites from an anchor result, and the doc's prose stays the human-owned abstraction. They detect **doc-area drift** (the subject moving or vanishing from the corpus), not a pure code rename — the query also matches the doc's own prose, so a rename that leaves the text unchanged won't shift the result; code-symbol drift is the maintenance named-referent check's job, and anchors complement it rather than replace it. Resolved via `qmd query --format json -c <collection>` against this repo's collections; absent qmd ⇒ anchors are inert (no error). Never required on any doc. The feature
|
|
151
|
+
- `anchors` (optional): A list of qmd queries (or `#docid`s) that re-resolve to the code/facts this doc abstracts as they move; anchors are retrieval context plus a drift tripwire, never a contract — an anchor that returns nothing IS the drift signal, nothing auto-rewrites from an anchor result, and the doc's prose stays the human-owned abstraction. They detect **doc-area drift** (the subject moving or vanishing from the corpus), not a pure code rename — the query also matches the doc's own prose, so a rename that leaves the text unchanged won't shift the result; code-symbol drift is the maintenance named-referent check's job, and anchors complement it rather than replace it. Resolved via `qmd query --format json -c <collection>` against this repo's collections; absent qmd ⇒ anchors are inert (no error). Never required on any doc. The feature template ships the exemplar, but `anchors:` may appear on any living doc the maintenance anchor-drift check globs — `docs/features/`, `docs/architecture/`, and `docs/operations/` — so the convention and the check stay one mental model.
|
|
154
152
|
|
|
155
153
|
---
|
|
156
154
|
|
|
@@ -243,7 +241,7 @@ description: Shared knowledge accumulated across agent sessions. All agents shou
|
|
|
243
241
|
## Documentation Baseline
|
|
244
242
|
|
|
245
243
|
- **Baselined:** {today}
|
|
246
|
-
- **Structure:** v{harness-version} (architecture, features, operations, history, memory; +
|
|
244
|
+
- **Structure:** v{harness-version} (architecture, features, operations, history, memory; + modules/, tests/ when present)
|
|
247
245
|
- **Spec version:** v{harness-version}
|
|
248
246
|
<!-- v{harness-version} resolves to the installed design epoch — read it from `.claude/harness.json` (`epoch`) / `docs/structure.md` frontmatter (`harness-version`); never hardcode a literal version here. -->
|
|
249
247
|
|
|
@@ -284,86 +282,11 @@ Append entries below, oldest at bottom. Format:
|
|
|
284
282
|
Memory file initialized during documentation baseline.
|
|
285
283
|
```
|
|
286
284
|
|
|
287
|
-
> The per-actor memory **inbox** (`docs/memory/inbox/`) is *not* a baseline scaffold — the `session-reflect` hook creates it mechanically on the first reflected session. See **§
|
|
285
|
+
> The per-actor memory **inbox** (`docs/memory/inbox/`) is *not* a baseline scaffold — the `session-reflect` hook creates it mechanically on the first reflected session. See **§11 Memory inbox entry** for its format.
|
|
288
286
|
|
|
289
287
|
---
|
|
290
288
|
|
|
291
|
-
## 5.
|
|
292
|
-
|
|
293
|
-
> **This skill does not generate boundaries.** Typed-boundary generation is owned by the **`boundary`** skill (`generate` mode), which detects the stack + IA and applies its boundary taxonomy (`references/boundary-taxonomy.md`) to emit typed files. The baseline does **not** scaffold `docs/boundaries/` — `/boundary generate` runs right after the baseline ("baseline boundaries"). This section is the generic **boundary-file template** plus the guidance for *recognizing* what deserves a boundary.
|
|
294
|
-
|
|
295
|
-
### What deserves a boundary
|
|
296
|
-
|
|
297
|
-
A boundary is a **horizontal, cross-module contract** where the failure is silent and crosses module boundaries — the developer in module A has no reason to know module B will break. No import error, no runtime exception — just wrong behavior.
|
|
298
|
-
|
|
299
|
-
Test: "If an agent edits this while working on a single feature, could it silently break something in a different feature?" If yes, it's a boundary.
|
|
300
|
-
|
|
301
|
-
**Include:**
|
|
302
|
-
|
|
303
|
-
- **Shared state shapes** — Redux store slices, persisted state, global context. Any shape that multiple modules read. Document every key, its type, and what reads it. Call out which slices are persisted and how rehydration handles shape changes (e.g., new fields become `undefined` for existing users).
|
|
304
|
-
- **Entity registration checklists** — When adding a new entity/resource type requires touching N files across N modules to avoid silent data loss. List every file and what breaks if skipped.
|
|
305
|
-
- **Cross-entity references by value** — When entity A stores entity B's identifier (slug, name, ID) as a plain value with no referential integrity. Document which fields reference what, and that renaming the target never propagates to the source.
|
|
306
|
-
- **Format contracts** — When two systems produce identifiers in different formats (e.g., server returns `[a-z0-9]+`, client generates `[a-z0-9_]+`). Document both formats, where each is used, and what breaks on mismatch (e.g., lookup by key returns `undefined`, key-splitting logic produces wrong matches).
|
|
307
|
-
- **Cross-module string coupling** — Action types, event names, status enums, or document type strings referenced by raw string literal instead of imported constant. List every file that hard-codes the string and what breaks if the source is renamed.
|
|
308
|
-
- **Pipeline ordering dependencies** — Multi-step pipelines where Step N assumes Step N-1 has already written data to shared state. Document the implicit dependency and what happens if ordering changes (silent quality degradation vs. hard failure vs. hang).
|
|
309
|
-
- **Completion signal contracts** — When modules communicate via return values, status fields, or Redux state transitions. Document the expected shape/type (e.g., `Promise<boolean>`, status enum values) and what happens if the contract changes (e.g., returning `undefined` instead of `true` causes permanent "failed" status).
|
|
310
|
-
- **Host/plugin contracts** — Config objects consumed by a framework/host where some fields are validated and others aren't. Document which fields are unvalidated and what breaks silently if they change.
|
|
311
|
-
- **Persistence shape safety** — How the persistence layer handles schema evolution. Document what happens when you add, remove, or rename a field in persisted state (e.g., no migration → stale data, new fields default to `undefined`).
|
|
312
|
-
|
|
313
|
-
**Exclude:**
|
|
314
|
-
|
|
315
|
-
- Module-internal architecture (well-encapsulated, no cross-module blast radius)
|
|
316
|
-
- Authentication/authorization flows (behind adapters, feature code doesn't touch them)
|
|
317
|
-
- Hook taxonomies and API reference (useful docs, but not boundaries — they don't cause cascading failures)
|
|
318
|
-
- Networking details (WebSocket, HTTP client setup) — unless the event routing has cross-module string coupling
|
|
319
|
-
- Feature folder conventions and code style (conventions, not breakage vectors)
|
|
320
|
-
- Anything where failure produces an import error, a clear runtime exception, or a visible UI error — those are self-diagnosing and don't need a boundary
|
|
321
|
-
|
|
322
|
-
### How to research a boundary
|
|
323
|
-
|
|
324
|
-
When mapping a boundary (the `boundary` skill's `generate`/`create` job — this guidance is shared), investigate:
|
|
325
|
-
|
|
326
|
-
1. **Shared state consumers** — For each Redux slice/context, find all files that read from it. Flag any file reading a slice it doesn't own (cross-module dependency).
|
|
327
|
-
2. **String-coupled actions** — Grep for Redux action type strings referenced as raw strings rather than imported constants. These are invisible breakage points.
|
|
328
|
-
3. **Entity lifecycle** — For each entity type, trace the full lifecycle: creation → change tracking → save payload → API → server. Identify every file that must be touched to support a new entity type.
|
|
329
|
-
4. **Identifier format mismatches** — Compare how identifiers are generated (server vs. client) and how they're used as keys. Look for format divergence.
|
|
330
|
-
5. **Pipeline data dependencies** — For multi-step processes, check what each step reads from shared state and what previous step wrote it. Test: "If I reorder these steps, does it fail loudly or silently?"
|
|
331
|
-
6. **Persistence rehydration** — Check what reconciler is used, whether transforms exist, and what happens to existing users when a persisted shape changes.
|
|
332
|
-
|
|
333
|
-
### Generic boundary-file template
|
|
334
|
-
|
|
335
|
-
One file per boundary in `docs/boundaries/`. The `boundary` skill emits typed files using its boundary taxonomy; this is the generic fallback shape.
|
|
336
|
-
|
|
337
|
-
```markdown
|
|
338
|
-
---
|
|
339
|
-
anchors: # optional — see §3 frontmatter reference
|
|
340
|
-
- "qmd query: store slice rehydration fallback"
|
|
341
|
-
---
|
|
342
|
-
|
|
343
|
-
# {Boundary Name}
|
|
344
|
-
|
|
345
|
-
[BOUNDARY: {type} · {severity}] <!-- type from the Application Boundary Scale; severity CRITICAL | HIGH | MED | LOW -->
|
|
346
|
-
|
|
347
|
-
**Bounds:** {module A} ↔ {module B} <!-- which modules sit on each side -->
|
|
348
|
-
|
|
349
|
-
## Shape
|
|
350
|
-
<!-- `transcribe`: a synthesized contract with no single code home (composed store tree, API envelope, the IA entity model, tenancy) — written inline, canonical here.
|
|
351
|
-
`point`: a self-locating shape (DB schema, route table) — a `file:line` pointer + invariants. Never copy a self-locating shape; it rots on the next change.
|
|
352
|
-
greenfield/pre-code `point` (contract decided, no code yet — e.g. boundary generate after a brainstorm): there's no file:line to point at, so instead (a) record the decided conventions inline here, (b) add a `planned <path>` line naming where the canonical source will land (e.g. `planned packages/api/src/db/schema.ts`), and (c) mark this row `point*` in the README index. Converts to (or gains) a real file:line pointer when the module lands. README index footnote: "* point-mode boundary whose pointer lands at implementation". -->
|
|
353
|
-
|
|
354
|
-
## Invariants
|
|
355
|
-
<!-- The rules that must hold across the boundary. -->
|
|
356
|
-
|
|
357
|
-
## Blast radius
|
|
358
|
-
<!-- What breaks, and where, if an invariant is violated. -->
|
|
359
|
-
|
|
360
|
-
## Safe-change checklist
|
|
361
|
-
<!-- Ordered steps to change this contract without silent breakage. Mark steps that fail silently if skipped. -->
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
---
|
|
365
|
-
|
|
366
|
-
## 6. Feature Documentation (docs/features/{feature}.md)
|
|
289
|
+
## 5. Feature Documentation (docs/features/{feature}.md)
|
|
367
290
|
|
|
368
291
|
Use for: every feature in `docs/features/`. The same file persists from design (Status: Draft) through implementation to live reference (Status: Active). Sections fill in as the feature matures — no template swap.
|
|
369
292
|
|
|
@@ -514,7 +437,7 @@ Resolved Open Questions can be summarized into Background; unresolved ones stay
|
|
|
514
437
|
|
|
515
438
|
---
|
|
516
439
|
|
|
517
|
-
##
|
|
440
|
+
## 6. Changelog
|
|
518
441
|
|
|
519
442
|
Use for: recording code changes with function-level detail.
|
|
520
443
|
|
|
@@ -563,11 +486,11 @@ Brief description of what changed and why.
|
|
|
563
486
|
|
|
564
487
|
---
|
|
565
488
|
|
|
566
|
-
##
|
|
489
|
+
## 7. Plan (docs/history/plans/YYYY-MM-DD-feature-name.md)
|
|
567
490
|
|
|
568
491
|
Use for: every implementation plan. Plans are created here directly with `Status: Draft`, flip to `Status: In Progress` when work starts, and freeze at `Status: Complete` or `Status: Abandoned`. Once frozen, never edit — write a new dated plan if scope changes.
|
|
569
492
|
|
|
570
|
-
The `boundary` skill
|
|
493
|
+
The `boundary` skill parses the **Proposed Changes** sections to check boundary impact before execution. Keep that structure stable — section headings and bullet shape are load-bearing for the parser.
|
|
571
494
|
|
|
572
495
|
```
|
|
573
496
|
# {Feature Name}
|
|
@@ -603,7 +526,7 @@ Why this work is happening *now*. Link to the spec for *what* we're building; th
|
|
|
603
526
|
|
|
604
527
|
### Cross-Module Contracts Affected
|
|
605
528
|
|
|
606
|
-
- List which
|
|
529
|
+
- List which cross-cutting contracts this plan touches (db schema, wire envelope, auth, events, env/config, …)
|
|
607
530
|
- "None" is a valid answer and means the `boundary` check will pass cleanly
|
|
608
531
|
|
|
609
532
|
## Implementation Steps
|
|
@@ -630,7 +553,7 @@ Why this work is happening *now*. Link to the spec for *what* we're building; th
|
|
|
630
553
|
|
|
631
554
|
---
|
|
632
555
|
|
|
633
|
-
##
|
|
556
|
+
## 8. Protected Files
|
|
634
557
|
|
|
635
558
|
Use for: documenting critical files that need approval before modification.
|
|
636
559
|
|
|
@@ -675,7 +598,7 @@ path/to/another/file.js
|
|
|
675
598
|
|
|
676
599
|
---
|
|
677
600
|
|
|
678
|
-
##
|
|
601
|
+
## 9. Architecture Decision Record (ADR)
|
|
679
602
|
|
|
680
603
|
Use for: capturing a single, point-in-time architectural decision with its context, alternatives considered, and consequences. Lives in `docs/architecture/adr/`.
|
|
681
604
|
|
|
@@ -792,7 +715,7 @@ tags: [adr]
|
|
|
792
715
|
|
|
793
716
|
---
|
|
794
717
|
|
|
795
|
-
##
|
|
718
|
+
## 10. Project Root README
|
|
796
719
|
|
|
797
720
|
Use for: the human-facing entry point at the repository root (`/README.md`) — what visitors and new contributors land on. Distinct from `docs/README.md` (the agent/doc index — see §1). The two coexist; don't merge them.
|
|
798
721
|
|
|
@@ -899,7 +822,7 @@ The baseline audit **does** scaffold the project root README when missing. The r
|
|
|
899
822
|
|
|
900
823
|
---
|
|
901
824
|
|
|
902
|
-
##
|
|
825
|
+
## 11. Memory inbox entry (docs/memory/inbox/{actor}.md)
|
|
903
826
|
|
|
904
827
|
Use for: the capture tier of the knowledge gradient — the durable lessons of each session (corrections, root-caused failures, decisions with rationale, discovered constraints), reflected by the `session-reflect` hook at session end. It is the raw input to distillation: `distiller facts` digests entries into fact-cards and **consumes** them, so the file holds exactly what is undigested.
|
|
905
828
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Markdown: Prettier unwraps prose to one logical line per paragraph
|
|
3
|
+
// (see .prettierrc → proseWrap:never) on save; the editor soft-wraps for
|
|
4
|
+
// reading, so no hard line breaks get baked into the source.
|
|
5
|
+
"[markdown]": {
|
|
6
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
7
|
+
"editor.formatOnSave": true,
|
|
8
|
+
"editor.wordWrap": "on"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -34,6 +34,15 @@ published SDK source) that calls the same routes is **independent of both market
|
|
|
34
34
|
wrapper**, and corroborates it → promotes. (A legacy/granular route family seen only in a third-party
|
|
35
35
|
MCP becomes a real finding once the official OSS client calls it too.)
|
|
36
36
|
|
|
37
|
+
**Open-core lineage as an absence oracle (independent corroboration of the open/closed seam).** When a
|
|
38
|
+
target is an **open-core product with a closed cloud edition** (a clonable `codebase` lineage repo + a
|
|
39
|
+
closed `session` runtime), a feature **verified ABSENT in the lineage repo** (grep/structure-map) **and
|
|
40
|
+
observed PRESENT in the cloud session** is **two independent lanes agreeing on the *seam*** → promotes the
|
|
41
|
+
open/closed-boundary claim to fact (the cloud-feature value itself stays a direct `session` observation).
|
|
42
|
+
The lineage repo is as useful as an *absence map* (what is NOT in the open floor) as it is a presence map;
|
|
43
|
+
"verified-absent-in-CE + observed-in-cloud" is independent of marketing and of the session alone. (Origin:
|
|
44
|
+
Akeneo — Reference Entities / DAM / Rules / Workflows observed in Serenity + grep-absent in Community Edition.)
|
|
45
|
+
|
|
37
46
|
**Closed-feedback confidence cap.** When the `community` dimension finds **no first-party feedback
|
|
38
47
|
loop** (no public issues / roadmap / changelog / forum — feedback funnelled to a gated channel), its
|
|
39
48
|
user-pain / most-requested-feature claims are **inference-from-changelog only → capped at
|
|
@@ -87,7 +96,10 @@ prose, not via a separate `claims.yaml`.)
|
|
|
87
96
|
a different, broader, differently-authed API than the published one: list ops the
|
|
88
97
|
app uses that the public API omits, AND public ops the app never calls — both are
|
|
89
98
|
findings. If there is NO published API, say so explicitly: "no published API — the
|
|
90
|
-
app surface is the only surface" is itself the finding, not an empty section.
|
|
99
|
+
app surface is the only surface" is itself the finding, not an empty section.
|
|
100
|
+
REQUIRES paired inputs (ingestion §6): the pre-nav in-page tap [session app-own
|
|
101
|
+
paths] + the unauth bundle/route-manifest [published paths]. Missing a lane → the
|
|
102
|
+
diff is un-feedable; say which lane is absent rather than implying overlap.)
|
|
91
103
|
## Auth & tenancy model (token type, where it lives, scope expression)
|
|
92
104
|
## API-path diff (adaptive, N-way over the runtime sources present) (the seam rule: bundle-declared vs
|
|
93
105
|
session-observed vs wire-observed. Title it for the sources ACTUALLY run —
|
|
@@ -156,6 +156,21 @@ flags**. To keep them consumable instead of triplicated **N times** (a real run
|
|
|
156
156
|
> public operations the app never calls, are both findings. The published surface is the integration
|
|
157
157
|
> story; the runtime surface is the real architecture. When a published API exists, Evaluation emits
|
|
158
158
|
> this split as a *named* output, not inline prose (evaluation template 3).
|
|
159
|
+
>
|
|
160
|
+
> **Paired inputs make the diff feedable (capture cue).** The split is only emittable if BOTH lanes were
|
|
161
|
+
> captured: when a target has **a published API AND an authed session**, the **pre-nav in-page fetch/XHR
|
|
162
|
+
> tap** (`session` — the app-own paths it actually calls) and the **unauth bundle/route-manifest**
|
|
163
|
+
> (`deployed-client-bundle` — the published paths) are **paired required inputs**. Install the tap *before*
|
|
164
|
+
> navigation (else on-load app calls are missed) and capture the manifest unauth; a session that only
|
|
165
|
+
> screenshots, or a bundle mine with no session, leaves the diff un-feedable. (Origin: Akeneo — 54
|
|
166
|
+
> session-observed app-own paths vs a 124-path unauth `/api/rest/v1` manifest, near-disjoint.)
|
|
167
|
+
>
|
|
168
|
+
> **Host-level dimensions cite, they don't append (seam allowlist).** The shared `api-path-catalog.md`
|
|
169
|
+
> `## source:` allowlist is **bundle / session / wire / distribution** only — the path-contributing
|
|
170
|
+
> runtime lanes. A host-level dimension (`infra-backend-fingerprint`) that wants to cross-reference the
|
|
171
|
+
> catalog does so **from its own `raw/`** (cite hosts/paths by reference), and does **not** append its own
|
|
172
|
+
> `## source:` section to the shared file. (Origin: Akeneo — infra appended a host-level note to the path
|
|
173
|
+
> catalog; benign but blurs the allowlist.)
|
|
159
174
|
|
|
160
175
|
---
|
|
161
176
|
|
|
@@ -478,6 +478,19 @@ Inferences from `localStorage` / `sessionStorage` / cookie / IndexedDB **key nam
|
|
|
478
478
|
| **Opaque session cookie** (HttpOnly, same-origin, auto-attached) | No `Authorization` header anywhere on the SPA; the cookie auto-attaches because all API is same-origin. **The negative finding is the tell.** | No |
|
|
479
479
|
| **Firebase ID token in IndexedDB** | `firebaseLocalStorageDb` → `stsTokenManager.accessToken`; Firebase Modular SDK v9+ store; short-lived (3600 s) + auto-refreshed. Confirm the Bearer model with one Firestore REST `GET documents/users/{uid}`. | Partially (IDB is JS-reachable, but token is short-lived + refreshed) |
|
|
480
480
|
|
|
481
|
+
> **Same-origin replay — mine an opaque-session-cookie API without ever reading the cookie.** When the
|
|
482
|
+
> taxonomy lands on **opaque session cookie** above (no `Authorization`, no JS-readable token, no CSRF
|
|
483
|
+
> meta — a server-session app: Symfony/PHP, Rails, Django, classic ASP.NET), the *absence* in JS storage
|
|
484
|
+
> **is** the positive fingerprint, not a dead end. Mine it with **in-page `fetch(path, {credentials:'same-origin'})`
|
|
485
|
+
> replay from the app origin**: the browser auto-attaches the httpOnly cookie, so once the in-page tap has
|
|
486
|
+
> revealed an endpoint you replay it for verbatim read bodies (and, Pass-2-gated, write bodies) **without
|
|
487
|
+
> ever reading, returning, or writing the cookie value** — the secret never reaches the harness, which is
|
|
488
|
+
> what keeps this inside the §7 ethics line. You do **not** need raw CDP `Network` for this case (it would
|
|
489
|
+
> only add the literal `Cookie`/request headers, which you'd redact anyway); the in-page fetch/XHR tap +
|
|
490
|
+
> same-origin replay is the complete tool. Reach for raw CDP only to reconstruct exact request headers for
|
|
491
|
+
> an *out-of-browser* reproducer, or for non-`fetch` transports (WS frames). (Origin tag: Akeneo — httpOnly
|
|
492
|
+
> `BAPID` Symfony session, 54-path internal API mined entirely by same-origin replay.)
|
|
493
|
+
|
|
481
494
|
**Key claims to look for in the JWT payload** (decode *structure* only — redact `sub`/`email`/`session_id`/`provider_id`, never log the signature):
|
|
482
495
|
|
|
483
496
|
| Claim | What it tells you |
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Markdown: Prettier unwraps prose to one logical line per paragraph
|
|
3
|
+
// (see .prettierrc → proseWrap:never) on save; the editor soft-wraps for
|
|
4
|
+
// reading, so no hard line breaks get baked into the source.
|
|
5
|
+
"[markdown]": {
|
|
6
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
7
|
+
"editor.formatOnSave": true,
|
|
8
|
+
"editor.wordWrap": "on"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Markdown: Prettier unwraps prose to one logical line per paragraph
|
|
3
|
+
// (see .prettierrc → proseWrap:never) on save; the editor soft-wraps for
|
|
4
|
+
// reading, so no hard line breaks get baked into the source.
|
|
5
|
+
"[markdown]": {
|
|
6
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
7
|
+
"editor.formatOnSave": true,
|
|
8
|
+
"editor.wordWrap": "on"
|
|
9
|
+
}
|
|
10
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nurix/etna",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"description": "Bootstrap a project with a Nurix harness — copies the harness's CLAUDE.md, skills, agents, rules, and hooks directly into the project from a bundled payload (no marketplace fetch, no network).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"etna": "bin/etna.js"
|
|
8
8
|
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@clack/prompts": "^0.11.0"
|
|
11
|
+
},
|
|
9
12
|
"files": [
|
|
10
13
|
"bin/",
|
|
11
14
|
"data/",
|