@haus-tech/haus-workflow 4.2.0 → 4.3.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.
@@ -171,7 +171,7 @@ upstream gets pruned automatically by `apply`'s existing orphan-pruning.
171
171
 
172
172
  ### New project (`project:new`)
173
173
 
174
- 1. Open and follow `references/new.md` in this skill's directory. It is a seven-phase AI-driven flow: elicit the request and propose features, gate on user intent, scaffold (registry stacks via `haus new --json --yes` with a `--dry-run` preview; any other stack via a user-confirmed official scaffolder plus manual rails), install context via `haus init`, seed `docs/SPEC.md` + `docs/plans/walking-skeleton.md`, build the walking skeleton with one subagent per feature, and verify (build + lint + tests + smoke boot). Failure `detail` is relayed verbatim and nothing is ever auto-deleted. Never run bare interactive `haus new`.
174
+ 1. Open and follow `references/new.md` in this skill's directory. It is a seven-phase AI-driven flow: elicit the request and propose features, gate on user intent, scaffold (registry stacks via `haus new --json --yes` with a `--dry-run` preview; any other stack via a user-confirmed official scaffolder plus manual rails), install context via `haus init`, seed `docs/SPEC.md` + `docs/plans/walking-skeleton.md`, build the walking skeleton with one subagent per feature (against a structure recorded in `docs/DESIGN.md`), verify (build + lint + tests + smoke boot), then write the project docs by following `references/init.md` from step 3 (deep read, `CLAUDE.md` body + `docs/`, recommend re-check, opt-ins). Repos are only ever created private. Failure `detail` is relayed verbatim and nothing is ever auto-deleted. Never run bare interactive `haus new`.
175
175
 
176
176
  ### Add optional skills (`project:add-skills`)
177
177
 
@@ -204,6 +204,11 @@ choices.
204
204
  2. If the project is already healthy, say so in one line and stop.
205
205
  3. Otherwise, for each item that needs attention, run the exact fix command the
206
206
  doctor named (commonly `haus apply --write` or `haus apply --refill-config`).
207
+ One suggestion is not a shell command: if the doctor suggests running the
208
+ writing-documentation skill (`/docs`) because the project docs were never
209
+ generated, invoke that skill directly (it's installed in this project at
210
+ `.claude/skills/writing-documentation/`) instead of running anything in
211
+ the terminal.
207
212
  4. Re-run `haus doctor` to confirm the verdict is now green.
208
213
  5. Report what you changed in plain language — what was wrong, what you ran, and
209
214
  that it's now resolved.
@@ -23,9 +23,14 @@ Ask about dimensions, never from a domain template:
23
23
  shopping → cart, product pages, login, checkout, search); the user multi-selects
24
24
  and may add their own. Generate this list per request; it is never enumerated here.
25
25
  3. Auth (none / simple / provider) and data (mocked / real DB / external API).
26
- 4. Practicals: project name (lowercase letters, digits, `. _ -`), GitHub org (default:
27
- WeAreHausTech; "personal" = omit `--org`), visibility (private default / public),
28
- create the GitHub repo at all (default yes).
26
+ 4. Practicals: project name (lowercase letters, digits, `. _ -`) and where the code
27
+ lives — exactly three choices, all private, never "public":
28
+ - a private repo in the org (default: WeAreHausTech),
29
+ - a private repo on personal GitHub (omit `--org`),
30
+ - local only, no GitHub repo (`--no-github`).
31
+ NEVER offer or pass `--public`: client projects must not be exposable by one
32
+ mis-click in a menu. A public repo is a deliberate manual act outside this flow
33
+ (the CLI flag exists for that; this skill never uses it).
29
34
 
30
35
  Pick the stack yourself from the answers. Confirm the stack with the user only on
31
36
  genuine ambiguity (e.g. web vs native unclear).
@@ -45,7 +50,7 @@ Check the registry first: `haus new --list --json`.
45
50
  **Stack in the registry (fast path):**
46
51
 
47
52
  1. Preview:
48
- `haus new <stack> <name> --json --yes --dry-run [--org <org>] [--public] [--no-github]`
53
+ `haus new <stack> <name> --json --yes --dry-run [--org <org>] [--no-github]`
49
54
  and show the planned steps in plain language. Phase 2's approval already covers
50
55
  running this for real — no further confirmation needed.
51
56
  2. Execute the same command without `--dry-run`. Parse the JSON:
@@ -68,6 +73,9 @@ Everything from here on runs inside the new project directory — `cd` into it f
68
73
  stay there.
69
74
 
70
75
  - Fast path: the chained `haus init` inside `haus new` already ran — go to seeding.
76
+ (That chained init is the CLI pipeline only: it installs skills and guardrails but
77
+ does not write project docs — those are written in Phase 6, where the deep read
78
+ sees the real code instead of an empty scaffold.)
71
79
  - Manual path:
72
80
  - Read: run `haus init --json --dry-run` and read the envelope yourself.
73
81
  - If it refuses with the zero-signal message — literally zero catalog items matched,
@@ -91,8 +99,17 @@ stay there.
91
99
  loop needs them installed either way.
92
100
  2. Read the new project's `CLAUDE.md` and `.haus-workflow/WORKFLOW.md`; they are
93
101
  authoritative from here on.
94
- 3. Per selected feature: dispatch one subagent per feature with a self-contained
95
- prompt (spec excerpt, file paths, verify command); it builds the feature end-to-end
102
+ 3. Decide the project's file/folder structure BEFORE dispatching any build agent:
103
+ derive it from the chosen stack's own idioms (e.g. Next.js app-router layout,
104
+ NestJS module-per-domain, React Router route-module structure, Expo router
105
+ conventions) plus the installed coding-style rule (organize by feature/domain,
106
+ not by type; many small files). Record the layout as a short tree with one line
107
+ of placement guidance per top-level folder in `docs/DESIGN.md`. Parallel agents
108
+ with no shared conventions each invent their own layout — this step is what
109
+ keeps the result coherent.
110
+ 4. Per selected feature: dispatch one subagent per feature with a self-contained
111
+ prompt (spec excerpt, file paths, the recorded structure conventions from
112
+ `docs/DESIGN.md`, verify command); it builds the feature end-to-end
96
113
  but minimal — pages/routes/models/navigation wired, core logic TDD-tested — and
97
114
  makes one conventional commit on `main`. Not production-complete — a base to
98
115
  iterate on. This session orchestrates only.
@@ -103,12 +120,22 @@ stay there.
103
120
 
104
121
  ## Phase 6 — Verify + hand off
105
122
 
