@haus-tech/haus-workflow 5.12.1 → 6.1.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.
@@ -13,19 +13,19 @@ the respective skill. Only routing, context carrying, the archive and the dispat
13
13
 
14
14
  `/request [task]`: without an argument, show the menu below.
15
15
 
16
- | Task | Does |
17
- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
18
- | `speca <request or gid>` | Source manifest → dispatch `request-specifier` → archive spec + reviewer block |
19
- | `designa <gid, slug or nr>` | Gate on `✅ Spec ok` → `superpowers:brainstorming` with the user → the design doc in the repo + `design.md` in the archive; never Asana |
20
- | `bedöm <gid, slug or nr>` | Gate → secure an analysis → dispatch `request-scorer` → archive JSON |
21
- | `status` | Queue state via request-sync, BLUF table with row numbers |
22
- | `godkänn <nr or gid>` | Move Offer status forward via request-sync; see the gate section |
23
- | `underkänn <nr or gid> <reason>` | Reason as an Asana comment + iteration counter via request-sync |
24
- | `döm <item>` | Human ruling on OLIKA: choose a run, order a rerun or reject the source material |
25
- | `detaljer <gid, slug or nr> [step]` | Print archived JSON/documents for the item |
26
- | `byt titel <nr or gid>` | Rename the Asana task to the spec title (`state.json.title`) via request-sync, on request only |
27
- | `utvärdera <item…> <model…>` | Run the flow once per named model against the experiment area, at least one model; `sammanställ` gives the sweep view, `rapport` a readable comparison |
28
- | `hjälp` | Explain the tasks, touch no files |
16
+ | Task | Does |
17
+ | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
18
+ | `speca <request or gid>` | Source manifest → dispatch `request-specifier` → archive spec + reviewer block |
19
+ | `designa <gid, slug or nr>` | Gate on `✅ Spec ok` → `superpowers:brainstorming` with the user → the design doc in the repo + `design.md` in the archive; never Asana; a clean record continues into `bedöm` |
20
+ | `bedöm <gid, slug or nr>` | Gate → form check → `bedom.mjs` prices (a design draft and its review in draft mode, analysis, two scorers, archive) → BLUF; with several items or none, a batch |
21
+ | `status` | Queue state via request-sync, BLUF table with row numbers |
22
+ | `godkänn <nr or gid>` | Move Offer status forward via request-sync; see the gate section |
23
+ | `underkänn <nr or gid> <reason>` | Reason as an Asana comment + iteration counter via request-sync |
24
+ | `döm <item>` | Human ruling on OLIKA: choose a run, order a rerun or reject the source material |
25
+ | `detaljer <gid, slug or nr> [del-N] [step]` | Print archived JSON/documents for the item, or for one split part |
26
+ | `byt titel <nr or gid>` | Rename the Asana task to the spec title (`state.json.title`) via request-sync, on request only |
27
+ | `utvärdera <item…> <model…>` | Run the flow once per named model against the experiment area, at least one model; `sammanställ` gives the sweep view, `rapport` a readable comparison |
28
+ | `hjälp` | Explain the tasks, touch no files |
29
29
 
30
30
  ## Hard rules
31
31
 
@@ -123,8 +123,18 @@ this skill (and the agents through their prompts) maintains it.
123
123
  the same request) becomes several directories: the score is set per item, so a directory
124
124
  with several specs cannot be assessed.
125
125
 
126
+ The archive root is the main checkout's `.haus-workflow/requests/`, never a worktree's
127
+ (ADR-0154). At the start of every task that reads or writes the archive, run
128
+ `node <skillkatalog>/scripts/archive.mjs rot` first and use its `ARKIVROT:` line as
129
+ `<arkivrot>` below; the cwd may be the main checkout or any of its worktrees.
130
+ `IGNORERAD: nej` stops the task before any write: name `haus apply --write` in the main
131
+ checkout as the fix (it writes the rule) and rerun `rot` once the user says it has run;
132
+ never run it yourself from this skill. `rot` refuses a bare repository, a submodule
133
+ checkout and a `--separate-git-dir` clone (their common dir is not named `.git`): run the
134
+ task from the superproject's own checkout, or from an ordinary clone.
135
+
126
136
  ```
127
- <repo-rot>/.haus-workflow/requests/<gid-eller-slug>/
137
+ <arkivrot>/<gid-eller-slug>/
128
138
  ├── spec.md ONE spec, byte-faithful: what the reviewer approves
129
139
  ├── granskarblock.md "## For the reviewer" (bundle: the part's own
130
140
  │ block, never a copied one, ADR-0118)
@@ -156,7 +166,9 @@ its stop (`designa` step 5), with no runs row, since the design is no dispatch.
156
166
  the line yourself, and never hand-edit the block. If the archive is still tracked in git:
157
167
  run `haus apply --write`, which both writes the rule and untracks the files.
158
168
  Pricing material must not enter the customer's history. `.haus-workflow/request.json` (the sync's
159
- config) stays tracked: it is configuration, not working material.
169
+ config) stays tracked: it is configuration, not working material. It lives in the main
170
+ checkout and carries the board's choices (`auto_sync_spec`, ADR-0157; `design_mode`,
171
+ ADR-0156).
160
172
  - **Old archive under `.haus/`:** moved by `haus apply` to
161
173
  `.haus-workflow/` (ADR-0103). Never write to `.haus/` again, and do not move it
162
174
  yourself: run `haus apply --write` and let the command do it.
@@ -179,6 +191,7 @@ its stop (`designa` step 5), with no runs row, since the design is no dispatch.
179
191
  "respec_varv": 0,
180
192
  "coverage_post": null,
181
193
  "design": null,
194
+ "board": null,
182
195
  "runs": []
183
196
  }
184
197
  ```
@@ -195,15 +208,19 @@ its stop (`designa` step 5), with no runs row, since the design is no dispatch.
195
208
  strings); `nasta-steg` and `bluf` refuse a split whose parts disagree on `of` or carry a
196
209
  non-integer `of`.
197
210
  - `stopp` = a stop outcome that the scripts have proven without a scorer:
198
- `{ "utfall": "KONCEPT" | "DIAGNOS" | "TILLBAKA_TILL_SPEC" | "ESKALERA", "kalla": "spec.md" | "impact.md" | "granskarblock.md" | "design-avvisad-<datum>.md", "date": "YYYY-MM-DD", "orsak"?: string }`,
199
- the last one for a design refused on `## Spec conflicts` (`designa` step 5).
211
+ `{ "utfall": "KONCEPT" | "DIAGNOS" | "TILLBAKA_TILL_SPEC" | "ESKALERA", "kalla": "spec.md" | "impact.md" | "granskarblock.md" | "design-avvisad-<datum>.md" | "design-intervju-kravs-<datum>.md", "date": "YYYY-MM-DD", "orsak"?: string }`,
212
+ `design-avvisad-<datum>.md` for a design refused on `## Spec conflicts` (`designa` step 5),
213
+ `design-intervju-kravs-<datum>.md` for the designer's `INTERVJU KRÄVS` in draft mode
214
+ (always ESKALERA; `add-design` clears it, since `designa` answers it).
200
215
  Written ONLY by `archive.mjs stopp` (which itself checks that the source carries
201
216
  what is claimed: the candidate marker in `spec.md`, the label `contradiction` in
202
217
  `impact.md`, the price-decisive open choice in `granskarblock.md`, ADR-0118, at
203
- least one conflict under `## Spec conflicts` in `design-avvisad-<datum>.md`).
218
+ least one conflict under `## Spec conflicts` in `design-avvisad-<datum>.md`, a first line
219
+ `INTERVJU KRÄVS: <reason>` in `design-intervju-kravs-<datum>.md`).
204
220
  `add-design` clears a design-conflict stop (`kalla` `impact.md`, `orsak`
205
221
  `design conflict: …`) and supersedes the analysis it came from (`impact.md` →
206
- `impact-superseded-<datum>.md`), or a receipt replaces it (`designa` step 5); every
222
+ `impact-superseded-<datum>.md`), or a receipt replaces it (`designa` step 5); it also
223
+ clears a stop from `design-intervju-kravs-<datum>.md`, which only a design answers; every
207
224
  other stop is reset ONLY by `archive.mjs respec`.
208
225
  `orsak` is set when `utfall` is `ESKALERA` (the command requires `--orsak` then,
209
226
  so a human sees why the item did not go back to the spec once more) and for the
@@ -219,10 +236,14 @@ its stop (`designa` step 5), with no runs row, since the design is no dispatch.
219
236
  later): an item never goes a third spec round on the same choice. Older archives
220
237
  lack the field and are read as `0`.
221
238
  - `coverage_post` mirrors the score envelope's optional `coverage_post: { yta, omfattning }`
222
- (ADR-0119). `archive.mjs add-run` copies the field from the
223
- latest pricing file that carries it, the skeleton (`ny-korning`/`ny-del`) sets
224
- it to `null`. `bluf` shows `täckningspost: <yta>` in the `anm` column when
225
- the field is set.
239
+ (ADR-0119) from the score pricing file that counts, the same file `bluf` reads the score
240
+ from: the round's main file, or the file a ruling's `galler_fil` names (ADR-0159).
241
+ `archive.mjs` recomputes it on `add-run` of a score pricing file, on `utslag` on the
242
+ score axis and on `set-status priced`, and sets it to `null` when that file has no
243
+ post or is not written yet; `respec` clears it. A `-run2` file sets it exactly when a
244
+ ruling makes it the counting file. Never write the field by hand. The skeleton
245
+ (`ny-korning`/`ny-del`) sets it to `null`. `bluf` shows `täckningspost: <yta>` in the
246
+ `anm` column when the field is set.
226
247
  - `design` is written ONLY by `archive.mjs add-design` and reset ONLY by
