mishkan-harness 0.1.0
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/LICENSE +21 -0
- package/README.md +205 -0
- package/bin/mishkan.js +221 -0
- package/docs/design/MISHKAN_agent_aliases.md +140 -0
- package/docs/design/MISHKAN_decisions.md +172 -0
- package/docs/design/MISHKAN_harness_design.md +820 -0
- package/docs/design/MISHKAN_ontology.md +87 -0
- package/docs/design/MISHKAN_token_optimisation.md +181 -0
- package/docs/engineer/README.md +37 -0
- package/docs/engineer/profile.example.md +79 -0
- package/docs/usage/01-installation.md +178 -0
- package/docs/usage/02-project-init.md +151 -0
- package/docs/usage/03-orchestration.md +218 -0
- package/docs/usage/04-memory-layer.md +201 -0
- package/docs/usage/05-selective-ingest.md +177 -0
- package/docs/usage/06-llm-providers.md +195 -0
- package/docs/usage/07-troubleshooting.md +316 -0
- package/docs/usage/08-glossary.md +154 -0
- package/docs/usage/09-workflows.md +123 -0
- package/docs/usage/README.md +77 -0
- package/package.json +43 -0
- package/payload/install/settings.hooks.json +47 -0
- package/payload/mishkan/AGENT_SPEC.md +154 -0
- package/payload/mishkan/agents/ahikam.md +58 -0
- package/payload/mishkan/agents/aholiab.md +68 -0
- package/payload/mishkan/agents/asaph.md +73 -0
- package/payload/mishkan/agents/baruch.md +88 -0
- package/payload/mishkan/agents/benaiah.md +76 -0
- package/payload/mishkan/agents/bezalel.md +83 -0
- package/payload/mishkan/agents/caleb.md +74 -0
- package/payload/mishkan/agents/deborah.md +63 -0
- package/payload/mishkan/agents/elasah.md +58 -0
- package/payload/mishkan/agents/eliashib.md +68 -0
- package/payload/mishkan/agents/ezra.md +69 -0
- package/payload/mishkan/agents/hanun.md +64 -0
- package/payload/mishkan/agents/hiram.md +68 -0
- package/payload/mishkan/agents/hizkiah.md +76 -0
- package/payload/mishkan/agents/huldah.md +59 -0
- package/payload/mishkan/agents/huram.md +66 -0
- package/payload/mishkan/agents/hushai.md +59 -0
- package/payload/mishkan/agents/igal.md +58 -0
- package/payload/mishkan/agents/ira.md +86 -0
- package/payload/mishkan/agents/jahaziel.md +71 -0
- package/payload/mishkan/agents/jakin.md +66 -0
- package/payload/mishkan/agents/jehonathan.md +62 -0
- package/payload/mishkan/agents/jehoshaphat.md +68 -0
- package/payload/mishkan/agents/joab.md +71 -0
- package/payload/mishkan/agents/joah.md +62 -0
- package/payload/mishkan/agents/maaseiah.md +61 -0
- package/payload/mishkan/agents/meremoth.md +65 -0
- package/payload/mishkan/agents/meshullam.md +67 -0
- package/payload/mishkan/agents/nathan.md +70 -0
- package/payload/mishkan/agents/nehemiah.md +93 -0
- package/payload/mishkan/agents/obed.md +60 -0
- package/payload/mishkan/agents/oholiab.md +67 -0
- package/payload/mishkan/agents/palal.md +63 -0
- package/payload/mishkan/agents/phinehas.md +73 -0
- package/payload/mishkan/agents/rehum.md +60 -0
- package/payload/mishkan/agents/salma.md +69 -0
- package/payload/mishkan/agents/seraiah.md +73 -0
- package/payload/mishkan/agents/shallum.md +66 -0
- package/payload/mishkan/agents/shaphan.md +64 -0
- package/payload/mishkan/agents/shemaiah.md +67 -0
- package/payload/mishkan/agents/shevna.md +58 -0
- package/payload/mishkan/agents/uriah.md +70 -0
- package/payload/mishkan/agents/zaccur.md +58 -0
- package/payload/mishkan/agents/zadok.md +67 -0
- package/payload/mishkan/agents/zerubbabel.md +69 -0
- package/payload/mishkan/cognee/.env.curated.example +61 -0
- package/payload/mishkan/cognee/.env.example +165 -0
- package/payload/mishkan/cognee/Dockerfile +50 -0
- package/payload/mishkan/cognee/README.md +129 -0
- package/payload/mishkan/cognee/docker-compose.curated-ui.yml +61 -0
- package/payload/mishkan/cognee/docker-compose.curated.yml +85 -0
- package/payload/mishkan/cognee/docker-compose.hardening.yml +16 -0
- package/payload/mishkan/cognee/docker-compose.selfhosted.yml +114 -0
- package/payload/mishkan/cognee/docker-compose.ui.yml +70 -0
- package/payload/mishkan/cognee/docker-compose.yml +71 -0
- package/payload/mishkan/cognee/ingest-curated.py +92 -0
- package/payload/mishkan/commands/dep-audit.md +24 -0
- package/payload/mishkan/commands/mishkan-init.md +25 -0
- package/payload/mishkan/commands/mishkan-resume.md +21 -0
- package/payload/mishkan/commands/promote.md +19 -0
- package/payload/mishkan/commands/sefer-pull.md +19 -0
- package/payload/mishkan/commands/sprint-close.md +21 -0
- package/payload/mishkan/config/curated-library.yaml +113 -0
- package/payload/mishkan/config/improvement-queries.md +29 -0
- package/payload/mishkan/config/model-routing.yaml +87 -0
- package/payload/mishkan/config/projects.yaml +38 -0
- package/payload/mishkan/evals/baruch/README.md +93 -0
- package/payload/mishkan/evals/baruch/fixtures/invalid/bad-outcome-enum.json +15 -0
- package/payload/mishkan/evals/baruch/fixtures/invalid/bad-sprint-pattern.json +15 -0
- package/payload/mishkan/evals/baruch/fixtures/invalid/bad-trigger-enum.json +15 -0
- package/payload/mishkan/evals/baruch/fixtures/invalid/malformed-json.json +7 -0
- package/payload/mishkan/evals/baruch/fixtures/invalid/missing-required-field.json +14 -0
- package/payload/mishkan/evals/baruch/fixtures/valid/blocked-vendor.json +15 -0
- package/payload/mishkan/evals/baruch/fixtures/valid/curated-shortcircuit.json +15 -0
- package/payload/mishkan/evals/baruch/fixtures/valid/partial-no-write.json +14 -0
- package/payload/mishkan/evals/baruch/fixtures/valid/resolved-cross-harness.json +15 -0
- package/payload/mishkan/evals/baruch/golden_case/expected.yaml +35 -0
- package/payload/mishkan/evals/baruch/golden_case/input.yaml +47 -0
- package/payload/mishkan/evals/baruch/golden_case/produced.json +15 -0
- package/payload/mishkan/evals/baruch/run.sh +129 -0
- package/payload/mishkan/hooks/model-route.py +96 -0
- package/payload/mishkan/hooks/post-tool-observe.sh +45 -0
- package/payload/mishkan/hooks/pre-tool-security.sh +150 -0
- package/payload/mishkan/hooks/session-start.sh +20 -0
- package/payload/mishkan/hooks/stop-reporter.sh +29 -0
- package/payload/mishkan/ontology.md +87 -0
- package/payload/mishkan/rules/backend/yasad.md +23 -0
- package/payload/mishkan/rules/common/dependencies.md +53 -0
- package/payload/mishkan/rules/common/quality.md +16 -0
- package/payload/mishkan/rules/common/security.md +20 -0
- package/payload/mishkan/rules/documentation/sefer.md +19 -0
- package/payload/mishkan/rules/frontend/panim.md +21 -0
- package/payload/mishkan/rules/infrastructure/migdal.md +22 -0
- package/payload/mishkan/scripts/dependency-audit.sh +171 -0
- package/payload/mishkan/scripts/ensure-curated-box.sh +66 -0
- package/payload/mishkan/scripts/mishkan-ingest.sh +92 -0
- package/payload/mishkan/scripts/observability-aggregate.sh +57 -0
- package/payload/mishkan/scripts/seed-curated-library.sh +62 -0
- package/payload/mishkan/scripts/sync-profile.sh +65 -0
- package/payload/mishkan/scripts/validate-research-log.sh +108 -0
- package/payload/mishkan/skills/asaph-a11y-seo-craft/SKILL.md +289 -0
- package/payload/mishkan/skills/baruch-research-reporting-craft/SKILL.md +460 -0
- package/payload/mishkan/skills/benaiah-devsecops-craft/SKILL.md +329 -0
- package/payload/mishkan/skills/bezalel-cto-craft/SKILL.md +391 -0
- package/payload/mishkan/skills/caleb-web-research-craft/SKILL.md +306 -0
- package/payload/mishkan/skills/cognee-promote/SKILL.md +40 -0
- package/payload/mishkan/skills/cognee-quickstart/SKILL.md +66 -0
- package/payload/mishkan/skills/context-compress/SKILL.md +36 -0
- package/payload/mishkan/skills/deborah-ux-craft/SKILL.md +295 -0
- package/payload/mishkan/skills/dependency-audit/SKILL.md +59 -0
- package/payload/mishkan/skills/dependency-vetting/SKILL.md +59 -0
- package/payload/mishkan/skills/documentation-craft/SKILL.md +468 -0
- package/payload/mishkan/skills/ezra-research-formulation-craft/SKILL.md +319 -0
- package/payload/mishkan/skills/hanun-observability-craft/SKILL.md +312 -0
- package/payload/mishkan/skills/hiram-ui-craft/SKILL.md +334 -0
- package/payload/mishkan/skills/hizkiah-implementation-craft/SKILL.md +701 -0
- package/payload/mishkan/skills/hushai-security-advisor-craft/SKILL.md +282 -0
- package/payload/mishkan/skills/ira-code-security-craft/SKILL.md +553 -0
- package/payload/mishkan/skills/jakin-intent-clarification-craft/SKILL.md +299 -0
- package/payload/mishkan/skills/jehonathan-publication-craft/SKILL.md +262 -0
- package/payload/mishkan/skills/joab-app-security-craft/SKILL.md +266 -0
- package/payload/mishkan/skills/meremoth-devops-craft/SKILL.md +298 -0
- package/payload/mishkan/skills/meshullam-infra-design-craft/SKILL.md +302 -0
- package/payload/mishkan/skills/mishkan-ingest/SKILL.md +65 -0
- package/payload/mishkan/skills/mishkan-init/SKILL.md +65 -0
- package/payload/mishkan/skills/nathan-architecture-craft/SKILL.md +547 -0
- package/payload/mishkan/skills/nehemiah-pm-craft/SKILL.md +484 -0
- package/payload/mishkan/skills/obed-asset-pipeline-craft/SKILL.md +286 -0
- package/payload/mishkan/skills/oholiab-design-system-craft/SKILL.md +334 -0
- package/payload/mishkan/skills/palal-systems-craft/SKILL.md +281 -0
- package/payload/mishkan/skills/qa-evaluation-craft/SKILL.md +406 -0
- package/payload/mishkan/skills/rehum-sre-advisor-craft/SKILL.md +228 -0
- package/payload/mishkan/skills/reporter-discipline-craft/SKILL.md +351 -0
- package/payload/mishkan/skills/research-pipeline/SKILL.md +55 -0
- package/payload/mishkan/skills/salma-frontend-implementation-craft/SKILL.md +369 -0
- package/payload/mishkan/skills/sefer-pull/SKILL.md +37 -0
- package/payload/mishkan/skills/shallum-database-craft/SKILL.md +347 -0
- package/payload/mishkan/skills/shaphan-summarisation-craft/SKILL.md +271 -0
- package/payload/mishkan/skills/shemaiah-evaluation-craft/SKILL.md +342 -0
- package/payload/mishkan/skills/sprint-report/SKILL.md +28 -0
- package/payload/mishkan/skills/team-lead-craft/SKILL.md +457 -0
- package/payload/mishkan/skills/zadok-contract-craft/SKILL.md +520 -0
- package/payload/mishkan/templates/case-node.schema.json +22 -0
- package/payload/mishkan/templates/mcp.json +22 -0
- package/payload/mishkan/templates/observability-log.schema.json +24 -0
- package/payload/mishkan/templates/project-CLAUDE.md +47 -0
- package/payload/mishkan/templates/research-log.schema.json +40 -0
- package/payload/mishkan/templates/settings.json +12 -0
- package/payload/mishkan/templates/settings.local.json +6 -0
- package/payload/mishkan/templates/sprint-state.schema.json +47 -0
- package/payload/mishkan/templates/team-report.schema.json +50 -0
- package/payload/mishkan/templates/user-CLAUDE.md +62 -0
- package/payload/mishkan/workflows/README.md +88 -0
- package/payload/mishkan/workflows/mishkan-architecture-panel.js +156 -0
- package/payload/mishkan/workflows/mishkan-codebase-audit.js +188 -0
- package/payload/mishkan/workflows/mishkan-deep-research.js +251 -0
- package/payload/mishkan/workflows/mishkan-init.js +156 -0
- package/payload/mishkan/workflows/mishkan-migration-wave.js +180 -0
- package/payload/mishkan/workflows/mishkan-release-readiness.js +163 -0
- package/payload/mishkan/workflows/mishkan-sprint-close.js +112 -0
- package/payload/user/CLAUDE.md +62 -0
- package/payload/user/rules/engineer-standards.md +66 -0
- package/payload/user/rules/y4nn-standards.md +167 -0
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nathan-architecture-craft
|
|
3
|
+
description: How Nathan reasons about software architecture decisions. Invoke when a design decision is in scope — module boundaries, service decomposition, data flow, sync/async, consistency model, state placement, contract evolution. Long-form craft skill; loads only when Nathan reaches for it.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Nathan — Architecture Craft
|
|
7
|
+
|
|
8
|
+
> Not a checklist. The way the prophet Nathan in the harness actually *thinks*
|
|
9
|
+
> when handed a system-design decision, with worked examples and the failure
|
|
10
|
+
> modes he watches for.
|
|
11
|
+
|
|
12
|
+
This skill is invoked **only when an architecture decision is in scope**. It is
|
|
13
|
+
not loaded into Nathan's context on every call — Nathan's agent file is
|
|
14
|
+
deliberately short. When the situation calls for design judgement, he reaches
|
|
15
|
+
for this skill; on routine routing or read-only review, he does not.
|
|
16
|
+
|
|
17
|
+
The orientation below is written as Nathan's working voice so future revisions
|
|
18
|
+
keep the same posture.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 1. What an architecture decision actually is
|
|
23
|
+
|
|
24
|
+
A decision is architectural when at least one of these is true:
|
|
25
|
+
|
|
26
|
+
- **Hard to reverse.** Changing it later requires a coordinated cross-component
|
|
27
|
+
effort, a migration, or a deprecation window. (Examples: choosing event
|
|
28
|
+
sourcing vs. CRUD; picking the consistency model of the user store; settling
|
|
29
|
+
the sync/async boundary between two services.)
|
|
30
|
+
- **Costs blast-radius if wrong.** A wrong call propagates into surface area
|
|
31
|
+
for many other decisions — every later team inherits the constraint.
|
|
32
|
+
- **Touches the contract.** Anything that changes the published shape of an
|
|
33
|
+
API, an event, a schema, or a guarantee.
|
|
34
|
+
- **Resolves a tension between forces** that won't go away on their own
|
|
35
|
+
(latency vs. consistency; flexibility vs. simplicity; coupling vs.
|
|
36
|
+
duplication; throughput vs. complexity).
|
|
37
|
+
|
|
38
|
+
Cosmetic, internal, replaceable-by-one-engineer-in-an-afternoon decisions are
|
|
39
|
+
**not** architectural. Don't dress them up as if they were. Don't write ADRs
|
|
40
|
+
for them.
|
|
41
|
+
|
|
42
|
+
If you cannot name the **force tension** the decision resolves, you do not
|
|
43
|
+
have an architecture decision — you have a coding decision. Hand it back.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 2. The sequence Nathan holds (non-negotiable)
|
|
48
|
+
|
|
49
|
+
`PRD → SRS → CONTRACT → ARCHITECTURE → MODELING → implementation`
|
|
50
|
+
|
|
51
|
+
Three things this sequence enforces:
|
|
52
|
+
|
|
53
|
+
1. **Decide before you ship.** A skipped stage means a load-bearing assumption
|
|
54
|
+
never got named, so it gets discovered the hard way — usually in production.
|
|
55
|
+
2. **Decisions land at the layer they belong to.** The architecture decision
|
|
56
|
+
sits where the rest of the architecture can see it, not buried in a
|
|
57
|
+
pull-request comment.
|
|
58
|
+
3. **Reviewable diffs.** When the spec is real, the diff implements the spec.
|
|
59
|
+
When the spec is missing, the diff *is* the spec — and nobody can review
|
|
60
|
+
it without re-deriving the intent.
|
|
61
|
+
|
|
62
|
+
When a stage is genuinely not needed, **say so explicitly and record why**.
|
|
63
|
+
"This is a single-service CLI; SRS is just the PRD restated, so we skip and
|
|
64
|
+
proceed to CONTRACT." Skipping silently is the violation — not skipping itself.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 3. The questions Nathan asks before drawing a single box
|
|
69
|
+
|
|
70
|
+
Architecture work is not started until these are answered, in writing:
|
|
71
|
+
|
|
72
|
+
1. **What problem are we solving** — in one sentence, no jargon. If you can't
|
|
73
|
+
say it in one sentence, you are solving two problems and have to split.
|
|
74
|
+
2. **Who is the user** — the human, the system, or the next service. Their
|
|
75
|
+
constraints are the constraints.
|
|
76
|
+
3. **What is the read shape vs. the write shape** — they almost never match.
|
|
77
|
+
The asymmetry is the first source of structure.
|
|
78
|
+
4. **What is the consistency requirement** — strong, read-your-writes,
|
|
79
|
+
eventual? A specific bound? Stated by whom? Will it survive contact with
|
|
80
|
+
the business?
|
|
81
|
+
5. **What is the failure mode that is unacceptable** — data loss, stale read,
|
|
82
|
+
double-write, downtime? Pick one. Optimising for "all of them" optimises
|
|
83
|
+
for none.
|
|
84
|
+
6. **What is in scope and what is *out* of scope** — name three things you
|
|
85
|
+
are deliberately not solving. If you can't, the scope is too wide.
|
|
86
|
+
7. **What is the time-to-deprecation horizon** — three months, three years,
|
|
87
|
+
ten years? Different horizons demand different decisions; pretending the
|
|
88
|
+
horizon is unknown is a dodge.
|
|
89
|
+
8. **What changes are likely** — not "what *might* change," but what the
|
|
90
|
+
roadmap and the people are already pointing at. Couple to the stable axes.
|
|
91
|
+
9. **What is the constraint that is non-negotiable** — regulatory, hardware,
|
|
92
|
+
team size, deadline. The constraint is the start of the design, not an
|
|
93
|
+
afterthought.
|
|
94
|
+
|
|
95
|
+
If any of these is genuinely unknown after honest investigation, **invoke the
|
|
96
|
+
research pipeline** (`research-pipeline` skill) — do not guess. Guessing on
|
|
97
|
+
question 4 (consistency) and question 5 (failure mode) is how systems are
|
|
98
|
+
built that work in the demo and fail in production.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 4. The four forces Nathan weighs
|
|
103
|
+
|
|
104
|
+
Every architecture decision resolves at least one of:
|
|
105
|
+
|
|
106
|
+
| Force pair | Resolved by |
|
|
107
|
+
|---|---|
|
|
108
|
+
| **Coupling vs. duplication** | Conway's Law + change-rate analysis |
|
|
109
|
+
| **Latency vs. consistency** | CAP under partition, PACELC otherwise |
|
|
110
|
+
| **Simplicity vs. flexibility** | YAGNI vs. the horizon (§3.7) |
|
|
111
|
+
| **Throughput vs. complexity** | Amdahl + operational headroom |
|
|
112
|
+
|
|
113
|
+
Two craft rules:
|
|
114
|
+
|
|
115
|
+
- **Name the trade-off explicitly.** A decision that names no trade-off is
|
|
116
|
+
either trivial or dishonest. Both must be flagged.
|
|
117
|
+
- **Choose the side that fails *legibly*.** When a system fails, it should
|
|
118
|
+
fail in the shape its operators can debug. Hidden complexity that silently
|
|
119
|
+
degrades is the worst failure mode in any production system.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 5. The shapes Nathan reaches for first
|
|
124
|
+
|
|
125
|
+
When the answers in §3 land in certain configurations, the shape is usually
|
|
126
|
+
predictable. Reach for these first; depart from them only with reason.
|
|
127
|
+
|
|
128
|
+
| If the situation is… | The first shape is usually… | The thing to watch for |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| Read-heavy, write-rare, eventual is fine | CQRS read model + materialised view | Stale-read SLO must be stated explicitly |
|
|
131
|
+
| Write-heavy, audit-mandatory, replayability needed | Event sourcing + projections | Schema evolution of events, projection rebuild cost |
|
|
132
|
+
| Multi-tenant SaaS, shared schema | Tenancy at the row level + RLS | "Noisy neighbour" on shared resources |
|
|
133
|
+
| Long-running workflow with retries | Orchestrator + state machine (Temporal-shaped) | Idempotency keys on every step |
|
|
134
|
+
| Synchronous user-facing path + slow integration | Sync boundary + async outbox | Outbox failure = silent data loss; alarm on it |
|
|
135
|
+
| Heterogeneous downstream sinks | Domain event bus + per-sink translator | Bus becomes a coupling point; resist enrichment |
|
|
136
|
+
| Strong consistency across two stores | One store of truth + projections | "Distributed transaction" is the smell; refactor |
|
|
137
|
+
| High cardinality, low write rate | Append-only log + index by query shape | Write-time vs read-time indexing trade |
|
|
138
|
+
|
|
139
|
+
These are *first reaches*, not laws. The point is to make the alternative
|
|
140
|
+
visible: when you pick something else, you state what it solved that the first
|
|
141
|
+
shape didn't.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 6. How Nathan writes an ADR (MADR shape, with bite)
|
|
146
|
+
|
|
147
|
+
```markdown
|
|
148
|
+
# ADR-NNNN: <decision in one line, present tense>
|
|
149
|
+
|
|
150
|
+
- Status: proposed | accepted | superseded by ADR-X
|
|
151
|
+
- Date: YYYY-MM-DD
|
|
152
|
+
- Deciders: <names / aliases>
|
|
153
|
+
|
|
154
|
+
## Context and Problem Statement
|
|
155
|
+
|
|
156
|
+
<2–4 sentences. What forced this decision now. The §3 answers compressed.>
|
|
157
|
+
|
|
158
|
+
## Decision Drivers
|
|
159
|
+
|
|
160
|
+
- <constraint or quality attribute, named>
|
|
161
|
+
- <…>
|
|
162
|
+
|
|
163
|
+
## Considered Options
|
|
164
|
+
|
|
165
|
+
1. <Option A — short label>
|
|
166
|
+
2. <Option B — short label>
|
|
167
|
+
3. <Option C — short label>
|
|
168
|
+
|
|
169
|
+
## Decision Outcome
|
|
170
|
+
|
|
171
|
+
Chosen: **<Option X>**, because <one sentence — the force it resolves>.
|
|
172
|
+
|
|
173
|
+
### Consequences
|
|
174
|
+
|
|
175
|
+
- Positive: <what becomes easier>
|
|
176
|
+
- Negative: <what becomes harder; the trade we accepted>
|
|
177
|
+
- Neutral: <what changes shape without changing cost>
|
|
178
|
+
|
|
179
|
+
## Pros and Cons of the Options
|
|
180
|
+
|
|
181
|
+
### <Option A>
|
|
182
|
+
- Good: …
|
|
183
|
+
- Good: …
|
|
184
|
+
- Bad: …
|
|
185
|
+
- Bad: …
|
|
186
|
+
|
|
187
|
+
### <Option B>
|
|
188
|
+
…
|
|
189
|
+
|
|
190
|
+
## Implementation Notes (only what is load-bearing)
|
|
191
|
+
|
|
192
|
+
- <Contract changes>
|
|
193
|
+
- <Migration shape>
|
|
194
|
+
- <Operational implications>
|
|
195
|
+
|
|
196
|
+
## Out of Scope
|
|
197
|
+
|
|
198
|
+
- <three explicitly-not-solved things from §3.6>
|
|
199
|
+
|
|
200
|
+
## Open Questions
|
|
201
|
+
|
|
202
|
+
- <if any. If many, the decision is premature.>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Three rules on ADR writing:
|
|
206
|
+
|
|
207
|
+
- **Every option section names at least one Bad.** "Considered Options" with
|
|
208
|
+
no negatives in any option are not considered — they are listed.
|
|
209
|
+
- **The Decision Outcome sentence names the force.** Not "we chose X because
|
|
210
|
+
it is better" — "we chose X because it resolves <coupling vs. duplication>
|
|
211
|
+
in favour of duplication, on the basis that the two domains change at
|
|
212
|
+
different rates."
|
|
213
|
+
- **Out of Scope is mandatory and non-empty.** If you can't name three things
|
|
214
|
+
you are not solving, your scope is leaky.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## 7. Recurring traps — what Nathan rejects on sight
|
|
219
|
+
|
|
220
|
+
These come back over and over. Reject them by name; explain the reason; offer
|
|
221
|
+
the durable alternative.
|
|
222
|
+
|
|
223
|
+
1. **"We'll make it generic so it's reusable."**
|
|
224
|
+
Premature generality is the most expensive mistake in this category.
|
|
225
|
+
Generic-first is duplication's evil twin: you pay coupling cost forever
|
|
226
|
+
for reuse you may never need. Build the second instance first; abstract
|
|
227
|
+
only when the third reveals the shape. *(Cite: §4 simplicity vs.
|
|
228
|
+
flexibility.)*
|
|
229
|
+
|
|
230
|
+
2. **"Distributed transaction across services."**
|
|
231
|
+
The word "transaction" spanning two services is a smell, not a solution.
|
|
232
|
+
The durable shapes are: one store of truth + projections; or a saga with
|
|
233
|
+
compensations; or split the bounded contexts so the cross-service write
|
|
234
|
+
stops being a single transaction conceptually. Reject the framing.
|
|
235
|
+
|
|
236
|
+
3. **"We'll sync them eventually."**
|
|
237
|
+
Eventual consistency is a real engineering choice and a load-bearing word
|
|
238
|
+
— *"eventually"* without a stated bound is not eventual consistency, it
|
|
239
|
+
is no consistency. Insist on a numeric bound (p99, max staleness) or
|
|
240
|
+
reject the design.
|
|
241
|
+
|
|
242
|
+
4. **"We can refactor later."**
|
|
243
|
+
"Later" is when the refactor is most expensive and least likely.
|
|
244
|
+
Architectural debt is not a sprint task; it is a tax on every future
|
|
245
|
+
feature. If a refactor is genuinely deferrable, name the deferring
|
|
246
|
+
condition explicitly: *"refactor when X measurable threshold is crossed."*
|
|
247
|
+
No threshold = no refactor.
|
|
248
|
+
|
|
249
|
+
5. **"Caching will fix it."**
|
|
250
|
+
Caching trades clarity of correctness for speed. Before adding a cache,
|
|
251
|
+
answer: invalidation policy, staleness budget, who pays the cost on
|
|
252
|
+
miss, and what happens on cache failure. A cache without an invalidation
|
|
253
|
+
strategy is an undocumented eventual-consistency boundary in disguise.
|
|
254
|
+
|
|
255
|
+
6. **"Just put it in Redis / Kafka / Postgres."**
|
|
256
|
+
The instinctive technology answer skips the §3 questions. Demand the
|
|
257
|
+
read shape, write shape, and consistency requirement before the tool
|
|
258
|
+
choice. The tool follows the shape; never the other way.
|
|
259
|
+
|
|
260
|
+
7. **"Microservices, because monoliths don't scale."**
|
|
261
|
+
Monoliths scale fine for most loads. Service decomposition is justified
|
|
262
|
+
by *team boundaries* and *independent deploy cadence*, not by load. Most
|
|
263
|
+
shops should be modular monolith with strict module boundaries until
|
|
264
|
+
Conway's Law forces the split.
|
|
265
|
+
|
|
266
|
+
8. **"We'll generate it from the schema."**
|
|
267
|
+
Code-generation is fine; it is also a coupling decision. The generated
|
|
268
|
+
surface becomes a contract; treat its regeneration as a contract change,
|
|
269
|
+
with the migration discipline that implies.
|
|
270
|
+
|
|
271
|
+
9. **"It's only for one team."**
|
|
272
|
+
The audience claim is rarely durable. Anything written down spreads.
|
|
273
|
+
Design for the audience that will inevitably read it, not the audience
|
|
274
|
+
that currently sits in the room.
|
|
275
|
+
|
|
276
|
+
10. **"Let's defer naming."**
|
|
277
|
+
Naming is the architecture decision in disguise. Bad names propagate as
|
|
278
|
+
bad mental models. If a thing cannot be named precisely, the boundary
|
|
279
|
+
is not yet right. *(Standards rule 11: naming is load-bearing.)*
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## 8. Worked example A — "Should the search be in-process or a service?"
|
|
284
|
+
|
|
285
|
+
Situation given to Nathan: a Laravel app has a fast-growing product search.
|
|
286
|
+
The PM wants Elasticsearch. The team is three people. Read load is 200 req/s
|
|
287
|
+
peak; writes are 50/day.
|
|
288
|
+
|
|
289
|
+
Nathan's path:
|
|
290
|
+
|
|
291
|
+
**§3 answers extracted:**
|
|
292
|
+
|
|
293
|
+
1. Problem: full-text + faceted search over ~80k products.
|
|
294
|
+
2. User: anonymous browsers; latency budget 200ms p95.
|
|
295
|
+
3. Read shape: query by free text + 4 facets, sorted by relevance. Write
|
|
296
|
+
shape: nightly catalog sync, small daily diffs.
|
|
297
|
+
4. Consistency: read-your-writes for editors; eventual (≤ 30s) for browsers
|
|
298
|
+
is acceptable, business confirmed.
|
|
299
|
+
5. Unacceptable failure: zero-result false-empty on a known-good query.
|
|
300
|
+
6. Out of scope: personalisation; semantic search; multi-language.
|
|
301
|
+
7. Horizon: 18 months to potential acquisition; the team is small.
|
|
302
|
+
8. Likely changes: catalog grows 2×; facet count grows; search-as-you-type.
|
|
303
|
+
9. Constraint: no new infra ops person; the three engineers are it.
|
|
304
|
+
|
|
305
|
+
**Force tension named:** *flexibility vs. simplicity* (§4.3). Elasticsearch
|
|
306
|
+
gives flexibility for the likely changes (§3.8). It also gives a new
|
|
307
|
+
operational surface to a team that has no operator (§3.9).
|
|
308
|
+
|
|
309
|
+
**First-reach shape (§5):** read-heavy + eventual-fine + change axis on the
|
|
310
|
+
read shape → CQRS read model + materialised view. In Postgres terms:
|
|
311
|
+
materialised views + `pg_trgm` + GIN indexes; or a `tsvector`-backed search
|
|
312
|
+
table.
|
|
313
|
+
|
|
314
|
+
**Decision Nathan proposes:** Postgres-native search now, with a clean
|
|
315
|
+
*search-port* abstraction (interface in the application boundary) so the
|
|
316
|
+
switch to Elasticsearch later is a port-implementation swap, not a rewrite.
|
|
317
|
+
|
|
318
|
+
**The trade-off, named:** we trade *peak flexibility* (no semantic search
|
|
319
|
+
yet, harder synonyms, weaker relevance tuning) for *peak simplicity* (no new
|
|
320
|
+
service, no new ops surface, no team capacity tax). The deferring condition
|
|
321
|
+
is stated: *"swap to Elasticsearch when relevance complaints exceed 1% of
|
|
322
|
+
queries or when facet count crosses 12."*
|
|
323
|
+
|
|
324
|
+
**ADR Out of Scope:** semantic search; cross-language analysis; ranking ML.
|
|
325
|
+
|
|
326
|
+
**What Nathan rejects:** the framing that "Elasticsearch is the answer
|
|
327
|
+
because catalogue search is what Elasticsearch is for." Tools follow shapes,
|
|
328
|
+
not category labels.
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## 9. Worked example B — "Two services need the same user data"
|
|
333
|
+
|
|
334
|
+
Situation: a Forms service and a Meet service both need user identity,
|
|
335
|
+
display name, avatar, locale. Currently both call the IAM service on every
|
|
336
|
+
request.
|
|
337
|
+
|
|
338
|
+
**§3 answers extracted:**
|
|
339
|
+
|
|
340
|
+
1. Problem: latency on the hot path (IAM round-trip × 2 per page).
|
|
341
|
+
2. User: end-users — every page render pays.
|
|
342
|
+
3. Read shape: identity fields, low cardinality per session, high read
|
|
343
|
+
frequency. Write shape: profile updates ~1/user/month.
|
|
344
|
+
4. Consistency: stale avatar for ≤ 60s is fine; stale display name on a
|
|
345
|
+
freshly-renamed user looks broken — must be < 5s.
|
|
346
|
+
5. Unacceptable failure: wrong user identity rendered.
|
|
347
|
+
6. Out of scope: SSO change; permission model; role propagation.
|
|
348
|
+
7. Horizon: this stays; identity does not get cheaper.
|
|
349
|
+
8. Likely changes: more services will want the same data.
|
|
350
|
+
9. Constraint: every service team owns its own deploy; no cross-team
|
|
351
|
+
release coordination available.
|
|
352
|
+
|
|
353
|
+
**Force tension named:** *coupling vs. duplication* (§4.1). Calling IAM
|
|
354
|
+
synchronously couples every service to IAM availability and adds a hop.
|
|
355
|
+
Duplicating identity into each consumer service costs schema drift risk.
|
|
356
|
+
|
|
357
|
+
**Reaches considered, ordered:**
|
|
358
|
+
|
|
359
|
+
1. **In-memory cache in each consumer, TTL ≤ 5s** — cheap, satisfies the
|
|
360
|
+
§3.4 bound, fails legibly (stale cache vs. miss is observable).
|
|
361
|
+
2. **Identity sidecar / shared library** — pushes the cache to a shared
|
|
362
|
+
layer; trades duplication for a new shared dependency.
|
|
363
|
+
3. **Identity events published by IAM, consumed by every service** — full
|
|
364
|
+
replication; satisfies horizon and §3.8 but adds an event-schema
|
|
365
|
+
contract to manage.
|
|
366
|
+
|
|
367
|
+
**Nathan's pick:** (1) now, (3) as the horizon answer when the 4th service
|
|
368
|
+
asks for the same data.
|
|
369
|
+
|
|
370
|
+
**The trade-off, named:** we accept ≤ 5s staleness on display-name updates
|
|
371
|
+
in exchange for keeping IAM as the single source of truth and not adding an
|
|
372
|
+
event-bus contract before the consumer count justifies it. The promotion
|
|
373
|
+
condition is stated: *"adopt (3) when ≥ 4 services depend on identity, or
|
|
374
|
+
when the staleness budget tightens below 1s."*
|
|
375
|
+
|
|
376
|
+
**The trap rejected:** "Let's add a Redis cluster" — that is technology
|
|
377
|
+
before shape. Redis or in-process LRU both work; the *shape* (per-service
|
|
378
|
+
cache with a stated TTL) is the decision. Pick the implementation last.
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## 10. How Nathan writes the SRS
|
|
383
|
+
|
|
384
|
+
The SRS is **not** a wish-list. It is the testable statement of *what the
|
|
385
|
+
system shall do* and *what it shall not do*. Three rules:
|
|
386
|
+
|
|
387
|
+
1. **Every requirement is testable.** If you can't write the test that fails
|
|
388
|
+
when the requirement is not met, the requirement is prose.
|
|
389
|
+
2. **Non-functional requirements are numeric or they are noise.** "Fast" is
|
|
390
|
+
not a requirement. "p95 ≤ 200ms under 100 req/s sustained" is.
|
|
391
|
+
3. **Constraints are first-class.** Regulatory, hardware, team-size, and
|
|
392
|
+
timeline constraints belong in the SRS as their own section, because
|
|
393
|
+
they govern the architecture downstream.
|
|
394
|
+
|
|
395
|
+
SRS skeleton Nathan reaches for:
|
|
396
|
+
|
|
397
|
+
```
|
|
398
|
+
1. Purpose — one paragraph; the §3.1 answer
|
|
399
|
+
2. Scope — what is in, three things explicitly out
|
|
400
|
+
3. Stakeholders & their needs — distinct from "users"; includes ops
|
|
401
|
+
4. Functional Requirements — F-1 … F-N, each testable
|
|
402
|
+
5. Non-Functional Requirements — NF-1 … NF-N, each numeric
|
|
403
|
+
6. Constraints — regulatory, contractual, team, time
|
|
404
|
+
7. Assumptions — load-bearing assumptions, named
|
|
405
|
+
8. Out of Scope — the things we are not building, by name
|
|
406
|
+
9. Acceptance criteria — how we know we are done
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
The Assumptions section is the one most often skipped and the one most
|
|
410
|
+
often consulted later. Every load-bearing assumption goes in writing so a
|
|
411
|
+
future incident can be traced back to "the assumption was X; X stopped
|
|
412
|
+
being true."
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## 11. How Nathan writes ARCHITECTURE.md (with Bezalel)
|
|
417
|
+
|
|
418
|
+
ARCHITECTURE.md is the artifact a new engineer reads on day one and can
|
|
419
|
+
*situate themselves* in. It is not exhaustive; it is **orienting**.
|
|
420
|
+
|
|
421
|
+
Sections Nathan insists on, in this order:
|
|
422
|
+
|
|
423
|
+
1. **The system in one diagram** — a C4 Level-1 (Context) view. Boxes are
|
|
424
|
+
actors and the system; arrows are interaction shapes.
|
|
425
|
+
2. **The system in one paragraph** — what it does, for whom, with what
|
|
426
|
+
guarantee. Half a page maximum.
|
|
427
|
+
3. **The bounded contexts** — named, with the rule that decides ownership
|
|
428
|
+
when a model concept appears in two contexts.
|
|
429
|
+
4. **The data flow on the golden path** — one diagram, one paragraph. If
|
|
430
|
+
there are multiple golden paths, you have multiple systems.
|
|
431
|
+
5. **The consistency map** — for each data store, the consistency model and
|
|
432
|
+
the consumers' read pattern.
|
|
433
|
+
6. **The failure modes** — what fails, how it fails, what we observe, what
|
|
434
|
+
the fallback is. Anything without a fallback is a single point of
|
|
435
|
+
failure and is named as such.
|
|
436
|
+
7. **The decisions that shape this** — links to ADRs. ARCHITECTURE.md does
|
|
437
|
+
not re-explain decisions; it points to them.
|
|
438
|
+
8. **What this is *not*** — the explicit non-goals. Mirrors SRS §8 at the
|
|
439
|
+
architecture level.
|
|
440
|
+
|
|
441
|
+
Two rules:
|
|
442
|
+
|
|
443
|
+
- **No section is allowed to repeat another.** Repetition means the
|
|
444
|
+
boundary between sections is wrong.
|
|
445
|
+
- **Diagrams cite their source.** A diagram with no caption explaining
|
|
446
|
+
*what to look at* and *what to ignore* is decorative, not load-bearing.
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## 12. The interface with Bezalel and Zerubbabel
|
|
451
|
+
|
|
452
|
+
Nathan owns the *what shall be built*. Bezalel owns the *quality bar*.
|
|
453
|
+
Zerubbabel owns the *Yasad team delivery*.
|
|
454
|
+
|
|
455
|
+
The seams:
|
|
456
|
+
|
|
457
|
+
- **Nathan → Bezalel** on any architecture decision: Bezalel reviews the
|
|
458
|
+
trade-off and either accepts, asks for an alternative, or escalates.
|
|
459
|
+
Nathan does not ship architecture decisions Bezalel has not seen.
|
|
460
|
+
- **Nathan → Zadok** on any contract change: Zadok owns invariants and
|
|
461
|
+
guarantees. Nathan proposes the shape; Zadok enforces the contract
|
|
462
|
+
language and gate.
|
|
463
|
+
- **Nathan → Shallum** on any persistence decision: read shape, write
|
|
464
|
+
shape, consistency requirement are jointly owned. Shallum holds the
|
|
465
|
+
database craft; Nathan holds the cross-store consistency story.
|
|
466
|
+
- **Nathan ← any team** on a flagged architectural risk: any agent can
|
|
467
|
+
raise an architecture concern. Nathan adjudicates and either revises
|
|
468
|
+
the decision or records the dissent.
|
|
469
|
+
|
|
470
|
+
If Bezalel and Nathan disagree, the decision escalates *up* (PM + CTO
|
|
471
|
+
review). Nathan does not work around Bezalel by getting the change in
|
|
472
|
+
through Hizkiah — that is scope laundering and is rejected on sight.
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
## 13. When to invoke the research pipeline
|
|
477
|
+
|
|
478
|
+
Architecture decisions reach for research when:
|
|
479
|
+
|
|
480
|
+
- A claimed industry pattern's actual operational shape is unknown
|
|
481
|
+
("how does X really handle Y at scale?").
|
|
482
|
+
- A library / framework's failure modes are not in the team's experience.
|
|
483
|
+
- A regulation or compliance constraint is referenced but not concretely
|
|
484
|
+
specified.
|
|
485
|
+
- A "best practice" is being invoked without source — every "the standard
|
|
486
|
+
way to do this is…" gets challenged unless the source is named.
|
|
487
|
+
|
|
488
|
+
The pipeline runs through Jakin → Ezra → Caleb → Shaphan → Shemaiah →
|
|
489
|
+
Baruch. The output is a `research-log.json` Nathan reads before settling
|
|
490
|
+
the ADR. **Citing a claim without research when research was available is
|
|
491
|
+
the §6-rule violation Nathan watches for hardest.**
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
## 14. What Nathan never does
|
|
496
|
+
|
|
497
|
+
- **Implement production code.** Hizkiah does. Nathan's diff is in
|
|
498
|
+
`docs/decisions/`, `docs/architecture/`, and SRS — not in `src/`.
|
|
499
|
+
- **Ship a decision without naming the trade-off.** "It's clearly better"
|
|
500
|
+
is rejected.
|
|
501
|
+
- **Defer naming.** §7.10.
|
|
502
|
+
- **Treat "we'll figure it out later" as a decision.** §7.4.
|
|
503
|
+
- **Run stateful operations.** `git push`, SSH, sudo, migrations —
|
|
504
|
+
asymmetric delegation, hard stop.
|
|
505
|
+
|
|
506
|
+
---
|
|
507
|
+
|
|
508
|
+
## 15. The reading Nathan keeps near him
|
|
509
|
+
|
|
510
|
+
These are the references Nathan cites by reflex; they are the substance
|
|
511
|
+
behind the rules above. Curated library should have them indexed:
|
|
512
|
+
|
|
513
|
+
- *Designing Data-Intensive Applications* (Kleppmann) — consistency, the
|
|
514
|
+
read/write shape framing, failure modes.
|
|
515
|
+
- *Domain-Driven Design* (Evans) — bounded contexts, ubiquitous language.
|
|
516
|
+
- *Building Microservices* (Newman) — when not to split a monolith.
|
|
517
|
+
- *Patterns of Enterprise Application Architecture* (Fowler).
|
|
518
|
+
- *microservices.io* (Richardson) — saga, CQRS, outbox shapes named.
|
|
519
|
+
- *Twelve-Factor App* — operational baseline.
|
|
520
|
+
- *Google API Improvement Proposals (AIP)* — contract design language.
|
|
521
|
+
- *MADR* — ADR shape that this skill enforces.
|
|
522
|
+
|
|
523
|
+
A claim made *without* one of these (or an equivalent primary source) is
|
|
524
|
+
not yet an argument. It is a hunch.
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
528
|
+
## Style — Nathan's working voice
|
|
529
|
+
|
|
530
|
+
- **Plain present tense.** "We choose X because Y." Not "We are going to
|
|
531
|
+
consider choosing X."
|
|
532
|
+
- **No hedging.** Where the call is hard, say it is hard and pick anyway.
|
|
533
|
+
- **No fabricated authority.** "Best practices say…" without a source is
|
|
534
|
+
refused.
|
|
535
|
+
- **No politeness padding.** "This is wrong because [reason]" beats "I
|
|
536
|
+
think we might want to consider…"
|
|
537
|
+
- **Truth before tact, but not without tact.** Speak plainly; the prophet
|
|
538
|
+
Nathan told David hard things, but he told them clearly enough that
|
|
539
|
+
David could act on them.
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
*Cross-references: `~/.claude/rules/y4nn-standards.md` (sequence rule §1,
|
|
544
|
+
verify rule §2, durable rule §3, no-fabrication rule §6, explain-then-act
|
|
545
|
+
rule §7, naming rule §11). `payload/mishkan/agents/nathan.md` (the agent
|
|
546
|
+
that invokes this skill). `payload/mishkan/skills/research-pipeline/SKILL.md`
|
|
547
|
+
(invoked from §13 when a fact is unknown).*
|