106
- 1. Gate: build passes, lint passes, tests green, dev server boots (smoke check).
123
+ 1. Gate: build passes, lint passes, tests green, dev server boots (smoke check),
124
+ and the layout matches the structure conventions recorded in `docs/DESIGN.md`.
107
125
  Record the results in `docs/plans/walking-skeleton.md`'s verification blocks.
108
- 2. Push to the remote (if a repo was created).
109
- 3. Summarize: what exists, what is mocked, where the spec and plan live, and the
110
- suggested next step — iterate per feature in fresh sessions inside the project
111
- directory.
126
+ 2. Write the project docs: follow `references/init.md` from step 3 to the end —
127
+ deep read, `CLAUDE.md` body + `docs/` files, `.haus-workflow/deep-context.json`,
128
+ the `haus recommend` re-check, the opt-in helpers offer, and the final
129
+ `haus apply --write`. This runs HERE, after the build, on purpose: the chained
130
+ CLI init installs the writing-documentation skill but never executes it, and a
131
+ deep read now sees the real features instead of an empty scaffold — so the docs
132
+ describe reality and `haus recommend` can match what was actually built.
133
+ (init.md steps 1–2 are already covered by Phase 4; do not redo them.)
134
+ Commit the docs output as its own conventional commit.
135
+ 3. Push to the remote (if a repo was created).
136
+ 4. Summarize: what exists, what is mocked, where the spec, plan, and docs live, and
137
+ the suggested next step — iterate per feature in fresh sessions inside the
138
+ project directory.
112
139
 
113
140
  ## Failure rules
114
141
 
@@ -11,6 +11,8 @@ Det är inte artighet — det är hela poängen. Skriver du analysen med klassni
11
11
 
12
12
  Du ställer aldrig frågor tillbaka. Räcker inte underlaget avgör du och redovisar, eller skriver ordagrant att du inte kunnat verifiera.
13
13
 
14
+ Analysen skrivs för `request-classify`, som hämtar ordagranna citat ur den som belägg — och för granskaren som vill kontrollera de citaten när en klassning ser konstig ut. Den är inte skriven för kunden och hamnar inte i ticketens beskrivning.
15
+
14
16
  ## Ingång
15
17
 
16
18
  **Godkänd spec** i Haus specformat. Ett rått önskemål duger inte — då analyserar du din egen tolkning. Saknas specen: avbryt och säg det, skriv den inte själv (`request-write-spec` gör det).
@@ -55,17 +57,19 @@ Varje påstående ska vara belagt i koden eller specen. Kan du inte belägga nå
55
57
 
56
58
  ## Vägval
57
59
 
58
- En verklig gaffel där båda vägarna fungerar. Du väljer och redovisar valet — det är därför ingen människa behövs i det här steget.
60
+ **Du beslutar, du frågar inte.** Ett vägval är en gaffel där båda vägarna fungerar. Du väljer och redovisar valet — det är därför steget klarar sig utan en människa, och det är också vad kunden betalar oss för.
61
+
62
+ Testfrågan: **skulle användaren märka skillnad mellan alternativen?**
59
63
 
60
- Två sorter får du inte ta:
64
+ **Nej** — delad komponent eller speciallösning, vilket mönster som återanvänds, var koden hamnar, hur något lagras när beteendet blir detsamma. Det här är ditt beslut. Välj det som är bäst för systemet på sikt och redovisa varför.
61
65
 
62
- **Design, utseende, flöde och UX.** De är kundens. Skriv i stället ut att frågan är öppen, med alternativen. Klassaren skickar posten till Koncept, och det är rätt.
66
+ **Ja** — funktionen beter sig olika, något ingår eller inte, användaren ser eller får olika saker. Då är det inte ditt val. Det är en fråga specen skulle ha besvarat, och den ska tillbaka dit. Skriv ut den i granskarblocket under _Avvikelse mot specen_, och beskriv vad som är obesvarat — välj inte "det troliga" och gå vidare.
63
67
 
64
- **Vägval som ändrar arbetets omfattning väsentligt** — typiskt att lagra på servern i stället för i webbläsaren, eller att bygga nytt i stället för att återanvända. Välj inte tyst. Redovisa båda vägarna med varsin konsekvensbeskrivning och skriv ut att valet är öppet, så att klassaren kan klassa båda och kunden får se dem med varsin prislapp.
68
+ Design, utseende, flöde och UX hör alltid till den andra kategorin.
65
69
 
66
- Du avgör _inte_ om skillnaden når över den gränsen — du känner inte klasserna. Regeln är enkel: rör alternativen olika lager (server mot klient, nytt mot återanvänt, ett flöde mot flera), redovisa båda.
70
+ Ett valt och redovisat vägval är inget öppet vägval. Skriv "vi lägger detta i den delade komponenten eftersom Z", inte "detta kan lösas som delad komponent eller som specialfall".
67
71
 
68
- Ett valt och redovisat vägval är inget öppet vägval. Skriv "vi lagrar X i Y eftersom Z", inte "X kan lagras i Y eller Z".
72
+ **Beslutet är ett kvitto.** Väljer vi tyst bär vi också ansvaret för valet. Redovisningen är därför kvittot: skriv vad som valdes, vad alternativet var, och varför. Det är enda gången någon kan granska omdömet i efterhand — klassningen och priset kommer se rimliga ut oavsett vilket alternativ som togs.
69
73
 
70
74
  ## Antaganden
71
75
 
@@ -86,8 +90,7 @@ Analysen som ett dokument, en sida. Sedan ett kort block till granskaren:
86
90
  ## Till granskaren
87
91
 
88
92
  **Ej verifierat:** [vad du inte kunnat belägga i koden, och varför]
89
- **Öppna vägval:** [de du lämnat öppna med flit — "inga" om inga]
90
- **Avvikelse mot specen:** [om koden säger något annat än specen förutsätter]
93
+ **Avvikelse mot specen:** [om koden säger något annat än specen förutsätter · utfallsval specen lämnat obesvarade]
91
94
  ```
92
95
 
93
96
  Sista raden är den viktigaste. Förutsätter specen något som inte stämmer i systemet är det ett fel som ska tillbaka till specen, inte något som ska klassas.
@@ -41,7 +41,6 @@ Ge inte dig själv repot i den här körningen. Har du det börjar du verifiera
41
41
  "customer": {
42
42
  "class": "",
43
43
  "rationale": "",
44
- "tradeoffs": [],
45
44
  "conditions": [],
46
45
  "dependencies": []
47
46
  },
@@ -67,12 +66,6 @@ Blir utfallet `KONCEPT`, `DIAGNOS` eller `TILLBAKA_TILL_SPEC` sätts `customer.c
67
66
 
68
67
  `INPUT_SAKNAS` och `ESKALERA` är interna. `customer` lämnas tomt; de ska aldrig nå kund.
69
68
 
