app-creator/docs/domain-pack-spec.md
Kjell Tore Guttormsen e4ae4ac5b4 design(app-creator): S5 — revider phase-design-draft per research-brief + skriv domain-pack-spec
Anvendt revisjons-mandat R1–R17 fra prototype-run/research/research-brief.md:
- features/{NN}-{slug}/-layout (brief.md + context.md) + 00-context/ (snapshots + pack-overrides.md)
- fase 7 omskrevet mot Voyage Handover-1 strict-mode (8 frontmatter-felter, state-machine, 3 påkrevde body-seksjoner + Research Plan); context.md-splitt (BMAD: embedding>linking); round-trip-test-krav
- flersesjons-protokoll formalisert (dokumentert praksis + lett state.json-session-felt)
- domain-pack-konsumering per fase (max-3-regel, domain_pack-felt)
- rapid mode + skippbare faser 2/4/5 med begrunnelse + hard lengde-grense (≤500 ord)
- fase 4 trigger-på-bruk; fase 3 ADR-ved-beslutning + åpne AQ-spørsmål; fase 5 mot ISO 25010:2023/WCAG 2.2/MASVS 2.1/privacy manifest
- fase 1: minimal-variant (default) vs full-variant; splittet kvalitets-sjekk; GJØR-vs-ER-skille; tidlig eierskaps-spørsmål; appetite + rabbit holes
- problem-gate + requirements-first/design-first + implementation-readiness-check
- release/ops-grense gjort eksplisitt i scope-lås; status-merking oppdatert

Ny docs/domain-pack-spec.md (domene-nøytral) per innholds-mandat D1–D7:
8-komponent-liste, pack.json-skjema, fil-sti-aktivering + materialisert snapshot,
uformell semver + pack-overrides.md escape hatch, Voyage-agnostisk håndtering,
skisse av ios-app- og claude-code-plugin-referanse-pakkene (S6 forfatter).

Beslutninger: domain-packs/ i plugin-roten; flersesjons = dokumentert + lett state-felt;
/trekrevise = lett intern variant + Voyages anchor-format kun på fase 7-briefer;
lengde-grense ≤500 ord/én skjerm; fase 1-default = minimal-variant.

prototype-run/friksjon.md: S5-bekreftelses-noter på #1–8 + R17-protokoll-tillegg (mål fase-overhead-tid).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 13:18:12 +02:00

