@haus-tech/haus-workflow 4.3.0 → 4.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.4.0](https://github.com/WeAreHausTech/haus-workflow/compare/v4.3.0...v4.4.0) (2026-08-24)
4
+
5
+ ### Features
6
+
7
+ - **skills:** add request-score and let assess describe open outcome choices ([#347](https://github.com/WeAreHausTech/haus-workflow/issues/347)) ([09bd070](https://github.com/WeAreHausTech/haus-workflow/commit/09bd0709c5123fb9d82a0410fa995020beb384a6))
8
+
3
9
  ## [4.3.0](https://github.com/WeAreHausTech/haus-workflow/compare/v4.2.0...v4.3.0) (2026-08-24)
4
10
 
5
11
  ### Features
@@ -90,9 +90,29 @@ Analysen som ett dokument, en sida. Sedan ett kort block till granskaren:
90
90
  ## Till granskaren
91
91
 
92
92
  **Ej verifierat:** [vad du inte kunnat belägga i koden, och varför]
93
- **Avvikelse mot specen:** [om koden säger något annat än specen förutsätter · utfallsval specen lämnat obesvarade]
93
+ **Avvikelse mot specen:** [om koden säger något annat än specen förutsätter]
94
+ **Obesvarade utfallsval:** [ett stycke per val — se nedan]
94
95
  ```
95
96
 
97
+ ### Obesvarade utfallsval
98
+
99
+ Ett utfallsval som specen lämnat öppet skrivs ut med tre saker, och alla tre behövs:
100
+
101
+ 1. **Vilka alternativen är.** Namnge dem, och var i koden vart och ett finns om de
102
+ bygger på något befintligt.
103
+ 2. **Om alternativen skiljer sig i vad som måste byggas.** Skriv rakt ut "båda mönstren
104
+ finns redan, samma arbete oavsett" eller "det ena kräver att X också ändras". Det är
105
+ en observation om koden, inte en bedömning av omfattning — du skriver aldrig att
106
+ något är stort, litet, enkelt eller dyrt.
107
+ 3. **Vilket alternativ analysen är skriven utifrån.** Du måste utgå från något för att
108
+ kunna beskriva systemet. Skriv "beskriven utifrån X", aldrig "vi väljer X" — valet
109
+ är inte ditt.
110
+
111
+ Skälet till punkt 2: den som poängsätter posten har inte repot och kan inte se om
112
+ alternativen kostar olika. Utan din rad måste den anta det värsta och stoppa posten,
113
+ även när båda vägarna är samma arbete. Det är den vanligaste orsaken till att en post
114
+ studsar tillbaka till specen i onödan.
115
+
96
116
  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.
97
117
 
98
118
  ## Vad du aldrig gör
@@ -0,0 +1,239 @@
1
+ ---
2
+ name: request-score
3
+ description: Sätter poäng på en spec plus påverkansanalys genom att jämföra uppdraget mot en skala av sexton referensuppdrag. Använd alltid när användaren vill "sätt poäng", "poängsätt", "kör poängen", "vad landar det här på", "var på skalan ligger det", eller när en spec har en påverkansanalys och ska prissättas. Används även som grind på en fullständig implementationsplan före första kodraden — "kör guarden", "stämmer poängen fortfarande". Använd den även när poängsättning bara antyds, t.ex. när någon klistrar in en spec med underlag och frågar hur stort det är. Output är JSON med poäng och belägg, aldrig ett pris.
4
+ ---
5
+
6
+ # request-score
7
+
8
+ Du sätter poäng på en post genom att jämföra den mot referensuppdragen i
9
+ `references/poangskala.md`. Läs skalan innan du poängsätter första posten i en session.
10
+
11
+ **Går filen inte att läsa: poängsätt inte.** Säg att `references/poangskala.md` saknas
12
+ och att skillen inte kan köras utan den. Sätt aldrig en poäng på minnet av hur skalan
13
+ brukar se ut. Skalan ändras när nya referensuppdrag läggs till, och en poäng satt på
14
+ en gammal skala ser likadan ut som en satt på rätt skala.
15
+
16
+ **Du sätter aldrig pris.** Poäng blir pris genom en fast processavgift plus poängen
17
+ gånger en konverteringsfaktor, och det räknas någon annanstans. Ligger prislistan i
18
+ sammanhanget: använd den inte och säg till. Vet du vad poängen kostar drar du mot den
19
+ poäng som känns rimlig att ta betalt för, och då mäter du inte längre uppdraget.
20
+
21
+ **Du skriver aldrig underlaget.** Saknas spec eller påverkansanalys, avbryt med
22
+ `INPUT_SAKNAS`. Skriv inte en påverkansanalys själv — då jämför du din egen text mot
23
+ skalan, och belägget blir teater. `request-assess-impact` gör det, helst i en egen
24
+ körning.
25
+
26
+ **Ge inte dig själv repot i den här körningen.** Har du det börjar du verifiera saker
27
+ vid sidan av underlaget, och då poängsätter du inte längre det du fått. Saknas något i
28
+ underlaget är svaret låg konfidens, inte en egen efterforskning.
29
+
30
+ ## Stoppfrågorna först
31
+
32
+ Poäng sätts bara på en post som går att bygga. Tre utfall stoppar poängsättningen:
33
+
34
+ | Utfall | När | Vad som ska hända |
35
+ | --- | --- | --- |
36
+ | `KONCEPT` | Formen är okänd — designfråga, oavgjort vägval, flera lösningsvägar utan beslut | Egen post som levererar ett förslag och en poäng på bygget |
37
+ | `DIAGNOS` | Orsaken är okänd och går att undersöka. Gäller framför allt fel där ingen vet varför något är trasigt | Tidsboxad undersökning som levererar besked och en poängsatt åtgärd |
38
+ | `TILLBAKA_TILL_SPEC` | Specen lämnar ett utfallsval obesvarat **och valet ändrar arbetsmängden** | Specen kompletteras, sedan ny körning |
39
+
40
+ ### Obesvarade utfallsval: förutsättning eller stopp
41
+
42
+ Påverkansanalysens granskarblock listar under _Obesvarade utfallsval_ de val specen
43
+ lämnat öppna, var och en med alternativen, om de skiljer sig i vad som måste byggas,
44
+ och vilket alternativ analysen är skriven utifrån. De ska inte behandlas lika. Ställ en
45
+ fråga per val:
46
+
47
+ **Ändrar valet hur mycket arbete posten kräver?** Analysens rad om huruvida
48
+ alternativen skiljer sig i vad som måste byggas är svaret. Saknas den raden — analysen
49
+ kan vara skriven före den här regeln — behandla valet som ett stopp och skriv i `notes`
50
+ att analysen behöver kompletteras.
51
+
52
+ **Nej** — då är det en **förutsättning**, inte ett stopp. Välj det rimligaste
53
+ alternativet, skriv in det i `assumptions_stated` med vad som valts och varför, och
54
+ poängsätt vidare. Förutsättningarna följer med förslaget till kund tillsammans med
55
+ specen och priset, så kunden godkänner alla tre på en gång. Väljer kunden annorlunda
56
+ är det en ändring som inte rör priset.
57
+
58
+ Typexempel: vilket av två befintliga sätt att visa att något laddar som används, vilken
59
+ av två likvärdiga formuleringar en text får, var i en befintlig vy ett fält placeras.
60
+
61
+ **Ja** — då stoppar posten. Utfallsvalet avgör vad som ska byggas och därmed vad det
62
+ kostar, och att gissa vore att prissätta något kunden inte beställt.
63
+
64
+ Typexempel: om en funktion ska finnas på både mobil och dator eller bara en av dem, om
65
+ befintlig data ska konverteras eller lämnas, om ett flöde ska ha ett steg till.
66
+
67
+ Är du osäker på om valet ändrar arbetsmängden: behandla det som ett stopp och skriv
68
+ ut varför. Ett onödigt stopp kostar några minuter, ett gissat utfallsval kostar en
69
+ felprissatt post.
70
+
71
+ Ett antagande som inte går att undersöka är inget stopp. Det blir ett villkor på posten:
72
+ "bygger på att X; faller X tidigt avbryts posten utan debitering". Osäkerhet löses med
73
+ kunskap eller villkor, aldrig med högre poäng för säkerhets skull.
74
+
75
+ ## Metoden: ringa in, aldrig skatta fritt
76
+
77
+ En siffra som kommer direkt ur en helhetsbedömning går inte att granska och blir olika
78
+ mellan två körningar. Ringa in i stället, i fyra steg. Alla fyra redovisas i utfallet.
79
+
80
+ **Steg 1 — hitta ett golv.** Läs skalan och hitta ett referensuppdrag som posten
81
+ **säkert är större än**. Skriv ut vilket och varför.
82
+
83
+ **Steg 2 — hitta ett tak.** Hitta ett referensuppdrag som posten **säkert är mindre
84
+ än**. Skriv ut vilket och varför.
85
+
86
+ Får du inget golv: posten är mindre än A1 och får A1:s poäng. Skalans nedre ände är
87
+ ändå dominerad av den fasta processavgiften.
88
+
89
+ Får du inget tak: posten är större än skalans högsta referensuppdrag. Sätt utfallet
90
+ till `OVER_SKALAN` och sätt ingen poäng — underlaget för den nivån är för tunt för att
91
+ jämföra mot, och posten ska offereras separat.
92
+
93
+ **Steg 3 — snäva in.** Gå igenom referensuppdragen mellan golv och tak. För varje: är
94
+ posten större eller mindre, och på vilken grund? Fortsätt tills du har två
95
+ angränsande referensuppdrag som posten ligger mellan.
96
+
97
+ **Steg 4 — placera.** Sätt poängen mellan de två. Ligger posten närmare det ena, säg
98
+ vilket och varför. Landar den på samma nivå som ett referensuppdrag, ge den det
99
+ ankarets poäng rakt av.
100
+
101
+ **Avrunda till skalans upplösning.** Under 3 poäng till närmaste 0,25, alltså 0,25,
102
+ 0,5, 0,75, 1, 1,25 och så vidare. Från 3 poäng och uppåt till närmaste hela poäng. En
103
+ finare siffra än så låtsas om en noggrannhet som inte finns: två oberoende bedömare
104
+ hamnar i olika klass i en femtedel av fallen. Avrundningen är mekanisk och sker efter
105
+ placeringen, aldrig genom att du väljer ett rundare tal medan du jämför.
106
+
107
+ ## Vad du jämför på
108
+
109
+ Jämför på vad ändringen **drar med sig**, inte på hur mycket kod som skrivs. Det som
110
+ skiljer referensuppdragen åt, i fallande ordning efter hur mycket de väger:
111
+
112
+ **Om en människa måste verifiera för hand, och i hur många fall.** Det är den tydligaste
113
+ skillnaden genom hela skalan. Ett uppdrag som täcks av automatiska tester ligger lågt.
114
+ Ett som kräver genomgång i flera scenarier, på flera enheter eller i flera miljöer
115
+ ligger högt.
116
+
117
+ **Förutsätt alltid att automatiska tester finns**, även när påverkansanalysen säger att
118
+ repot saknar testsvit. Räkna bara det manuella arbete som återstår när en fungerande
119
+ testsvit gjort sitt: det som kräver en människa av sin natur, alltså kontroll mot en
120
+ extern tjänsts testläge, visuell granskning, eller genomgång på flera enheter eller i
121
+ flera miljöer. Att ett repo saknar tester är Haus egen tekniska skuld, och den ska
122
+ kunden inte betala för. Skriv i så fall en rad om det under `notes`, så att skulden
123
+ syns i stället för att bakas in i priset.
124
+
125
+ **Vad som händer om det blir fel.** Felaktig betalning, felaktig åtkomst till någon
126
+ annans uppgifter, förlorad data eller bruten befintlig funktion väger tungt. Fel text
127
+ eller fel sorteringsordning väger lätt.
128
+
129
+ **Om ändringen rör kod som flera kunder använder.** Då tillkommer migrering per
130
+ installation och en risk som når utanför beställaren. Se A9 och A10.
131
+
132
+ **Om ett externt system berörs**, och om kopplingen är ny eller befintlig.
133
+
134
+ **Om en sekvens som användaren passerar i ordning ändras**, och hur många steg.
135
+
136
+ **Om något ska formges som inte finns i systemet i dag.**
137
+
138
+ Antal filer och antal rader är **inte** jämförelsegrunder. Se noten sist i skalan: två
139
+ referensuppdrag med samma poäng skiljer sig med en tiopotens i filantal.
140
+
141
+ ## Typen
142
+
143
+ Använd typen för att hitta jämförbara referensuppdrag snabbare, ingenting annat. Ett
144
+ uppdrag av en typ som saknas i skalan poängsätts mot de närmaste i storlek, inte mot
145
+ någon påhittad justering. Skriv ut vilken typ du bedömt posten som — den loggas för att
146
+ kunna mäta i efterhand om någon typ hamnar systematiskt fel.
147
+
148
+ ## Grindläget
149
+
150
+ Körs skillen på en fullständig implementationsplan efter kundens godkännande, sätt
151
+ `mode` till `guard`. Samma skala, samma metod.
152
+
153
+ Endast ny strukturell information ur fullplanen får flytta poängen, aldrig en
154
+ omvärdering av samma fakta. Rapportera vilket jämförelsesteg som ändrades och citatet ur
155
+ fullplanen som orsakade det. Grinden är symmetrisk — en lägre poäng rapporteras lika
156
+ tydligt som en högre.
157
+
158
+ Bygger fullplanen ett annat vägval än det som såldes är det en händelse att rapportera
159
+ även när poängen blir densamma.
160
+
161
+ ## Output
162
+
163
+ ```json
164
+ {
165
+ "request_id": "",
166
+ "mode": "pricing | guard",
167
+ "outcome": "POANG | KONCEPT | DIAGNOS | TILLBAKA_TILL_SPEC | OVER_SKALAN | INPUT_SAKNAS",
168
+ "score": null,
169
+ "type": "",
170
+ "bracket": {
171
+ "floor": { "anchor": "", "score": null, "why": "" },
172
+ "ceiling": { "anchor": "", "score": null, "why": "" },
173
+ "between": ["", ""],
174
+ "steps": []
175
+ },
176
+ "drivers": [],
177
+ "confidence": "hog | medel | lag",
178
+ "conditions": [],
179
+ "assumptions_stated": [],
180
+ "dependencies": [],
181
+ "notes": [],
182
+ "customer_rationale": "",
183
+ "guard_diff": []
184
+ }
185
+ ```
186
+
187
+ `score` sätts bara när `outcome` är `POANG`, och alltid på skalans upplösning: steg om
188
+ 0,25 under 3 poäng, hela poäng från 3 och uppåt.
189
+
190
+ `bracket.steps` är jämförelserna från steg 3, en per referensuppdrag du vägde mot, var
191
+ och en med ankarets id, om posten är större eller mindre, och på vilken grund. Det är
192
+ det som gör poängen granskbar. En poäng utan inringning är inte ett giltigt utfall.
193
+
194
+ `drivers` är de två eller tre faktorer som mest avgjorde placeringen, med citat ur
195
+ påverkansanalysen. Citat, inte parafras.
196
+
197
+ `assumptions_stated` är de utfallsval specen lämnat öppna som **inte** ändrar
198
+ arbetsmängden: vad du valt, och varför. De går med förslaget till kund som
199
+ förutsättningar och godkänns tillsammans med specen och priset.
200
+
201
+ `notes` är iakttagelser som inte hör till poängen men som någon bör känna till, till
202
+ exempel att ett repo saknar testsvit.
203
+
204
+ `confidence` sätts till `lag` när posten inte liknar något referensuppdrag, när golv och
205
+ tak ligger långt isär och inget referensuppdrag finns emellan, eller när
206
+ påverkansanalysen anger att något inte kunnat verifieras och det påverkar placeringen.
207
+ Låg konfidens är ett giltigt utfall och ska inte döljas genom att välja en poäng som
208
+ ser rimlig ut.
209
+
210
+ ### Motiveringen till kund
211
+
212
+ `customer_rationale` skrivs i kundens språk och beskriver arbetet som ska göras, inte
213
+ hur skalan räknade. Nämn aldrig poäng, referensuppdrag, ankare eller skalan. Kunden ska
214
+ kunna invända mot omfattningen, inte mot modellen.
215
+
216
+ Den ska vara förenlig med specens _Ingår inte_. Motiverar du poängen med arbete som
217
+ specen uttryckligen undantar har du poängsatt fel post.
218
+
219
+ ## Efter körning
220
+
221
+ Granskaren läser inringningen, inte slutpoängen. En rimlig poäng med fel jämförelser är
222
+ en felkalibrering som råkade landa rätt, och den kommer tillbaka i en post där den inte
223
+ gör det.
224
+
225
+ Korrigeringar går till skalan, alltså till referensuppdragen eller till den här
226
+ instruktionen, och till kalibreringsloggen. Aldrig till priset på den enskilda posten.
227
+
228
+ Visar det sig återkommande att poster av ett visst slag är svåra att placera, är det ett
229
+ tecken på att skalan har ett hål och behöver ett referensuppdrag till. Rapportera det.
230
+
231
+ ## Acceptanstestet — granskarens sak, inte din
232
+
233
+ Skillen verifieras genom att köras mot poster med känt utfall. Det underlaget ligger med
234
+ flit **inte** i den här mappen — en körning som kan läsa facit kan inte längre testas. Du
235
+ ska varken leta efter det eller rapportera det som saknat.
236
+
237
+ För granskaren gäller två mått: att två oberoende körningar av samma post ger samma
238
+ poäng, och att inringningen håller vid granskning. Det första är det som avgör om
239
+ kunderna får samma pris för samma arbete.