70
- ### Öppna vägval
71
-
72
- Lämnade `request-assess-impact` ett vägval öppet med flit: klassa **båda** vägarna och lägg dem i `tradeoffs` med varsin klass och en rads konsekvens. Välj inte åt kunden.
73
-
74
- Kalibreringsloggens Vafab-fall är precis det: samma kundbehov, backend- eller webbläsarlagring, en klass i prisskillnad — och valet kom ur intern designdialog snarare än ur kundens behov. Regeln därifrån gäller.
75
-
76
69
  ## Efter körning
77
70
 
78
71
  Granskaren läser svaren fråga för fråga, inte slutklassen. Ett rätt slutresultat med fel belägg är en felkalibrering som råkade landa rätt, och den kommer tillbaka i en post där den inte gör det.
@@ -1,6 +1,6 @@
1
1
  # Klassningsinstruktion (maskinversion)
2
2
 
3
- **v0.5 · Internt.** Körbar instruktion för AI-klassning av ett inkommande önskemål. Principerna finns i klassningsprotokollet, som är överordnat vid konflikt. Det dokumentet är för människor och ingår inte i körningen — hittar du en regelkonflikt eskalerar du enligt regel 6, och granskaren avgör mot protokollet. v0.5: kriterier måste vara oberoende — samma förhållande får inte räknas två gånger, och touchpoint-kriteriet räknar bara lager som inget annat kriterium redan gjort anspråk på. Hålet uppstod i v0.4 när kriterier gick från antingen-eller till att adderas. v0.4: LARGE tillagd och stegen gjorda enhetliga — ett Medium-kriterium är basen, varje ytterligare kriterium och varje bump är ett steg upp, taket är LARGE. Tidigare saknades steget mellan MEDIUM och offert helt, vilket gjorde varje Medium med en bump till offert. v0.3 efter divergenstest (två körningar, samma underlag, olika klass utan eskalering): flerstegsflöde och datamodelländring omdefinierade. v0.2 efter två oberoende testkörningar: konsekvens-B1, bygg-avgränsad B2, undantag för ärvda antaganden och robusthetsinstruktioner, genomförbarhetsvillkor.
3
+ **v0.6 · Internt.** Körbar instruktion för AI-klassning av ett inkommande önskemål. Principerna finns i klassningsprotokollet, som är överordnat vid konflikt. Det dokumentet är för människor och ingår inte i körningen — hittar du en regelkonflikt eskalerar du enligt regel 6, och granskaren avgör mot protokollet. v0.6: B2 omdefinierad. Frågan flyttar från vad planen säger om testning till vad ändringen kräver, och gränsen går mellan verifiering (en människa tittar, kostar minuter) och testning (en människa arbetar sig igenom, kostar timmar). Den gamla lydelsen tillät belägg endast ur byggets verifieringssteg, vilket gjorde att en plan som glömde nämna manuell testning slapp bumpen — kriteriet mätte planens utförlighet i stället för arbetets innehåll. v0.5: kriterier måste vara oberoende — samma förhållande får inte räknas två gånger, och touchpoint-kriteriet räknar bara lager som inget annat kriterium redan gjort anspråk på. Hålet uppstod i v0.4 när kriterier gick från antingen-eller till att adderas. v0.4: LARGE tillagd och stegen gjorda enhetliga — ett Medium-kriterium är basen, varje ytterligare kriterium och varje bump är ett steg upp, taket är LARGE. Tidigare saknades steget mellan MEDIUM och offert helt, vilket gjorde varje Medium med en bump till offert. v0.3 efter divergenstest (två körningar, samma underlag, olika klass utan eskalering): flerstegsflöde och datamodelländring omdefinierade. v0.2 efter två oberoende testkörningar: konsekvens-B1, bygg-avgränsad B2, undantag för ärvda antaganden och robusthetsinstruktioner, genomförbarhetsvillkor.
4
4
 
5
5
  ## Roll och uppgift
6
6
 
@@ -100,7 +100,13 @@ Bumpar mäter konsekvens av fel, aldrig att posten tekniskt vidrör en kategori.
100
100
 
101
101
  **B1 — Konsekvensrisk:** Kan ett fel i just denna post orsaka något av det som listas i KONSEKVENSRISK? Ställ frågan konkret: "vad är det värsta som händer om det här blir fel?" — visas en notis felaktigt är svaret nej; debiteras någon fel eller ser någon annans data är svaret ja. (Att koden anropar eller ligger nära känslig mekanik räcker inte; befintliga mönster som återanvänds räknas aldrig.)
102
102
 
103
- **B2 — Mänskligt testbehov i bygget:** Kräver byggets egen verifiering manuell mänsklig testning i fler än ett scenario, på flera enheter eller i flera miljöer? Belägg får endast hämtas ur byggets verifieringssteg — acceptanstest, kundmoment och verifiering som utförs av någon annan än Haus räknas aldrig (de är leveransvillkor, inte byggkostnad). Automatiska tester och enkel okulär kontroll räknas inte.
103
+ **B2 — Testbehov som inte går att automatisera bort:** Förutsätt att ändringen täcks av automatiska tester, även om de inte finns i dag. Manuell testning ska aldrig göra om det maskinen klarar. Kvarstår något som ändå kräver en människa?
104
+
105
+ _Skilj på verifiering och testning._ **Verifiering** är att en människa tittar och bekräftar att något blev som tänkt: ett nytt menyval, ett fält i ett befintligt formulär, en knapp enligt befintligt mönster, en kolumn i en befintlig tabell. Det kostar minuter och räknas INTE. **Testning** är att en människa måste arbeta sig igenom något: gå ett flöde steg för steg, pröva olika utfall och feltillstånd, använda en fysisk enhet, eller bedöma om upplevelsen håller. Det kostar timmar och räknas.
106
+
107
+ Testning krävs typiskt när ändringen rör: ett nytt eller ändrat flöde som någon måste gå igenom från början till slut · identifiering som inte går att köra automatiskt (BankID, extern inloggningstjänst, betalväxelns egen dialog) · affärskritiska flöden där automatiken finns men inte räcker som enda kvitto före driftsättning (betalning, order, behörighet) · upplevd kvalitet, när bedömningen av hur något känns eller ser ut är poängen med uppdraget — en ny vy, ett omgjort flöde; en justerad färg eller marginal är verifiering · fysiska enheter (AR, kamera, riktiga telefoner, utskrift, skanner) · externa system utan testmiljö, där enda sättet att veta är att köra mot skarpt.
108
+
109
+ Belägg hämtas ur ändringens innehåll: vad som byggs enligt spec och plan. Kundens acceptanstest räknas aldrig — det är ett leveransvillkor, inte en byggkostnad.
104
110
 