227
248
  `archive.mjs respec`: `{ "path": "<absolute path to the canonical file in the repo>",
228
249
  "file": "design.md", "sha256": "<marker-stripped hash of design.md, identical to the canonical file>",
@@ -231,7 +252,23 @@ its stop (`designa` step 5), with no runs row, since the design is no dispatch.
231
252
  `add-design` writes no runs row: `runs[]` records dispatches and the design is not
232
253
  one; the receipt is the field itself, write-once per version (a new design puts the
233
254
  old copy aside as `design-superseded-<datum>.md`). Older archives lack the field
234
- and are read as `null`.
255
+ and are read as `null`. The field may also carry
256
+ `review` = `{ verdict, sha256, date, model }`, written ONLY by `archive.mjs add-design-review`
257
+ (the second reader's verdict on a draft), reset by `add-design` and `respec`
258
+ (both put `design-review.md` aside as `design-review-superseded-<datum>.md`);
259
+ `precheck --design` refuses to price a `stopp`. Whether the design is a draft is read
260
+ from `mode: draft` in `design.md`'s frontmatter, never from `state.json` (ADR-0156).
261
+ - `board` is the receipt of the last Offer status move this flow recorded: speca step 7, bedöm step 8 (on a split root, the move of the parent) and `underkänn`; `godkänn` and `byt titel` record none. Form `{ "offer_status": "<value>", "date": "YYYY-MM-DD" }`, written ONLY by `archive.mjs synced` and reset to `null` by `archive.mjs respec` and by `add-run` on a round's main pricing file. On a split root it is the receipt of the sync that moved the parent; `respec` or a new round's main pricing file on one of its parts resets the root's receipt too; a cache note, never the truth (Hard rules).
262
+ - `korning` = the running receipt `{ "pid": <heltal>, "started": "<ISO>", "katalog": "<abs>|null" }`
263
+ or `null`: written ONLY by `archive.mjs korning-start` (under the archive lock; it
264
+ refuses a living pid, so two starters never price the same item) and cleared ONLY by
265
+ `archive.mjs korning-slut`. `nasta-steg` writes `pågår (pid N)` while the pid lives and
266
+ `avbruten körning` when it is dead; the next `korning-start` takes a dead pid over;
267
+ `respec` refuses while a pid lives. Older archives lack the field and are read as
268
+ `null` (ADR-0155).
269
+ - a runs row may carry `repo_sha`, the `HEAD` of the checkout the assessor read, written
270
+ by `korning.mjs` through `add-run --repo-sha` on `impact.md` rows; absent on older rows
271
+ and on rows the main conversation stamps (ADR-0155).
235
272
  - `umbrella` is written ONLY by `archive.mjs paraply` (ADR-0144):
236
273
  `{ "date": "YYYY-MM-DD", "sha256": "<marker-stripped hash of the umbrella spec.md>" }`,
237
274
  the receipt that the parent's `spec.md` was rewritten one level up after a split.
@@ -239,7 +276,7 @@ its stop (`designa` step 5), with no runs row, since the design is no dispatch.
239
276
  parts keep their inherited copies of it. `paraply` also sets `title` from the umbrella's
240
277
  heading; approval, design, runs, stops and the parts are untouched. The field is absent
241
278
  until `paraply` writes it and is never reset.
242
- - `approval` is written by the gate in `designa` or `bedöm`:
279
+ - `approval` is written ONLY by `archive.mjs approve`, run by the gate in `designa` or `bedöm` after it has read the board, and copied unchanged into a new split part by `archive.mjs ny-del` (the part inherits the approved spec, ADR-0144):
243
280
  `{ "source": "asana" | "manual", "by": "<namn, krävs vid manual>",
244
281
  "status_read": "<värde>", "date": "YYYY-MM-DD" }`.
245
282
  The note is traceability, never the approval itself.
@@ -321,7 +358,7 @@ its stop (`designa` step 5), with no runs row, since the design is no dispatch.
321
358
  Model runs from `utvärdera` live in a tree of their own and are never pricing items:
322
359
 
323
360
  ```
324
- <repo-rot>/.haus-workflow/requests/experiments/<slug>/
361
+ <arkivrot>/experiments/<slug>/
325
362
  ├── experiment.json ticket reference, date, model list, manifest hash,
326
363
  │ status per run
327
364
  ├── <modell>/ `default` as the model value gives the directory name
@@ -403,6 +440,8 @@ Model runs from `utvärdera` live in a tree of their own and are never pricing i
403
440
  the heading skeleton in `RUBRIKER:` follows that language, see the prompt template) and
404
441
  `DEPS:` (`installerade` when `node_modules/` or equivalent exists under
405
442
  REPO-ROT, otherwise `saknas`; without a repo always `saknas`).
443
+ `REPO-ROT:` is the checkout whose code is read; it is not the archive root, which
444
+ `rot` gives.
406
445
  Write the manifest to `<katalog>/kallmanifest.md` in every directory the spec
407
446
  is archived in (step 5), so that `bedöm` can give the assessor the same manifest without
408
447
  building a new one. The manifest's first line is `SPRÅK: <svenska|engelska>`,
@@ -490,7 +529,13 @@ på request-write-spec/references/specformat.md>`. The script sets
490
529
  stop nothing.
491
530
  7. **Reply BLUF:** one line per spec (heading + any flags), then the reviewer block
492
531
  in its entirety. Offer to place the specs on the board via request-sync (🔍); do
493
- it only on explicit request. Placing a spec on the board is no rename: request-sync
532
+ it only on explicit request when the main checkout's `.haus-workflow/request.json`
533
+ (`ARKIVROT:`'s parent) carries `auto_sync_spec: false`; otherwise (`true` or absent,
534
+ ADR-0157) place every spec of this round that passed the form check in step 6 on the board now, in this turn, in the
535
+ main conversation, one item at a time through request-sync's ordinary spec sync (the
536
+ Decision read, the read-back, the three automatic rename cases are request-sync's and do
537
+ not change), a candidate included (the customer dialogue is its next step), a spec with a BRIST or a standing stop (`PRISAVGORANDE`, ADR-0118) never, it waits for `synka` as today. The ⚖️ sync is not covered: it waits for `synka` (`bedöm` step 8, ADR-0155).
538
+ Placing a spec on the board is no rename: request-sync
494
539
  renames the task to the spec title by itself only in the three automatic cases
495
540
  (ADR-0144): the task name is empty, `Original request title` is empty, or the task is
496
541
  one of several minted from one source. In the Closing, under the board line,
@@ -498,30 +543,49 @@ på request-write-spec/references/specformat.md>`. The script sets
498
543
  title and `byt titel <item>` is the optional next action. When an item is placed on the board: set status
499
544
  `spec_synced`, rename the slug directory to the minted gid, note the slug
500
545
  in `former_slug` and update `request_id` in `state.json`.
546
+ Then record the write: `node <skillkatalog>/scripts/archive.mjs synced <katalog> --offer-status "<the status request-sync set>"`.
501
547
  **Close per `## Closing: where the item stands`** (the table from
502
- `archive.mjs nasta-steg`, the board line, the ISÄR check), never without.
548
+ `archive.mjs nasta-steg`, the board line, the ISÄR check, and the wrap-up lines at a
549
+ resting point), never without.
503
550
 
504
551
  ## Task: `designa`
505
552
 
506
553
  Runs the design leg: brainstorming with the user against the approved spec, the
507
554
  design doc saved in the customer repo and recorded in the archive. Runs in the main
508
555
  conversation (the brainstorming skill asks the user questions), in a session whose cwd
509
- is the customer repo. Nothing here touches Asana: the design is internal source
556
+ is the customer repo or one of its worktrees (the archive root comes from `rot`). Nothing here touches Asana: the design is internal source
510
557
  material for `bedöm`'s assessor and never reaches the board.
511
558
 
559
+ **Draft mode (ADR-0156).** When `.haus-workflow/request.json` in the main checkout carries
560
+ `design_mode: draft`, an approved item without a design is designed by the machine inside
561
+ `bedöm`: `bedom.mjs` passes the mode on, `korning.mjs` dispatches `request-designer` (opus),
562
+ records the doc with `add-design`, has `request-design-reviewer` (fable) read it, and goes on
563
+ to the analysis only on `VERDICT: fortsätt`. `designa <item>` is still the interactive path
564
+ in both modes and supersedes a draft. A draft carries `mode: draft` in its frontmatter and
565
+ three sections the interactive doc may omit: `## Assumptions` (every HOW question the machine
566
+ answered, the option taken, the options not taken), `## Removed or renamed` (every symbol
567
+ the design deletes or renames; `precheck --design` and `add-design` grep each one outside
568
+ the files under `## Files touched`, a hit refuses the record) and `## Files touched`. An
569
+ architectural item comes back as `intervju krävs` with the receipt
570
+ `design-intervju-kravs-<datum>.md` and an ESKALERA stop that `designa` clears, and a reviewer
571
+ `stopp` leaves the item `designed` with `design-review.md` in the archive; both route here,
572
+ to the interview.
573
+
512
574
  1. **Gate. Identical to `bedöm` step 1.** Read Offer status via request-sync in the
513
575
  main conversation immediately before the run. Only `✅ Spec ok` (normalized on the
514
576
  alphabetic core) lets it through. An item without a gid follows `bedöm`'s rules for
515
577
  that case (refuse when the repo has `.haus-workflow/request.json`, otherwise the
516
578
  explicit "approved by whom" question). An item with a gid but no local archive
517
- directory: not supported, say so and stop. Note the passed gate in
518
- `state.json.approval` exactly as `bedöm` does; a later `bedöm` rereads the board.
579
+ directory: not supported, say so and stop. Record the passed gate with
580
+ `archive.mjs approve` exactly as `bedöm` does; a later `bedöm` rereads the board.
519
581
  2. **Form check.** Run `node <skillkatalog>/scripts/precheck.mjs <katalog>`. A
520
582
  `KANDIDAT:` line or a standing `stopp` means the item is not ready for a design,
521
583
  with one exception: a stop from `impact.md` whose `orsak` starts with
522
584
  `design conflict:` (the assessor found the design unbuildable) is exactly what a
523
585
  redesign answers, continue to step 3; `add-design` clears that stop and puts the
524
586
  old analysis aside as `impact-superseded-<datum>.md` when it records the redesign.
587
+ The same holds for an ESKALERA stop from `design-intervju-kravs-<datum>.md` (the
588
+ designer asked for this interview): continue, `add-design` clears it.
525
589
  Any other such line or stop: route it as the stop outcome (see `bedöm`) and stop. A
526
590
  `spec.md` with more than one spec block is a BRIST, as in `bedöm`. Other BRISTER:
527
591
  fix the link that is defective before anything is designed.
@@ -530,8 +594,9 @@ material for `bedöm`'s assessor and never reaches the board.
530
594
  Otherwise, if `state.json.design` is set, run
531
595
  `node <skillkatalog>/scripts/precheck.mjs <katalog> --design`. Three branches:
532
596
  (a) it passes (the hash still matches `design.md` and the canonical file): ask ONE
533
- question via AskUserQuestion: keep it, or redesign. Keep: close per step 6 without
534
- a new brainstorming. Redesign: continue; `add-design` supersedes the old one
597
+ question via AskUserQuestion: keep it, or redesign. Keep: continue per step 6 without
598
+ a new brainstorming; a kept design that passed `precheck --design` continues into
599
+ `bedöm` the same way a fresh record does. Redesign: continue; `add-design` supersedes the old one
535
600
  (`design-superseded-<datum>.md`), it never overwrites.
