@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.
- package/CHANGELOG.md +14 -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 +11 -8
- 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-sync/SKILL.md +163 -39
- package/library/global/skills/request-write-spec/SKILL.md +10 -1
- package/package.json +3 -3
|
@@ -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,
|
|
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, `. _ -`)
|
|
27
|
-
|
|
28
|
-
|
|
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>] [--
|
|
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.
|
|
95
|
-
|
|
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.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
**
|
|
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
|
-
|
|
68
|
+
Design, utseende, flöde och UX hör alltid till den andra kategorin.
|
|
65
69
|
|
|
66
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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 —
|
|
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
|
|
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 —
|
|
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.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.
|
|
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",
|