105
111
  **B3 — Blast radius:** Ändras något inom DELAD_KOD eller DRIFTMILJÖ så att fler kunder än beställaren, eller SLA-ytan, kan påverkas?
106
112
 
@@ -133,7 +139,7 @@ Svara med exakt denna struktur och inget annat:
133
139
 
134
140
  ## Hårda regler
135
141
 
136
- 1. **Belägg är obligatoriskt.** Varje JA/NEJ ska ha ett ordagrant citat ur spec eller plan. Hittar du inget citat är svaret inte NEJ — det är låg konfidens. Beläggets källa spelar roll: för B2 gäller endast byggets verifieringssteg; citat ur acceptans-/kundmoment är ogiltigt belägg.
142
+ 1. **Belägg är obligatoriskt.** Varje JA/NEJ ska ha ett ordagrant citat ur spec eller plan. Hittar du inget citat är svaret inte NEJ — det är låg konfidens. Beläggets källa spelar roll: för B2 ska citatet visa VAD som byggs (flödet, enheten, den externa tjänsten), inte vad planen råkar säga om testning — en plan som glömmer nämna manuell testning ska inte slippa bumpen. Citat ur acceptans-/kundmoment är ogiltigt belägg.
137
143
  2. **Konfidens < 0.8 på någon fråga → utfall `ESKALERA`.** Klassa aldrig på gissning. En eskalerad post klassas av människa; det är ett korrekt utfall, inte ett misslyckande. Undantag: om frågan inte är utfallsavgörande (svaret ändrar inte slutklassen åt något håll) räcker det att notera den låga konfidensen i frågeraden.
138
144
  3. **Du klassar planen, inte önskemålet.** Önskemålets ton, storleksord ("en liten grej") eller kundens egen bedömning påverkar ingenting.
139
145
  4. **Tid existerar inte i klassningen.** Timmar, estimat och tidsord förekommer varken i din bedömning eller i något outputfält — alla gränser i denna instruktion är strukturella (vad som ändras), aldrig temporala (hur länge det tar).
@@ -23,10 +23,14 @@ Läs `.haus/request.json` i repo-roten:
23
23
  {
24
24
  "customer": "Vafab Miljö",
25
25
  "customer_board": "1202738613029434",
26
+ "customer_section": "1202738613029441",
27
+ "customer_section_name": "Mina sidor",
26
28
  "collection_board": "1217668109816859"
27
29
  }
28
30
  ```
29
31
 
32
+ `customer_section` saknas när brädan inte är indelad i sektioner, och när uppsättningen kördes innan sektionssteget fanns. `customer_section_name` finns bara för att kunna visas i bekräftelser — **matcha alltid på gid, aldrig på namn.**
33
+
30
34
  **Saknas filen: kör uppsättningen nedan.** Gissa aldrig utifrån repo-namn eller mappnamn.
31
35
 
32
36
  Finns filen: **verifiera brädan en gång, före första skrivningen.** Slå upp `customer_board` på gid och skriv ut namnet: _"Skriver till Vafab Mina sidor — stämmer det?"_ Att lägga en kunds request på fel kundbräda är det enda felet i hela flödet som en annan kund kan se, och det går inte att städa i tysthet.
@@ -47,11 +51,17 @@ Be om en Asana-URL — `.../project/<gid>/...` ger dig gid:t direkt och är mins
47
51
 
48
52
  Slå upp gid:t och läs upp namnet för bekräftelse. **Ser namnet ut som en test- eller provbräda — "test", "sandbox", "torrsim", ett årtal som passerat — säg det rakt ut och fråga en gång till.** En felkopplad kundbräda upptäcks först när en kund ser någon annans request.
49
53
 
50
- **3 — Samlingsbräda?**
54
+ **3 — Vilken sektion på kundbrädan?**
55
+
56
+ Vissa kundbrädor är indelade i sektioner, där varje sektion motsvarar ett projekt. En task som skapas utan sektion hamnar i brädans default och blir svår att hitta.
57
+
58
+ Hämta brädans sektioner. **En sektion:** ingen fråga, använd den. **Flera sektioner:** lista dem med namn och gid, en per rad, och fråga vilken requests från det här repot ska hamna i.
59
+
60
+ **4 — Samlingsbräda?**
51
61
 
52
62
  `1217668109816859` (TECH · Offer pipeline) om inget annat sägs. Nämn den, be om bekräftelse, gå vidare.
53
63
 
54
- **4 — Kontrollera uppsättningen**
64
+ **5 — Kontrollera uppsättningen**
55
65
 
56
66
  Hämta fälten på båda brädorna och gå igenom tre saker:
57
67
 
@@ -59,23 +69,25 @@ Hämta fälten på båda brädorna och gå igenom tre saker:
59
69
  - **Är de delade fälten samma fält?** Jämför gid, inte namn. Två fält med samma namn och olika gid är en dubblett — de driftar isär omedelbart, och felet syns först hos kunden.
60
70
  - **Går alternativen att slå upp?** Normaliserat, enligt regeln ovan. Rapportera vilka som inte gick att matcha och vilka alternativ som faktiskt finns.
61
71
 
62
- **5 — Skriv filen**
72
+ **6 — Skriv filen**
63
73
 
64
74
  ```json
65
75
  {
66
76
  "customer": "SamSa",
67
77
  "customer_board": "1217634399775198",
78
+ "customer_section": "1217634399775205",
79
+ "customer_section_name": "Mina sidor",
68
80
  "collection_board": "1217668109816859"
69
81
  }