536
601
  (b) its only design BRISTER are the hash lines
537
602
  (`design.md: hashen är inte state.design.sha256 …` and/or
@@ -604,12 +669,7 @@ material for `bedöm`'s assessor and never reaches the board.
604
669
  item's state (status `priced` or `guard_run`, a standing stop other than a design
605
670
  conflict) is not fixed in the doc: `respec`, or decide the stop first.
606
671
 
607
- 6. **Reply BLUF:** one line per item (the design's title and path), the
608
- `## Spec conflicts` section verbatim when it is not `none`, the commit offer, then
609
- **Close per `## Closing: where the item stands`** (the table from
610
- `archive.mjs nasta-steg`, the board line, the ISÄR check), never without. For a doc
611
- refused on conflicts, the Closing's part 4 presents the conflicts as the choice
612
- (`## Avgjorda val`, `respec`, `speca <adress>`).
672
+ 6. **Continue into `bedöm`, or close.** When `add-design` recorded the doc, `precheck --design` wrote no BRIST and `## Spec conflicts` is `none`, run `bedöm <adress>` now, in the same turn, from its step 1 (the gate is reread from the board; the design is internal, so nothing reaches the customer before `bedöm`'s own sync rule, ADR-0153): the turn then ends with `bedöm`'s BLUF and Closing, never with a second block. If `bedöm` stops before its step 8 (its gate, a candidate, a contradiction), its Closing still carries the design doc's path and the commit offer. VARNING lines stop nothing: the chain runs. In every other case (a refused doc, a BRIST, an interview that ended without a file), **Reply BLUF:** one line per item (the design's title and path), the `## Spec conflicts` section verbatim when it is not `none`, the commit offer, then **Close per `## Closing: where the item stands`** (the table from `archive.mjs nasta-steg`, the board line, the ISÄR check), never without. For a doc refused on conflicts, the Closing's part 4 presents the conflicts as the choice (`## Avgjorda val`, `respec`, `speca <adress>`).
613
673
 
614
674
  ## Task: `bedöm`
615
675
 
@@ -634,7 +694,10 @@ drift guard.
634
694
  - **The item has a gid but lacks a local archive directory:** not supported yet
635
695
  (hydration from the board comes with the batch step); say so and stop;
636
696
  the reviewer block cannot be recreated from Asana.
637
- - Note the passed gate in `state.json.approval` (the manual case with `by`).
697
+ - Record the passed gate with
698
+ `node <skillkatalog>/scripts/archive.mjs approve <katalog> --source asana --status "<Offer status as read>"`
699
+ (the manual case: `--source manual --by <name>`); the script refuses any status
700
+ other than ✅ Spec ok, so a gate that was not read cannot be noted.
638
701
  The next `bedöm` reads the status again.
639
702
  - **Gate 1b, the design (only when the assessor is to be dispatched).** When
640
703
  `impact.md` is missing, or precheck rejects it on source-material provenance
@@ -647,6 +710,15 @@ drift guard.
647
710
  with one exception: a split part (`state.split.parent` set) is not gated, the
648
711
  split copied the parent's `design.md` into it, and the assessor gets it as the
649
712
  `DESIGN` block.
713
+ In draft mode (`design_mode: draft` in `.haus-workflow/request.json` in the main
714
+ checkout, ADR-0156), an item whose only design lines are the no-design signature,
715
+ `DESIGN: saknas` and the two BRISTER `design.md: saknas` and
716
+ `state.json: fältet "design" är null`, is not refused: it goes on to step 2, and
717
+ `bedom.mjs` has the design drafted and reviewed before the analysis (`designa`, Draft
718
+ mode). A recorded design is gated as above in both modes, a draft included: an
719
+ interactive doc without the draft sections passes with VARNING lines only, and a
720
+ stopped review (`designgranskningen stoppade utkastet`) is a BRIST whose way on is
721
+ `designa <adress>`.
650
722
  2. **Form check.** Run `node <skillkatalog>/scripts/precheck.mjs <katalog> --impact`
651
723
  (without `--impact` if the analysis does not exist yet). A `spec.md` with more than one
652
724
  spec block is a BRIST: split the item per the archive rule before anything is dispatched.
@@ -660,6 +732,37 @@ drift guard.
660
732
  an identical repeat call is harmless), and route the item as the stop outcome
661
733
  below. No analysis and no score may ever be dispatched on a
662
734
  candidate.
735
+
736
+ **Steps 3 to 7 run as ONE process in production (ADR-0155).** After step 2 has passed,
737
+ run `node <skillkatalog>/scripts/bedom.mjs --repo-rot <abs> --arkiv <arkivrot> --post <gid>`
738
+ as a background process and wait for its exit: it starts `korning.mjs` in production mode
739
+ on the item directory, which runs the analysis when it is missing or stale, the two
740
+ scorers at once, `kontroll.mjs`, `compare-scores.mjs` and the archiving through
741
+ `archive.mjs`, exactly as steps 3 to 7 describe; those steps are the contract the script
742
+ implements and its tests pin, not instructions for the main conversation, which
743
+ dispatches no agent and runs no check in this leg. `--repo-rot` is the checkout whose
744
+ code the assessor reads (the session's cwd; a worktree is fine) and `--arkiv` is
745
+ `ARKIVROT:` from `rot`. The starter writes the running receipt (`archive.mjs korning-start`,
746
+ `state.korning`) before the process starts and clears it after
747
+ (`korning-slut`), skips an item whose receipt carries a living pid (`pågår`), and stops
748
+ starting items when the batch's cost reaches `max_usd_per_batch` in
749
+ `.haus-workflow/request.json` (default 100 USD; `--max-usd` overrides one run), counting an
750
+ item in flight at the average of the finished ones. Read its
751
+ final table (`| post | status | poäng | utfall | wall | USD |`), paste it under the BLUF
752
+ in step 8, and route every row by its status: `priced` goes on to step 8, `stopp` and
753
+ `väntar på dom` take the stop and OLIKA routing below, `ofärdig` shows the reason from
754
+ the table and `<post>/korningar/<körning>/stderr.log`, `grind` and `tak nått` show the
755
+ reason and stop, and a `pågår` row is left alone.
756
+ `bedom.mjs` passes the board's design mode on to `korning.mjs` as `--design-mode`
757
+ (`design_mode` in `.haus-workflow/request.json`; `interview` and an absent key read as
758
+ `intervju`; the flag overrides one run). In draft mode the process drafts a missing design
759
+ (`request-designer`, recorded with `add-design`) and has `request-design-reviewer` read it
760
+ before the analysis (ADR-0156); the verdict is a judgment and is never redispatched. A
761
+ `stopp` row whose reason starts with `intervju krävs:` (the stop from
762
+ `design-intervju-kravs-<datum>.md`) or reads `designgranskningen stoppade (design-review.md)`
763
+ routes to `designa <adress>`, the interview. Commit nothing in `--repo-rot` while
764
+ the process runs: the impact row records the `HEAD` the assessor read (`repo_sha`).
765
+
663
766
  3. **Analysis.** If `impact.md` is missing, or precheck rejects it on
664
767
  source-material provenance (the analysis was made against another spec or another design): this requires a repo in
665
768
  the session (otherwise stop: a guessed analysis is forbidden by the skill itself).
@@ -692,9 +795,10 @@ drift guard.
692
795
  (the command sets status `assessed`), skip steps 4 to 7 and route
693
796
  the item as the stop outcome below: no scorer is dispatched on source material
694
797
  that already says the spec must go back. When the deviation line's text after the
695
- label starts with `design conflict:`, pass `--orsak "<that text>"`: the item goes
696
- back to the design, not to the spec, and the Closing routes it to `designa <adress>`
697
- (a redesign clears the stop, see `add-design`). `ingen` and `precisering` go
798
+ label starts with `design conflict:`, the command reads that text from `impact.md` as
799
+ the stop's `orsak` (#595; an `--orsak` that contradicts the file is refused, exit 2):
800
+ the item goes back to the design, not to the spec, and the Closing routes it to
801
+ `designa <adress>` (a redesign clears the stop, see `add-design`). `ingen` and `precisering` go
698
802
  on to step 4. If precheck rejects the new
699
803
  draft → redispatch the assessor ONCE per the redispatch rule, and give
700
804
  the rejected draft a receipt exactly as in speca step 6: archive it as
@@ -718,8 +822,12 @@ drift guard.
718
822
  `resolve-anchors.mjs` (evidence anchors to verbatim source blocks;
719
823
  OLÖST/FLERTYDIG is a contract breach) and contract-check in one process; a
720
824
  protocol-term breach in a pure customer-text field is rewritten by a cheap model
721
- instead of costing a new scorer run. The `REPARERAT:` lines are shown in
722
- the BLUF reply and written into the runs row's `--note`.
825
+ instead of costing a new scorer run. The `REPARERAT:` lines are written into the runs
826
+ row's `--note`, never pasted into the chat; the BLUF reply mentions a repair in plain
827
+ words only when it matters to the reviewer (`## Reply wording`). A runs row takes ONE
828
+ `--note` (`add-run` reads only the first): when step 6 adds comparison rows to the same
829
+ row, pass both in one value joined with `; `, each repair line prefixed `reparerat: `
830
+ (the form `korning.mjs` writes).
723
831
  `impact.md` is ALWAYS sent to contract-check, never only the spec:
724
832
  the script reads the label on `**Deviation from the spec:**` and rejects every
725
833
  outcome other than TILLBAKA_TILL_SPEC when the analysis carries `contradiction`
@@ -727,11 +835,13 @@ drift guard.
727
835
  has still reached this point has source material the script must get to see). The same script requires
728
836
  every `bracket.steps[i]` to be exactly `{anchor, relation, grund}`.
729
837
  BROTT that remain after the repairs → redispatch ONCE per
730
- the redispatch rule, with the error lines in the prompt. If breaches remain: show them and
731
- stop without archiving the reply as a valid round, but do not throw it away:
838
+ the redispatch rule, with the error lines in the prompt. If breaches remain: stop
839
+ without archiving the reply as a valid round, but do not throw it away:
732
840
  archive it as `score-pricing-vN-avvisad.json` (outside the N count) with
733
841
  the check's error lines in a runs row, so even failed runs have a
734
- receipt. An `AVVIKELSE:` line is always shown to the user.
842
+ receipt. Tell the user in plain words that the scoring failed an automatic check
843
+ twice and was not counted (`## Reply wording`). An `AVVIKELSE:` line is always
844
+ reported to the user, as what the scorer flagged, in plain words (`## Reply wording`).
735
845
  6. **Double run (drift guard).** Run 2 ALWAYS starts at the same time as
