@haus-tech/haus-workflow 4.2.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 +20 -0
- package/dist/cli.js +113 -11
- package/library/catalog/manifest.json +558 -7
- package/library/catalog/validation-rules.json +2 -4
- package/library/global/skills/haus-workflow/SKILL.md +6 -1
- package/library/global/skills/haus-workflow/references/new.md +38 -11
- package/library/global/skills/request-assess-impact/SKILL.md +30 -7
- package/library/global/skills/request-classify/SKILL.md +0 -7
- package/library/global/skills/request-classify/references/klassningsinstruktion.md +9 -3
- package/library/global/skills/request-score/SKILL.md +239 -0
- package/library/global/skills/request-score/references/poangskala.md +1135 -0
- package/library/global/skills/request-sync/SKILL.md +163 -39
- package/library/global/skills/request-write-spec/SKILL.md +10 -1
- package/package.json +3 -3
|
@@ -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 —
|
|
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
|
-
**
|
|
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
|
-
**
|
|
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
|
|
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
|
-
**
|
|
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
|
|
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
|
|
104
|
-
| ------------------------------ |
|
|
105
|
-
| `request_id` | task gid
|
|
106
|
-
| `original_request` | Original request
|
|
107
|
-
| `source` | Source
|
|
108
|
-
| `customer` | Customer
|
|
109
|
-
| `requested_by` | Requested by
|
|
110
|
-
| `type` | Request type
|
|
111
|
-
| `funding` | Funding
|
|
112
|
-
| `spec` |
|
|
113
|
-
| `impact` |
|
|
114
|
-
| `classification` |
|
|
115
|
-
| `customer.class`, läge pricing | Class (offered)
|
|
116
|
-
| `customer.class`, läge guard | Class (revised)
|
|
117
|
-
| `customer.rationale` | Class rationale
|
|
118
|
-
| `customer.conditions` ej tom | Conditional classification
|
|
119
|
-
| `decision` | Decision
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
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.**
|
|
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.**
|
|
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.
|
|
3
|
+
"version": "4.4.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.
|
|
62
|
-
"@typescript-eslint/parser": "8.
|
|
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",
|