70
82
  ```
71
83
 
72
- Skriv den även om steg 4 hittade problem — filen handlar om vilka brädor som gäller, fältuppsättningen är ett annat problem och ska inte blockera. Redovisa innehållet, och säg att filen bör checkas in: ett fel board-gid syns då i en diff i stället för att upptäckas i efterhand.
84
+ Skriv den även om steg 5 hittade problem — filen handlar om vilka brädor som gäller, fältuppsättningen är ett annat problem och ska inte blockera. Redovisa innehållet, och säg att filen bör checkas in: ett fel board-gid syns då i en diff i stället för att upptäckas i efterhand.
73
85
 
74
- **6 — Rapportera och gå vidare**
86
+ **7 — Rapportera och gå vidare**
75
87
 
76
88
  Sammanfatta vad som skrevs och vad som saknas, i den ordningen. Fortsätt sedan med det användaren faktiskt bad om — uppsättningen är en förutsättning, inte ett ärende i sig.
77
89
 
78
- Hittade steg 4 problem som gör nästa operation omöjlig, säg vilket och stanna där. Halvskapade requests är dyrare att reda ut än ett avbrott.
90
+ Hittade steg 5 problem som gör nästa operation omöjlig, säg vilket och stanna där. Halvskapade requests är dyrare att reda ut än ett avbrott.
79
91
 
80
92
  ## Slå upp fälten, hårdkoda dem aldrig
81
93
 
@@ -100,30 +112,109 @@ Hittar du inte ett fält du ska skriva till: avbryt och säg vilket. Skapa aldri
100
112
 
101
113
  Domän-JSON till vänster, fältnamn till höger. Ingen annan skill får se högerkolumnen.
102
114
 
103
- | Domän | Fält | Not |
104
- | ------------------------------ | -------------------------- | --------------------------------------------------- |
105
- | `request_id` | task gid | — |
106
- | `original_request` | Original request | Skrivs en gång. Ändras aldrig, inte ens för stavfel |
107
- | `source` | Source | Kunden skrev själv · Mejl · Möte · Haus initierade |
108
- | `customer` | Customer | |
109
- | `requested_by` | Requested by | people-fält, kräver user gid |
110
- | `type` | Request type | Bug · Improvement · Wear |
111
- | `funding` | Funding | |
112
- | `spec` | task description | Ersätter hela beskrivningen |
113
- | `impact` | kommentar | Ny kommentar, aldrig en ersättning |
114
- | `classification` | kommentar | Ny kommentar, aldrig en ersättning |
115
- | `customer.class`, läge pricing | Class (offered) | Skrivs aldrig över efter kundbeslut |
116
- | `customer.class`, läge guard | Class (revised) | |
117
- | `customer.rationale` | Class rationale | |
118
- | `customer.conditions` ej tom | Conditional classification | se nedan |
119
- | `decision` | Decision | Beställd · Ej beställd · Uppskjuten |
120
- | `decision_reason` | Decision reason | |
121
-
122
- **Specen bor i beskrivningen, allt maskinellt i kommentarer.** Beskrivningen ska alltid visa nuvarande spec — den är det granskaren och kunden läser. Påverkansanalys och klassnings-JSON läggs som kommentarer, aldrig som redigeringar: en omkörning ska lägga sig bredvid den förra, inte radera den. Det är den spårbarhet protokollet kräver, och det är också hur man i efterhand ser vad som ändrades mellan varven.
115
+ | Domän | Fält | Not |
116
+ | ------------------------------ | ------------------------------------------------------------ | --------------------------------------------------- |
117
+ | `request_id` | task gid | — |
118
+ | `original_request` | Original request + beskrivningens `## Ursprunglig förfrågan` | Skrivs en gång. Ändras aldrig, inte ens för stavfel |
119
+ | `source` | Source | Kunden skrev själv · Mejl · Möte · Haus initierade |
120
+ | `customer` | Customer | |
121
+ | `requested_by` | Requested by | people-fält, kräver user gid |
122
+ | `type` | Request type | Bug · Improvement · Wear |
123
+ | `funding` | Funding | |
124
+ | `spec` | beskrivningens `## Specifikation` | Bara den sektionen. Låst efter `Decision`, se nedan |
125
+ | `impact` | subtask `Påverkansanalys vN` | Ny subtask varje varv, aldrig en redigering |
126
+ | `classification` | subtask `Klassning vN` | Ny subtask varje varv, aldrig en redigering |
127
+ | `customer.class`, läge pricing | Class (offered) + beskrivningens `## Klass och pris` | Skrivs aldrig över efter kundbeslut |
128
+ | `customer.class`, läge guard | Class (revised) | |
129
+ | `customer.rationale` | Class rationale + beskrivningens `## Klass och pris` | Låst efter `Decision`, se nedan |
130
+ | `customer.conditions` ej tom | Conditional classification | se nedan |
131
+ | `decision` | Decision | Beställd · Ej beställd · Uppskjuten |
132
+ | `decision_reason` | Decision reason | |
123
133
 
124
134
  `Conditional classification` är härledd: villkorslistan är tom eller inte. Sätt alltid ett värde när en klassning skrivs — aldrig tomt, eftersom tomt är reserverat för "ingen har klassat än". Bär fältet flera värden samtidigt är det felkonfigurerat som flerval; skriv ett värde och säg till.
125
135
 
