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