736
846
  run 1, with the same prompt and in a new isolated run; in production
737
847
  both Agent calls are dispatched at once (#500, ADR-0113), the prompts are
@@ -765,13 +875,18 @@ drift guard.
765
875
  rows `double_run: "olika"` with `superseded_by: null`).
766
876
  Status `assessed`. No customer text may go to
767
877
  request-sync while the hold stands (`archive.mjs sparr` is the interpreter).
768
- Show in the BLUF reply the evidence behind the disagreement, side by side:
769
- the diff rows (outcome, score, anchor, confidence) have no
770
- row link to the evidence, `drivers[]` is a list of its own, so show
771
- all `drivers[].citat`/`pastaende` from both runs
772
- as support for the whole outcome. It was the evidence that decided the ruling in
773
- every measured genuine disagreement. Then refer to `döm <item>` and
774
- STOP: no rerun, no escalation, no choice of run.
878
+ Describe in the BLUF reply the evidence behind the disagreement, per
879
+ `## Reply wording`: first one sentence on what the runs disagree on (the price,
880
+ the conditions, what is priced, how the work compares with the reference
881
+ assignments; two runs can disagree at the same score), then for each run, one or
882
+ two sentences on where it landed and
883
+ what it leaned on, built from all of its `drivers[].citat`/`pastaende` (the
884
+ diff rows have no row link to the evidence, `drivers[]` is a list of its own),
885
+ quoting the source text where it decides. It was the evidence that decided the
886
+ ruling in every measured genuine disagreement. Never paste the diff rows:
887
+ the diff rows go into run 1's runs row `--note`, so `detaljer <item> state` shows
888
+ them. Then refer to `döm <item>` and STOP: no rerun, no escalation, no choice
889
+ of run.
775
890
  - **LIKA_TOLERANS** (a score difference ≤ 0.5 with the same outcome, regardless of
776
891
  confidence, a confidence difference alone never rejects a pair within
777
892
  the tolerance) → the pair counts as confirmed. The run the verdict line points out
@@ -782,7 +897,12 @@ drift guard.
782
897
  the difference lies within the tolerance. Set `double_run: "tolerans"` on
783
898
  both runs rows. The tolerance is a deliberate pricing rule: the highest
784
899
  value protects the margin, and an average is still never
785
- computed. Show the tolerance rows in the BLUF reply. A pair of two
900
+ computed. Write the tolerance rows into the main file's runs row `--note`, so
901
+ `detaljer <item> state` shows them, and say in the BLUF reply, per
902
+ `## Reply wording`, that the two scorings landed close and which score applies;
903
+ a row that shows something only one run found (an alternative, a different type)
904
+ is told in a sentence too.
905
+ A pair of two
786
906
  `OVER_SKALAN` with the SAME floor where only the confidence differs
787
907
  also writes `LIKA_TOLERANS`, but with no score to compare (OVER_SKALAN carries
788
908
  `score: null`) run 1 wins deterministically, never "the highest
@@ -822,16 +942,34 @@ ref-hash.mjs på request-score/references/poangskala.md>
822
942
  as it is (`| post | poäng | utfall | konfidens | anm |`, one row per
823
943
  directory and part; the score from the files, stop outcomes from `stopp`, OLIKA and
824
944
  tolerance in `anm`), NEVER handwritten: a handwritten table
825
- misreported in a live run. Under the table, one line
826
- per deviation worth seeing (ESKALERA, DELA_UPP,
827
- INPUT_SAKNAS, AVVIKELSE lines). The JSON is not shown in the chat:
828
- `detaljer <item>` does that. Writing back to the board happens via request-sync
945
+ misreported in a live run. When the item's design is a draft (the first line of
946
+ `archive.mjs antaganden <katalog>` reads `Designläge: draft`), paste
947
+ `node <skillkatalog>/scripts/archive.mjs antaganden <katalog>` under the BLUF as it is: every
948
+ question the machine answered with the option taken and the options not taken, the review
949
+ verdict and the spec conflicts; this is the human's reading before `synka`, never
950
+ handwritten. Under the table, one plain sentence per deviation
951
+ worth seeing (an escalation, a split, missing input, something the scorer
952
+ flagged), per `## Reply wording`. The JSON is not shown in the chat:
953
+ `detaljer <item>` does that. When `bedöm` was entered from `designa` (designa step 6), the BLUF also carries the design doc's path and the commit offer `designa` would have printed. Writing back to the board happens via request-sync
829
954
  in the main conversation, only on explicit request, and it is that move
830
955
  that takes the item ✅ Spec ok → ⚖️ Poängsättning redo för granskning per
831
- the sync's rules. **Close per `## Closing: where the item stands`**
956
+ the sync's rules. Then record the write: `node <skillkatalog>/scripts/archive.mjs synced <katalog> --offer-status "<the status request-sync set>"` (not on a split part, whose receipt is `set-split-gid`; on the split root, in the run that moves the parent). **Close per `## Closing: where the item stands`**
832
957
  (the table from `archive.mjs nasta-steg`, the board line, the ISÄR check, and
833
958
  a stop outcome or OLIKA as a choice the user must make; a `DELA_UPP` as the two
834
- separate choices in the routing below), never without.
959
+ separate choices in the routing below; the wrap-up lines at a resting point), never without.
960
+
961
+ **Several items in one `bedöm`.** `bedöm` with several items, or with none, is a batch:
962
+ with none, the candidates are every item at ✅ Spec ok in request-sync's queue reading
963
+ (as `status`) that has an archive directory. A split root is left out: its parts are priced
964
+ one by one (`<gid>/del-N`) and the parent moves when the last part is in (the routing below).
965
+ Steps 1 and 2 run per item in the main
966
+ conversation (one request-sync read and one `approve` each; an item that fails its gate
967
+ or form check is listed with the reason and left out), then ONE `bedom.mjs` with one
968
+ `--post` per item that passed (two at a time, `--parallellt 2`), then step 8 per item in
969
+ one reply, each with its own `bluf` and `nasta-steg` tables and the starter's USD column.
970
+ The ⚖️ sync still waits for `synka`, the user's explicit request to publish the score (step
971
+ 8, in any wording; ADR-0155): after a batch, that request publishes every `priced` item in turn, one request-sync write and one `synced` receipt at a time, never
972
+ in parallel.
835
973
 
836
974
  **Stop outcomes are routed, never interpreted.** A stop outcome is archived as the round's
837
975
  file (step 7), the status becomes `assessed`, never `priced`, and the item is routed:
@@ -839,9 +977,14 @@ file (step 7), the status becomes `assessed`, never `priced`, and the item is ro
839
977
  - `DELA_UPP` → the Closing offers two separate yes/no choices (ADR-0144), each answered on its own:
840
978
  1. **Split the item** (as before): a new analysis round per part; the parts become
841
979
  directories of their own, `del-1/ … del-M/` under the parent's directory, with `split`
842
- set (`parent`/`part`/`of`), each `state.json` written by the orchestrator as before
843
- (`ny-del` stays the experiment's command: its skeleton carries `experiment: true`,
844
- which `set-status priced` refuses), and a part without a ceiling becomes `OVER_SKALAN`,
980
+ set (`parent`/`part`/`of`), each created with
981
+ `node <skillkatalog>/scripts/archive.mjs ny-del <förälderns katalog> --typ split --part N --of M`,
982
+ never a hand-written `state.json`: under a real item at the scorer's `DELA_UPP` it
983
+ writes a production part (no `experiment` marker, `split.parent` the parent's gid or,
984
+ without one, its directory name, the parent's `approval` inherited, `part`/`of`
985
+ integers checked against the siblings under the parent's lock; `--request-id` is
986
+ optional there and must match the parent) and refuses anything else, exit 2; under
987
+ an experiment directory it stays the experiment's command. A part without a ceiling becomes `OVER_SKALAN`,
845
988
  never DELA_UPP again. Sub-items inherit, per the skill, the item's spec and never write
846
989
  one of their own: the parent's `spec.md`, `granskarblock.md` and `design.md` are COPIED
847
990
  unchanged into each part directory, separately (one reviewer block per part directory,
@@ -927,14 +1070,20 @@ get wrong:
927
1070
  - **`underkänn <nr|gid> <reason>`:** the reason is mandatory: without a reason, ask
928
1071
  for it. request-sync adds the reason as a comment on the item, raises
929
1072
  the iteration counter and moves the status backward per its backward-move rules.
1073
+ When the move was from ⚖️, request-sync reports it done and the item has an archive
1074
+ directory, record the move: `node <skillkatalog>/scripts/archive.mjs synced <katalog> --offer-status "<the status request-sync set>"`
1075
+ (not on a split part, whose receipt is `split.gid`), so `nasta-steg` stops calling the
1076
+ ⚖️ sync done. A refused move records nothing. `godkänn` records no receipt, and `byt titel` moves no status, so neither writes one.
930
1077
  - **An item without a board** (archive only): `godkänn` notes
931
- `approval: {source: "manual", date}` in `state.json` after an explicit
1078
+ `approval: {source: "manual", by, date}` in `state.json` through
1079
+ `archive.mjs approve <katalog> --source manual --by <name>` after an explicit
932
1080
  confirmation question. Say clearly that this is not visible to anyone other than the archive.
933
1081
  - The verbs touch Offer status and comments, never Score, Class or
934
1082
  description fields.
935
1083
  - **Close per `## Closing: where the item stands`** when the item has an
936
1084
  archive directory: the table from `archive.mjs nasta-steg` plus the board line, so
937
- the move is visible together with what it opens up for (`designa`, customer, nothing).
1085
+ the move is visible together with what it opens up for (`designa`, customer, nothing),
1086
+ and the wrap-up lines at a resting point.
938
1087
 
939
1088
  ## Task: `döm`
940
1089
 
@@ -957,9 +1106,11 @@ run again for the same item, whose resumability rule re-evaluates a
957
1106
  `"väntar på dom"` variant and makes the outcome visible to the report when it runs
958
1107
  (see `utvärdera`).
959
1108
 
960
- 1. **Show the source material.** Run the comparison script on the current pair and show
961
- every diff row with the evidence side by side (as in bedöm step 6). No
962
- summary instead of the evidence: the ruling is made on it.
1109
+ 1. **Show the source material.** Run the comparison script on the current pair and
1110
+ describe every difference it finds, with each run's evidence in sentences and the
1111
+ source quotes that drove it (as in bedöm step 6, `## Reply wording`); the raw rows
1112
+ stay behind `detaljer <item> state`. No summary instead of the evidence: the ruling
1113
+ is made on it.
963
1114
  2. **Ask the reviewer** (AskUserQuestion) with three paths.
964
1115
  - **"Run N holds"** (N is 1 or 2, whichever of the two measured
965
1116
  runs was right): write the ruling via `archive.mjs utslag <katalog> --typ viktning --beslut "<ordagrant>" --beslutad-av <namn> --axel score --n <n> --galler-fil <fil>`.
@@ -1036,13 +1187,21 @@ facts in the analysis above.
1036
1187
 
1037
1188
  ## Task: `detaljer`
1038
1189
 
1039
- `detaljer <gid|slug|nr> [step]`: print archived files for the item: without
1190
+ `detaljer <gid|slug|nr> [del-N] [step]`: print archived files for the item: without
1040
1191
  a step, a list of what exists; with a step (`spec`, `granskarblock`, `design`,
1041
- `analys`, `poäng`, `state`) the file's content raw (`design` prints `design.md`);
1192
+ `granskning`, `analys`, `poäng`, `state`) the file's content raw (`design` prints `design.md`,
1193
+ `granskning` prints `design-review.md` when present);
1042
1194
  `klass` reads older archives'