126
- Asana konverterar markdown till `html_notes`. Använd `html_notes` för spec och kommentarer, inte `notes`, annars tappas struktur.
136
+ Asana konverterar markdown till `html_notes`. Använd `html_notes` för beskrivningen, för subtaskarnas innehåll och för kommentarer, inte `notes`, annars tappas struktur — rubriker, kursiv text och de vågräta linjerna mellan sektionerna försvinner alla med `notes`.
137
+
138
+ ## Beskrivningen och subtaskarna
139
+
140
+ **Beskrivningen är det enda någon faktiskt läser, och det är dessutom vad kunden ser.** Den ska därför bära requesten i läsbar form och ingenting annat. Maskineriet — påverkansanalys och klassning — ligger i subtasks, som inte ärver kundbrädan och därmed är interna utan att någon behöver komma ihåg det.
141
+
142
+ Beskrivningen har de här rubrikerna, i den här ordningen, åtskilda av en vågrät linje:
143
+
144
+ ```
145
+ ## Ursprunglig förfrågan
146
+ _Så som önskemålet kom in — 2026-08-21_
147
+
148
+ [kundens ord]
149
+
150
+ ---
151
+
152
+ ## Specifikation
153
+ _Vad vi föreslår att vi bygger — uppdaterad 2026-08-21_
154
+
155
+ [specen]
156
+
157
+ ---
158
+
159
+ ## Klass och pris
160
+ _Omfattning och pris — uppdaterad 2026-08-21_
161
+
162
+ [klass och kundvänlig motivering]
163
+ ```
164
+
165
+ **Linjen mellan sektionerna** skrivs som `<hr/>`. Asana renderar den i tasks — till skillnad från `<h3>`, som inte finns i beskrivningsfältet. Håll dig därför till `<h2>` för rubrikerna (`##` i markdown), aldrig en nivå djupare.
166
+
167
+ **Raden under varje rubrik** säger vad sektionen är och när den senast skrevs. Den finns för att sektionerna kommer från skilda tillfällen: utan den läses beskrivningen som en text skriven i ett svep, och då ser det ut som att allt beslutats samtidigt. Datumet gör det synligt att specen och priset tillkom efter kundens ursprungliga ord — och att de kan ha tillkommit olika dagar.
168
+
169
+ Raden är i kundens språk, precis som resten av beskrivningen. Aldrig skillnamn, aldrig protokolltermer, aldrig "genererad av". Datumformat `ÅÅÅÅ-MM-DD`. `## Ursprunglig förfrågan` får skapandedagens datum och behåller det för alltid — den sektionen skrivs aldrig om, så "uppdaterad" hör inte hemma där.
170
+
171
+ **Ta datumet från systemet, inte ur minnet.** En modell som skriver dagens datum på känsla skriver ofta fel år, och ett felaktigt datum är värre än inget: det ser ut som ett faktum.
172
+
173
+ Varje sektion har exakt en källa:
174
+
175
+ | Sektion | Källa | Skrivs |
176
+ | -------------------------- | ------------------------------------------------------------- | --------------------------- |
177
+ | `## Ursprunglig förfrågan` | kundens ord, eller utdraget ur mejl/brief | vid skapandet, sedan aldrig |
178
+ | `## Specifikation` | `request-write-spec` | vid varje specvarv |
179
+ | `## Klass och pris` | `request-classify`: `customer.class` och `customer.rationale` | vid varje klassningsvarv |
180
+
181
+ - **Varje steg uppdaterar bara sin egen sektion och lämnar resten orörd.** Tidigare skrev bara en skill till beskrivningen; nu skriver flera, och ett steg som ersätter hela fältet raderar de andras arbete. Det gäller även datumraden: du uppdaterar din egen sektions rad, aldrig någon annans.
182
+ - **Ursprunglig förfrågan** är kundens ord ordagrant, eller det relevanta utdraget ur ett längre mejl eller en brief. Skrivs en gång, redigeras aldrig. Fältet `Original request` behålls parallellt som skrivskyddad kopia.
183
+ - **Klass och pris** är klassen och den kundvänliga motiveringen. Inga protokolltermer, inga frågerader. Samma text står i `Class rationale`-fältet: fältet finns för att kunna filtreras och läsas i listvyer, sektionen för att kunna läsas i sitt sammanhang.
184
+
185
+ Beskrivningen har ingen sektion för vägval, och ska inte få en. Val som påverkar vad kunden får besvaras i specen — som acceptanskriterium eller under _Ingår inte_ — och är därmed redan en del av `## Specifikation`. Val som bara rör hur vi bygger är interna och ligger i påverkansanalysens subtask.
186
+
187
+ ### Beskrivningen låses vid kundbeslut
188
+
189
+ Så snart `Decision` har ett värde är beskrivningen det kunden sagt ja till. **Skriv inte om någon sektion efter den punkten.** Det gäller alla tre sektionerna, oavsett vilket läge klassningen kördes i och oavsett vad som ändrats.
190
+
191
+ Ägartabellen ovan beskriver vad som gäller fram till kundbeslutet.
192
+
193
+ **Läs `Decision` innan varje skrivning till beskrivningen.** Det är en kontroll som ska utföras, inte något du antar utifrån ärendets status — ett ärende kan ha fått ett beslut mellan två av dina körningar.
194
+
195
+ Blir klassen en annan vid grinden: fyll `Class (revised)`, lägg klassningen som ny subtask, flytta posten till ⚖️ och stanna där. En människa avgör vad kunden får se, och det blir i så fall ett nytt beslut — inte en tyst redigering av ett gammalt.
196
+
197
+ Detsamma gäller om en klassning körs om i prisläget på ett ärende som redan har ett `Decision`. Kontrollera fältet innan du skriver, inte vilket läge du kördes i.
198
+
199
+ Skälet: en klass som ändras uppåt är en prishöjning. Sker den genom att beskrivningen skrivs om finns inget spår av vad kunden faktiskt godkände, och den fria exiten — modellens centrala kundlöfte — går inte att lösa ut, eftersom det inte längre går att visa vad som ändrats.
200
+
201
+ Låset gäller beskrivningen och de fält som bär samma text som den: `Class (offered)` och `Class rationale`. Det som är internt får alltid skrivas — subtaskarna (det är hela poängen med dem: de är löpnumrerade och ärver inte kundbrädan, så en klassning efter kundbeslut landar där som vanligt), `Class (revised)`, `Conditional classification` och räknarna.
202
+
203
+ **Påverkansanalys och klassning läggs som subtasks, inte som kommentarer.**
204
+
205
+ ```
206
+ Ticket
207
+ ├── beskrivning: de tre sektionerna ovan
208
+ ├── Påverkansanalys (subtask)
209
+ └── Klassning (subtask)
210
+ ```
211
+
212
+ - Subtasks ärver inte kundbrädan och är därmed interna. Kontrollera att de inte multi-homas dit.
213
+ - **Ett nytt varv skapar en ny subtask, den ersätter inte den förra.** Namnge med löpnummer: "Klassning v1", "Klassning v2". Beskrivningen kan inte bära historik, och det är subtaskarna som ger den tillbaka — i läsbar form, till skillnad från en kommentarsström.
214
+ - Klassningens subtask innehåller den läsbara tabellen — fråga, svar, belägg — och därunder den råa JSON:en, som behövs för att diffa vid grinden men som ingen läser.
215
+ - Finns flera parallella underlag namnges subtaskarna så parningen syns: "Klassning — delad komponent", "Klassning — specialfall".
216
+
217
+ **Kommentarer används inte längre för påverkansanalys eller klassning.** De är kvar för det som faktiskt kommenteras — feedback vid bakåtflytt — och där gäller fortsatt att de är append-only och aldrig redigeras.
127
218
 
128
219
  ## Var en request kommer ifrån
129
220
 
@@ -131,11 +222,11 @@ Ursprunget avgör vad du gör, och det avgör också hur underlaget ska tolkas s
131
222
 
132
223
  ### Kunden skrev själv på sin bräda
133
224
 
134
- Kundens ord ligger i beskrivningen, och specen ska sedan ta beskrivningens plats. Det är den **enda destruktiva operationen i hela flödet**, och ordningen är inte förhandlingsbar:
225
+ Kundens ord ligger i beskrivningen, och beskrivningen ska sedan skrivas om till sektionsform. Det är den **enda destruktiva operationen i hela flödet**, och ordningen är inte förhandlingsbar:
135
226
 
136
227
  1. Kopiera beskrivningen ordagrant till `Original request`
137
228
  2. **Läs tillbaka fältet och verifiera att texten landat**
138
- 3. Först då skriv specen över beskrivningen
229
+ 3. Först då skriv om beskrivningen — samma text ordagrant under `## Ursprunglig förfrågan`, specen under `## Specifikation`
139
230
 
140
231
  Hoppar du över steg 2 och skrivningen tyst misslyckas är kundens egna ord borta för alltid — vilket är precis det `Original request` finns för att förhindra. `Source` = kunden skrev själv.
141
232
 
@@ -143,11 +234,11 @@ Hoppar du över steg 2 och skrivningen tyst misslyckas är kundens egna ord bort
143
234
 
144
235
  Här skapar agenten både task och spec i ett svep, och kundens ord ligger kvar utanför Asana. Då står granskaren med en spec och inget att hålla den mot.
145
236
 