186 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Domain-pack-spec (app-creator)
<!-- Skrevet: 2026-05-11 (S5) -->
<!-- Status: FØRSTEUTKAST. Domene-nøytral spec. Referanse-pakkene (ios-app, claude-code-plugin) forfattes i S6 — kun skissert her (§ 7). Spec-en er hypotese inntil den første referanse-pakken faktisk er bygget og konsumert av en pipeline-fase. -->
<!-- Begrunnelse / research-grunnlag: prototype-run/research/research-brief.md § 5 (D1D7), prototype-run/research/C-domain-packs.md § 5, friksjon #5 og #7. -->
## D1 — Hva en domain pack er
En **domain pack** er en gjenbrukbar kunnskaps-bunt som app-creator-fasene 1 og 37 konsumerer for å realisere en app i et bestemt domene (iOS-app, Claude Code-plugin, web-app, …). Den ligger som et **mellomlag** mellom:
- **app-spesifikk kunnskap** (fase 35 — denne appens arkitektur, design, constraints), og
- **task-spesifikk kunnskap** (fase 7 — denne featurens brief).
Domene-laget er det som svarer "dette er en iOS-app, så her er konvensjonene, mønstrene, fallgruvene, sjekklistene og guardrails som gjelder for *alle* iOS-apper" — slik at hver app ikke gjenoppfinner det.
**En domain pack er MER enn en Anthropic-skill.** En skill dekker primært *patterns* + delvis *gotchas* + *reference-impl* — den er optimalisert for å lære en agent å gjøre én ting. En domain pack legger til *conventions*, *checklists*, *guardrails* og *scaffolding* som førsteklasses navngitte komponenter, fordi en app-pipeline trenger ikke bare "hvordan gjør jeg X" men også "hvilke ikke-forhandlbare regler gjelder", "hva er fase-exit-kriteriene", og "hvilke fil-templater materialiseres inn i prosjektet". (Research-grunnlag: dekomponering av modne kunnskaps-bunter på tvers av Cursor rules, Copilot instructions, Anthropic skills, Yeoman/Cookiecutter/Copier, ESLint shareable configs, Azure CAF / AWS WAF — `C-domain-packs.md` § 1.)
**Hva en domain pack IKKE er:**
- Ikke en runtime — det finnes ikke noe "domain-pack-engine" som lastes inn. En fase-agent leser `state.json`, resolver pack-stien, leser den/de spesifikke fil(ene) den trenger. Zero eksterne verktøy, zero npm-deps.
- Ikke alltid-på. Ingen always-on injeksjon, ingen glob-magi. Eksplisitt fil-sti-lasting per fase (se D4).
- Ikke en erstatning for app-spesifikt arbeid. Pakken bærer det *generiske* for domenet; fase 35 bærer det *spesifikke* for appen; `pack-overrides.md` lar appen avvike fra pakken der det trengs (se D5).
## D2 — De 8 komponentene
Hver komponent er en dedikert fil eller katalog under en `domain-pack/`-rot. Seks av disse åtte gjenkommer pålitelig på tvers av modne kunnskaps-bunter (manifest, conventions, patterns, gotchas, checklists, reference-impl); scaffolding og glossary er domene-avhengige men ofte nyttige.
| # | Komponent | Fil / katalog | Hva den inneholder | core / supplementary |
|---|-----------|---------------|--------------------|--------------------|
| 1 | Manifest | `pack.json` | Maskinlesbart metadata — se D3. | core |
| 2 | Conventions | `conventions.md` | Domene-spesifikke ikke-forhandlbare beslutninger (plattform-regler, kode-konvensjoner, navnemønstre). Guardrails ligger som underseksjon: regler med enforcement-vekt (App Store-constraints, GDPR-håndtering = conventions du *ikke* avviker fra uten god grunn). | core |
| 3 | Patterns | `patterns/` | Én fil per gjenbrukbart mønster (f.eks. `patterns/offline-first-swiftdata.md`, `patterns/command-router.md`). Fasene `Read` spesifikke filer ved behov — aldri hele katalogen. | supplementary (per-fil) |
| 4 | Gotchas | `gotchas.md` | Eksplisitt "ikke gjør dette"-liste — kjente fallgruver, ting som ser riktige ut men ikke er det. | core |
| 5 | Checklists | `checklist.md` | Fase-exit-kriterier som checkbokser; mapper til brief-validering i fase 7. Standard-baserte sjekklister lever HER (App Store-submission-checklist, MASVS 2.1, WCAG 2.2 AA, privacy-manifest-mal — for `ios-app`; plugin-validator-pass, CLAUDE.md-grade — for `claude-code-plugin`). Dette er komponenten som løser "manglende eierfaser"-problemet (friksjon #7). | core |
| 6 | Scaffolding | `scaffold/` | Fil-templater som materialiseres inn i per-app-artefakt-treet (f.eks. `scaffold/PrivacyInfo.xcprivacy`, `scaffold/plugin.json`). Konsumeres av fase 7 / fase 3 når en konkret fil skal opprettes. | supplementary |
| 7 | Reference impl | `examples/` | Eksempel-briefer, eksempel-artefakter — konsumeres av brief-generator i fase 6/7 som "slik ser en god feature-brief ut i dette domenet". | supplementary |
| 8 | Glossary | `glossary.md` | Domene-vokabular — lastes selektivt (fase 1 ved behov, ved oppslag). | supplementary |
**Hard lengde-grense per fil:** ~500 ord / én skjerm der mulig. Lange filer er usynlige for agenten (Cursor-erfaringen: regler ignoreres når de blir for lange). Hvis en pattern-fil eller checklist sprenger grensen: del den i flere filer under `patterns/` eller seksjoner i `checklist.md` som lastes uavhengig. `examples/`-filer er unntatt grensen (de er referanse-materiale, ikke instruksjon).
**Katalog-layout:**
```
domain-pack/ ({name}/)
├── pack.json
├── conventions.md
├── gotchas.md
├── checklist.md
├── glossary.md
├── patterns/
│ ├── {pattern-a}.md
│ └── {pattern-b}.md
├── scaffold/
│ ├── {template-fil-1}
│ └── {template-fil-2}
└── examples/
└── {eksempel-feature-brief}.md
```
## D3 — `pack.json`-skjema
Minimalt JSON-manifest. Ingen npm-semantikk, ingen build-step, ingen lock-fil.
```json
{
"schema": "domain-pack/v1",
"name": "ios-app",
"version": "0.1.0",
"domain": "iOS-app-utvikling (Swift/SwiftUI)",
"description": "Domene-kunnskap for iOS-app-utvikling med Swift/SwiftUI",
"phases": [1, 3, 4, 5, 6, 7],
"verified": { "date": "2026-05-11", "against": "iOS 18, HIG WWDC2025, MASVS 2.1, WCAG 2.2" }
}
```
| Felt | Type | Påkrevd | Betydning |
|------|------|---------|-----------|
| `schema` | string | ja | Skjema-versjon. `"domain-pack/v1"` for nå. Bumps hvis manifest-strukturen endres. |
| `name` | string | ja | Pakke-navn, URL-trygg slug. Brukes i `@`-notasjon (`ios-app@0.1.0`) og i `00-context/domain-pack-{name}.md`. |
| `version` | string | ja | Uformell semver — se D5. |
| `domain` | string | ja | Menneskelesbar domene-beskrivelse. |
| `description` | string | ja | Én-linjes formålsbeskrivelse. |
| `phases` | number[] | ja | Hvilke pipeline-faser som *kan* laste fra pakken (17). En fase som ikke er i lista laster ikke pack-filer. |
| `verified` | object | ja | `{ "date": "YYYY-MM-DD", "against": "..." }` — sist-verifisert-dato + mot hvilken versjon av domenet (iOS-versjon, HIG-utgave, standard-versjoner). Gjør at man ser når en pakke er i ferd med å råtne. |
Ingenting i `pack.json` er menneske-leselig *innhold* — alt innhold lever i markdown-filene. Manifestet er kun maskinlesbart metadata.
## D4 — Referanse / aktiverings-mekanisme
**Eksplisitt fil-sti-lasting per fase.** Hver fase-prompt (i `phase-design-draft.md`) lister hvilke pack-filer den `Read`-er ved oppstart — progressive disclosure, verbatim fra Anthropic-skill-mønsteret. Ingen glob-magi, ingen always-on injeksjon. Eksempel (fra `phase-design-draft.md` § Domain-pack-konsumering):
| Fase | `Read`-er typisk |
|------|------------------|
| 1 (intervju) | `conventions.md`, evt. `glossary.md` |
| 3 (arkitektur) | `conventions.md`, `patterns/{relevant}.md` (max 12), evt. `gotchas.md` |
| 4 (designsystem) | `conventions.md`, `patterns/{ui-relevant}.md` |
| 5 (constraints) | `checklist.md`, `gotchas.md` |
| 6 (feature-derivasjon) | `checklist.md`, evt. `examples/` |
| 7 (feature-brief) | `checklist.md`, `examples/`, `scaffold/` (når artefakter materialiseres) |
**Max-3-regel.** En fase laster aldri mer enn 3 pack-filer ved oppstart. Trenger den en fjerde underveis (en spesifikk `patterns/`-fil), leser den den når behovet oppstår — den preloader ikke. Dette holder kontekst-budsjettet ledig for nedstrøms-faser (arvet fra kiur og `phase-design-draft.md` § Context Budget).
**`domain_pack`-felt i `state.json`** og i app-artefaktenes frontmatter: `domain_pack: "ios-app@0.1.0"`. Pack-identiteten er del av app-state. `null` hvis appen ikke bruker en pack.
**Materialisert snapshot i `00-context/`.** Ved init av app-creator-instansen (eller når en pack legges til) materialiseres et snapshot av pakken — versjonen appen bruker — inn i `{app-creator-instance-dir}/00-context/domain-pack-{name}.md`. Snapshotet er en sammenslått, lesbar form av pakkens core-komponenter (conventions + gotchas + checklist + de patterns appen faktisk bruker), med pack-versjonen innskrevet i toppen. Begrunnelse: embedding slår linking for AI-konsum (BMAD-prinsippet) — fase 7-`context.md` embedder utdrag fra dette snapshotet, ikke pekere til en ekstern pakke som kan ha endret seg. (Copier-mønsteret: den genererte appen "kjenner" sin egen versjon av kilden.)
**core vs supplementary-merking.** Hver pack-fil merkes `core` (alltid relevant for de fasene den gjelder) eller `supplementary` (lastes kun ved eksplisitt behov). Snapshotet i `00-context/` inkluderer core-komponentene; supplementary lastes on-demand fra `domain-packs/{name}/` direkte.
**Ingen runtime-framework.** Hele mekanikken er: fase-agent leser `state.json` → finner `domain_pack`-verdien → resolver stien (`domain-packs/{name}/` i plugin-roten) → leser den/de fil(ene) fase-prompten ber om → bruker `00-context/`-snapshotet for embedding i fase 7. Matcher filsystem-som-state-invarianten. Zero eksterne verktøy.
## D5 — Versjonering
**`version` følger semver-semantikk uformelt:**
- **major** — breaking: fjerne en komponent, rename et `pack.json`-felt, endre `schema`, omstrukturere `checklist.md` slik at fase 7-brief-validering bryter.
- **minor** — additivt: ny `patterns/`-fil, nye checklist-items, ny scaffold-template.
- **patch** — fixes: rette en gotcha, oppdatere `verified.date`, korrigere en konvensjon uten å endre dens betydning.
En breaking pack-bump behandles som det den er: skriv et changelog-notat (i pakkens egen `CHANGELOG.md` hvis den vokser dit, ellers i app-creators CHANGELOG), bump major. Inntil pakker ekstraheres til eget repo er versjons-feltet primært dokumentasjon — ingen lock-fil trengs fordi forfatteren er eneste konsument og pakker committes sammen med app-creator. `@`-notasjonen (`ios-app@0.1.0`) muliggjør framtidig snapshot-pinning via git-tag hvis en pakke senere får eget repo.
**Skriv pack-versjon inn i app-artefakter.** `domain_pack: "ios-app@0.1.0"` i `state.json`, i hver brief-frontmatter (fase 16) og i fase 7-`brief.md`. Toppen av `00-context/domain-pack-{name}.md`-snapshotet skriver hvilken pack-versjon det er et snapshot av, og hvilken dato det ble materialisert. Slik vet man alltid hvilken pack-versjon som genererte et gitt prosjekt — selv om pakken senere endrer seg. (Copier-mønsteret.)
**`pack-overrides.md` som escape hatch — first-class.** Ethvert pack-felt skal kunne overrides per-app via `{app-creator-instance-dir}/00-context/pack-overrides.md`. Aldri hardkode en pack-verdi uten at app-konteksten kan si "for denne appen, ikke dette" (Projen-lærdommen: "stivhet uten fluktvei = tidsbomb"). `pack-overrides.md` er en enkel markdown-fil: en seksjon per overstyring, med (a) hvilken pack-fil/regel som overstyres, (b) hva den nye verdien er, (c) hvorfor. Fase-agentene leser `pack-overrides.md` *sammen med* pack-filene og lar override-en vinne ved konflikt. Eksempel:
```markdown
# Pack-overrides — {app-slug}
## conventions.md → "min-iOS-versjon"
**Pack sier:** iOS 18 baseline.
**Denne appen:** iOS 17 baseline.
**Hvorfor:** målgruppen har eldre enheter; verifisert mot {kilde}.
## checklist.md → "App Privacy Details — tracking"
**Pack sier:** fyll ut tracking-seksjon.
**Denne appen:** N/A — appen sporer ingenting, ingen SDK-er med tracking.
**Hvorfor:** all-local, ingen analytics.
```
**Lagrings-sted (S5-beslutning): `domain-packs/` i plugin-roten.** Pakker committes sammen med app-creator-pluginen. Alternativet — `~/.claude/domain-packs/` (delt globalt på tvers av apper) — vurderes hvis det blir behov for å dele pakker mellom app-creator-instanser i ulike repos, eller hvis en pakke vokser nok til å fortjene eget repo. Inntil da: i plugin. (Begrunnelse: forfatteren er eneste konsument, fork-and-own-modellen tilsier at pakkene er en del av pluginen man forker, ingen lock-fil trengs.)
## D6 — Voyage-agnostisk håndtering
Når en feature-brief overleveres til Voyage (fase 7):
- Relevant pack-utdrag embeddes i `features/{NN}-{slug}/context.md`**ikke i `brief.md`**. `brief.md` er den rene Voyage-kontrakten (Handover 1); `context.md` er det implementerers-agenten leser for å forstå kontrakten.
- Voyage ser **kun en velformet brief + en kontekst-fil**. Ingen "domain-pack-generert"-merking, ingen pack-navn, ingen pack-versjon synlig for Voyage. Pack-identiteten er app-creator-intern state — den lever i `state.json` og i app-artefaktenes frontmatter, ikke i det som overleveres.
- Voyage vet ikke at domain-packs finnes, og skal ikke vite det. Asymmetrien er bevisst (samme prinsipp som "Voyage vet ikke om app-creator" i `CLAUDE.md`): det er det som lar lag 1 (Voyage) og lag 2 (app-creator) utvikles uavhengig uten å lekke ansvar.
Praktisk: når fase 7 skriver `context.md`, henter den relevante avsnitt fra `00-context/domain-pack-{name}.md`-snapshotet (med `pack-overrides.md` anvendt), parafraserer/utdrag-er dem inn under `## Domain-pack-utdrag`-seksjonen som *bare kontekst* — uten metadata om hvor det kom fra.
## D7 — Referanse-pakkene (skisse — S6 forfatter dem)
app-creator shipper to referanse-pakker som eksempel-implementasjoner. Fork-and-own-brukere lager egne. **Disse skisseres her, ikke spesifiseres — S6 er forfatter-sesjonen.**
### `ios-app`-pakke (fra Akashics reelle behov)
- **`pack.json`:** `name: "ios-app"`, `version: "0.1.0"`, `phases: [1, 3, 4, 5, 6, 7]`, `verified` mot iOS 18 / HIG WWDC2025 / MASVS 2.1 / WCAG 2.2.
- **`conventions.md`:** HIG-regler (navigasjon, layout, "Liquid Glass"-konformans-notat); Swift/SwiftUI-konvensjoner; MVVM-vs-TCA-veiledning (når hva); min-iOS-versjon-policy; guardrails-underseksjon (App Store-constraints du ikke avviker fra; GDPR-håndtering).
- **`patterns/`:** `offline-first-swiftdata.md`, `local-notifications.md`, `widget-live-activities-shared-model.md` (deling av datamodell mellom app/widget/Live Activity), `current-location-regeneration.md` (current-location-basert beregning + fallback ved nektet permission).
- **`gotchas.md`:** required-reason-API-deklarasjon (manglende = avvisning); ATS-unntak uten begrunnelse; `NSUsageDescription` manglende = umiddelbar App Store-avvisning; vanlige App Store Review-avvisnings-triggere.
- **`checklist.md`:** App Store-submission-checklist (aldersmerking, screenshot-spec, eksport-compliance, region-krav DSA/ICP/GRAC, App Store Connect-metadata); MASVS 2.1-checklist (8 kontroll-grupper); WCAG 2.2 AA-checklist (inkl. de 4 nye 2.2-kriteriene); privacy-manifest-mal (`PrivacyInfo.xcprivacy`-felter, per-SDK-krav); App Privacy Details "nutrition label"-felter.
- **`scaffold/`:** `PrivacyInfo.xcprivacy`-mal; `NSUsageDescription`-inventar-mal; App Store Connect-metadata-mal.
- **`examples/`:** ett eksempel-feature-brief for en iOS-feature (sannsynligvis avledet fra en faktisk Akashic-feature etter at Akashic når fase 7).
- **`glossary.md`:** iOS/App Store-vokabular (TestFlight, App Review, entitlements, capabilities, ATT, ATS, …).
### `claude-code-plugin`-pakke (ekstraksjon fra eksisterende CLAUDE.md + `.claude/rules/`)
- **`pack.json`:** `name: "claude-code-plugin"`, `version: "0.1.0"`, `phases: [1, 3, 5, 6, 7]` (sannsynligvis ikke 4 — plugins har sjelden et "designsystem").
- **`conventions.md`:** `plugin.json`-manifest-regler; frontmatter-regler (commands/agents/skills) fra ktg-privat CLAUDE.md; navnekonvensjoner (`command.md`, `descriptive-name-agent.md`, `skill-name/SKILL.md`); context-budget-regler (max-3, ingen hele-katalog-lasting, progressive disclosure).
- **`patterns/`:** `command-router.md`; `agent-definition.md`; `skill-progressive-disclosure.md`; `three-layer-architecture.md` (à la kiur).
- **`gotchas.md`:** `hooks` er objekt ikke array; `matcher` er string ikke nestet objekt; ikke deklarer `"hooks"` i `plugin.json` (auto-discovers); aldri last hele kataloger.
- **`checklist.md`:** plugin-validator-pass; CLAUDE.md grade B (70+); hook-format-regler; CLAUDE.md-vedlikehold-i-samme-commit-regel.
- **`scaffold/`:** plugin-katalog-skjelett (`.claude-plugin/plugin.json`, `commands/`, `agents/`, `skills/`, `hooks/hooks.json`, `README.md`).
- **`examples/`:** eksisterende plugin-strukturer i ktg-privat som referanse (kiur for 3-lags-arkitektur, harness for "ikke last alt på en gang", vegnormalene for ren MCP/RAG).
- **`glossary.md`:** plugin-vokabular (slash-command, subagent, hook-event, skill, marketplace, `${CLAUDE_PLUGIN_ROOT}`, …).
## Åpne spørsmål / restrisiko
- **Snapshot-materialiserings-mekanikk.** Nøyaktig hvordan `00-context/domain-pack-{name}.md` genereres fra `domain-packs/{name}/` (hvilke filer slås sammen, i hvilken rekkefølge, hvor mye trimmes) — låses når den første pakken faktisk materialiseres i S7. Inntil da: "core-komponentene, sammenslått, pack-versjon innskrevet".
- **`pack.md` med YAML-frontmatter som alternativ til `pack.json`.** Thread C nevnte begge. S5-valg: `pack.json` (rent maskinlesbart, ingen risiko for at noen putter innhold i frontmatter). Revurderes hvis det viser seg upraktisk.
- **Når en fase trenger en `patterns/`-fil som ikke er i `phases`-lista.** Skal pakken da utvides, eller skal fasen klare seg uten? Sannsynlig: utvid pakken (en pattern relevant for en fase hører i pakken) — men det er en S6+-beslutning per konkret tilfelle.
- **Pakke-deling på tvers av repos.** Hvis app-creator-instanser i ulike repos vil dele samme `ios-app`-pakke: da må lagrings-stedet flyttes til `~/.claude/domain-packs/` eller eget repo. Ikke et problem så lenge forfatteren er eneste konsument med pakkene i plugin-roten.
## Kilder
- `prototype-run/research/research-brief.md` § 5 (D1D7) — innholds-mandatet denne spec-en realiserer.
- `prototype-run/research/C-domain-packs.md` — dekomponering av modne kunnskaps-bunter (Cursor rules, Copilot instructions, Anthropic skills, Yeoman/Cookiecutter/Copier, ESLint shareable configs, Azure CAF / AWS WAF) + erfaringsrapporter (Cursor-drift, eslint-config-love breaking changes, Projen escape-hatches).
- `prototype-run/research/D-feature-artifacts.md` § 2 — BMAD-prinsippet (embedding slår linking for AI-konsum) som begrunner `00-context/`-snapshot framfor ekstern peker.
- `prototype-run/friksjon.md` #5 (flat layout antok ikke domain-pack-kontekst), #7 (tre sjekkliste-grupper uten eierfase — løses av `checklist.md`-komponenten).
- `phase-design-draft.md` — fase-seksjonene som konsumerer pakkene; `CLAUDE.md` — verktøy-agnostisk- og Voyage-agnostisk-invariantene D6 respekterer.