@nurix/etna 0.19.33 → 0.19.35
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/data/harness-index.json +5 -1
- package/data/harnesses/code/CLAUDE.md +21 -11
- package/data/harnesses/code/harness.json +2 -2
- package/data/harnesses/code/rules/general.md +1 -0
- package/data/harnesses/code/rules/testing.md +1 -1
- package/data/harnesses/code/rules/verification.md +51 -0
- package/data/harnesses/code/skills/test-plan/SKILL.md +3 -3
- package/data/harnesses/delivery/.prettierignore +29 -0
- package/data/harnesses/delivery/.prettierrc.json +3 -0
- package/data/harnesses/delivery/.vscode/settings.json +19 -0
- package/data/harnesses/delivery/CLAUDE.md +123 -0
- package/data/harnesses/delivery/agents/brainstorm.md +144 -0
- package/data/harnesses/delivery/agents/data-generator.md +23 -0
- package/data/harnesses/delivery/agents/eval-runner.md +23 -0
- package/data/harnesses/delivery/agents/judge.md +23 -0
- package/data/harnesses/delivery/agents/lld-mode.md +56 -0
- package/data/harnesses/delivery/agents/maintenance.md +229 -0
- package/data/harnesses/delivery/agents/prompt-iterator.md +23 -0
- package/data/harnesses/delivery/agents/red-team.md +23 -0
- package/data/harnesses/delivery/agents/regression-runner.md +28 -0
- package/data/harnesses/delivery/agents/retro.md +46 -0
- package/data/harnesses/delivery/codex/agents/brainstorm.toml +142 -0
- package/data/harnesses/delivery/codex/agents/data-generator.toml +22 -0
- package/data/harnesses/delivery/codex/agents/eval-runner.toml +22 -0
- package/data/harnesses/delivery/codex/agents/judge.toml +22 -0
- package/data/harnesses/delivery/codex/agents/lld-mode.toml +52 -0
- package/data/harnesses/delivery/codex/agents/maintenance.toml +228 -0
- package/data/harnesses/delivery/codex/agents/prompt-iterator.toml +22 -0
- package/data/harnesses/delivery/codex/agents/red-team.toml +22 -0
- package/data/harnesses/delivery/codex/agents/regression-runner.toml +27 -0
- package/data/harnesses/delivery/codex/agents/retro.toml +45 -0
- package/data/harnesses/delivery/harness.json +11 -0
- package/data/harnesses/delivery/hooks/generate-ownership-index.mjs +148 -0
- package/data/harnesses/delivery/hooks/hooks.json +16 -0
- package/data/harnesses/delivery/rules/changelog.md +19 -0
- package/data/harnesses/delivery/rules/evals.md +23 -0
- package/data/harnesses/delivery/rules/model-tiers.md +18 -0
- package/data/harnesses/delivery/rules/nomenclature.md +34 -0
- package/data/harnesses/delivery/rules/prompting.md +23 -0
- package/data/harnesses/delivery/skills/brainstorm/README.md +56 -0
- package/data/harnesses/delivery/skills/brainstorm/SKILL.md +173 -0
- package/data/harnesses/delivery/skills/brainstorm/references/doctrine.md +98 -0
- package/data/harnesses/delivery/skills/brainstorm/references/harvest.md +86 -0
- package/data/harnesses/delivery/skills/brainstorm/references/session-schema.md +186 -0
- package/data/harnesses/delivery/skills/brainstorm/scripts/detector.mjs +460 -0
- package/data/harnesses/delivery/skills/cost-report/SKILL.md +24 -0
- package/data/harnesses/delivery/skills/documentation/SKILL.md +129 -0
- package/data/harnesses/delivery/skills/documentation/references/examples.md +279 -0
- package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +44 -0
- package/data/harnesses/delivery/skills/documentation/references/style-guide.md +340 -0
- package/data/harnesses/delivery/skills/documentation/references/untemplated.md +38 -0
- package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +140 -0
- package/data/harnesses/delivery/skills/documentation/templates/Readme.md +31 -0
- package/data/harnesses/delivery/skills/documentation/templates/api-reference.md +20 -0
- package/data/harnesses/delivery/skills/documentation/templates/architecture-decision.md +121 -0
- package/data/harnesses/delivery/skills/documentation/templates/backlog.md +33 -0
- package/data/harnesses/delivery/skills/documentation/templates/changelog-entry.md +57 -0
- package/data/harnesses/delivery/skills/documentation/templates/changelog-index.md +41 -0
- package/data/harnesses/delivery/skills/documentation/templates/docs-readme.md +72 -0
- package/data/harnesses/delivery/skills/documentation/templates/domain-model.md +30 -0
- package/data/harnesses/delivery/skills/documentation/templates/environment-registry.md +15 -0
- package/data/harnesses/delivery/skills/documentation/templates/feature.md +149 -0
- package/data/harnesses/delivery/skills/documentation/templates/glossary.md +11 -0
- package/data/harnesses/delivery/skills/documentation/templates/memory-main.md +25 -0
- package/data/harnesses/delivery/skills/documentation/templates/migration-runbook.md +34 -0
- package/data/harnesses/delivery/skills/documentation/templates/non-goals.md +11 -0
- package/data/harnesses/delivery/skills/documentation/templates/operations-procedure.md +36 -0
- package/data/harnesses/delivery/skills/documentation/templates/plan.md +64 -0
- package/data/harnesses/delivery/skills/documentation/templates/protected-files.md +37 -0
- package/data/harnesses/delivery/skills/documentation/templates/root-readme.md +104 -0
- package/data/harnesses/delivery/skills/documentation/templates/security-overview.md +27 -0
- package/data/harnesses/delivery/skills/documentation/templates/structure.md +65 -0
- package/data/harnesses/delivery/skills/documentation/templates/system-overview.md +32 -0
- package/data/harnesses/delivery/skills/documentation/templates/testing-strategy.md +29 -0
- package/data/harnesses/delivery/skills/escalate/SKILL.md +25 -0
- package/data/harnesses/delivery/skills/prompt-eval/SKILL.md +22 -0
- package/data/harnesses/delivery/skills/prompt-library/SKILL.md +36 -0
- package/data/harnesses/delivery/skills/route/SKILL.md +21 -0
- package/data/harnesses/etna/CLAUDE.md +1 -1
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/rules/general.md +1 -0
- package/data/harnesses/etna/rules/testing.md +1 -1
- package/data/harnesses/hr/harness.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// harness/code/hooks/generate-ownership-index.mjs — SessionStart hook: scan docs/features/**/*.md,
|
|
2
|
+
// extract the focal frontmatter (owns / module / keywords / status), and inject a compact
|
|
3
|
+
// code-path → owning-doc index via additionalContext. Fires on startup/resume/clear/compact so the
|
|
4
|
+
// map survives /clear and /compact and is regenerated fresh every time. Writes no file.
|
|
5
|
+
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
|
|
9
|
+
// Read all of stdin synchronously; returns "" if nothing is piped.
|
|
10
|
+
function readStdin() {
|
|
11
|
+
try {
|
|
12
|
+
return fs.readFileSync(0, "utf8");
|
|
13
|
+
} catch (e) {
|
|
14
|
+
return "";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Resolve the project root: CLAUDE_PROJECT_DIR env, else payload cwd, else process cwd.
|
|
19
|
+
function resolveProjectDir(payload) {
|
|
20
|
+
return process.env.CLAUDE_PROJECT_DIR || (payload && payload.cwd) || process.cwd();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Recursively collect every .md file under dir (returns [] if the dir is absent).
|
|
24
|
+
function listMarkdown(dir) {
|
|
25
|
+
const out = [];
|
|
26
|
+
let entries;
|
|
27
|
+
try {
|
|
28
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
29
|
+
} catch (e) {
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
const full = path.join(dir, entry.name);
|
|
34
|
+
if (entry.isDirectory()) out.push(...listMarkdown(full));
|
|
35
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) out.push(full);
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Pull the leading `--- … ---` frontmatter block; "" if the file has none.
|
|
41
|
+
function frontmatter(text) {
|
|
42
|
+
const m = /^?---\r?\n([\s\S]*?)\r?\n---/.exec(text);
|
|
43
|
+
return m ? m[1] : "";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Trim surrounding whitespace, then strip one layer of matching quotes.
|
|
47
|
+
function unquote(s) {
|
|
48
|
+
return String(s).trim().replace(/^["']|["']$/g, "").trim();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Read one frontmatter key: scalar (`k: v`), inline array (`k: [a, b]`), or a following `- item` block.
|
|
52
|
+
// Returns a string for scalars, an array for lists, or undefined when the key is absent.
|
|
53
|
+
function field(block, key) {
|
|
54
|
+
const lines = block.split(/\r?\n/);
|
|
55
|
+
const head = new RegExp(`^${key}\\s*:\\s*(.*)$`);
|
|
56
|
+
for (let i = 0; i < lines.length; i++) {
|
|
57
|
+
const m = head.exec(lines[i]);
|
|
58
|
+
if (!m) continue;
|
|
59
|
+
const raw = m[1].trim();
|
|
60
|
+
if (raw === "") {
|
|
61
|
+
const items = [];
|
|
62
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
63
|
+
const li = /^\s*-\s+(.*)$/.exec(lines[j]);
|
|
64
|
+
if (!li) break;
|
|
65
|
+
items.push(unquote(li[1]));
|
|
66
|
+
}
|
|
67
|
+
return items;
|
|
68
|
+
}
|
|
69
|
+
if (raw.startsWith("[")) {
|
|
70
|
+
return raw.replace(/^\[|\]$/g, "").split(",").map((s) => unquote(s)).filter(Boolean);
|
|
71
|
+
}
|
|
72
|
+
return unquote(raw);
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Coerce a field that may be scalar/array/undefined into a clean string array.
|
|
78
|
+
function asList(v) {
|
|
79
|
+
if (v == null) return [];
|
|
80
|
+
return (Array.isArray(v) ? v : [v]).map((s) => String(s).trim()).filter(Boolean);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Build the ownership index text from every feature doc's frontmatter.
|
|
84
|
+
function buildIndex(projectDir) {
|
|
85
|
+
const featuresDir = path.join(projectDir, "docs", "features");
|
|
86
|
+
const files = listMarkdown(featuresDir);
|
|
87
|
+
const lines = [];
|
|
88
|
+
let deprecated = 0;
|
|
89
|
+
for (const file of files) {
|
|
90
|
+
let text;
|
|
91
|
+
try {
|
|
92
|
+
text = fs.readFileSync(file, "utf8");
|
|
93
|
+
} catch (e) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const block = frontmatter(text);
|
|
97
|
+
if (!block) continue;
|
|
98
|
+
const owns = asList(field(block, "owns"));
|
|
99
|
+
if (owns.length === 0) continue;
|
|
100
|
+
const status = (field(block, "status") || "active").toString().toLowerCase();
|
|
101
|
+
if (status === "deprecated") {
|
|
102
|
+
deprecated += 1;
|
|
103
|
+
continue; // keep deprecated docs out of the routing lines
|
|
104
|
+
}
|
|
105
|
+
const moduleLabel = (field(block, "module") || "—").toString();
|
|
106
|
+
const keywords = asList(field(block, "keywords"));
|
|
107
|
+
const doc = path.relative(projectDir, file).split(path.sep).join("/");
|
|
108
|
+
const kw = keywords.length ? `[${keywords.join(", ")}]` : "[]";
|
|
109
|
+
for (const glob of owns) {
|
|
110
|
+
lines.push(`${glob} → ${doc} · ${moduleLabel} · ${kw} · ${status}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (lines.length === 0) return "";
|
|
114
|
+
lines.sort();
|
|
115
|
+
const header =
|
|
116
|
+
"# Ownership index (generated) — code-path glob → owning feature doc · module · keywords · status\n" +
|
|
117
|
+
"# Match the file or topic you're about to touch, then read the owning doc before changing it.\n";
|
|
118
|
+
const footer = deprecated > 0 ? `\n# (${deprecated} deprecated feature doc(s) omitted)` : "";
|
|
119
|
+
return header + lines.join("\n") + footer;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function main() {
|
|
123
|
+
const raw = readStdin();
|
|
124
|
+
let payload = {};
|
|
125
|
+
try {
|
|
126
|
+
payload = raw ? JSON.parse(raw) : {};
|
|
127
|
+
} catch (e) {
|
|
128
|
+
payload = {};
|
|
129
|
+
}
|
|
130
|
+
const index = buildIndex(resolveProjectDir(payload));
|
|
131
|
+
if (!index) return; // no feature docs yet → inject nothing
|
|
132
|
+
process.stdout.write(
|
|
133
|
+
JSON.stringify({
|
|
134
|
+
hookSpecificOutput: {
|
|
135
|
+
hookEventName: "SessionStart",
|
|
136
|
+
additionalContext: index,
|
|
137
|
+
},
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
main();
|
|
144
|
+
} catch (e) {
|
|
145
|
+
// Best-effort: a routing index is a convenience, never a gate. Inject nothing on failure.
|
|
146
|
+
} finally {
|
|
147
|
+
process.exit(0);
|
|
148
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Every unit of work leaves one record — `docs/history/changelog/YYYY-MM-DD-{three-words}.md` (the three words name the work, not the commit) — plus its row in `docs/history/CHANGELOG.md`, appended in the same pass so the index never trails the folder. Entry format, field rules, and the closed exemption list are the `documentation` skill's `templates/changelog-entry.md`; this rule owns when an entry is owed and how it lives. An entry is never a commit summary — it carries the refinement context only the working session holds, which no diff reconstructs.
|
|
4
|
+
|
|
5
|
+
## When an entry is owed
|
|
6
|
+
|
|
7
|
+
| Trigger | What to write |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| A plan reaches `Status: Complete` | A draft entry for that plan, linked to it — written now, while the session still holds the context |
|
|
10
|
+
| The user asks for a changelog | The entry for the work in hand. No commit required |
|
|
11
|
+
| A commit is made | Every non-exempt commit is covered by an entry — the `commit` skill writes or completes it |
|
|
12
|
+
|
|
13
|
+
## Lifecycle
|
|
14
|
+
|
|
15
|
+
Draft (created before its commit exists) → complete (missing fields filled from the diff and the session) → frozen the moment it rides in a commit. **Immutability begins at commit, not at creation** — a draft is meant to be edited, which is what lets a completed plan record its context before anything is committed; a committed entry is history, and a correction is a new entry linking back, **never** an edit.
|
|
16
|
+
|
|
17
|
+
## Granularity
|
|
18
|
+
|
|
19
|
+
A commit is the smallest unit an entry may describe; above that the mapping is judgment — four commits may be four entries or one, whichever reads better as history. An entry spanning several commits rides in the **last** of them, naming the predecessors in `Commits:`. When work exceeds what a draft describes, write a second entry rather than stretching the draft — the first stays an honest account of the plan.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Evals
|
|
2
|
+
|
|
3
|
+
Golden-set conventions, rubric design, and pass thresholds — the measurement half of eval-first. The loop that applies them is the `prompt-eval` skill; the certification they produce is recorded per the `prompt-library` skill.
|
|
4
|
+
|
|
5
|
+
## Golden sets
|
|
6
|
+
|
|
7
|
+
- One set per prompt family at `evals/{family}/` — items in `cases.md` (or `cases/*.md` when large), the rubric in `rubric.md`, the threshold declared at the top of the rubric.
|
|
8
|
+
- **An item is input + expected properties**, not input + one blessed output — score what must be true of the answer (fields present, grounded in the supplied context, refusal when the input demands one), never string equality on prose.
|
|
9
|
+
- **Edge cases are the set's value**: adversarial inputs, missing-information inputs, inputs that *should* trigger the fallback. `data-generator` drafts them; a human reviews before they join the set — a wrong expected property poisons every future run.
|
|
10
|
+
- Sets are append-mostly: production failures become new items the same week they're found. Removing an item is a design change to the family and is recorded like one.
|
|
11
|
+
|
|
12
|
+
## Rubrics
|
|
13
|
+
|
|
14
|
+
- Every dimension gets **anchors** — a written example of a 1, a 3, and a 5 — or graders drift; a bare "score helpfulness 1–5" is not a rubric.
|
|
15
|
+
- **Mechanical before judgment**: anything checkable in code (format validity, required fields, length bounds, banned content) is checked in code and gates before any graded dimension spends a model call.
|
|
16
|
+
- Judgment dimensions are graded at the economy tier against the anchors; grader-vs-human disagreement above ~1 anchor step, recurring, is a rubric defect — fix the anchors, then re-run.
|
|
17
|
+
- **Rubric changes re-certify the family.** A rubric edit invalidates every score produced under the old rubric; never tune a rubric and a prompt in the same change.
|
|
18
|
+
|
|
19
|
+
## Thresholds & determinism
|
|
20
|
+
|
|
21
|
+
- Each family declares one pass threshold (house default: **0.90** weighted across dimensions; safety-critical dimensions are pass/fail gates, not weighted terms).
|
|
22
|
+
- Runs are reproducible: fixed item order, temperature 0 where the task allows, the full set every time — a sampled run is a smoke check, never a certification.
|
|
23
|
+
- A certified score always names its context: prompt version, tier, rubric version, date. Scores without all four are not comparable and never quoted.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Model Tiers
|
|
2
|
+
|
|
3
|
+
The tier → model mapping — **the only file in this harness that names a model.** Policy, skills, and agent bodies speak in tier labels; when a model generation changes, this file and the owned agents' frontmatter `model:` pins are the two surfaces to edit, and nothing else moves.
|
|
4
|
+
|
|
5
|
+
## The mapping
|
|
6
|
+
|
|
7
|
+
| Tier | Model | Frontmatter pin | Character |
|
|
8
|
+
| --- | --- | --- | --- |
|
|
9
|
+
| **economy** | Claude Haiku 4.5 (`claude-haiku-4-5`) | `model: haiku` | Mechanical throughput: eval execution, data generation, regression sweeps |
|
|
10
|
+
| **standard** | Claude Sonnet 5 (`claude-sonnet-5`) | `model: sonnet` | The iteration workhorse: drafting, revising, comparing |
|
|
11
|
+
| **frontier** | Claude Opus 5 (`claude-opus-5`) | `model: opus` | Judgment: the ship gate, adversarial probing, second opinions |
|
|
12
|
+
|
|
13
|
+
## Updating the mapping
|
|
14
|
+
|
|
15
|
+
1. Edit the table above to the new generation.
|
|
16
|
+
2. Update the six owned agents' `model:` pins in `.claude/agents/` to match (`eval-runner`, `data-generator`, `regression-runner` → economy; `prompt-iterator` → standard; `judge`, `red-team` → frontier).
|
|
17
|
+
3. A generation change invalidates prompt certifications — `regression-runner` re-certifies the library and runs fresh demotion experiments (cheaper generations routinely absorb work from the tier above; the experiments are how the routing table finds out).
|
|
18
|
+
4. The `maintenance` audit checks the three-way parity — this table ↔ the pins ↔ the routing table's tiers — and flags any mismatch as drift.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Nomenclature
|
|
2
|
+
|
|
3
|
+
Naming and casing for code — identifiers, files, folders. The rationale throughout is consistency: one concept, one name, one casing shape, in every repo that loads this rule. Database naming is not here — see § Database.
|
|
4
|
+
|
|
5
|
+
Names state intent in full words — clarity over brevity; no abbreviations unless universally understood (`id`, `url` ✅ · `cfg`, `btn`, `idx` ❌).
|
|
6
|
+
|
|
7
|
+
## Casing
|
|
8
|
+
|
|
9
|
+
| Casing | Used for | Example |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| `camelCase` | variables, functions, methods, properties; a module file exporting no component | `calculateTotal`, `sessionClient.ts` |
|
|
12
|
+
| `PascalCase` | classes, type definitions, components; the file exporting one | `PaymentProcessor`, `AppsListPage.tsx` |
|
|
13
|
+
| `UPPER_SNAKE_CASE` | constants, environment variables | `MAX_RETRY_COUNT` |
|
|
14
|
+
| `kebab-case` | URLs, CSS class names, HTML IDs, multi-word folders | `user-profile`, `workspace-provisioning/` |
|
|
15
|
+
| `snake_case` | database tables, columns, indexes — § Database | `created_at` |
|
|
16
|
+
|
|
17
|
+
**A file exporting one component carries that component's name exactly**, so an import names the file it came from; a single-word folder is plain lowercase (`lib`, `surfaces`). ❌ Never `snake_case` a file or folder — that casing belongs to the database.
|
|
18
|
+
|
|
19
|
+
## Identifier shape
|
|
20
|
+
|
|
21
|
+
| Identifier | Shape | Example |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| Variable | noun phrase | `paymentStatus` |
|
|
24
|
+
| Function / method | verb phrase naming the action | `validateInput` |
|
|
25
|
+
| Boolean | `is` / `has` / `can` / `should` prefix — **never** a bare adjective | `hasPermission` |
|
|
26
|
+
| Array / collection | plural noun | `errorMessages` |
|
|
27
|
+
| Class / component | singular noun phrase | `RequestHandler` |
|
|
28
|
+
| Event handler | `handle` or `on` prefix | `handleSubmit`, `onPageLoad` |
|
|
29
|
+
| Interface | `I` prefix acceptable; type aliases stay plain | `IConfigOptions`, `AuthResponse` |
|
|
30
|
+
| Async function | verb phrase; `Async` suffix acceptable | `loadConfigAsync` |
|
|
31
|
+
|
|
32
|
+
## Database
|
|
33
|
+
|
|
34
|
+
Table, column, index, and key naming for relational schemas — the `id` / `slug` / `label` vocabulary, junction `_map` tables, and Drizzle mirrors — lives in [`database.md`](database.md), which routes general code naming back here.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Prompting
|
|
2
|
+
|
|
3
|
+
House prompt style — how production prompts in this repo are written. The library format is the `prompt-library` skill; quality measurement is the `evals` rule; this file is the craft.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
- **Be explicit, and say why.** State the task, the audience, the constraints, and the motivation — models generalize better from a stated *why* than from a pile of dos and don'ts.
|
|
8
|
+
- **Structure beats prose.** Separate instructions, context, examples, and output format with clear delimiters (XML-style tags are the house default: `<instructions>`, `<context>`, `<examples>`, `<output_format>`). Never interleave data with instructions.
|
|
9
|
+
- **Examples are load-bearing.** Two or three diverse, realistic examples beat ten repetitive ones; every example must be one the golden set would score as passing.
|
|
10
|
+
- **Permit uncertainty.** Tell the model what to do when it can't comply — a stated fallback ("say 'insufficient information'") beats a hallucinated answer, and rubrics score the fallback as correct.
|
|
11
|
+
- **Untrusted input stays untrusted.** Anything user- or document-supplied renders inside its own delimited block; instructions never come from inside it.
|
|
12
|
+
|
|
13
|
+
## Economy
|
|
14
|
+
|
|
15
|
+
- **Don't ask the model for what code can do.** Formatting, counting, filtering, deterministic transforms — do them in code around the prompt, not in the prompt.
|
|
16
|
+
- **Every token in a production prompt is a per-call cost.** Cut preamble, restated context, and defensive repetition; if a clause never changes an output (the evals will tell you), it goes.
|
|
17
|
+
- **One prompt, one job.** A prompt accreting second and third jobs gets split into family siblings — chaining certified prompts beats one uncertifiable mega-prompt.
|
|
18
|
+
|
|
19
|
+
## Iteration discipline
|
|
20
|
+
|
|
21
|
+
- The first draft rarely survives; iterate against the golden set (`prompt-eval`), not against one hand-picked example.
|
|
22
|
+
- Read failing outputs closely before editing — the fix for a reasoning failure (add motivation, add an example) differs from the fix for a format failure (tighten the output block).
|
|
23
|
+
- Record rejected variants and their eval deltas in the changelog entry; the next session inherits why the current wording won.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Brainstorm — process, not archive
|
|
2
|
+
|
|
3
|
+
A Claude Code skill that is a **thinking partner for designing large-scale software changes**.
|
|
4
|
+
The session's product is the repo's living documentation: the conversation helps the user think
|
|
5
|
+
correctly, the record stays readable at any pause, and the session ends with a harvest so
|
|
6
|
+
complete that the session folder is useless — it moves to history and the user deletes or
|
|
7
|
+
commits it.
|
|
8
|
+
|
|
9
|
+
> Spec (single source of truth): `docs/architecture/skills/brainstorm/` in the etna repo. The etna
|
|
10
|
+
> copy of this skill (`skills/brainstorm/`) is canonical; the user-level path
|
|
11
|
+
> `~/.claude/skills/brainstorm/` is a symlink to it.
|
|
12
|
+
|
|
13
|
+
## The architecture — one capability, two seats
|
|
14
|
+
|
|
15
|
+
Prose obligations decay in the conversing seat: the fleet audit behind v3 found the same rules
|
|
16
|
+
dying in every real session, even the successful ones. So the capability is split:
|
|
17
|
+
|
|
18
|
+
| Seat | Component | Owns |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| Conversation (main loop) | `SKILL.md` — the facilitator | The dialogue, the basis gate, the moves, one write: appending everything to `ops/capture.md` |
|
|
21
|
+
| Paper (dispatched agent) | `agents/brainstorm.md` — the twin, pinned strong tier | Every working-surface file: distilling ops into pillars, recomposing the thesis whole, the semantic audits, the harvest |
|
|
22
|
+
| Integrity (script) | `scripts/detector.mjs` | Mechanical checks with stable rule IDs; blocks the manifest and the move while gates fail |
|
|
23
|
+
| Quality (authoring-time) | `evals/` (never ships) | Session-replay scenarios, the two-agent audit, contrastive facilitation |
|
|
24
|
+
|
|
25
|
+
Every twin dispatch is paired-logged in `ops/sync-log.md` — the facilitator writes the dispatch
|
|
26
|
+
line, the twin writes the result — so reconciliation is observable, never asserted.
|
|
27
|
+
|
|
28
|
+
## The session lifecycle
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
/brainstorm start
|
|
32
|
+
→ basis gate (a document, an old session folder of any format, or a brain dump)
|
|
33
|
+
→ bootstrap docs/research/{topic}-brainstorm/ (ops/ untracked; twin writes the surface)
|
|
34
|
+
→ converse: dump / interview / probe / blindspot / converge — steerable in plain language
|
|
35
|
+
→ "let me read" anytime: compose on demand, read the thesis, come back
|
|
36
|
+
/brainstorm stop
|
|
37
|
+
→ converge → manifest → ONE user approval → apply → uselessness test
|
|
38
|
+
→ folder moves to docs/history/brainstorms/{topic}/ (the completion marker)
|
|
39
|
+
→ the user decides: delete or commit
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The working surface: `thesis.md` (claim → argument → what changed, recomposed whole, stamped),
|
|
43
|
+
`forks.md` (open questions with close conditions — the only convergence currency), `ledger.md`
|
|
44
|
+
(commitments: Decision / Why / How to apply / Resolves, declined options inline with re-evaluate
|
|
45
|
+
conditions), `state.md` (anchor + the aspect map), `basis/`, `fragments/` (harvest-native,
|
|
46
|
+
drafted in destination format), and untracked `ops/` (raw capture + sync log; deleted at stop).
|
|
47
|
+
|
|
48
|
+
## Files
|
|
49
|
+
|
|
50
|
+
- `SKILL.md` — the facilitator hub
|
|
51
|
+
- `references/doctrine.md` — thesis / forces / forks / commitments / consequences epistemics
|
|
52
|
+
- `references/session-schema.md` — the single format authority (what the detector enforces)
|
|
53
|
+
- `references/harvest.md` — the stop pipeline and routing map
|
|
54
|
+
- `scripts/detector.mjs` — the rule registry (`node detector.mjs <folder> [--gate=…] [--json]`)
|
|
55
|
+
- `scripts/fixtures/` — contrastive fixtures + runner (authoring-time; never ships)
|
|
56
|
+
- `evals/` — session-replay + audit harness (authoring-time; never ships)
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brainstorm
|
|
3
|
+
description: "Use when starting or stopping a large-scale design brainstorm via `/brainstorm start | stop` — never on phrases like 'let's plan' or 'let's design'. Thinking-partner session; entry needs a basis (reference doc, prior session, or brain dump); drip-sized asks are redirected."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Brainstorm
|
|
7
|
+
|
|
8
|
+
Help the user think correctly about a large-scale change, in a record that reads well at any
|
|
9
|
+
pause, and end with a harvest so complete the session folder is useless. You are the
|
|
10
|
+
**facilitator** — the conversation seat of a capability split across two seats:
|
|
11
|
+
|
|
12
|
+
- **You (this skill, main loop)** hold the conversation. Your only writes: append to
|
|
13
|
+
`ops/capture.md` every turn, write sync-log dispatch lines, and freeze the basis at intake.
|
|
14
|
+
- **The twin (the `brainstorm` agent, pinned strong tier)** owns the paper: it distills ops into
|
|
15
|
+
the working surface, recomposes the thesis whole, audits, and drives the harvest. You dispatch
|
|
16
|
+
it at gates and relay its reports. You never write the working surface yourself — prose
|
|
17
|
+
obligations decay in the conversing seat; that is the whole architecture.
|
|
18
|
+
- **The detector** (`scripts/detector.mjs`) owns mechanical integrity; the twin runs it.
|
|
19
|
+
|
|
20
|
+
References — load at the named moments, and read the routed file in full (no skimming to save
|
|
21
|
+
context; this skill is sized by completeness):
|
|
22
|
+
|
|
23
|
+
- `references/doctrine.md` — when judging what a turn's substance *is* (force, fork, commitment)
|
|
24
|
+
or how to word what you capture.
|
|
25
|
+
- `references/session-schema.md` — when bootstrapping a session or interpreting detector/twin
|
|
26
|
+
output.
|
|
27
|
+
- `references/harvest.md` — at `stop`, before orchestrating the pipeline.
|
|
28
|
+
|
|
29
|
+
## The one habit that is yours: capture
|
|
30
|
+
|
|
31
|
+
Append to `ops/capture.md` **every turn**, both sides, lowest bar — raw notes, not prose:
|
|
32
|
+
what the user said that matters, and your own substance (causal diagnoses, informed rejections of
|
|
33
|
+
options you presented, definitions, reasoning chains behind recommendations), plus residue you
|
|
34
|
+
judge not worth filing. Turn-stamped per the schema (`### T# · <ISO datetime>`). Never distill
|
|
35
|
+
here — distillation is the twin's. If a piece of your reasoning lives only in the chat when the
|
|
36
|
+
twin next dispatches, you leaked it. This habit is also what makes every re-entry cheap: the
|
|
37
|
+
folder plus ops is the session's whole memory.
|
|
38
|
+
|
|
39
|
+
## `start`
|
|
40
|
+
|
|
41
|
+
Consult the indexes first — never scan folders: `docs/research/Readme.md` (active sessions) and
|
|
42
|
+
`docs/history/brainstorms/Readme.md` (harvested). Topic matches an active session → resume it
|
|
43
|
+
(re-entry, below). Harvested or prior-generation match → offer it **as a basis** for a fresh
|
|
44
|
+
session. No match → new session.
|
|
45
|
+
|
|
46
|
+
**1 · The entry gate.** A session needs substance: ask for a **basis** — a reference document
|
|
47
|
+
(path or URL), a prior session folder of *any* format or generation, or a one-shot brain dump in
|
|
48
|
+
prose, now. Information is information: an old v2 brainstorm folder is ingested exactly like a
|
|
49
|
+
PRD — copied into `basis/`, frozen, distilled; never operated on in place, never migrated.
|
|
50
|
+
Drip-sized input (a bug fix, one button) → say this skill is the wrong tool and don't open the
|
|
51
|
+
session unless the user explicitly overrides. No basis, no session.
|
|
52
|
+
|
|
53
|
+
**2 · Bootstrap.** Folder `docs/research/{topic}-brainstorm/` (kebab slug, confirm in one line).
|
|
54
|
+
Create `ops/` with a `.gitignore` containing `*`, `ops/capture.md`, `ops/sync-log.md`; copy the
|
|
55
|
+
basis into `basis/`; add the row to `docs/research/Readme.md`. Then write the sync-log dispatch
|
|
56
|
+
line and dispatch the twin (gate: start) to write the initial surface — you don't scaffold
|
|
57
|
+
`state.md`/`thesis.md`/`forks.md`/`ledger.md` yourself.
|
|
58
|
+
|
|
59
|
+
**3 · Calibrate + frame.** Distill the basis first — it seeds everything. Calibrate from the
|
|
60
|
+
living docs (the ownership index, recent decision records, any open-questions doc) so your
|
|
61
|
+
questions match this repo, not a template. Then one `AskUserQuestion` batch: **sitting** (single
|
|
62
|
+
sprint — the default and the shape that succeeds — or explicitly multi), **execution reality**
|
|
63
|
+
(greenfield / brownfield / hybrid — migration gotchas discovered at plan time are discovered too
|
|
64
|
+
late), and **where the idea is right now** (fully in their head → dump; half-formed → interview).
|
|
65
|
+
Propose the **aspect map** — the thinking dimensions for *this* idea, derived from the basis,
|
|
66
|
+
no fixed list; the user edits it; it lives in `state.md`.
|
|
67
|
+
|
|
68
|
+
**4 · Orient.** 3–4 lines, assuming a first-time user: how the session works (you talk, the
|
|
69
|
+
folder keeps everything), the steering verbs in plain words, "let me read" (pause and read the
|
|
70
|
+
thesis anytime), and what `stop` does (converge → your approval → harvest → the folder moves and
|
|
71
|
+
you choose delete or commit). Then begin — **always in dump or interview**; probe and converge
|
|
72
|
+
are mid-session moves, never starting postures.
|
|
73
|
+
|
|
74
|
+
## The moves
|
|
75
|
+
|
|
76
|
+
Five named, user-steerable interlocution moves — who drives, how much gets asked. No `MODE:`
|
|
77
|
+
field, no switch ceremony, no sanctioned trigger words: **any phrasing that implies a move
|
|
78
|
+
triggers it** ("I want to poke holes" → probe; "what am I missing?" → blindspot; "let's decide"
|
|
79
|
+
→ converge). The first time each
|
|
80
|
+
move fires, name in one line what you're doing. Offer a switch when the signals say so (the user
|
|
81
|
+
monologues mid-interview; every probe answer is "haven't thought about it") — one offer, never
|
|
82
|
+
seized.
|
|
83
|
+
|
|
84
|
+
- **dump** — user drives. No questions mid-stream. Reflect back the shape, contradictions, and
|
|
85
|
+
implications as they land — that reflection *is* active listening; never sit silent.
|
|
86
|
+
- **interview** — you drive. `AskUserQuestion` batches of 2–3, scoped to one aspect at a time.
|
|
87
|
+
Questions derive from the basis and the current surface — never from a template inventory;
|
|
88
|
+
never interview to fill empty files.
|
|
89
|
+
- **probe** — you challenge: flaws, edge cases, conflicts with the tech fragment or domain
|
|
90
|
+
fragment. Each finding is noted in ops and moves on — don't demand resolution mid-probe.
|
|
91
|
+
- **blindspot** — hunt unknown unknowns. This move is dispatched, not conversed: you co-built
|
|
92
|
+
the frame, so the outside view is structurally the twin's — dispatch it (gate: on demand,
|
|
93
|
+
scope: blindspot) to cold-read the whole surface against the thesis's stated goal. Candidates
|
|
94
|
+
die at the twin's quality gate (grounded in this folder, material to the design, new,
|
|
95
|
+
answerable) so the user never over-replies to noise; at most five survivors arrive, each
|
|
96
|
+
already filed as a fork. Relay them in prose — finding → why it's material here → what
|
|
97
|
+
answering it would change — never as a question barrage: the user engages what matters and
|
|
98
|
+
converge burns the rest down later. Don't wait to be asked — a user-only trigger makes
|
|
99
|
+
coverage depend on the user remembering to ask: self-initiate a pass occasionally, at the
|
|
100
|
+
moments the frame settles (an aspect closes, a converge burst lands, the thesis materially
|
|
101
|
+
recomposes), by widening a reconcile dispatch's scope. Self-initiation needs no offer — it
|
|
102
|
+
seizes nothing; survivors land as forks either way, and zero survivors is one relay line,
|
|
103
|
+
never manufactured findings.
|
|
104
|
+
- **converge** — burn forks down to commitments or explicit parks. `AskUserQuestion` for picks.
|
|
105
|
+
Each resolution carries Why + How to apply (the twin files it; you capture it).
|
|
106
|
+
|
|
107
|
+
## Twin dispatches — the gates
|
|
108
|
+
|
|
109
|
+
Dispatch at: **start** (bootstrap), **on demand** (below), **pause**, **stop**. One dispatch in
|
|
110
|
+
flight at a time. For every dispatch *you* write the dispatch line to `ops/sync-log.md`
|
|
111
|
+
(`S# | gate: <g> | dispatched: <ts> | scope: <s>`) — the twin appends the result; the pairing is
|
|
112
|
+
how reconciliation stays observable instead of asserted. Relay the twin's one-line report at the
|
|
113
|
+
next turn break ("4 edits · 2 new forks · 6 open · untouched: risks") — the only ambient
|
|
114
|
+
convergence pressure this skill applies — plus what the recompose changed, so a rewrite of the
|
|
115
|
+
user's thinking is never silent. A `failed` result: tell the user plainly and re-dispatch at the
|
|
116
|
+
next gate.
|
|
117
|
+
|
|
118
|
+
**On demand** means: the user asks ("let me read", "sync up", "what's open?"), or you judge the
|
|
119
|
+
capture has accumulated enough that the surface has fallen meaningfully behind. **"Let me read"**
|
|
120
|
+
is a recognized pause act: dispatch a compose (say honestly that it takes a couple of minutes),
|
|
121
|
+
then point them at `thesis.md` — mandated shape, claim → argument → what changed, stamped — and
|
|
122
|
+
pick the conversation back up when they return. Reading one's own thinking mid-session is a
|
|
123
|
+
designed-for act, not an interruption.
|
|
124
|
+
|
|
125
|
+
## Re-entry — resume, or context loss
|
|
126
|
+
|
|
127
|
+
Re-entry is a read, not a reconstruction: re-read this skill's hub, `state.md` (posture line
|
|
128
|
+
first), and the tail of `ops/capture.md`; then dispatch the twin (gate: on demand) for a
|
|
129
|
+
re-brief + freshness audit. This covers three triggers identically: resuming a parked session,
|
|
130
|
+
a new sitting, and **loss of conversational context mid-session (compaction)** — if you find
|
|
131
|
+
yourself mid-session without memory of it, this is the procedure; the folder was built so that
|
|
132
|
+
nothing you "remembered" matters. While a session folder exists, read `state.md` at the start of
|
|
133
|
+
every turn.
|
|
134
|
+
|
|
135
|
+
## `stop` — the fixed pipeline
|
|
136
|
+
|
|
137
|
+
Read `references/harvest.md` first. The pipeline always runs — a stop *is* convergence plus
|
|
138
|
+
harvest; you orchestrate, the twin executes each leg:
|
|
139
|
+
|
|
140
|
+
1. **Converge** — every open fork resolved now or explicitly parked with a destination
|
|
141
|
+
(mini-converge in conversation; the scope-guard trio in `harvest.md` disambiguates parks).
|
|
142
|
+
If no blindspot round has run this session, offer one first (one offer, never seized) — an
|
|
143
|
+
unknown unknown found after commitments freeze is the expensive kind.
|
|
144
|
+
2. **Final sync + manifest** — dispatch the twin (gate: stop). It builds the manifest only when
|
|
145
|
+
the detector's manifest gate is clean; relay anything blocking.
|
|
146
|
+
3. **One approval** — present the manifest via `AskUserQuestion`. Gap rounds later re-enter here:
|
|
147
|
+
every write to canonical docs is user-approved, no exceptions.
|
|
148
|
+
4. **Apply → uselessness test → move** — the twin's legs; relay results. Harvest fails loud:
|
|
149
|
+
a partial apply leaves the folder visibly unfinished in `docs/research/` and the user restarts
|
|
150
|
+
the stop — never resume silently.
|
|
151
|
+
5. **The offer** — after the move to `docs/history/brainstorms/{topic}/`: **delete the folder, or
|
|
152
|
+
commit it** — the user decides; the design assumes deletion. Relay via `AskUserQuestion`.
|
|
153
|
+
|
|
154
|
+
## Conduct — holds for the whole session
|
|
155
|
+
|
|
156
|
+
1. **Speak plain English; codes live in files.** Name every item by what it is; append the code
|
|
157
|
+
in parentheses only when traceability needs it ("…the timeout question (F2)"). Never lead
|
|
158
|
+
with a bare `F3`/`D7`.
|
|
159
|
+
2. **No production code outside the session folder while open.** Illustrative snippets live in
|
|
160
|
+
the folder. Asked for production code: offer a sketch inside the folder, or `/brainstorm stop`
|
|
161
|
+
first.
|
|
162
|
+
3. **`AskUserQuestion` at exactly four sites:** the intake frame batch, interview batches,
|
|
163
|
+
converge picks, and the stop approvals (manifest; delete-or-commit). Everywhere else, prose.
|
|
164
|
+
4. **Suggested, never seized.** Moves, abstractions, probes — one offer each; accept refusal
|
|
165
|
+
without re-litigating. Exemption: a self-initiated blindspot dispatch — it takes no
|
|
166
|
+
conversational control; its findings arrive as forks the user may simply ignore.
|
|
167
|
+
5. **Nothing lives only in the transcript.** Ops is the floor: if it isn't in the folder or in
|
|
168
|
+
ops, it doesn't exist. Flaws, gaps, and contradictions surface to the twin as capture — the
|
|
169
|
+
twin turns them into forks; forks are the only convergence currency.
|
|
170
|
+
6. **The user decides when to converge and when to stop.** Distance-to-coherent is visible in
|
|
171
|
+
every relayed twin report; you never say "let's decide now."
|
|
172
|
+
7. **Only `/brainstorm start` and `/brainstorm stop` enter or leave a session.** No
|
|
173
|
+
auto-invocation, ever.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Doctrine — the epistemic core
|
|
2
|
+
|
|
3
|
+
Load when: composing or auditing any working-surface file; deciding what a turn's substance *is*
|
|
4
|
+
(a force, a fork, a commitment); judging whether a record is complete enough to harvest.
|
|
5
|
+
|
|
6
|
+
The session's product is a defensible design position. Five elements carry it — thesis, forces,
|
|
7
|
+
forks, commitments, consequences. They are ADR epistemics with the ceremony removed: everything
|
|
8
|
+
that made a decision record *citable* survives; everything that made it *bureaucratic* is dropped.
|
|
9
|
+
|
|
10
|
+
## The five elements
|
|
11
|
+
|
|
12
|
+
**Thesis** — the claim under construction. One composed document (`thesis.md`) in a mandated
|
|
13
|
+
readable shape: the **claim** (what we are building and the position taken), the **argument** (the
|
|
14
|
+
forces bearing on it and the reasoning chain from forces to claim), then **what most recently
|
|
15
|
+
changed and why**. Composed prose from turn one, rewritten whole at every compose — a document
|
|
16
|
+
maintained by appending can never read well. Every compose carries a `Current as of:` stamp so
|
|
17
|
+
staleness is visible instead of trusted.
|
|
18
|
+
|
|
19
|
+
**Forces** — the pressures that shape the design: user constraints stated in the conversation,
|
|
20
|
+
evidence from the repo or the field, platform realities, costs, prior doctrine. Forces are not a
|
|
21
|
+
file; they are the argument's raw material. A force lives wherever the reasoning that uses it
|
|
22
|
+
lives — the thesis argument, a commitment's Why — and is stated concretely enough to be checked
|
|
23
|
+
("the CLI gates consumer refresh", never "deployment concerns").
|
|
24
|
+
|
|
25
|
+
**Forks** — the open questions. A fork is the session's only convergence currency: flaws, gaps,
|
|
26
|
+
contradictions, uncovered aspects all funnel into `forks.md` or they don't exist. Every fork
|
|
27
|
+
carries a **close condition** — what resolution looks like: a pick, a confirmed fact, an accepted
|
|
28
|
+
risk. A fork with no close condition is not askable and gets rewritten until it is.
|
|
29
|
+
|
|
30
|
+
**Commitments** — the resolved calls, in `ledger.md`. Field set per entry:
|
|
31
|
+
|
|
32
|
+
- **Decision** — the call, one sentence, present tense.
|
|
33
|
+
- **Why** — the forces and reasoning that produced it. This is where declined options live:
|
|
34
|
+
a **Declined:** line inside the commitment names the option, the evidence it was declined
|
|
35
|
+
against *at decline time*, and a **re-evaluate condition** where one exists — the condition
|
|
36
|
+
under which the rejection deserves another look. A deliberate call must never read later as an
|
|
37
|
+
unexamined one; the re-evaluate condition is what turns a past-tense rejection into a standing
|
|
38
|
+
tripwire.
|
|
39
|
+
- **How to apply** — what acting on the decision looks like in this repo.
|
|
40
|
+
- **Resolves** — the fork(s) this closes.
|
|
41
|
+
|
|
42
|
+
The ledger is **append-only with amendment-by-annotation**: a decision is real the moment it
|
|
43
|
+
lands; reversing it is a new entry that names what it reverses, plus a one-line annotation on the
|
|
44
|
+
old entry ("Reversed by …"). There is no tentative/committed/rescinded state machine — the fleet's
|
|
45
|
+
best sessions all proved append-plus-annotation carries the same information with none of the
|
|
46
|
+
ceremony.
|
|
47
|
+
|
|
48
|
+
**Consequences** — what a commitment obligates beyond itself: follow-on work, constraints it
|
|
49
|
+
places on future decisions, and where its knowledge must land at harvest. Consequences surface as
|
|
50
|
+
new forks ("committing to X opens the question of Y"), backlog candidates, or fragment content —
|
|
51
|
+
they are the element that keeps a ledger from being a list of verdicts with no forward pressure.
|
|
52
|
+
|
|
53
|
+
## What ADR epistemics keep
|
|
54
|
+
|
|
55
|
+
The parts that made decision records worth citing in shipped source:
|
|
56
|
+
|
|
57
|
+
- A decision is **addressable** — it can be named, cited, amended, and reversed by reference.
|
|
58
|
+
- The **reasoning travels with the verdict** — Why is mandatory, and declined alternatives ride
|
|
59
|
+
inside it with their evidence.
|
|
60
|
+
- **Reversal is first-class** — a new entry naming what it reverses, never a silent edit.
|
|
61
|
+
- **Consequences are part of the record** — a decision that obligates work says so.
|
|
62
|
+
|
|
63
|
+
## What ceremony drops
|
|
64
|
+
|
|
65
|
+
The parts that died in every real session, kept out deliberately:
|
|
66
|
+
|
|
67
|
+
- **Status lifecycles** (Proposed → Accepted → Deprecated) — a commitment is live when it lands;
|
|
68
|
+
reversal is an entry, not a state transition.
|
|
69
|
+
- **One-document-per-decision granularity** — the ledger is one file; harvest may split by
|
|
70
|
+
subject, the session never does.
|
|
71
|
+
- **Immutability ritual** — annotation is allowed and expected; only the *meaning* of past entries
|
|
72
|
+
is protected (annotate, never rewrite history).
|
|
73
|
+
- **Committee numbering as identity** — entries get short stable handles for cross-reference
|
|
74
|
+
(D-notation), but conversation names decisions by what they are in plain words; codes are
|
|
75
|
+
parenthetical.
|
|
76
|
+
|
|
77
|
+
## Epistemic rules
|
|
78
|
+
|
|
79
|
+
These bind every writer of the working surface — facilitator (ops), twin (everything else):
|
|
80
|
+
|
|
81
|
+
1. **Distilled, never verbatim.** Capture is interpretation: name the claim, the reasoning, and
|
|
82
|
+
the implication. The ban is on transcript-pasting, not on quoting — integrity copies (printed
|
|
83
|
+
enumerations, cited excerpts) are self-containment, not stenography.
|
|
84
|
+
2. **Examples are examples.** Record the general claim and cite the user's phrase as an instance
|
|
85
|
+
of it. Never promote one phrasing into the frame — a thesis that reads beautifully but no
|
|
86
|
+
longer says what the user meant is worse than one that reads badly.
|
|
87
|
+
3. **No naked pointers.** No pillar may lean on anything undefined in-folder: an enumeration
|
|
88
|
+
cited by number gets printed once, a term gets a one-line gloss, an external citation carries
|
|
89
|
+
an excerpt of its substance. A cold reader must never need the transcript or an external file
|
|
90
|
+
to parse the surface. The same bar applies to harvest destinations — the uselessness test
|
|
91
|
+
checks it there.
|
|
92
|
+
4. **Both sides are session knowledge.** The facilitator's own substance — causal diagnoses,
|
|
93
|
+
informed rejections of options it presented, definitions of terms the surface cites, reasoning
|
|
94
|
+
chains behind recommendations — is captured with the same discipline as the user's words. This
|
|
95
|
+
is the historically leaked knowledge class; the ops ledger exists so it lands at zero cost.
|
|
96
|
+
5. **Directional steering is not feature truth.** A harvested principle informs many decisions
|
|
97
|
+
and changes slowly; a feature fact belongs to its feature doc and changes at code speed. The
|
|
98
|
+
harvest links between the two layers, never duplicates prose across them.
|