146
- **Klistra in det relevanta stycket ur mejlet eller anteckningen ordagrant** i `Original request` — inte en sammanfattning, inte en parafras. Risken för glid är störst just här, eftersom underlaget är råare och agenten tolkat mer.
237
+ **Klistra in det relevanta stycket ur mejlet eller anteckningen ordagrant** i `Original request` och under `## Ursprunglig förfrågan` i beskrivningen — inte en sammanfattning, inte en parafras. Risken för glid är störst just här, eftersom underlaget är råare och agenten tolkat mer.
147
238
 
148
239
  Blir det flera requests ur samma underlag får var och en **sitt eget relevanta stycke**, inte hela mejlet klistrat en gång per post. Ett fält som innehåller allt håller ingenting.
149
240
 
150
- `Source` = mejl eller möte. Offer status sätts till 🔍 Spec redo för granskning, men bara om specen faktiskt är skriven. En tom task i granskningskön ser ut som ett fel i skillen när det är ett fel i regeln.
241
+ `Source` = mejl eller möte. Statusarna sätts enligt skapandesekvensen nedan. Notera bara att en task inte får hamna i ett granskningsläge utan att specen faktiskt är skriven — en tom task i granskningskön ser ut som ett fel i skillen när det är ett fel i regeln.
151
242
 
152
243
  **Länka syskonposter.** Ett mejl eller ett möte producerar ofta flera saker, och `request-write-spec` avgör var snitten går. Beroendet mellan posterna måste finnas på ärendena, inte bara som en mening i ett granskarblock ingen läser om en vecka.
153
244
 
@@ -168,14 +259,41 @@ Ett delat fält är **samma** fält på båda brädorna. Finns två fält med sa
168
259
 
169
260
  Ordningen spelar roll, eftersom de interna fälten inte existerar på kundbrädan.
170
261
 
171
- 1. **Skapa på kundbrädan** med det som finns där: task name, `Original request`, `Customer`, `Requested by`.
172
- 2. **Verifiera att den landat på samlingsbrädan.** Speglingen sker automatiskt men inte alltid direkt — läs tillbaka uppgiftens projekt. Har den inte kommit fram, lägg till den dit själv.
173
- 3. **Sätt `Source` och `Offer status`.** Först nu finns fälten.
262
+ **1 — Skapa på kundbrädan** med det som finns där: task name, `Original request`, `Customer`, `Requested by`. Lägg tasken i rätt sektion (se nedan), och **sätt `Request status` redan här**, explicit:
174
263
 
175
- Försöker du sätta dem i steg 1 avbryter uppslagningen, och du står med en halvskapad request.
264
+ | Läge vid skapandet | Request status |
265
+ | ------------------------------------ | --------------- |
266
+ | Inget skrivet än, bara önskemålet | Mottaget |
267
+ | Spec finns och ligger för granskning | Under bedömning |
268
+
269
+ **2 — Verifiera att den landat på samlingsbrädan.** Speglingen sker via en Asana-regel och är asynkron — läs tillbaka uppgiftens projekt och vänta in den. Har den inte kommit fram, lägg till den dit själv.
270
+
271
+ **3 — Sätt `Source` och `Offer status`.** Först nu finns fälten. `Offer status` ska motsvara det `Request status` du satte i steg 1:
272
+
273
+ | Läge | Offer status |
274
+ | ---------------- | --------------------------- |
275
+ | Inget skrivet än | 📥 Inkommet |
276
+ | Spec finns | 🔍 Spec redo för granskning |
277
+
278
+ **4 — Verifiera att båda statusfälten har värden.** Läs tillbaka tasken och kontrollera `Request status` och `Offer status`. Har något inte landat: säg det och stanna.
279
+
280
+ Försöker du sätta `Offer status` eller `Source` i steg 1 avbryter uppslagningen, och du står med en halvskapad request.
281
+
282
+ **En task du skapar lämnar aldrig skillen med tomt `Request status` eller tomt `Offer status`.** Kundbrädan grupperas på det ena fältet, offertbrädan på det andra — en task utan värde hamnar utanför alla grupper. Den finns, men ingen ser den, och felet upptäcks först när någon undrar var den tog vägen. Glappet är verkligt: `Offer status` existerar bara på offertbrädan, så mellan steg 1 och steg 3 är det fältet oundvikligen tomt. Därför sätts `Request status` i steg 1 — den täcker glappet.
283
+
284
+ Efter skapandet rör du aldrig `Request status` igen. Då härleds den av Asana-regeln ur `Offer status`.
176
285
 
177
286
  Task name ska vara det förändrade tillståndet, inte uppgiften, samma regel som specrubriken. Finns ingen spec än: använd önskemålets egna ord, och byt namn när specen skrivs.
178
287
 
288
+ ### Sektion på kundbrädan
289
+
290
+ - **Finns `customer_section` i konfigurationen:** använd den, men verifiera först att sektionen fortfarande finns på brädan — sektioner byter namn och tas bort. Är den borta: fråga vilken som gäller nu och uppdatera `.haus/request.json`.
291
+ - **Saknas `customer_section` och brädan har flera sektioner:** fråga **en gång** och använd svaret för hela omgången. Skapar du tio tasks ur ett mejl ska du inte fråga tio gånger. Erbjud att spara svaret i konfigurationsfilen så frågan inte återkommer.
292
+ - **Har brädan bara en sektion:** fråga inte.
293
+ - **Spänner omgången flera sektioner** — ett mejl innehåller ofta önskemål som hör till olika projekt — gissa inte utifrån innehållet. Fråga en gång om alla ska till samma sektion, och be om fördelningen om svaret är nej.
294
+
295
+ Matcha alltid på gid. `customer_section_name` finns bara för att kunna visas i en bekräftelse.
296
+
179
297
  ## Statusarna
180
298
 
181
299
  **Offer status** driver arbetet. Varje läge är en inkorg:
@@ -188,7 +306,9 @@ Task name ska vara det förändrade tillståndet, inte uppgiften, samma regel so
188
306
  | ⚖️ Klassning redo för granskning | människa |
189
307
  | 📤 Klar – till kund | kundens svar, se `Decision` |
190
308
 
191
- **Request status** är kundens vy och ska härledas, inte sättas fritt. Sätt den bara när du också sätter det som styr den, och skriv aldrig ett värde som motsäger Offer status eller Decision.
309
+ **Request status** är kundens vy och härleds av en Asana-regel ur `Offer status`. **Sätt den en enda gång — vid skapandet, innan `Offer status` finns att härleda ur.** Därefter rör du den aldrig; regeln äger den. Startvärdet ska vara exakt det regeln hade härlett, så att fälten aldrig kan säga emot varandra.
310
+
311
+ Skälet: `Request status` är det enda i hela flödet en kund ser. Två fält som båda sätts för hand driftar isär, och just den driften syns hos någon annan.
192
312
 
