@haus-tech/haus-workflow 5.9.0 → 5.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/cli.js +31 -21
- package/library/catalog/manifest.json +4 -4
- package/library/global/agents/request-assessor.md +5 -1
- package/library/global/agents/request-specifier.md +3 -1
- package/library/global/skills/request/SKILL.md +394 -59
- package/library/global/skills/request/scripts/archive.mjs +546 -49
- package/library/global/skills/request/scripts/korning.mjs +41 -4
- package/library/global/skills/request/scripts/lib.mjs +189 -0
- package/library/global/skills/request/scripts/precheck.mjs +105 -130
- package/library/global/skills/request-assess-impact/SKILL.md +12 -0
- package/library/global/skills/request-sync/SKILL.md +61 -100
- package/library/global/skills/request-write-spec/SKILL.md +15 -1
- package/package.json +3 -3
|
@@ -16,12 +16,14 @@ the respective skill. Only routing, context carrying, the archive and the dispat
|
|
|
16
16
|
| Task | Does |
|
|
17
17
|
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
18
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 |
|
|
19
20
|
| `bedöm <gid, slug or nr>` | Gate → secure an analysis → dispatch `request-scorer` → archive JSON |
|
|
20
21
|
| `status` | Queue state via request-sync, BLUF table with row numbers |
|
|
21
22
|
| `godkänn <nr or gid>` | Move Offer status forward via request-sync; see the gate section |
|
|
22
23
|
| `underkänn <nr or gid> <reason>` | Reason as an Asana comment + iteration counter via request-sync |
|
|
23
24
|
| `döm <item>` | Human ruling on OLIKA: choose a run, order a rerun or reject the source material |
|
|
24
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 |
|
|
25
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 |
|
|
26
28
|
| `hjälp` | Explain the tasks, touch no files |
|
|
27
29
|
|
|
@@ -59,6 +61,10 @@ the respective skill. Only routing, context carrying, the archive and the dispat
|
|
|
59
61
|
`impact.md` (it is part of the source material for the scoring), but no
|
|
60
62
|
reviewer block may ever be sent along in material that goes to request-sync
|
|
61
63
|
for customer-visible fields.
|
|
64
|
+
- **The design doc never reaches Asana.** `designa` writes nothing via request-sync,
|
|
65
|
+
and `design.md` is internal source material for the assessor (pasted as the
|
|
66
|
+
`DESIGN` block); no design content may be sent along in material that goes to
|
|
67
|
+
request-sync for customer-visible fields.
|
|
62
68
|
- **The archive is a cache, Asana is the truth.** On conflict, the board wins.
|
|
63
69
|
- **Approval is never assumed.** That a spec exists in the archive does not mean it
|
|
64
70
|
has been reviewed. See the gate under `bedöm`.
|
|
@@ -93,16 +99,12 @@ section follows it.
|
|
|
93
99
|
| `spec.md` | **customer-facing** | the customer's (ADR-0114, unchanged) |
|
|
94
100
|
| `impact.md` | internal | English |
|
|
95
101
|
| `granskarblock.md` | internal | English |
|
|
102
|
+
| `design.md` | internal | English |
|
|
96
103
|
| score JSON: `customer_rationale`, `conditions`, `assumptions_stated`, `alternatives`, `coverage_post.yta` | **customer-facing** | the customer's (unchanged) |
|
|
97
104
|
| score JSON: evidence, bracketing, drivers, everything else | internal | English |
|
|
98
105
|
| `korning.json`, `state.json`, `matning.json`, `experiment.json` | machine | unchanged |
|
|
99
106
|
| The Asana description's three sections | **customer-facing** | the customer's (unchanged) |
|
|
100
|
-
|
|
|
101
|
-
|
|
102
|
-
The subtask titles (`Analys`, `Påverkansanalys vN`, `Poängsättning vN`) stay in
|
|
103
|
-
Swedish. They are lookup keys in Asana, the same class as the field names: `request-sync`
|
|
104
|
-
looks up an existing `Analys` and reuses it, and a rename would split the items into
|
|
105
|
-
before and after without anyone noticing.
|
|
107
|
+
| A split part's subtask: its name and its scope line | **customer-facing** | the spec's language |
|
|
106
108
|
|
|
107
109
|
Where this skill names a heading or row of the analysis or the reviewer block, it uses
|
|
108
110
|
the English literal the agents write: `## For the reviewer`, _Deviation from the spec_
|
|
@@ -142,7 +144,9 @@ new runs.
|
|
|
142
144
|
Rejected attempts carry an `-avvisad` suffix and stand outside the N count:
|
|
143
145
|
the pricing's `<typ>-pricing-vN-avvisad.json` and the text steps'
|
|
144
146
|
`spec-avvisad-<datum>.md` / `impact-avvisad-<datum>.md` (ADR-0099); see the
|
|
145
|
-
redispatch rule in the dispatch contract.
|
|
147
|
+
redispatch rule in the dispatch contract. A design doc refused on
|
|
148
|
+
`## Spec conflicts` is copied in as `design-avvisad-<datum>.md`: the receipt for
|
|
149
|
+
its stop (`designa` step 5), with no runs row, since the design is no dispatch.
|
|
146
150
|
|
|
147
151
|
- Directory name: the Asana gid when the item is on the board, otherwise a kebab slug of
|
|
148
152
|
the spec heading. A bundle without a gid: `<slug>-1`, `<slug>-2`, … When a gid is minted later:
|
|
@@ -165,7 +169,7 @@ redispatch rule in the dispatch contract.
|
|
|
165
169
|
"slug": "<kebab-rubrik>",
|
|
166
170
|
"former_slug": null,
|
|
167
171
|
"title": "<spec-rubrik>",
|
|
168
|
-
"status": "spec_draft | spec_synced | assessed | priced | guard_run",
|
|
172
|
+
"status": "spec_draft | spec_synced | designed | assessed | priced | guard_run",
|
|
169
173
|
"bundle": { "parent_slug": null, "part": null, "of": null },
|
|
170
174
|
"split": { "parent": null, "part": null, "of": null },
|
|
171
175
|
"approval": null,
|
|
@@ -174,6 +178,7 @@ redispatch rule in the dispatch contract.
|
|
|
174
178
|
"stopp": null,
|
|
175
179
|
"respec_varv": 0,
|
|
176
180
|
"coverage_post": null,
|
|
181
|
+
"design": null,
|
|
177
182
|
"runs": []
|
|
178
183
|
}
|
|
179
184
|
```
|
|
@@ -181,14 +186,29 @@ redispatch rule in the dispatch contract.
|
|
|
181
186
|
- `bundle` = specs from the same request (set by speca on a bundle).
|
|
182
187
|
`split` = sub-items from a DELA_UPP outcome (set by bedöm). Both have the form
|
|
183
188
|
`{parent…, part: N, of: M}`. Never both on the same directory.
|
|
189
|
+
A split part's `split` additionally carries `gid` once its Asana subtask exists:
|
|
190
|
+
written ONLY by `archive.mjs set-split-gid <del-katalog> --gid <gid>` (ADR-0144),
|
|
191
|
+
digits only and write-once (the same gid again is a no-op, a different one is refused).
|
|
192
|
+
`nasta-steg` reads it to say whether the part is synced, and every later sync of the
|
|
193
|
+
part passes it to request-sync, so the subtask is updated instead of created twice.
|
|
194
|
+
Absent until the subtask exists. `part` and `of` are integers (JSON numbers, never
|
|
195
|
+
strings); `nasta-steg` and `bluf` refuse a split whose parts disagree on `of` or carry a
|
|
196
|
+
non-integer `of`.
|
|
184
197
|
- `stopp` = a stop outcome that the scripts have proven without a scorer:
|
|
185
|
-
`{ "utfall": "KONCEPT" | "DIAGNOS" | "TILLBAKA_TILL_SPEC" | "ESKALERA", "kalla": "spec.md" | "impact.md" | "granskarblock.md", "date": "YYYY-MM-DD", "orsak"?: string }
|
|
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).
|
|
186
200
|
Written ONLY by `archive.mjs stopp` (which itself checks that the source carries
|
|
187
201
|
what is claimed: the candidate marker in `spec.md`, the label `contradiction` in
|
|
188
|
-
`impact.md`, the price-decisive open choice in `granskarblock.md`, ADR-0118
|
|
189
|
-
|
|
190
|
-
`
|
|
191
|
-
|
|
202
|
+
`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`).
|
|
204
|
+
`add-design` clears a design-conflict stop (`kalla` `impact.md`, `orsak`
|
|
205
|
+
`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
|
|
207
|
+
other stop is reset ONLY by `archive.mjs respec`.
|
|
208
|
+
`orsak` is set when `utfall` is `ESKALERA` (the command requires `--orsak` then,
|
|
209
|
+
so a human sees why the item did not go back to the spec once more) and for the
|
|
210
|
+
design sources (the conflicts for `design-avvisad-<datum>.md`, the design conflict
|
|
211
|
+
text for `impact.md`, see `bedöm` step 3), and is absent otherwise.
|
|
192
212
|
`archive.mjs set-status priced` refuses while the field is set. Older archives
|
|
193
213
|
lack the field and are read as `null`.
|
|
194
214
|
- `respec_varv` is a monotonic counter, raised by 1 by every `archive.mjs respec`
|
|
@@ -203,7 +223,23 @@ redispatch rule in the dispatch contract.
|
|
|
203
223
|
latest pricing file that carries it, the skeleton (`ny-korning`/`ny-del`) sets
|
|
204
224
|
it to `null`. `bluf` shows `täckningspost: <yta>` in the `anm` column when
|
|
205
225
|
the field is set.
|
|
206
|
-
- `
|
|
226
|
+
- `design` is written ONLY by `archive.mjs add-design` and reset ONLY by
|
|
227
|
+
`archive.mjs respec`: `{ "path": "<absolute path to the canonical file in the repo>",
|
|
228
|
+
"file": "design.md", "sha256": "<marker-stripped hash of design.md, identical to the canonical file>",
|
|
229
|
+
"spec_sha256": "<the spec.md hash the design was made against>", "date": "YYYY-MM-DD" }`.
|
|
230
|
+
The status `designed` sits between approval and `assessed`; `add-design` sets it.
|
|
231
|
+
`add-design` writes no runs row: `runs[]` records dispatches and the design is not
|
|
232
|
+
one; the receipt is the field itself, write-once per version (a new design puts the
|
|
233
|
+
old copy aside as `design-superseded-<datum>.md`). Older archives lack the field
|
|
234
|
+
and are read as `null`.
|
|
235
|
+
- `umbrella` is written ONLY by `archive.mjs paraply` (ADR-0144):
|
|
236
|
+
`{ "date": "YYYY-MM-DD", "sha256": "<marker-stripped hash of the umbrella spec.md>" }`,
|
|
237
|
+
the receipt that the parent's `spec.md` was rewritten one level up after a split.
|
|
238
|
+
The approved spec it replaced lies beside it as `spec-superseded-<datum>.md`, and the
|
|
239
|
+
parts keep their inherited copies of it. `paraply` also sets `title` from the umbrella's
|
|
240
|
+
heading; approval, design, runs, stops and the parts are untouched. The field is absent
|
|
241
|
+
until `paraply` writes it and is never reset.
|
|
242
|
+
- `approval` is written by the gate in `designa` or `bedöm`:
|
|
207
243
|
`{ "source": "asana" | "manual", "by": "<namn, krävs vid manual>",
|
|
208
244
|
"status_read": "<värde>", "date": "YYYY-MM-DD" }`.
|
|
209
245
|
The note is traceability, never the approval itself.
|
|
@@ -253,7 +289,9 @@ redispatch rule in the dispatch contract.
|
|
|
253
289
|
`node <skillkatalog>/scripts/ref-hash.mjs <referensfil>`, NEVER raw
|
|
254
290
|
`shasum` on the whole file: the installer stamps the files with the package version, so a
|
|
255
291
|
whole-file hash changes value at every haus release and would invalidate
|
|
256
|
-
all archived runs. The same tool is used for `underlag_sha256`.
|
|
292
|
+
all archived runs. The same tool is used for `underlag_sha256`. An `impact.md`
|
|
293
|
+
row additionally carries `design.md` when the directory holds one (`underlagFor`),
|
|
294
|
+
and precheck `--impact` compares that hash too.
|
|
257
295
|
The reference files lie under the Claude config directory (`CLAUDE_CONFIG_DIR`
|
|
258
296
|
or `~/.claude`). A later guard run compares the hash and refuses to diff on
|
|
259
297
|
skew ("rescoring required, the scale has changed").
|
|
@@ -405,7 +443,9 @@ på request-write-spec/references/specformat.md>`. The script sets
|
|
|
405
443
|
`node <skillkatalog>/scripts/archive.mjs respec <katalog>` BEFORE the new
|
|
406
444
|
spec is written. The command owns the whole invalidation (the analysis is put aside
|
|
407
445
|
as superseded, status, `approval`, `granskarutslag` and `stopp` are reset,
|
|
408
|
-
`runs[]` is never touched
|
|
446
|
+
`runs[]` is never touched, and any `design.md` is put aside as
|
|
447
|
+
`design-superseded-<datum>.md` with `design` reset the same way); never write
|
|
448
|
+
those fields by hand. The reason stands in
|
|
409
449
|
the runs contract: a new spec is unreviewed by definition, a ruling against a
|
|
410
450
|
replaced spec is no longer valid, and an old analysis against a new spec is
|
|
411
451
|
exactly the skew the provenance check exists to stop.
|
|
@@ -450,12 +490,127 @@ på request-write-spec/references/specformat.md>`. The script sets
|
|
|
450
490
|
stop nothing.
|
|
451
491
|
7. **Reply BLUF:** one line per spec (heading + any flags), then the reviewer block
|
|
452
492
|
in its entirety. Offer to place the specs on the board via request-sync (🔍); do
|
|
453
|
-
it only on explicit request.
|
|
493
|
+
it only on explicit request. Placing a spec on the board is no rename: request-sync
|
|
494
|
+
renames the task to the spec title by itself only in the three automatic cases
|
|
495
|
+
(ADR-0144): the task name is empty, `Original request title` is empty, or the task is
|
|
496
|
+
one of several minted from one source. In the Closing, under the board line,
|
|
497
|
+
say which case applied: renamed automatically, or the task keeps the customer's
|
|
498
|
+
title and `byt titel <item>` is the optional next action. When an item is placed on the board: set status
|
|
454
499
|
`spec_synced`, rename the slug directory to the minted gid, note the slug
|
|
455
500
|
in `former_slug` and update `request_id` in `state.json`.
|
|
456
501
|
**Close per `## Closing: where the item stands`** (the table from
|
|
457
502
|
`archive.mjs nasta-steg`, the board line, the ISÄR check), never without.
|
|
458
503
|
|
|
504
|
+
## Task: `designa`
|
|
505
|
+
|
|
506
|
+
Runs the design leg: brainstorming with the user against the approved spec, the
|
|
507
|
+
design doc saved in the customer repo and recorded in the archive. Runs in the main
|
|
508
|
+
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
|
|
510
|
+
material for `bedöm`'s assessor and never reaches the board.
|
|
511
|
+
|
|
512
|
+
1. **Gate. Identical to `bedöm` step 1.** Read Offer status via request-sync in the
|
|
513
|
+
main conversation immediately before the run. Only `✅ Spec ok` (normalized on the
|
|
514
|
+
alphabetic core) lets it through. An item without a gid follows `bedöm`'s rules for
|
|
515
|
+
that case (refuse when the repo has `.haus-workflow/request.json`, otherwise the
|
|
516
|
+
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.
|
|
519
|
+
2. **Form check.** Run `node <skillkatalog>/scripts/precheck.mjs <katalog>`. A
|
|
520
|
+
`KANDIDAT:` line or a standing `stopp` means the item is not ready for a design,
|
|
521
|
+
with one exception: a stop from `impact.md` whose `orsak` starts with
|
|
522
|
+
`design conflict:` (the assessor found the design unbuildable) is exactly what a
|
|
523
|
+
redesign answers, continue to step 3; `add-design` clears that stop and puts the
|
|
524
|
+
old analysis aside as `impact-superseded-<datum>.md` when it records the redesign.
|
|
525
|
+
Any other such line or stop: route it as the stop outcome (see `bedöm`) and stop. A
|
|
526
|
+
`spec.md` with more than one spec block is a BRIST, as in `bedöm`. Other BRISTER:
|
|
527
|
+
fix the link that is defective before anything is designed.
|
|
528
|
+
3. **Already designed?** A design-conflict stop let through by step 2 skips this
|
|
529
|
+
step: redesign, continue to step 4 (keeping an unbuildable design answers nothing).
|
|
530
|
+
Otherwise, if `state.json.design` is set, run
|
|
531
|
+
`node <skillkatalog>/scripts/precheck.mjs <katalog> --design`. Three branches:
|
|
532
|
+
(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
|
|
535
|
+
(`design-superseded-<datum>.md`), it never overwrites.
|
|
536
|
+
(b) its only design BRISTER are the hash lines
|
|
537
|
+
(`design.md: hashen är inte state.design.sha256 …` and/or
|
|
538
|
+
`design.md: den kanoniska filen … har en annan hash än design.md`), with
|
|
539
|
+
`request_id`, `spec_sha256` and `## Spec conflicts` still passing: the canonical
|
|
540
|
+
copy drifted (typically formatted on commit). Rerun
|
|
541
|
+
`node <skillkatalog>/scripts/archive.mjs add-design <katalog> --file <state.design.path>`
|
|
542
|
+
(no brainstorming; the old archive copy is put aside as `design-superseded-<datum>.md`),
|
|
543
|
+
then ask keep/redesign as in (a).
|
|
544
|
+
(c) any other BRIST: redesign, continue to step 4.
|
|
545
|
+
4. **Brainstorming.** Invoke `superpowers:brainstorming` via the Skill tool. The
|
|
546
|
+
opening message carries, byte-faithfully: the original request
|
|
547
|
+
(`## Ursprunglig förfrågan` from the archive or the board), `spec.md`,
|
|
548
|
+
`granskarblock.md` and `kallmanifest.md` as the source manifest, then the block
|
|
549
|
+
below verbatim (the id and the hash filled in: the hash comes from
|
|
550
|
+
`node <skillkatalog>/scripts/ref-hash.mjs <katalog>/spec.md`):
|
|
551
|
+
|
|
552
|
+
```
|
|
553
|
+
INSTRUKTIONER TILL BRAINSTORMING:
|
|
554
|
+
- The approved spec is fixed. Questions may refine HOW, never change WHAT the
|
|
555
|
+
customer gets. A question whose answer would change the spec is recorded under
|
|
556
|
+
`## Spec conflicts` in the design doc instead of being answered.
|
|
557
|
+
- Classify as the skill says, but the design doc is written on every path (spike,
|
|
558
|
+
bounded, architectural). The bounded path's "short design in chat" is written to
|
|
559
|
+
the file as well.
|
|
560
|
+
- The doc is written in English (an internal artefact, per the language contract).
|
|
561
|
+
- The doc starts with the frontmatter (unquoted values) `request_id: <katalogens id>`,
|
|
562
|
+
`spec_sha256: <hash>` and `date: <YYYY-MM-DD>`, and carries the section
|
|
563
|
+
`## Spec conflicts` with the single word `none` or one list item per conflict.
|
|
564
|
+
No size words, no hours, no score talk: the assessor reads the doc and must not
|
|
565
|
+
inherit a size signal.
|
|
566
|
+
- Save the doc at `docs/superpowers/specs/<YYYY-MM-DD>-<katalogens id>-<slug>-design.md`
|
|
567
|
+
in the customer repo.
|
|
568
|
+
- Stop after the doc is written and self-reviewed. Do not invoke `writing-plans`:
|
|
569
|
+
the developer does that when the customer orders.
|
|
570
|
+
- Do not commit. The task stages the file and offers the commit in its closing line.
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
A brainstorming session that ends without a file records nothing: `state.json` is
|
|
574
|
+
untouched and `designa` can be rerun.
|
|
575
|
+
|
|
576
|
+
5. **Record.** Format the doc with the repo's formatter first (`yarn prettier --write <sökväg>`
|
|
577
|
+
when the repo has prettier, otherwise nothing): a format-on-commit hook must not
|
|
578
|
+
change the bytes after they are recorded. Then run
|
|
579
|
+
`node <skillkatalog>/scripts/archive.mjs add-design <katalog> --file <absolut sökväg till designdokumentet>`.
|
|
580
|
+
The command verifies the doc (the frontmatter `request_id` against the directory's
|
|
581
|
+
id, `spec_sha256` against the current `spec.md`, `## Spec conflicts` is `none`, the
|
|
582
|
+
file lies inside the repo), puts an existing `design.md` aside, copies the doc
|
|
583
|
+
byte-identically into the directory as `design.md`, writes `state.json.design` and
|
|
584
|
+
sets status `designed`. It writes no runs row (see the `state.json` contract). Then
|
|
585
|
+
run `node <skillkatalog>/scripts/precheck.mjs <katalog> --design` and show any
|
|
586
|
+
BRIST or VARNING lines. Stage the file (`git add <sökväg>`); never commit (the
|
|
587
|
+
house git rule: commit only on explicit OK).
|
|
588
|
+
|
|
589
|
+
**A refused doc with conflicts** (exit 2 on `## Spec conflicts`): copy the refused
|
|
590
|
+
doc into the directory as `design-avvisad-<datum>.md` (`-2` on collision, never
|
|
591
|
+
overwrite: the receipt, like `spec-avvisad-<datum>.md`), then run
|
|
592
|
+
`node <skillkatalog>/scripts/archive.mjs stopp <katalog> --utfall TILLBAKA_TILL_SPEC --kalla design-avvisad-<datum>.md --orsak "<the conflict lines, one sentence each>"`;
|
|
593
|
+
if `state.json.respec_varv` is already ≥ 1, `--utfall ESKALERA` with the same
|
|
594
|
+
`--orsak`, as in speca step 6. A standing design-conflict stop (bedöm step 3) is
|
|
595
|
+
replaced by the receipt: the redesign showed the spec is the problem, so the spec
|
|
596
|
+
route wins. The stop is what `nasta-steg`, `bedöm` and the Closing read. From there
|
|
597
|
+
the item goes to customer dialogue, then
|
|
598
|
+
`## Avgjorda val`, `respec` and a new `speca`, exactly as a price-decisive open
|
|
599
|
+
choice does (ADR-0118). The doc also stays in the repo under its own name so the
|
|
600
|
+
conversation is not lost, but it is never recorded as the item's design.
|
|
601
|
+
**Other exit-2 refusals** on the doc (a mismatched `request_id`, a stale
|
|
602
|
+
`spec_sha256`, the file outside the repo or under `.haus-workflow/`): fix the doc
|
|
603
|
+
and rerun `add-design`; nothing is recorded until it passes. A refusal on the
|
|
604
|
+
item's state (status `priced` or `guard_run`, a standing stop other than a design
|
|
605
|
+
conflict) is not fixed in the doc: `respec`, or decide the stop first.
|
|
606
|
+
|
|
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>`).
|
|
613
|
+
|
|
459
614
|
## Task: `bedöm`
|
|
460
615
|
|
|
461
616
|
Runs the pricing leg: an impact analysis if it is missing, then scoring with a
|
|
@@ -481,6 +636,17 @@ drift guard.
|
|
|
481
636
|
the reviewer block cannot be recreated from Asana.
|
|
482
637
|
- Note the passed gate in `state.json.approval` (the manual case with `by`).
|
|
483
638
|
The next `bedöm` reads the status again.
|
|
639
|
+
- **Gate 1b, the design (only when the assessor is to be dispatched).** When
|
|
640
|
+
`impact.md` is missing, or precheck rejects it on source-material provenance
|
|
641
|
+
(step 3's condition), run `node <skillkatalog>/scripts/precheck.mjs <katalog> --design`
|
|
642
|
+
first. `DESIGN: saknas` or any BRIST from the flag: refuse, show the lines and the
|
|
643
|
+
command `designa <adress>`, and stop (a drifted canonical copy is re-recorded there
|
|
644
|
+
without a new brainstorming, designa step 3). An item whose `impact.md` is present and
|
|
645
|
+
provenance-valid is not gated: it was analysed under the old rules and may be
|
|
646
|
+
re-scored. New items always hit the gate, since they have no `impact.md` yet,
|
|
647
|
+
with one exception: a split part (`state.split.parent` set) is not gated, the
|
|
648
|
+
split copied the parent's `design.md` into it, and the assessor gets it as the
|
|
649
|
+
`DESIGN` block.
|
|
484
650
|
2. **Form check.** Run `node <skillkatalog>/scripts/precheck.mjs <katalog> --impact`
|
|
485
651
|
(without `--impact` if the analysis does not exist yet). A `spec.md` with more than one
|
|
486
652
|
spec block is a BRIST: split the item per the archive rule before anything is dispatched.
|
|
@@ -495,7 +661,7 @@ drift guard.
|
|
|
495
661
|
below. No analysis and no score may ever be dispatched on a
|
|
496
662
|
candidate.
|
|
497
663
|
3. **Analysis.** If `impact.md` is missing, or precheck rejects it on
|
|
498
|
-
source-material provenance (the analysis was made against another spec): this requires a repo in
|
|
664
|
+
source-material provenance (the analysis was made against another spec or another design): this requires a repo in
|
|
499
665
|
the session (otherwise stop: a guessed analysis is forbidden by the skill itself).
|
|
500
666
|
Dispatch `request-assessor` per the prompt template: the spec's reviewer block
|
|
501
667
|
is sent along as internal source material (the same trust domain; the flags there are
|
|
@@ -505,13 +671,19 @@ drift guard.
|
|
|
505
671
|
language is never guessed again, the same line goes to the scorer in step 4);
|
|
506
672
|
the assessor verifies the manifest itself and must never take it as true
|
|
507
673
|
(ADR-0113: the assessor explored the repo from zero even though the manifest already
|
|
508
|
-
existed).
|
|
674
|
+
existed). The `DESIGN` block carries `design.md` from the directory byte-faithfully
|
|
675
|
+
(the hard rule: pasted, never pointed to by path), or the line `DESIGN: ingen` when
|
|
676
|
+
the directory has no design (a split part of a parent analysed under the old rules,
|
|
677
|
+
or a standalone assessor run). Archive the reply as `impact.md`
|
|
509
678
|
(including its "## For the reviewer" block: show the block to the user,
|
|
510
679
|
never to customer fields), stamp with
|
|
511
680
|
`node <skillkatalog>/scripts/archive.mjs add-run <katalog> --file impact.md
|
|
512
681
|
--skill request-assess-impact --agent request-assessor
|
|
513
682
|
--model <ur MODELL-svansraden>` (the script sets `underlag_sha256` against
|
|
514
|
-
`spec.md
|
|
683
|
+
`spec.md`, and hashes `design.md` into `underlag_sha256` via `underlagFor` when
|
|
684
|
+
the file exists; precheck's provenance check on `--impact` compares both hashes,
|
|
685
|
+
so an analysis made against a superseded design is rejected the same way one made
|
|
686
|
+
against a replaced spec is). Run precheck again with `--impact`. Then read the line
|
|
515
687
|
`AVVIKELSE: <etikett>` from the precheck output (the label on the analysis's row
|
|
516
688
|
`**Deviation from the spec:**`; not to be confused with the agents' tail line):
|
|
517
689
|
`motsägelse` means that the spec presupposes something that does not hold in
|
|
@@ -519,7 +691,10 @@ drift guard.
|
|
|
519
691
|
`node <skillkatalog>/scripts/archive.mjs stopp <katalog> --utfall TILLBAKA_TILL_SPEC --kalla impact.md`
|
|
520
692
|
(the command sets status `assessed`), skip steps 4 to 7 and route
|
|
521
693
|
the item as the stop outcome below: no scorer is dispatched on source material
|
|
522
|
-
that already says the spec must go back.
|
|
694
|
+
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
|
|
523
698
|
on to step 4. If precheck rejects the new
|
|
524
699
|
draft → redispatch the assessor ONCE per the redispatch rule, and give
|
|
525
700
|
the rejected draft a receipt exactly as in speca step 6: archive it as
|
|
@@ -655,28 +830,69 @@ ref-hash.mjs på request-score/references/poangskala.md>
|
|
|
655
830
|
that takes the item ✅ Spec ok → ⚖️ Poängsättning redo för granskning per
|
|
656
831
|
the sync's rules. **Close per `## Closing: where the item stands`**
|
|
657
832
|
(the table from `archive.mjs nasta-steg`, the board line, the ISÄR check, and
|
|
658
|
-
a stop outcome or OLIKA as a choice the user must make
|
|
833
|
+
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.
|
|
659
835
|
|
|
660
836
|
**Stop outcomes are routed, never interpreted.** A stop outcome is archived as the round's
|
|
661
837
|
file (step 7), the status becomes `assessed`, never `priced`, and the item is routed:
|
|
662
838
|
|
|
663
|
-
- `DELA_UPP` →
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
839
|
+
- `DELA_UPP` → the Closing offers two separate yes/no choices (ADR-0144), each answered on its own:
|
|
840
|
+
1. **Split the item** (as before): a new analysis round per part; the parts become
|
|
841
|
+
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`,
|
|
845
|
+
never DELA_UPP again. Sub-items inherit, per the skill, the item's spec and never write
|
|
846
|
+
one of their own: the parent's `spec.md`, `granskarblock.md` and `design.md` are COPIED
|
|
847
|
+
unchanged into each part directory, separately (one reviewer block per part directory,
|
|
848
|
+
ADR-0118, no part directory shares its block with another), while `impact.md` is written per
|
|
849
|
+
part by the new analysis round. The parts inherit the parent's design the way they
|
|
850
|
+
inherit its spec: `state.design` stays `null` on a part, the parent's record is the
|
|
851
|
+
receipt, and bedöm's gate 1b does not run on a part.
|
|
852
|
+
**Every part becomes a subtask under the parent**, never a separate request: the sync
|
|
853
|
+
that follows a part's own `bedöm` round creates it, named as the part's changed state
|
|
854
|
+
with its scope line, both from the analysis round that pointed out the parts; the
|
|
855
|
+
orchestrator passes both to request-sync in the spec's language (the analysis round
|
|
856
|
+
writes English, so translate the name and the scope line when the spec is Swedish, the
|
|
857
|
+
same rule as the spec title). Then run
|
|
858
|
+
`node <skillkatalog>/scripts/archive.mjs set-split-gid <del-katalog> --gid <deluppgiftens gid>`
|
|
859
|
+
and pass the recorded `split.gid` to request-sync on every later sync of that part, so the
|
|
860
|
+
subtask is updated instead of created twice. Moving the parent from ✅ Spec ok to ⚖️ is
|
|
861
|
+
request-sync's job in the run that writes the last part's subtask: pass it `split.of`
|
|
862
|
+
and every part's state (`priced` with its score, or `OVER_SKALAN`, and its `split.gid`).
|
|
863
|
+
The parent row of `nasta-steg` says when that run is due:
|
|
864
|
+
`se delarna (K av M delar prissatta)` until every part is done, then the sync row,
|
|
865
|
+
`sync föräldern till brädan (request-sync ⚖️)`.
|
|
866
|
+
2. **Rewrite the parent as an umbrella** (optional, and only after choice 1 has created
|
|
867
|
+
the part directories: `paraply` refuses a parent without parts, and a no to the split
|
|
868
|
+
means no umbrella): dispatch `request-specifier` in umbrella mode, the template with the
|
|
869
|
+
`PARAPLY:` block (see the dispatch contract). Split the reply as in speca step 5,
|
|
870
|
+
write the spec to a scratch file outside the archive and show the draft BLUF with
|
|
871
|
+
its reviewer block. On an explicit yes, run
|
|
872
|
+
`node <skillkatalog>/scripts/archive.mjs paraply <katalog> --file <utkastet>`: it puts
|
|
873
|
+
the old `spec.md` aside as `spec-superseded-<datum>.md`, copies the umbrella in, sets
|
|
874
|
+
`title` from its heading and records `state.umbrella`; approval, design, runs, stops
|
|
875
|
+
and the parts are untouched (the parts keep the approved spec they were priced
|
|
876
|
+
against). A refusal (the form check or the title line) is redispatched ONCE with the
|
|
877
|
+
refusal lines as `RÄTTNINGAR:`; a second refusal stops and the parent keeps its spec.
|
|
878
|
+
After `OK: paraply`, write the description's `## Specifikation` from the umbrella via
|
|
879
|
+
request-sync, under the lock (`Decision` read first), never with a rename; when the
|
|
880
|
+
umbrella title differs from the task name, the Closing lists `byt titel <item>` as the
|
|
881
|
+
optional next action. No to the umbrella leaves the parent's description as it is.
|
|
670
882
|
- `OVER_SKALAN` → the item is quoted separately; never split further (the split is done
|
|
671
883
|
one step, the skill's own rule).
|
|
672
884
|
- `TILLBAKA_TILL_SPEC` / `KONCEPT` / `DIAGNOS` → back to the spec step
|
|
673
|
-
or the customer dialogue respectively; show the reason.
|
|
885
|
+
or the customer dialogue respectively; show the reason. A `TILLBAKA_TILL_SPEC` from
|
|
886
|
+
`impact.md` whose `orsak` starts with `design conflict:` routes to `designa <item>`
|
|
887
|
+
(a redesign, bedöm step 3), not to `speca`. If the outcome came from the scripts (a candidate in
|
|
674
888
|
`spec.md`, `contradiction` in `impact.md`, a price-decisive open choice in
|
|
675
|
-
`granskarblock.md`, ADR-0118
|
|
889
|
+
`granskarblock.md`, ADR-0118, conflicts in a refused design's
|
|
890
|
+
`design-avvisad-<datum>.md`), `state.json.stopp` carries it via
|
|
676
891
|
`archive.mjs stopp` and there is no round file; if it came from the scorer,
|
|
677
892
|
the round file is archived as before and `stopp` stays `null` (the command takes
|
|
678
|
-
only the
|
|
679
|
-
`
|
|
893
|
+
only the script-proven sources: `spec.md`, `impact.md`, `granskarblock.md` and a
|
|
894
|
+
`design-avvisad-<datum>.md` receipt). A respec resets `stopp`; `add-design` clears
|
|
895
|
+
a design-conflict stop from `impact.md`.
|
|
680
896
|
- `ESKALERA` / `INPUT_SAKNAS` → show the reason and stop, or a price-decisive
|
|
681
897
|
choice that remains after respec (source `granskarblock.md`, reason in
|
|
682
898
|
`stopp.orsak`, ADR-0118).
|
|
@@ -718,7 +934,7 @@ get wrong:
|
|
|
718
934
|
description fields.
|
|
719
935
|
- **Close per `## Closing: where the item stands`** when the item has an
|
|
720
936
|
archive directory: the table from `archive.mjs nasta-steg` plus the board line, so
|
|
721
|
-
the move is visible together with what it opens up for (`
|
|
937
|
+
the move is visible together with what it opens up for (`designa`, customer, nothing).
|
|
722
938
|
|
|
723
939
|
## Task: `döm`
|
|
724
940
|
|
|
@@ -821,11 +1037,34 @@ facts in the analysis above.
|
|
|
821
1037
|
## Task: `detaljer`
|
|
822
1038
|
|
|
823
1039
|
`detaljer <gid|slug|nr> [step]`: print archived files for the item: without
|
|
824
|
-
a step, a list of what exists; with a step (`spec`, `granskarblock`, `
|
|
825
|
-
`poäng`, `state`) the file's content raw
|
|
1040
|
+
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`);
|
|
1042
|
+
`klass` reads older archives'
|
|
826
1043
|
classification files (before ADR-0098). For `klass`/`poäng`: the latest
|
|
827
1044
|
`-pricing-vN.json` without a suffix (never `-run2`/`-avvisad`).
|
|
828
1045
|
|
|
1046
|
+
## Task: `byt titel`
|
|
1047
|
+
|
|
1048
|
+
`byt titel <nr|gid>`: rename the item's Asana task to the spec title, on request only
|
|
1049
|
+
(ADR-0144). The task name follows the customer: request-sync renames it by itself only
|
|
1050
|
+
in the three automatic cases (empty task name, empty `Original request title`, or one of
|
|
1051
|
+
several tasks minted from one source), and this task is the only other way the spec title
|
|
1052
|
+
reaches the name.
|
|
1053
|
+
|
|
1054
|
+
1. **Gate: the item has a gid.** Addressing as for `godkänn` (a row number from the latest
|
|
1055
|
+
`status` listing in the same session, or a gid; never fuzzy heading matching). An item
|
|
1056
|
+
without a gid is not on the board: say so and stop. An item with a gid but no archive
|
|
1057
|
+
directory: say so and stop, the spec title lives only in the archive.
|
|
1058
|
+
2. **Read the title.** Read `title` from the directory's `state.json` (`add-run` writes it
|
|
1059
|
+
from the heading of `spec.md`, `paraply` from the umbrella's). A `null` title: say so
|
|
1060
|
+
and stop.
|
|
1061
|
+
3. **Rename via request-sync** in the main conversation (the Skill tool): the gid and the
|
|
1062
|
+
title, nothing else. request-sync keeps ADR-0124's order: `Original request title` is
|
|
1063
|
+
written and read back before the task name changes. A title equal to the current task
|
|
1064
|
+
name is no rename: say so and change nothing.
|
|
1065
|
+
4. **Close per `## Closing: where the item stands`**: the table from `archive.mjs nasta-steg`
|
|
1066
|
+
and the board line. The archive status does not change.
|
|
1067
|
+
|
|
829
1068
|
## Task: `utvärdera`
|
|
830
1069
|
|
|
831
1070
|
Model evaluation: `utvärdera <item…> <model…>`, with at least one model. Runs an
|
|
@@ -944,6 +1183,21 @@ The question is therefore about the cost, not the risk of losing data.
|
|
|
944
1183
|
The manifest ends with the section `## Avgjorda val`: every choice that a human
|
|
945
1184
|
has decided after an earlier stop, one line each, verbatim as the answer was given;
|
|
946
1185
|
`inga` if there are none. The specifier must never flag a choice that stands there.
|
|
1186
|
+
The design is an optional pinned input, like the manifest: when the production
|
|
1187
|
+
archive holds a recorded design for the item, copy it byte-identically to
|
|
1188
|
+
`experiments/<slug>/design.md` and note its hash with
|
|
1189
|
+
`archive.mjs experiment experiments/<slug> --satt design_sha256=<hash>`
|
|
1190
|
+
(`ref-hash.mjs` on the file). `korning.mjs` reads the file when it exists, copies
|
|
1191
|
+
it into every part directory before the assessor runs (so `add-run` hashes it) and
|
|
1192
|
+
pastes it as the assessor's `DESIGN` block. Without the file every round runs as
|
|
1193
|
+
today. Known limitation, recorded so nobody measures against it by accident: a
|
|
1194
|
+
sweep regenerates the spec per round while the design is fixed against one
|
|
1195
|
+
production spec, so a sweep with a design measures the assessor and the scorer
|
|
1196
|
+
against a design that may not match the round's spec byte for byte, and a bundle's
|
|
1197
|
+
parts all get the one experiment design, while production designs are per item
|
|
1198
|
+
directory; `experiment.json.design_sha256` and the part's `impact.md` runs row
|
|
1199
|
+
(`underlag_sha256["design.md"]`, shown by `detaljer`) tell the reader which
|
|
1200
|
+
design the round ran against.
|
|
947
1201
|
3. **The escalation choice is made once** per `speca`'s rules and applies to all
|
|
948
1202
|
rounds; the escalation choice too is part of what is held constant.
|
|
949
1203
|
If the choice triggers: the agent becomes `request-specifier-eskalerad` instead of
|
|
@@ -1098,7 +1352,8 @@ The question is therefore about the cost, not the risk of losing data.
|
|
|
1098
1352
|
the split itself, see step 4; the rules here apply when it runs):
|
|
1099
1353
|
part directories
|
|
1100
1354
|
`<modell>/k<N>/del-1/ … del-N/` with `split` set, the parent's `spec.md` +
|
|
1101
|
-
`granskarblock.md`
|
|
1355
|
+
`granskarblock.md` (and `design.md`, when the experiment has one) copied in, a new
|
|
1356
|
+
analysis + score per part. If a
|
|
1102
1357
|
bundle part is split, it becomes `del-N/del-M/` under that part, never a new
|
|
1103
1358
|
sibling in the root (`bundle` and `split` are never set on the same directory).
|
|
1104
1359
|
A part without a ceiling becomes `OVER_SKALAN` and is never split further. Other
|
|
@@ -1251,7 +1506,7 @@ the human's, made on experience of the system. The report shows the spread.
|
|
|
1251
1506
|
|
|
1252
1507
|
## Closing: where the item stands
|
|
1253
1508
|
|
|
1254
|
-
The tasks `speca`, `bedöm`, `godkänn`, `underkänn` and `
|
|
1509
|
+
The tasks `speca`, `designa`, `bedöm`, `godkänn`, `underkänn`, `döm` and `byt titel` ALWAYS end
|
|
1255
1510
|
with this block (#530). A reply that ends without it leaves
|
|
1256
1511
|
the user to guess where the item stands, what they should do and which command
|
|
1257
1512
|
runs on, and the archive and the board can then drift apart silently (`spec_draft`
|
|
@@ -1262,32 +1517,39 @@ locally, empty Offer status on the board). The block consists of four parts, in
|
|
|
1262
1517
|
directory and part), NEVER handwritten, for the same reason as `bluf`: a
|
|
1263
1518
|
handwritten closing drops exactly the row that would have said what is
|
|
1264
1519
|
waiting. The script computes the rows from `state.json` (status, `stopp`,
|
|
1265
|
-
`respec_varv`, `approval`, an unlifted OLIKA via the hold, the scorer's current
|
|
1266
|
-
outcome from the pricing file
|
|
1520
|
+
`respec_varv`, `approval`, `design`, an unlifted OLIKA via the hold, the scorer's current
|
|
1521
|
+
outcome from the pricing file and, on a split root, how many parts are done) with the
|
|
1522
|
+
rules from this skill's own gates;
|
|
1267
1523
|
the rule table with a source reference per row stands above the function
|
|
1268
1524
|
`nastaStegFor` in the script. A state the script does not know is written as
|
|
1269
1525
|
`okänt läge: <status>`, never as a guess.
|
|
1270
1526
|
2. **The board line.** If the item has a gid: fetch Offer status via request-sync in
|
|
1271
1527
|
the main conversation (never from memory) and write the line
|
|
1272
1528
|
`Bräda: <Offer status>` directly under the table. If the item lacks a gid: write
|
|
1273
|
-
`Bräda: ingen (posten ligger inte på brädan)`.
|
|
1529
|
+
`Bräda: ingen (posten ligger inte på brädan)`. For an item at
|
|
1530
|
+
⚖️ Poängsättning redo för granskning, add one line: the analysis and the pricing are
|
|
1531
|
+
not on the board (ADR-0144), `detaljer <item>` shows them.
|
|
1274
1532
|
3. **The ISÄR check.** The archive status and the Offer status must correspond to each other
|
|
1275
1533
|
per the table below (the values are request-sync's, normalized on
|
|
1276
1534
|
the alphabetic core as there). If they differ, a line
|
|
1277
1535
|
`ISÄR: arkiv <x>, bräda <y>` is written, followed by the command that closes the gap.
|
|
1278
1536
|
|
|
1279
|
-
| archive status (`state.json`)
|
|
1280
|
-
|
|
|
1281
|
-
| `spec_draft`
|
|
1282
|
-
| `spec_synced`
|
|
1283
|
-
| `spec_synced`/`spec_draft` with `approval` set
|
|
1284
|
-
| `
|
|
1285
|
-
|
|
|
1537
|
+
| archive status (`state.json`) | expected Offer status | closes the gap |
|
|
1538
|
+
| ------------------------------------------------------ | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1539
|
+
| `spec_draft` | empty or 📥 Inkommet | sync via request-sync (🔍) when the spec is to be reviewed |
|
|
1540
|
+
| `spec_synced` | 🔍 Spec redo för granskning | `godkänn`/`underkänn`, or sync if the board stands at 📥 |
|
|
1541
|
+
| `spec_synced`/`spec_draft` with `approval` set | ✅ Spec ok | `designa`; if the board stands at 🔍, the approval note is older than the board, reread the gate |
|
|
1542
|
+
| `designed` | ✅ Spec ok | `bedöm`; if the board stands at 🔍, the approval note is older than the board, reread the gate |
|
|
1543
|
+
| `assessed` with the scorer's `DELA_UPP` (a split root) | ✅ Spec ok until every part is done, then ⚖️ Poängsättning redo för granskning | the parent row of `nasta-steg` (`se delarna (K av M delar prissatta)`), then the sync that moves the parent, `sync föräldern till brädan (request-sync ⚖️)` |
|
|
1544
|
+
| `assessed`/`priced`, the score synced | ⚖️ Poängsättning redo för granskning | sync via request-sync if the board still stands at ✅ |
|
|
1545
|
+
| done (`godkänn` from ⚖️) | 📤 Klar – till kund | nothing, the customer's `Decision` decides the rest |
|
|
1286
1546
|
|
|
1287
1547
|
The archive is a cache and Asana the truth (Hard rules): an ISÄR is always resolved
|
|
1288
1548
|
in the direction of the board, never by rewriting the board to match
|
|
1289
1549
|
the archive. An experiment variant (`experiment: true`) has no board line and
|
|
1290
|
-
no ISÄR check; it never reaches Asana.
|
|
1550
|
+
no ISÄR check; it never reaches Asana. A split part has no Offer status of its own:
|
|
1551
|
+
its place on the board is its subtask (`split.gid`), so a part row gets no board line
|
|
1552
|
+
and no ISÄR check.
|
|
1291
1553
|
|
|
1292
1554
|
4. **The choice, when there is one.** A stop outcome (`TILLBAKA_TILL_SPEC`,
|
|
1293
1555
|
`ESKALERA`, `KONCEPT`, `DIAGNOS`) and an unlifted `double_run: olika`
|
|
@@ -1296,8 +1558,12 @@ locally, empty Offer status on the board). The block consists of four parts, in
|
|
|
1296
1558
|
open choice from `stopp.orsak` or the source file; for OLIKA the two
|
|
1297
1559
|
runs' evidence side by side, see bedöm step 6) and the command that
|
|
1298
1560
|
carries out the answer (`speca <item>` after `## Avgjorda val` + `respec`,
|
|
1299
|
-
`döm <item>`, customer dialogue). A
|
|
1300
|
-
|
|
1561
|
+
`döm <item>`, customer dialogue). A `TILLBAKA_TILL_SPEC` from `impact.md` whose
|
|
1562
|
+
`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
|
|
1564
|
+
is only routed is read as "the machine is working on it", and nobody does anything.
|
|
1565
|
+
A `DELA_UPP` is presented as two separate yes/no choices, split the item and rewrite
|
|
1566
|
+
the parent as an umbrella (bedöm's routing, ADR-0144), each answered on its own.
|
|
1301
1567
|
|
|
1302
1568
|
## Mechanical scripts: `scripts/`
|
|
1303
1569
|
|
|
@@ -1313,7 +1579,7 @@ cheaper, faster and without judgment drift. Every script carries sha256 for the
|
|
|
1313
1579
|
reference files whose rules it mirrors and WARNS when a catalog bump has changed them
|
|
1314
1580
|
(contract drift must be discovered by a check, not by a customer):
|
|
1315
1581
|
|
|
1316
|
-
- `scripts/precheck.mjs <arkivkatalog> [--impact]`: the form check BEFORE expensive
|
|
1582
|
+
- `scripts/precheck.mjs <arkivkatalog> [--impact] [--design]`: the form check BEFORE expensive
|
|
1317
1583
|
dispatches: headings, exactly one spec block, 2–5 bullets, forbidden vocabulary,
|
|
1318
1584
|
reviewer block rows, state.json fields. Distinguishes BRISTER (exit 1, stops)
|
|
1319
1585
|
from VARNING (a heuristic: shown, does not stop). The headings are matched via
|
|
@@ -1326,7 +1592,21 @@ reference files whose rules it mirrors and WARNS when a catalog bump has changed
|
|
|
1326
1592
|
`**Deviation from the spec:**` is read and written as `AVVIKELSE: ingen`,
|
|
1327
1593
|
`AVVIKELSE: precisering` or `AVVIKELSE: motsägelse`; a row without a
|
|
1328
1594
|
label is a BRIST. The orchestrator reads candidate and deviation from those
|
|
1329
|
-
lines, never from the files itself.
|
|
1595
|
+
lines, never from the files itself. The spec rules live in `lib.mjs` (`specForm`),
|
|
1596
|
+
shared with `archive.mjs paraply` (ADR-0144).
|
|
1597
|
+
With `--design` (`designa` step 3 and `bedöm` gate 1b): `design.md` must exist,
|
|
1598
|
+
`state.design` must be set, the hash of `design.md` must equal `state.design.sha256`,
|
|
1599
|
+
the canonical file at `state.design.path` must exist and hash the same, the
|
|
1600
|
+
frontmatter `request_id` must equal the directory's id, `spec_sha256` must equal the
|
|
1601
|
+
current `spec.md` hash, and `## Spec conflicts` must be `none`; each failure is a
|
|
1602
|
+
BRIST. Size words, hours and score words in the design body are a VARNING (the
|
|
1603
|
+
assessor is instructed to ignore them, the reviewer should see them). The line
|
|
1604
|
+
`DESIGN: ok` (the file exists and `state.design` is set) or `DESIGN: saknas` is
|
|
1605
|
+
written always, even at exit 1, so the orchestrator reads the state from the line
|
|
1606
|
+
and never from the files. With `--impact`, a `design.md` in the directory must
|
|
1607
|
+
match the analysis row's `underlag_sha256["design.md"]`, the same provenance rule
|
|
1608
|
+
as for `spec.md`, except that a missing design hash is a BRIST, not a VARNING:
|
|
1609
|
+
the design existed when the analysis should have seen it.
|
|
1330
1610
|
- `scripts/resolve-anchors.mjs <run.json> <spec.md> [impact.md]`: resolves
|
|
1331
1611
|
evidence anchors (`belagg_ankare`/`ankare`) to verbatim source blocks, runs
|
|
1332
1612
|
BEFORE contract-check. Exit 0 = everything resolved (or no anchors in the file), 1 =
|
|
@@ -1377,20 +1657,48 @@ reference files whose rules it mirrors and WARNS when a catalog bump has changed
|
|
|
1377
1657
|
- `scripts/archive.mjs <kommando> <katalog> [flaggor]`: the archive's mechanics
|
|
1378
1658
|
(full list in the script's header): `add-run`, `next-n`, `sparr`,
|
|
1379
1659
|
`utslag`, `set-status`, `kalibrering`, `ny-korning`, `proveniens`, plus
|
|
1380
|
-
`
|
|
1660
|
+
`add-design <katalog> --file <path>` (verifies the design doc: frontmatter
|
|
1661
|
+
`request_id` = the directory's id, `spec_sha256` = the current `spec.md` hash,
|
|
1662
|
+
`## Spec conflicts` = `none`, the file inside the repo root; puts an existing
|
|
1663
|
+
`design.md` aside as `design-superseded-<datum>.md`, copies the doc in
|
|
1664
|
+
byte-identically, writes `state.design` and sets status `designed`; no runs row;
|
|
1665
|
+
refuses a file under `.haus-workflow/`, a `priced` or `guard_run` item and any
|
|
1666
|
+
standing stop except a design conflict from `impact.md`, which it clears, putting
|
|
1667
|
+
`impact.md` aside as `impact-superseded-<datum>.md`;
|
|
1668
|
+
exit 2 on every refusal, under the archive lock),
|
|
1669
|
+
`set-split-gid <del-katalog> --gid <gid>` (records a split part's Asana subtask gid in
|
|
1670
|
+
`split.gid` under the archive lock; refuses a directory without `split`, a gid that is not
|
|
1671
|
+
digits only and a different gid already recorded, while the same gid again is a no-op;
|
|
1672
|
+
ADR-0144),
|
|
1673
|
+
`paraply <katalog> --file <spec>` (rewrites the parent's spec as an umbrella: refuses a
|
|
1674
|
+
split part, an item without `approval`, a file that fails the spec form check
|
|
1675
|
+
`precheck.mjs` runs, a file without a title line and an unreadable file; puts `spec.md`
|
|
1676
|
+
aside as `spec-superseded-<datum>.md`, copies the file in, sets `title` from its heading
|
|
1677
|
+
and records `state.umbrella = { date, sha256 }`; approval, design, runs, stops and the
|
|
1678
|
+
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>]`
|
|
1381
1680
|
(writes `state.stopp` after checking that the source carries the outcome;
|
|
1382
|
-
`--kalla
|
|
1681
|
+
`--kalla design-avvisad-<datum>.md` requires at least one conflict under
|
|
1682
|
+
`## Spec conflicts` in that receipt and takes `TILLBAKA_TILL_SPEC` or `ESKALERA`,
|
|
1683
|
+
and replaces a standing design-conflict stop from `impact.md` (any other standing
|
|
1684
|
+
stop refuses a different one, exit 2);
|
|
1685
|
+
`--kalla impact.md` sets status `assessed`, the other sources do not touch
|
|
1383
1686
|
the status), `respec <katalog>` (puts `impact.md` aside as
|
|
1384
|
-
`impact-superseded-<datum>.md
|
|
1385
|
-
`approval`, `granskarutslag
|
|
1687
|
+
`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
|
|
1386
1690
|
`bluf <katalog>` (the markdown table `| post | poäng | utfall | konfidens | anm |`
|
|
1387
1691
|
over the directory and its `del-N/` recursively, the bundle root as
|
|
1388
|
-
`bunt (N delar)
|
|
1692
|
+
`bunt (N delar)`, a split root with `K av M delar prissatta` in `anm`; the values from
|
|
1693
|
+
the files, never from prose) and
|
|
1389
1694
|
`nasta-steg <katalog>` (read-only, the markdown table
|
|
1390
1695
|
`| post | står | väntar på | nästa |` over the directory and its `del-N/`
|
|
1391
1696
|
recursively: where the item stands, what a human is expected to do and which
|
|
1392
1697
|
`/request` command runs on, from `state.json` and the scorer's current
|
|
1393
|
-
outcome per the rule table in the script;
|
|
1698
|
+
outcome per the rule table in the script; on a split root the parent row counts the
|
|
1699
|
+
parts (`se delarna (K av M delar prissatta)`) until every part is `priced` or
|
|
1700
|
+
`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
|
|
1394
1702
|
`okänt läge: <status>` with exit 0, a broken `state.json` is exit 2, see
|
|
1395
1703
|
`## Closing: where the item stands`). `add-run` reads
|
|
1396
1704
|
`effort:` from the agent definition when `--effort` is omitted and canonicalizes
|
|
@@ -1498,6 +1806,25 @@ continue as if the check had passed.
|
|
|
1498
1806
|
English `**Concept candidate**` or `**Diagnosis candidate**`); the
|
|
1499
1807
|
specifier decides that itself per the skill.
|
|
1500
1808
|
|
|
1809
|
+
In umbrella mode (`bedöm`'s `DELA_UPP` choice 2, ADR-0144) the prompt is the template
|
|
1810
|
+
above with `ESKALERAD: nej`, `ÖNSKEMÅL:` from the description's `## Ursprunglig förfrågan`,
|
|
1811
|
+
`KÄLLOR:` from `kallmanifest.md` and `SPRÅK:` from its first line, and it ends with one
|
|
1812
|
+
more block:
|
|
1813
|
+
|
|
1814
|
+
```
|
|
1815
|
+
PARAPLY:
|
|
1816
|
+
<förälderns spec.md bytetroget>
|
|
1817
|
+
|
|
1818
|
+
DELAR:
|
|
1819
|
+
del 1: <delens namn, det ändrade läget>: <omfattningsraden>
|
|
1820
|
+
del 2: <delens namn, det ändrade läget>: <omfattningsraden>
|
|
1821
|
+
```
|
|
1822
|
+
|
|
1823
|
+
The parent's spec is pasted byte-faithfully (the hard rule); the part lines come from
|
|
1824
|
+
the analysis round that pointed out the parts, one per part directory, in part order.
|
|
1825
|
+
The umbrella dispatch writes no runs row: `state.umbrella` is its receipt once `paraply`
|
|
1826
|
+
accepts the draft.
|
|
1827
|
+
|
|
1501
1828
|
`request-assessor`:
|
|
1502
1829
|
|
|
1503
1830
|
```
|
|
@@ -1524,6 +1851,9 @@ continue as if the check had passed.
|
|
|
1524
1851
|
|
|
1525
1852
|
GRANSKARBLOCK (internt underlag, följer aldrig med i analysens kundtext):
|
|
1526
1853
|
<granskarblock.md bytetroget>
|
|
1854
|
+
|
|
1855
|
+
DESIGN (beslutad i brainstorming, internt underlag, följer aldrig med i analysens kundtext):
|
|
1856
|
+
<design.md bytetroget, eller raden "DESIGN: ingen">
|
|
1527
1857
|
```
|
|
1528
1858
|
|
|
1529
1859
|
`RUBRIKER:` is the analysis's own heading skeleton, the English literals from
|
|
@@ -1531,6 +1861,11 @@ continue as if the check had passed.
|
|
|
1531
1861
|
The skeleton is independent of `SPRÅK:`, which steers only the analysis's customer-facing
|
|
1532
1862
|
parts, not this internal structure.
|
|
1533
1863
|
|
|
1864
|
+
`DESIGN` is the item's design doc from the directory (`design.md`, written by
|
|
1865
|
+
`designa`), pasted, never pointed to by path: the hard rule "documents are pasted
|
|
1866
|
+
byte-faithfully" applies. Without a design (a split part of a parent analysed under
|
|
1867
|
+
the old rules, or a standalone assessor run) the block is the single line `DESIGN: ingen`.
|
|
1868
|
+
|
|
1534
1869
|
`request-scorer` (source material by path, ADR-0099: never pasted):
|
|
1535
1870
|
|
|
1536
1871
|
```
|