1043
1195
  classification files (before ADR-0098). For `klass`/`poäng`: the latest
1044
1196
  `-pricing-vN.json` without a suffix (never `-run2`/`-avvisad`).
1045
1197
 
1198
+ On a split root, the listing without a step also lists the parts (the `del-1/ … del-M/`
1199
+ directories with `split` set), one line each with the part's status and, when recorded,
1200
+ its subtask gid (`split.gid`). `detaljer <item> del-N [step]` reads that part's directory
1201
+ (the form `<gid>/del-N` that `bedöm` and `bedom.mjs` print is the same address) the same way: its own `impact.md`, pricing files and `state.json`, and the copies of the
1202
+ parent's `spec.md`, `granskarblock.md` and `design.md` it inherited. A `del-N` that does
1203
+ not exist: say so and list the parts that do.
1204
+
1046
1205
  ## Task: `byt titel`
1047
1206
 
1048
1207
  `byt titel <nr|gid>`: rename the item's Asana task to the spec title, on request only
@@ -1068,9 +1227,9 @@ reaches the name.
1068
1227
  ## Task: `utvärdera`
1069
1228
 
1070
1229
  Model evaluation: `utvärdera <item…> <model…>`, with at least one model. Runs an
1071
- item through the whole flow once per named model, each round with all
1072
- three agents (the specifier, the assessor, the scorer) forced to the round's
1073
- model, so that each round measures an actual model difference instead of noise between
1230
+ item through the whole flow once per named model, each round with
1231
+ every agent step forced to the round's model (six with `design_mode=draft`: specifier,
1232
+ designer, reviewer, assessor, two scorers; `--modell default` keeps the pins), so that each round measures an actual model difference instead of noise between
1074
1233
  a fixed production mix and a single experiment model.