193
313
  **Att hämta en kö** är det vanligaste anropet: alla poster med ett givet Offer status. Filtrera alltid på samlingsbrädan.
194
314
 
@@ -200,14 +320,18 @@ Feedback är en kommentar plus en flytt bakåt till närmaste AI-läge. Två reg
200
320
 
201
321
  **Ändrad spec ogiltigförklarar klassningen.** Går en post bakåt till 📥 ska den passera ⚖️ igen på vägen tillbaka. Skriv inte över `Class (offered)` med ett nytt värde utan att posten gjort den resan.
202
322
 
323
+ En bakåtflytt producerar en ny spec, och den ska in i beskrivningen — läs därför `Decision` först. Har posten redan ett kundbeslut gäller låsregeln och beskrivningen rörs inte.
324
+
203
325
  ## Vad du aldrig gör
204
326
 
205
327
  **Skriver till kund.** Du sätter fält och flyttar statusar. Att skicka förslaget är en människas beslut.
206
328
 
207
- **Skriver över beskrivningen utan att först ha verifierat `Original request`.**
329
+ **Skriver över beskrivningen utan att först ha verifierat `Original request`** — och skriver aldrig över en sektion som ett annat steg äger.
330
+
331
+ **Skriver till beskrivningen utan att ha läst `Decision`.** Har ärendet ett kundbeslut är beskrivningen låst, oavsett vad som ändrats.
208
332
 
209
- **Rör `Class (offered)` efter att `Decision` är satt.** Den är låst. Blir klassen högre vid grinden är det ett nytt beslut, inte en överskrivning — `Class (revised)` fylls, posten flyttas tillbaka till ⚖️, och människan avgör vad kunden får se.
333
+ **Rör `Class (offered)` eller `Class rationale` efter att `Decision` är satt.** De bär samma text som beskrivningen och är låsta med den. Blir klassen högre vid grinden är det ett nytt beslut, inte en överskrivning — `Class (revised)` fylls, posten flyttas tillbaka till ⚖️, och människan avgör vad kunden får se.
210
334
 
211
335
  **Sätter `Decision` själv.** Det är kundens svar, det kommer utifrån.
212
336
 
213
- **Raderar eller redigerar kommentarer.** Loggen är append-only.
337
+ **Raderar eller redigerar kommentarer.** Feedbackloggen är append-only.
@@ -43,6 +43,12 @@ Frågan är inte estetisk. Klassningen räknar omfattning per post, så en odela
43
43
 
44
44
  **Inget "eller" i listan.** Ett "eller" i en utfallspunkt är ett obeslutat vägval i förklädnad. Avgör det (se nedan) — skriv aldrig in det.
45
45
 
46
+ **Leta efter dolda utfallsval.** En del frågor ser ut som tekniska detaljer men avgör vad användaren faktiskt får — "ska den komma tillbaka på nästa enhet?", "gäller det bara den här användaren eller alla?", "syns ändringen direkt eller vid nästa inloggning?". Sådana frågor är specfrågor, inte byggbeslut, och de ska besvaras här: som acceptanskriterium om svaret är givet, under _Ingår inte_ om avgränsningen är svaret, och som öppen fråga i granskarblocket om det inte går att avgöra ur underlaget.
47
+
48
+ Testfrågan: **skulle användaren märka skillnad mellan alternativen?** Ja → specfråga, besvara den. Nej → byggbeslut, det tas i påverkansanalysen och du ska inte röra det.
49
+
50
+ Missar du en sådan fråga blir den ett tyst val längre fram i kedjan, fattat av någon som bedömer teknik och inte behov — och då prissätts något ingen beslutat.
51
+
46
52
  **Lösningen pekar på listan.** Varje mening under Lösning ska motsvara en punkt under När det är klart. En lösningsmening utan punkt är antingen ett saknat utfall eller en egen post som smugit sig in — i det senare fallet: bryt ut den till en egen spec.
47
53
 
48
54
  **Ingen tid, inget pris.** Timmar, estimat och kronor finns inte i specen. Priset sätts av klassningen och möter kunden i förslaget. Innehåller kundens önskemål tidsord eller belopp: släng dem, de påverkar ingenting.
@@ -93,13 +99,16 @@ Skriv varje spec som ett eget block, exakt enligt formatet. Efter alla specar: e
93
99
  ## Till granskaren
94
100
 
95
101
  **Antaganden:** [tolkningar av otydligt underlag, en rad var — "tom" om inga]
96
- **Vägval jag gjort:** [beslut du fattat på eget bevåg + en rads motivering]
102
+ **Vägval jag gjort:** [beslut du fattat på eget bevåg + en rads motivering — märk ut de som rör vad användaren får, de är specbeslut och det är dem granskaren måste titta på]
103
+ **Öppna utfallsval:** [frågor om vad användaren får som inte gick att avgöra ur underlaget — "inga" om inga. Rena byggbeslut hör inte hit]
97
104
  **Flaggor:** [Koncept-/Diagnos-kandidat med skäl · misstänkt bunt/beroende till annan post · sådant som ser ut att röra behörighet, betalning, oåterkallelig data eller personuppgifter]
98
105
  **Struket ur underlaget:** [tidsord, belopp, interna anteckningar som inte hör hemma i spec]
99
106
  ```
100
107
 
101
108
  Behörighets-/betalnings-/dataflaggan finns för att klassningen bumpar sådana poster — granskaren ska inte behöva upptäcka det själv.
102
109
 
110
+ De två vägvalsraderna är åtskilda för att de kräver olika sak av granskaren: den första är beslut som redan är fattade och bara ska bekräftas, den andra är hål i specen som måste fyllas innan posten går vidare. Ett öppet utfallsval som ligger kvar i den första raden ser ut som ett fattat beslut och passerar granskningen.
111
+
103
112
  ## Exempel i korthet
104
113
 
105
114
  Rått önskemål: _"Som chef vill jag själv kunna radera en skattning så att olämpligt innehåll kan tas bort direkt utan att ringa Haus."_
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haus-tech/haus-workflow",
3
- "version": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "description": "Haus AI workflow CLI for Claude Code.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -58,8 +58,8 @@
58
58
  "@types/fs-extra": "11.0.4",
59
59
  "@types/node": "22.20.1",
60
60
  "@types/semver": "7.8.0",
61
- "@typescript-eslint/eslint-plugin": "8.65.0",
62
- "@typescript-eslint/parser": "8.65.0",
61
+ "@typescript-eslint/eslint-plugin": "8.67.0",
62
+ "@typescript-eslint/parser": "8.67.0",
63
63
  "c8": "11.0.0",
64
64
  "esbuild": "0.28.2",
65
65
  "eslint": "9.39.5",