1075
1234
  `default` as the model value gives the agent defaults (today's production mix) and
1076
1235
  runs without an override; the directory name then becomes `baseline/`, for all other values
@@ -1154,6 +1313,11 @@ The question is therefore about the cost, not the risk of losing data.
1154
1313
  carries the same value is a no-op. `sprak` is read from the request's body text by
1155
1314
  the main conversation, just as in `speca` step 2; `korning.mjs` refuses
1156
1315
  to start without it (it never guesses the language, ADR-0114).
1316
+ `design_mode` is optional: `--satt design_mode=draft|intervju` in a call of its own,
1317
+ absent is `intervju`. With `draft`, `korning.mjs` drafts and reviews the design in every
1318
+ part directory that has no `design.md` before the assessor, the same two steps as
1319
+ production (ADR-0156), so a measurement sweep compares machine drafts with human designs
1320
+ on the same specs before any board opts in; a pinned design (step 2) is never redrafted.
1157
1321
 
1158
1322
  At the same time, note the item's `permalink_url` (`--satt permalink_url=<url>`)
1159
1323
  when the gid reply carries it. It comes from the same read-only fetch
@@ -1215,12 +1379,16 @@ The question is therefore about the cost, not the risk of losing data.
1215
1379
  model:
1216
1380
 
1217
1381
  ```
1218
- node <skillkatalog>/scripts/svep.mjs --repo-rot <abs> --konto <namn> \
1382
+ node <skillkatalog>/scripts/svep.mjs --repo-rot <abs> --arkiv <arkivrot> --konto <namn> \
1219
1383
  --modell <modell> [--modell <modell>]... \
1220
1384
  --exp experiments/<slug> [--exp experiments/<slug>]... \
1221
1385
  [--tickets-parallellt 2] [--modeller-parallellt 4] [--om | --hoppa-över]
1222
1386
  ```
1223
1387
 
1388
+ `--repo-rot <abs>` is the checkout whose code is read; `--arkiv <abs>` is
1389
+ `ARKIVROT:` from `rot` (ADR-0154, ADR-0155); a worktree as `--repo-rot` is
1390
+ fine, the archive root never comes from it.
1391
+
1224
1392
  Every round is started by `svep.mjs` as ONE `korning.mjs` process, and that is
1225
1393
  what gives the measurement for free. The parallel rule: two tickets at a time, at most
1226
1394
  four models for one ticket in flight (`--modeller-parallellt`, #526), and
@@ -1269,7 +1437,8 @@ The question is therefore about the cost, not the risk of losing data.
1269
1437
  a run without the field as measured under unknown concurrency (#526).
1270
1438
  - **The provenance is stamped AFTER `korning.json`, never before**, otherwise
1271
1439
  the stamp lacks the billing data. The command itself computes `skill_sha256`
1272
- (over `SKILL.md` plus the four agent definitions) and `underlag_sha256`,
1440
+ (over `SKILL.md` plus the six agent definitions, `request-designer` and
1441
+ `request-design-reviewer` among them) and `underlag_sha256`,
1273
1442
  reads `korning.json` and notes `fakturerade_modeller` (the
1274
1443
  canonicalized key set from `modelUsage`, suffixes like `[1m]` stripped,
1275
1444
  ADR-0099), and also stamps every `del-N/`. Without that stamp it is
@@ -1314,8 +1483,8 @@ The question is therefore about the cost, not the risk of losing data.
1314
1483
  anchor resolution, double run per bedöm) against the directory it is given, without
1315
1484
  the approval gate, and touches nothing outside it. If the model is `default`,
1316
1485
  the ordinary prompt templates and the agents' defaults are used, no override. If
1317
- it is a model name, every agent process gets a model override to it on ALL
1318
- three agents; the override is `--model` on the process, never a prompt line, and
1486
+ it is a model name, every agent process gets a model override to it on every
1487
+ agent step; the override is `--model` on the process, never a prompt line, and
1319
1488
  the agent definitions are never touched; the effort is taken from the definition
1320
1489
  as usual, except when `korning.mjs` has been given `--effort`: then every
1321
1490
  agent process gets the same `--effort` override, the step entry and `runs[]` carry it
@@ -1504,13 +1673,45 @@ across items with different model sets, or state which outcome
1504
1673
  was correct. The judgment of what is an acceptable outcome is
1505
1674
  the human's, made on experience of the system. The report shows the spread.
1506
1675
 
1676
+ ## Reply wording: what the reviewer reads
1677
+
1678
+ The sentences the orchestrator writes around the scripts' tables (the BLUF lines, how
1679
+ two scorings compared, a repair, a retake, a disagreement) say what the result means
1680
+ for the reviewer's decision, in plain sentences. The tables from `bluf` and
1681
+ `nasta-steg` are pasted as they are; this rule governs the sentences around them.
1682
+
1683
+ - **No internal vocabulary in those sentences:** no reference-scale position names
1684
+ (the anchor ids), no rule or protocol terms (floor, ceiling, between, LIKA,
1685
+ LIKA_TOLERANS, OLIKA, BROTT, REPARERAT, contract, tolerance rows) and no archive file
1686
+ names. Outcome codes (ESKALERA, DELA_UPP, INPUT_SAKNAS, OVER_SKALAN,
1687
+ TILLBAKA_TILL_SPEC, KONCEPT, DIAGNOS) are said as what they mean (an escalation, a
1688
+ split, missing input, above the scale and quoted separately). Quoting the item's own
1689
+ source text from `drivers[].citat` is fine.
1690
+ - **After a pricing check, answer in this order:**
1691
+ 1. Did the two scorings agree, and how close they were.
1692
+ 2. Which score applies, with the reason in a clause; when both runs land above the
1693
+ scale, that the item has no score and is quoted separately.
1694
+ 3. Anything that should lower trust in the number: a scoring that failed an
1695
+ automatic check and was redone, a repair to customer text, something the scorer
1696
+ flagged, an alternative or a type only one run found. A routine repair that changes nothing the reviewer decides on needs no
1697
+ mention.
1698
+ 4. On disagreement, the evidence in sentences: first what the runs disagree on, then
1699
+ per run where it landed and what it leaned on, then the ruling command.
1700
+ - **Raw details stay behind `/request detaljer <item>`:** `poäng` prints the
1701
+ scoring, `state` the runs rows with their notes (the repairs, and the comparison rows
1702
+ a `bedöm` double run wrote).
1703
+ Point there in one line when the reviewer may want them.
1704
+
1705
+ Example: "Two independent scorings landed close (2.75 and 3), so 3 applies. One of
1706
+ them failed an automatic check and was redone once; the redo agreed with the other run."
1707
+
1507
1708
  ## Closing: where the item stands
1508
1709
 
1509
1710
  The tasks `speca`, `designa`, `bedöm`, `godkänn`, `underkänn`, `döm` and `byt titel` ALWAYS end
1510
- with this block (#530). A reply that ends without it leaves
1711
+ with this block (#530). A `designa` that continues into `bedöm` (designa step 6) ends the turn with `bedöm`'s block, once: the block is per turn, never per task. A reply that ends without it leaves
1511
1712
  the user to guess where the item stands, what they should do and which command
1512
1713
  runs on, and the archive and the board can then drift apart silently (`spec_draft`
1513
- locally, empty Offer status on the board). The block consists of four parts, in order:
1714
+ locally, empty Offer status on the board). The block consists of five parts, in order:
1514
1715
 
1515
1716
  1. **The table from `node <skillkatalog>/scripts/archive.mjs nasta-steg <katalog>`**
1516
1717
  is pasted as it is (`| post | står | väntar på | nästa |`, one row per
@@ -1526,7 +1727,9 @@ locally, empty Offer status on the board). The block consists of four parts, in
1526
1727
  2. **The board line.** If the item has a gid: fetch Offer status via request-sync in
1527
1728
  the main conversation (never from memory) and write the line
1528
1729
  `Bräda: <Offer status>` directly under the table. If the item lacks a gid: write
1529
- `Bräda: ingen (posten ligger inte på brädan)`. For an item at
1730
+ `Bräda: ingen (posten ligger inte på brädan)`. When step 7 placed the item on the board
1731
+ under `auto_sync_spec`, the board line ends with `(synkad automatiskt, auto_sync_spec)`.
1732
+ For an item at
1530
1733
  ⚖️ Poängsättning redo för granskning, add one line: the analysis and the pricing are
1531
1734
  not on the board (ADR-0144), `detaljer <item>` shows them.
1532
1735
  3. **The ISÄR check.** The archive status and the Offer status must correspond to each other
@@ -1556,22 +1759,49 @@ locally, empty Offer status on the board). The block consists of four parts, in
1556
1759
  are presented as a choice the user must make, not just as routing:
1557
1760
  "here is your choice", followed by the alternatives (for TILLBAKA_TILL_SPEC the
1558
1761
  open choice from `stopp.orsak` or the source file; for OLIKA the two
1559
- runs' evidence side by side, see bedöm step 6) and the command that
1762
+ runs' evidence in sentences, see bedöm step 6 and `## Reply wording`) and the command that
1560
1763
  carries out the answer (`speca <item>` after `## Avgjorda val` + `respec`,
1561
1764
  `döm <item>`, customer dialogue). A `TILLBAKA_TILL_SPEC` from `impact.md` whose
1562
1765
  `orsak` starts with `design conflict:` routes to `designa <item>` (a redesign, bedöm
1563
- step 3), not to `speca`; the command for that case is `designa <item>`. A stop that
1766
+ step 3), not to `speca`; the command for that case is `designa <item>`. A row
1767
+ `designed, granskningen stoppade` is a choice: read `design-review.md` (`detaljer <item>`)
1768
+ and run `designa <item>` for the interview, or accept the draft as it stands with
1769
+ `node <skillkatalog>/scripts/archive.mjs add-design-review <katalog> --file <katalog>/design-review.md --verdict fortsätt --model människa`
1770
+ (the human's verdict is a receipt; the reviewer is never run again on the same doc). A
1771
+ `stopp ESKALERA ur design-intervju-kravs-<datum>.md` row is the designer asking for the
1772
+ interview: run `designa <item>`. A stop that
1564
1773
  is only routed is read as "the machine is working on it", and nobody does anything.
1565
1774
  A `DELA_UPP` is presented as two separate yes/no choices, split the item and rewrite
1566
1775
  the parent as an umbrella (bedöm's routing, ADR-0144), each answered on its own.
1776
+ A `pågår` row from `nasta-steg` is not a choice: the item is being priced by
1777
+ `bedom.mjs`, wait for its table.
1778
+
1779
+ 5. **Wrapping up, at a resting point.** A resting point is a turn that leaves the item
1780
+ on the board at 🔍 (spec review), ⚖️ (price review) or 📤 (done, with the customer),
1781
+ with no part-4 choice open. There, end with a few plain lines on
1782
+ what to do before the session closes, per `## Reply wording` (no anchor ids, protocol
1783
+ terms or archive file names):
1784
+ - Commit the design document and the setup files (the board connection and what
1785
+ `haus apply` wrote), if they are not committed yet; in a temporary workspace, get
1786
+ them onto the main branch before the workspace is removed. This line replaces the
1787
+ separate design commit offer in the same turn.
1788
+ - Keep the specs, analyses and scores out of the customer's history: they stay in the
1789
+ local request archive, which is kept out of git on purpose.
1790
+ - When the customer orders, planning starts from the saved design document; if the
1791
+ spec changes before that, the design is redone first.
1792
+
1793
+ Leave out a line that does not apply (nothing to commit, no design yet). No line about
1794
+ moving the archive out of a workspace: the archive always lives in the main checkout
1795
+ (ADR-0154). An old archive left in a workspace shows up as `archive.mjs rot`'s
1796
+ VARNING line; pass that line on to the user in plain words when it appears.
1567
1797
 
1568
1798
  ## Mechanical scripts: `scripts/`
1569
1799
 
1570
- Twelve deterministic scripts live in the directory: the five checks below,
1800
+ Thirteen deterministic scripts live in the directory: the five checks below,
1571
1801
  `kontroll.mjs` which runs the scorer's check chain in one process,
1572
1802
  `archive.mjs` which owns the archive's directories, holds and `experiment.json`,
1573
- `svep.mjs` which is utvärdera's starter,
1574
- `korning.mjs` which is utvärdera's inner process, `report.mjs` which
1803
+ `svep.mjs` which is utvärdera's starter, `bedom.mjs` which is bedöm's starter,
1804
+ `korning.mjs` which is utvärdera's inner process and bedöm's in production, `report.mjs` which
1575
1805
  renders the model report (see `utvärdera rapport`), `lib.mjs` with the shared
1576
1806
  building blocks and `ref-hash.mjs` for stable hashing. The checks replace
1577
1807
  model runs where the check is pure form:
@@ -1591,7 +1821,10 @@ reference files whose rules it mirrors and WARNS when a catalog bump has changed
1591
1821
  _Lösning_ (_Solution_) is a BRIST. With `--impact` the label on the analysis's row
1592
1822
  `**Deviation from the spec:**` is read and written as `AVVIKELSE: ingen`,
1593
1823
  `AVVIKELSE: precisering` or `AVVIKELSE: motsägelse`; a row without a
1594
- label is a BRIST. The orchestrator reads candidate and deviation from those
1824
+ label is a BRIST. When the row carries text after its label, the line
1825
+ `AVVIKELSE-TEXT: <text>` follows right after `AVVIKELSE:`; the orchestrator and
1826
+ `korning.mjs` read the design-conflict text from that line, never from the file
1827
+ (ADR-0155). The orchestrator reads candidate and deviation from those
1595
1828
  lines, never from the files itself. The spec rules live in `lib.mjs` (`specForm`),
1596
1829
  shared with `archive.mjs paraply` (ADR-0144).
1597
1830
  With `--design` (`designa` step 3 and `bedöm` gate 1b): `design.md` must exist,
@@ -1607,6 +1840,16 @@ reference files whose rules it mirrors and WARNS when a catalog bump has changed
1607
1840
  match the analysis row's `underlag_sha256["design.md"]`, the same provenance rule
1608
1841
  as for `spec.md`, except that a missing design hash is a BRIST, not a VARNING:
1609
1842
  the design existed when the analysis should have seen it.
1843
+ `--design` also checks the draft's form (ADR-0156): it prints
1844
+ `DESIGN-LÄGE: draft|intervju` (from `mode:` in the frontmatter); on a draft a missing or
1845
+ malformed `## Assumptions`, `## Removed or renamed` or `## Files touched` is a BRIST, on an
1846
+ interactive doc a VARNING; every symbol under `## Removed or renamed` is grepped
1847
+ (`git grep`, in the repo of the canonical file) outside the files under `## Files touched`
1848
+ and a hit is a BRIST with its `file:line`, while a grep that cannot run is a VARNING; and a
1849
+ `state.design.review` verdict `stopp` is a BRIST. `--design-utkast <abs fil> [--repo-rot <abs>]`
1850
+ checks a draft file without `state.design` (the experiment channel): the same section and
1851
+ symbol checks, the frontmatter against the directory's id and the current `spec.md` hash,
1852
+ `## Spec conflicts` `none`, and the `DESIGN-LÄGE:` line; exit 1 on a BRIST.
1610
1853
  - `scripts/resolve-anchors.mjs <run.json> <spec.md> [impact.md]`: resolves
1611
1854
  evidence anchors (`belagg_ankare`/`ankare`) to verbatim source blocks, runs
1612
1855
  BEFORE contract-check. Exit 0 = everything resolved (or no anchors in the file), 1 =
@@ -1664,20 +1907,55 @@ reference files whose rules it mirrors and WARNS when a catalog bump has changed
1664
1907
  byte-identically, writes `state.design` and sets status `designed`; no runs row;
1665
1908
  refuses a file under `.haus-workflow/`, a `priced` or `guard_run` item and any
1666
1909
  standing stop except a design conflict from `impact.md`, which it clears, putting
1667
- `impact.md` aside as `impact-superseded-<datum>.md`;
1910
+ `impact.md` aside as `impact-superseded-<datum>.md`; also refuses a draft whose sections
1911
+ fail the form check and a removed symbol still in use outside the touched files, and
1912
+ resets `design.review`, ADR-0156;
1668
1913
  exit 2 on every refusal, under the archive lock),
1914
+ `add-design-review <katalog> --file <abs> --verdict fortsätt|stopp --model <m>` (the one
1915
+ writer of `state.design.review`: copies the reviewer's reply byte-identically to
1916
+ `design-review.md`, an earlier one put aside as `design-review-superseded-<datum>.md`,
1917
+ writes `{ verdict, sha256, date, model }` and prints `OK: design-review <verdict> (<sha256>)`;
1918
+ refuses an item without a design, a verdict outside the two literals, an unreadable file
1919
+ and an experiment directory, exit 2; no runs row; under the archive lock; ADR-0156),
1920
+ `antaganden <katalog>` (read-only, what `bedöm` step 8 pastes before `synka`: the line
1921
+ `Designläge: draft|intervju`, then `Antaganden (N):` with one block per assumption (the
1922
+ question, `vald:`, `ej valda:`, `skäl:`), or `Antaganden: inga`, or
1923
+ `Antaganden: avsnitt saknas`, then `Granskning: <verdict> (<K> fynd)` or
1924
+ `Granskning: ingen`, then `Spec conflicts: none` or the count with the lines; refuses an
1925
+ item without `design.md`, exit 2; ADR-0156),
1669
1926
  `set-split-gid <del-katalog> --gid <gid>` (records a split part's Asana subtask gid in
1670
1927
  `split.gid` under the archive lock; refuses a directory without `split`, a gid that is not
1671
1928
  digits only and a different gid already recorded, while the same gid again is a no-op;
1672
1929
  ADR-0144),
1930
+ `approve <katalog> --source asana|manual` (`--status "<Offer status as read>"` for
1931
+ asana, `--by <name>` for manual; the one writer of `state.approval`, under the archive
1932
+ lock, overwriting an earlier note; refuses an asana status whose alphabetic core is not
1933
+ `specok`, manual without `--by` and an experiment directory, exit 2; ADR-0153),
1934
+ `synced <katalog> --offer-status "<Offer status>"` (the one writer of `state.board`, the
1935
+ receipt of a board write: `{ offer_status, date }`, the value verbatim, under the archive
1936
+ lock, overwriting the previous receipt; refuses a missing or empty `--offer-status`, an
1937
+ experiment directory and a split part, whose receipt is `split.gid`, exit 2; `nasta-steg`
1938
+ reads it; ADR-0153),
1939
+ `korning-start <katalog> --pid <N> [--katalog-korning <abs>]` /
1940
+ `korning-slut <katalog>` (the running receipt's two writers, `state.korning`, under the
1941
+ archive lock; start refuses a living pid, exit 2 `pågår (pid N)`, and takes a dead one
1942
+ over; both refuse an experiment directory, exit 2; `bedom.mjs` runs them around every
1943
+ item; ADR-0155),
1944
+ `rot [<dir>]` (takes no archive directory: prints `ARKIVROT: <abs>`, the main checkout's
1945
+ `.haus-workflow/requests/`, and `IGNORERAD: ja|nej`, exit 0, plus a third line
1946
+ `VARNING: arkiv i worktree: <abs> (flytta per ADR-0154)` when the cwd's own checkout holds
1947
+ an archive of its own; refuses a directory outside a git repository, a bare repository, a
1948
+ submodule checkout and a `--separate-git-dir` clone, exit 2; ADR-0154),
1673
1949
  `paraply <katalog> --file <spec>` (rewrites the parent's spec as an umbrella: refuses a
1674
1950
  split part, an item without `approval`, a file that fails the spec form check
1675
1951
  `precheck.mjs` runs, a file without a title line and an unreadable file; puts `spec.md`
1676
1952
  aside as `spec-superseded-<datum>.md`, copies the file in, sets `title` from its heading
1677
1953
  and records `state.umbrella = { date, sha256 }`; approval, design, runs, stops and the
1678
1954
  parts are untouched; prints `OK: paraply <sha256>`; ADR-0144),
1679
- `stopp <katalog> --utfall KONCEPT|DIAGNOS|TILLBAKA_TILL_SPEC|ESKALERA --kalla spec.md|impact.md|granskarblock.md|design-avvisad-<datum>.md [--orsak <text>]`
1955
+ `stopp <katalog> --utfall KONCEPT|DIAGNOS|TILLBAKA_TILL_SPEC|ESKALERA --kalla spec.md|impact.md|granskarblock.md|design-avvisad-<datum>.md|design-intervju-kravs-<datum>.md [--orsak <text>]`
1680
1956
  (writes `state.stopp` after checking that the source carries the outcome;
1957
+ `--kalla design-intervju-kravs-<datum>.md` requires a first line `INTERVJU KRÄVS: <reason>`
1958
+ and takes only `ESKALERA` with `--orsak`, written by `korning.mjs` in draft mode;
1681
1959
  `--kalla design-avvisad-<datum>.md` requires at least one conflict under
1682
1960
  `## Spec conflicts` in that receipt and takes `TILLBAKA_TILL_SPEC` or `ESKALERA`,
1683
1961
  and replaces a standing design-conflict stop from `impact.md` (any other standing
@@ -1685,8 +1963,9 @@ reference files whose rules it mirrors and WARNS when a catalog bump has changed
1685
1963
  `--kalla impact.md` sets status `assessed`, the other sources do not touch
1686
1964
  the status), `respec <katalog>` (puts `impact.md` aside as
1687
1965
  `impact-superseded-<datum>.md` and `design.md` as `design-superseded-<datum>.md`,
1688
- resets status (to `spec_draft`), `approval`, `granskarutslag`, `stopp` and
1689
- `design`, never touches `runs[]`) and
1966
+ resets status (to `spec_draft`), `approval`, `granskarutslag`, `stopp`,
1967
+ `design` and `board`, never touches `runs[]`; `design.review` goes with `design`, and `design-review.md` is put aside as
1968
+ `design-review-superseded-<datum>.md`) and
1690
1969
  `bluf <katalog>` (the markdown table `| post | poäng | utfall | konfidens | anm |`
1691
1970
  over the directory and its `del-N/` recursively, the bundle root as
1692
1971
  `bunt (N delar)`, a split root with `K av M delar prissatta` in `anm`; the values from
@@ -1698,11 +1977,19 @@ reference files whose rules it mirrors and WARNS when a catalog bump has changed
1698
1977
  outcome per the rule table in the script; on a split root the parent row counts the
1699
1978
  parts (`se delarna (K av M delar prissatta)`) until every part is `priced` or
1700
1979
  `OVER_SKALAN` and then names the sync that moves the parent, and a part row says
1701
- whether its subtask is recorded (`split.gid`); an unknown state is written as
1980
+ whether its subtask is recorded (`split.gid`); a living `korning.pid` gives `pågår (pid N)`
1981
+ with `vänta; bedöm igen när bedom.mjs är klar`, a dead one prefixes the row with
1982
+ `avbruten körning, ` (ADR-0155); a `designed` item whose review stopped gives
1983
+ `| <post> | designed, granskningen stoppade | människa | designa <id> (intervju; se design-review.md) |`
1984
+ (ADR-0156) and an `INTERVJU KRÄVS` stop gives
1985
+ `| <post> | stopp ESKALERA ur design-intervju-kravs-<datum>.md | människa | designa <id> (intervju; se design-intervju-kravs-<datum>.md) |`;
1986
+ an unknown state is written as
1702
1987
  `okänt läge: <status>` with exit 0, a broken `state.json` is exit 2, see
1703
1988
  `## Closing: where the item stands`). `add-run` reads
1704
1989
  `effort:` from the agent definition when `--effort` is omitted and canonicalizes
1705
- `--model`; `set-status priced` refuses when `stopp` is set.
1990
+ `--model`, and `add-run … [--repo-sha <sha>]` writes `repo_sha` on the row (40 lowercase
1991
+ hex digits, otherwise exit 2; `korning.mjs` passes it on `impact.md` rows, ADR-0155);
1992
+ `set-status priced` refuses when `stopp` is set.
1706
1993
  `experiment <experimentkatalog> [--satt nyckel=värde]... [--variant <modell>]... [--korning <modell>/k<N> --status <klar|ofärdig|stopp|väntar på dom> [--orsak <text>] [--pid <heltal>]]`
1707
1994
  is the ONLY writer of `experiment.json` (see `utvärdera` step 1): a locked
1708
1995
  read-modify-write with an atomic write; the directory and file are created if they are
@@ -1714,7 +2001,7 @@ reference files whose rules it mirrors and WARNS when a catalog bump has changed
1714
2001
  the starter's pid on the row; a status write without `--pid` replaces the row
1715
2002
  entirely, so the pid disappears with the final status (#516). Exit 0 ok, 2
1716
2003
  a usage or state error.
1717
- - `scripts/svep.mjs --repo-rot <abs> --konto <namn> --modell <m>... --exp experiments/<slug>... [--tickets-parallellt 2] [--modeller-parallellt 4] [--om | --hoppa-över]`:
2004
+ - `scripts/svep.mjs --repo-rot <abs> [--arkiv <abs>] --konto <namn> --modell <m>... --exp experiments/<slug>... [--tickets-parallellt 2] [--modeller-parallellt 4] [--om | --hoppa-över]`:
1718
2005
  utvärdera's starter (see `utvärdera` step 4 and Batch). Runs two tickets at
1719
2006
  a time with at most four models per ticket in flight, the next ticket when one is completely
1720
2007
  done, and does per round `ny-korning`, the start of `korning.mjs`,
@@ -1725,12 +2012,39 @@ reference files whose rules it mirrors and WARNS when a catalog bump has changed
1725
2012
  `väntar på dom` is tested with `sparr`, `ofärdig` is rerun, except when the row carries
1726
2013
  a living `pid` (in progress in another sweep, skipped as `pågår`, #516). An `--exp` without
1727
2014
  `onskemal.md`, `kallmanifest.md` or `experiment.json` with `request_id` is marked
1728
- and skipped. Exit 0 when no run became `ofärdig`, 1 otherwise, 2 on a
1729
- usage error.
1730
- - `scripts/korning.mjs --katalog <abs k<N>> --exp <abs experimentkatalog> --repo-rot <abs> --request-id <gid eller slug> --modell <modell|default> [--claude <kommando>] [--delar-parallellt 2] [--effort <low|medium|high|xhigh|max|default>]`:
2015
+ and skipped. `--arkiv` is the archive root; omitted, it is derived from
2016
+ `--repo-rot`'s git common dir (ADR-0154). Exit 0 when no run became
2017
+ `ofärdig`, 1 otherwise, 2 on a usage error.
2018
+ - `scripts/bedom.mjs --repo-rot <abs> [--arkiv <abs>] --post <gid|gid/del-N>... [--parallellt 2] [--max-usd <n>] [--claude <kommando>] [--om] [--sprak <svenska|engelska>]`:
2019
+ production's starter (see `bedöm`), one `korning.mjs --post` process per item, two at a
2020
+ time. `--post` is relative to the archive root (`--arkiv`, or derived from `--repo-rot`'s
2021
+ git common dir as in `svep.mjs`); an absolute `--post` is a usage error. Per item: the
2022
+ receipt via `archive.mjs korning-start`/`korning-slut` (the latter always, also when the
2023
+ run fails), the run directory `<post>/korningar/<stämpel>/` with `stderr.log`,
2024
+ `matning.json` and the raw replies under `steg/`, the cap from `request.json`
2025
+ (`max_usd_per_batch`, default 100 USD, `--max-usd` overrides; once the finished items'
2026
+ USD, plus each item in flight at the average of the finished ones, reaches it no further
2027
+ item starts, `tak nått`, and a running item is never killed), `--startare <its own pid>` on
2028
+ every `korning.mjs` it starts, SIGINT and SIGTERM both killing the running items and
2029
+ clearing their receipts (exit 130),
2030
+ and the final table `| post | status | poäng | utfall | wall | USD |` in argument order
2031
+ with the line `tak: <n> USD, använt: <m> USD`. Exit 0 when every item ended in a result
2032
+ (`priced`, `stopp`, `väntar på dom`), 1 on `ofärdig`, `pågår`, `grind` or `tak nått`, 2
2033
+ on a usage error (ADR-0155).
2034
+ `bedom.mjs` takes `--design-mode draft|intervju` and passes it to every `korning.mjs` it
2035
+ starts; without the flag the value is `request.json`'s `design_mode` (`interview` is read
2036
+ as `intervju`), and without that key `intervju` (ADR-0156).
2037
+ - `scripts/korning.mjs --katalog <abs k<N>> --exp <abs experimentkatalog> --repo-rot <abs> --request-id <gid eller slug> --modell <modell|default> [--claude <kommando>] [--delar-parallellt 2] [--effort <low|medium|high|xhigh|max|default>] [--sprak <svenska|engelska>]`:
1731
2038
  utvärdera's inner process (see `utvärdera` step 4), a script without
1732
- model turns. Builds the prompts from `onskemal.md`, `kallmanifest.md` and
1733
- `experiment.json`, where `sprak` is MANDATORY: if it is missing, an
2039
+ model turns. In production (`bedom.mjs`) `--post <abs postkatalog>` replaces `--exp`
2040
+ plus `--request-id` (giving `--request-id` with `--post` is a usage error, the id comes
2041
+ from the item's `state.json`) and runs `bedöm` steps 3 to 7 on the item directory,
2042
+ printing `STATUS: <priced|assessed|stopp|väntar på dom|ofärdig>` on stdout (ADR-0155).
2043
+ `--startare <pid>` (production only, a usage error with `--exp`) is the starter's pid,
2044
+ checked every 30 s: a dead starter aborts the run like SIGTERM (exit 130).
2045
+ `--sprak` overrides the language in both modes; in production it otherwise comes from
2046
+ `SPRÅK:` in `kallmanifest.md`, and a missing language is exit 2. In utvärdera it builds
2047
+ the prompts from `onskemal.md`, `kallmanifest.md` and `experiment.json`, where `sprak` is MANDATORY: if it is missing, an
1734
2048
  instruction is written on stderr and the script ends with exit 2 before any prompt
1735
2049
  is built (ADR-0114). Every agent step is a `claude -p --agent` process of its own with
1736
2050
  the raw reply under `k<N>/steg/`, and the checks (precheck, `kontroll.mjs`,
@@ -1742,9 +2056,22 @@ reference files whose rules it mirrors and WARNS when a catalog bump has changed
1742
2056
  before; everything else is passed to the process and to `add-run --effort` as
1743
2057
  requested, never verified (#525). `korning.json` is the sum over the steps
1744
2058
  (`korningsmotor`, `steg` with `effort_begard` and `samtidiga_processer` per
1745
- step, `modellverifiering` plus the report's usual keys). Exit 0 when
1746
- the run went through, 1 when at least one part became unfinished, 2 on a
1747
- usage error.
2059
+ step, `modellverifiering` plus the report's usual keys). The impact row gets
2060
+ `--repo-sha`, the checkout's `HEAD` when the assessor read it (ADR-0155).
2061
+ `korning.mjs` takes `--design-mode draft|intervju` (default `intervju`; in utvärdera the
2062
+ value is `design_mode` in `experiment.json`). With `draft`, a part without `design.md`
2063
+ (in production: and not a split part) gets two steps before the assessor (ADR-0156):
2064
+ `request-designer`, whose doc is written at the `designa` path in `--repo-rot` and recorded
2065
+ with `add-design` (in utvärdera written as the part's `design.md` and checked with
2066
+ `precheck --design-utkast`), then `request-design-reviewer`, whose reply is recorded with
2067
+ `add-design-review` (in utvärdera copied as the part's `design-review.md`).
2068
+ `INTERVJU KRÄVS:` gives `stopp` with `intervju krävs: <reason>` and writes nothing, a
2069
+ refusal on `## Spec conflicts` gives the receipt and the stop of `designa` step 5, any other
2070
+ refusal, BRIST or symbol hit gives `ofärdig`, and `VERDICT: stopp` gives `stopp` with
2071
+ `designgranskning: <first finding>`. A reviewer reply without a `VERDICT:` first line is a
2072
+ script-proven breach and is redispatched ONCE; the verdict itself never is.
2073
+ Exit 0 when the run went through, 1 when at least one part became
2074
+ unfinished, 2 on a usage error.
1748
2075
  - `scripts/kontroll.mjs <svar.txt> <spec.md> <impact.md> --expect-id <id> --ut <ren.json> [--fixa-kundtext] [--claude <kommando>] [--fix-modell sonnet] [--fix-fil <rå.json>]`:
1749
2076
  the scorer's check chain in ONE process (see `bedöm` step 5): tail lines,
1750
2077
  JSON extraction, deterministic repairs, then check-lasta,
@@ -1769,7 +2096,7 @@ an item that passes can still be stopped by the protocols themselves, and that i
1769
2096
  their job. On a script error (exit 2 or a crash): show the error and stop, never
1770
2097
  continue as if the check had passed.
1771
2098
 
1772
- ## Dispatch contract (applies to all three agents)
2099
+ ## Dispatch contract (applies to every agent)
1773
2100
 
1774
2101
  - The prompt is self-contained: the agent does not see this conversation.
1775
2102
  - **Prompt templates, the labels verbatim:**
@@ -1825,6 +2152,58 @@ continue as if the check had passed.
1825
2152
  The umbrella dispatch writes no runs row: `state.umbrella` is its receipt once `paraply`
1826
2153
  accepts the draft.
1827
2154
 
2155
+ `request-designer` (draft mode, ADR-0156):
2156
+
2157
+ ```
2158
+ SPEC:
2159
+ <spec.md bytetroget>
2160
+
2161
+ GRANSKARBLOCK:
2162
+ <granskarblock.md bytetroget>
2163
+
2164
+ URSPRUNGLIG FÖRFRÅGAN:
2165
+ <onskemal.md ordagrant när posten har en, annars "(saknas i arkivet)": då arbetar designern ur specen ensam>
2166
+
2167
+ REPO-ROT: <absolut sökväg>
2168
+ DEPS: <installerade | saknas>
2169
+ SPRÅK: <svenska | engelska>
2170
+ KÄLLOR:
2171
+ <kallmanifest.md ordagrant, eller "inga">
2172
+
2173
+ KONFIG: <absolut sökväg till .haus-workflow/workflow-config.md>
2174
+ ID: <katalogens id>
2175
+ SPEC-SHA256: <ref-hash.mjs på spec.md>
2176
+ DATUM: <YYYY-MM-DD>
2177
+ ```
2178
+
2179
+ `request-design-reviewer` (draft mode, ADR-0156):
2180
+
2181
+ ```
2182
+ SPEC:
2183
+ <spec.md bytetroget>
2184
+
2185
+ GRANSKARBLOCK:
2186
+ <granskarblock.md bytetroget>
2187
+
2188
+ DESIGN:
2189
+ <design.md bytetroget, utkastet som granskas>
2190
+
2191
+ REPO-ROT: <absolut sökväg>
2192
+ DEPS: <installerade | saknas>
2193
+ SPRÅK: <svenska | engelska>
2194
+ ```
2195
+
2196
+ The designer and the reviewer are dispatched only by `korning.mjs`, never from the main
2197
+ conversation: a design without a human is a background step, the interview is `designa`.
2198
+ The designer triages as brainstorming does (spike, bounded, architectural) without
2199
+ loading it, takes the recommended option on every HOW question and records it under
2200
+ `## Assumptions`, puts every WHAT question under `## Spec conflicts` unanswered and every
2201
+ defect outside the spec's _När det är klart_ under `## Out of scope`; it replies with the
2202
+ doc, or with the single line `INTERVJU KRÄVS: <reason>` for an architectural item. The
2203
+ reviewer verifies and never redesigns: its reply starts with `VERDICT: fortsätt` or
2204
+ `VERDICT: stopp`, then `## Findings`. `KONFIG:` is a path the designer reads for repo-wide
2205
+ answers (the test command, the formatter); the file is never pasted.
2206
+
1828
2207
  `request-assessor`:
1829
2208
 
1830
2209
  ```
@@ -1865,6 +2244,11 @@ continue as if the check had passed.
1865
2244
  `designa`), pasted, never pointed to by path: the hard rule "documents are pasted
1866
2245
  byte-faithfully" applies. Without a design (a split part of a parent analysed under
1867
2246
  the old rules, or a standalone assessor run) the block is the single line `DESIGN: ingen`.
2247
+ In draft mode (ADR-0156) the doc is a draft (`mode: draft`) written by `request-designer`,
2248
+ and the reviewer's verdict sits beside it in the archive as `design-review.md`. The block
2249
+ is pasted the same way and the assessor's rule is unchanged: every decision in it is
2250
+ taken, the machine-taken ones included; the human reads those in the Closing
2251
+ (`antaganden`), not in a reopened analysis.
1868
2252
 
1869
2253
  `request-scorer` (source material by path, ADR-0099: never pasted):
1870
2254
 
@@ -1888,12 +2272,12 @@ continue as if the check had passed.
1888
2272
  `contract-check --sprak` rejects customer text in the wrong language.
1889
2273
 
1890
2274
  - **Tail lines after the main content**, in this order: `MODELL: <modell-id>`
1891
- (all agents), `LÄSTA: <kommaseparerade absoluta sökvägar eller "inga">`
2275
+ (all agents; the designer's `INTERVJU KRÄVS:` reply is the one line and carries none), `LÄSTA: <kommaseparerade absoluta sökvägar eller "inga">`
1892
2276
  (only the scorer: its Read is prompt-restricted, the line makes the rule
1893
2277
  reviewable), `AVVIKELSE: <text>` (only if something in the prompt broke the agent's
1894
2278
  rules, e.g. a price list in the source material). The tail lines are stripped before every
1895
2279
  mechanical check and before archiving; MODELL is noted in the runs row,
1896
- AVVIKELSE is always shown to the user. LÄSTA is checked MECHANICALLY by
2280
+ AVVIKELSE is always reported to the user, in plain words (`## Reply wording`). LÄSTA is checked MECHANICALLY by
1897
2281
  `scripts/check-lasta.mjs` (ADR-0099): the line must carry the source material's two
1898
2282
  pointed-out paths (both mandatory) and may beyond that carry only files
1899
2283
  under the skill's own directory (the reference file); everything else is a
@@ -1912,7 +2296,9 @@ continue as if the check had passed.
1912
2296
  with an `-avvisad` suffix (pricing: `<typ>-pricing-vN-avvisad.json`;
1913
2297
  text steps: `spec-avvisad-<datum>.md` / `impact-avvisad-<datum>.md`) and gets
1914
2298
  a runs row of its own with the check's error lines: two runs of the same step
1915
- without a trace of why is exactly the gap the receipt closes.
2299
+ without a trace of why is exactly the gap the receipt closes. In the chat, a retake is
2300
+ told in plain words ("one scoring failed an automatic check and was redone once"),
2301
+ never by its archive file name (`## Reply wording`).
1916
2302
 
1917
2303
  ## Do not use when
1918
2304