diff --git a/README.md b/README.md index 2aef32c..c10707e 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,6 @@ The build runs all three guards before it writes anything: check-rules: OK — 87 rules, 16 files scanned, 3 aliases + 41 constant sets checked, 275 formulas verified check-kits: OK — 25 roles, 10 trades, 218 catalogue items, every kit key resolves, every posting can use what it carries, every loadout distinct check-lang: OK — en.json, 926 keys, no leaf/branch collisions -check-behaviour: OK — 28 behavioural tests +check-behaviour: OK — 36 behavioural tests ``` diff --git a/docs/REVIEW_LOG.md b/docs/REVIEW_LOG.md index bfd2793..ed51e51 100644 --- a/docs/REVIEW_LOG.md +++ b/docs/REVIEW_LOG.md @@ -4941,3 +4941,73 @@ stable keys after import (raw ids do not survive one), the handouts come in player-visible and the GM text does not, and **phase one runs straight out of the box** — Nia leading the cordon on Tradecraft 53. Then everything imported was deleted again, which the pack does not notice. + +## PAPER WINDOW — played with the shipped pregens + +Ran the starter end to end with the six pregens exactly as they import. It closed, and +it found four defects in what I had shipped an hour earlier — all four in the scenario +data rather than the engine, and every one of them silent. + +**R-247. The Borrowed Authority did not work, and said nothing.** I wrote the +credential's scope as `"operate"`, which is not one of the five scope tiers. An +unrecognised scope ranks 0 — *nothing* — so `scopeStanceFor` returned "impossible" for +a routine site inspection by a surveyor at a demolition site. No error, no warning: the +credential was simply inert, and the first scene of the starter is the Borrowed +Authority tutorial. Fixed to `"routine"`, guarded in check-kits, and covered by a test +that asserts an unrecognised scope makes everything impossible so the failure mode is +documented rather than rediscovered. + +**R-248. The contact subsystem was unreachable — in the scenario built around it.** I +gave the case file a standing record for the Returned Clerks and no group *item*. +`resolveContact` looks up the group and returns null without one, so READ, SIGNAL and +OFFER did nothing at all. PAPER WINDOW's central scene is a three-stage negotiation with +those clerks. The group is now data in `scenario-starter.mjs`, consumed by the builder, +and a test asserts every standing on a shipped case file has a group behind it. + +**R-249. A phase kind written to the wrong field.** I wrote `kindId` on the legs; +`resolveLegDialog` reads `leg.kind` and falls back to a regular expression on the terrain +prose. It worked only because "Extraction — closing the register" happens to begin with +the word. Rename a phase and the return clock stops moving. + +**And one that was not a defect.** Phase four resolved as Difficult when the scenario +table says Average — because Resources had reached 0 and destitution makes every +remaining phase Difficult. That is the rule working, and it was the best beat in the +session: they ran out of supplies and the way home doubled in difficulty. + +### How it actually played + +The credential carried them in and then the stretch for an asbestos exclusion spent it +to **Trust 0** — two hours bought, and nothing left for later. Phases one, two, three and +four **all failed**, which the scenario is explicitly built to survive: Containment 8 → 2, +Resources 8 → 0, Clearance 6 → 5, and the case still closed. + +The investigation split cleanly across four players and three of the four discoveries +landed. Amira's READ turned up **both** taboos on one roll — Read the Room granting the +extra fact — and Elin **criticalled on 01** for the desire. SIGNAL and OFFER at +favourable took the clerks to **Standing 2**, which fired Evelyn's rewards automatically +and put the clean settlement on the table. + +The Cancellation Man opened with a **critical on 01** against Callum, whose riot shield +was raised and whose arm therefore had 10 points of armour. A critical ignores armour +entirely: 10 through, Major Wound, 15 → 5. That is the shield lesson and the graded +defence lesson in a single roll, in round one, without any prompting from me. + +Then the closing scene did the thing the scenario promises: **two of six requirements +succeeded and the settlement still completed.** Nia's authority failed and spent the +Clearance anyway; Callum's containment failed for a point; Elin certified them and is +now personally responsible for reviewing all 317 cases; Owen's repair worked and took +the last of the spare cells. Sennen's **special on 07** recovered the crown stamp with +the procedure intact, using the +20% Evelyn had given him at Standing 2 — a reward +granted by the contact engine, spent in the final scene. That chain is the whole design +working unassisted. + +### One thing the starter needs saying out loud + +**Nobody on this team can aim the return.** Transposition is trained by exactly one +posting in the register — the Anchor Officer — and none of the six has it, so all six +roll the printed 1%. The rule that failure gets an agent home *near* the target and +never strands them is what makes that survivable, but asking a GM to roll six dice that +are all going to fail teaches nothing. The extraction page now says so: narrate it, roll +only if somebody wants a clean arrival, and note at debrief that the department sent six +people to a crossing and no anchor. That is the campaign rather than an oversight — but +it is a deliberate choice a GM should be able to see, not a hole they fall into. diff --git a/packs/armour/000003.log b/packs/armour/000003.log new file mode 100644 index 0000000..9b6d27d Binary files /dev/null and b/packs/armour/000003.log differ diff --git a/packs/armour/000005.ldb b/packs/armour/000005.ldb deleted file mode 100644 index c982555..0000000 Binary files a/packs/armour/000005.ldb and /dev/null differ diff --git a/packs/armour/000006.log b/packs/armour/000006.log deleted file mode 100644 index 1a1bb27..0000000 Binary files a/packs/armour/000006.log and /dev/null differ diff --git a/packs/armour/CURRENT b/packs/armour/CURRENT index cacca75..1a84852 100644 --- a/packs/armour/CURRENT +++ b/packs/armour/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/armour/LOG b/packs/armour/LOG index ff37f12..9981dfc 100644 --- a/packs/armour/LOG +++ b/packs/armour/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.314417 1742cf000 Recovering log #3 -2026/08/11-23:23:08.314570 1742cf000 Level-0 table #5: started -2026/08/11-23:23:08.314789 1742cf000 Level-0 table #5: 4591 bytes OK -2026/08/11-23:23:08.315089 1742cf000 Delete type=0 #3 -2026/08/11-23:23:08.315117 1742cf000 Delete type=3 #2 +2026/08/11-23:39:03.882913 16f9c7000 Delete type=3 #1 diff --git a/packs/armour/LOG.old b/packs/armour/LOG.old deleted file mode 100644 index 507c1cb..0000000 --- a/packs/armour/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.827615 17117f000 Delete type=3 #1 diff --git a/packs/armour/MANIFEST-000002 b/packs/armour/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/armour/MANIFEST-000002 differ diff --git a/packs/armour/MANIFEST-000004 b/packs/armour/MANIFEST-000004 deleted file mode 100644 index 9c05997..0000000 Binary files a/packs/armour/MANIFEST-000004 and /dev/null differ diff --git a/packs/expedition/000003.log b/packs/expedition/000003.log new file mode 100644 index 0000000..263295b Binary files /dev/null and b/packs/expedition/000003.log differ diff --git a/packs/expedition/000005.ldb b/packs/expedition/000005.ldb deleted file mode 100644 index 4ff460d..0000000 Binary files a/packs/expedition/000005.ldb and /dev/null differ diff --git a/packs/expedition/000006.log b/packs/expedition/000006.log deleted file mode 100644 index 268b187..0000000 Binary files a/packs/expedition/000006.log and /dev/null differ diff --git a/packs/expedition/CURRENT b/packs/expedition/CURRENT index cacca75..1a84852 100644 --- a/packs/expedition/CURRENT +++ b/packs/expedition/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/expedition/LOG b/packs/expedition/LOG index c83cac5..a9b58c6 100644 --- a/packs/expedition/LOG +++ b/packs/expedition/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.332681 174adb000 Recovering log #3 -2026/08/11-23:23:08.332779 174adb000 Level-0 table #5: started -2026/08/11-23:23:08.332918 174adb000 Level-0 table #5: 4129 bytes OK -2026/08/11-23:23:08.333190 174adb000 Delete type=0 #3 -2026/08/11-23:23:08.333236 174adb000 Delete type=3 #2 +2026/08/11-23:39:03.926223 1701d3000 Delete type=3 #1 diff --git a/packs/expedition/LOG.old b/packs/expedition/LOG.old deleted file mode 100644 index a6bf6d4..0000000 --- a/packs/expedition/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.870148 17198b000 Delete type=3 #1 diff --git a/packs/expedition/MANIFEST-000002 b/packs/expedition/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/expedition/MANIFEST-000002 differ diff --git a/packs/expedition/MANIFEST-000004 b/packs/expedition/MANIFEST-000004 deleted file mode 100644 index 47fbcd4..0000000 Binary files a/packs/expedition/MANIFEST-000004 and /dev/null differ diff --git a/packs/gear/000003.log b/packs/gear/000003.log new file mode 100644 index 0000000..629ba6d Binary files /dev/null and b/packs/gear/000003.log differ diff --git a/packs/gear/000005.ldb b/packs/gear/000005.ldb deleted file mode 100644 index d9bac03..0000000 Binary files a/packs/gear/000005.ldb and /dev/null differ diff --git a/packs/gear/000006.log b/packs/gear/000006.log deleted file mode 100644 index d1deb9b..0000000 Binary files a/packs/gear/000006.log and /dev/null differ diff --git a/packs/gear/CURRENT b/packs/gear/CURRENT index cacca75..1a84852 100644 --- a/packs/gear/CURRENT +++ b/packs/gear/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/gear/LOG b/packs/gear/LOG index e3e88c3..967f2c9 100644 --- a/packs/gear/LOG +++ b/packs/gear/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.316151 174adb000 Recovering log #3 -2026/08/11-23:23:08.316320 174adb000 Level-0 table #5: started -2026/08/11-23:23:08.316628 174adb000 Level-0 table #5: 31614 bytes OK -2026/08/11-23:23:08.316965 174adb000 Delete type=0 #3 -2026/08/11-23:23:08.317018 174adb000 Delete type=3 #2 +2026/08/11-23:39:03.885484 16e9af000 Delete type=3 #1 diff --git a/packs/gear/LOG.old b/packs/gear/LOG.old deleted file mode 100644 index 61717b2..0000000 --- a/packs/gear/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.829491 170973000 Delete type=3 #1 diff --git a/packs/gear/MANIFEST-000002 b/packs/gear/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/gear/MANIFEST-000002 differ diff --git a/packs/gear/MANIFEST-000004 b/packs/gear/MANIFEST-000004 deleted file mode 100644 index f7cd73c..0000000 Binary files a/packs/gear/MANIFEST-000004 and /dev/null differ diff --git a/packs/npcs/000003.log b/packs/npcs/000003.log new file mode 100644 index 0000000..09b2bf6 Binary files /dev/null and b/packs/npcs/000003.log differ diff --git a/packs/npcs/000005.ldb b/packs/npcs/000005.ldb deleted file mode 100644 index 29f69de..0000000 Binary files a/packs/npcs/000005.ldb and /dev/null differ diff --git a/packs/npcs/000006.log b/packs/npcs/000006.log deleted file mode 100644 index ac2ef10..0000000 Binary files a/packs/npcs/000006.log and /dev/null differ diff --git a/packs/npcs/CURRENT b/packs/npcs/CURRENT index cacca75..1a84852 100644 --- a/packs/npcs/CURRENT +++ b/packs/npcs/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/npcs/LOG b/packs/npcs/LOG index aefc8a1..282cecf 100644 --- a/packs/npcs/LOG +++ b/packs/npcs/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.298312 174adb000 Recovering log #3 -2026/08/11-23:23:08.300367 174adb000 Level-0 table #5: started -2026/08/11-23:23:08.301985 174adb000 Level-0 table #5: 225945 bytes OK -2026/08/11-23:23:08.302352 174adb000 Delete type=0 #3 -2026/08/11-23:23:08.302416 174adb000 Delete type=3 #2 +2026/08/11-23:39:03.901710 16f9c7000 Delete type=3 #1 diff --git a/packs/npcs/LOG.old b/packs/npcs/LOG.old deleted file mode 100644 index 78abf31..0000000 --- a/packs/npcs/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.845061 17198b000 Delete type=3 #1 diff --git a/packs/npcs/MANIFEST-000002 b/packs/npcs/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/npcs/MANIFEST-000002 differ diff --git a/packs/npcs/MANIFEST-000004 b/packs/npcs/MANIFEST-000004 deleted file mode 100644 index 116e469..0000000 Binary files a/packs/npcs/MANIFEST-000004 and /dev/null differ diff --git a/packs/powers/000003.log b/packs/powers/000003.log new file mode 100644 index 0000000..d723043 Binary files /dev/null and b/packs/powers/000003.log differ diff --git a/packs/powers/000005.ldb b/packs/powers/000005.ldb deleted file mode 100644 index 7f540c6..0000000 Binary files a/packs/powers/000005.ldb and /dev/null differ diff --git a/packs/powers/000006.log b/packs/powers/000006.log deleted file mode 100644 index 43e306f..0000000 Binary files a/packs/powers/000006.log and /dev/null differ diff --git a/packs/powers/CURRENT b/packs/powers/CURRENT index cacca75..1a84852 100644 --- a/packs/powers/CURRENT +++ b/packs/powers/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/powers/LOG b/packs/powers/LOG index 0a51aaa..128de7a 100644 --- a/packs/powers/LOG +++ b/packs/powers/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.309911 1742cf000 Recovering log #3 -2026/08/11-23:23:08.310322 1742cf000 Level-0 table #5: started -2026/08/11-23:23:08.310473 1742cf000 Level-0 table #5: 3295 bytes OK -2026/08/11-23:23:08.310750 1742cf000 Delete type=0 #3 -2026/08/11-23:23:08.310794 1742cf000 Delete type=3 #2 +2026/08/11-23:39:03.919152 1701d3000 Delete type=3 #1 diff --git a/packs/powers/LOG.old b/packs/powers/LOG.old deleted file mode 100644 index 0099045..0000000 --- a/packs/powers/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.862697 17198b000 Delete type=3 #1 diff --git a/packs/powers/MANIFEST-000002 b/packs/powers/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/powers/MANIFEST-000002 differ diff --git a/packs/powers/MANIFEST-000004 b/packs/powers/MANIFEST-000004 deleted file mode 100644 index 20de082..0000000 Binary files a/packs/powers/MANIFEST-000004 and /dev/null differ diff --git a/packs/pregens/000003.log b/packs/pregens/000003.log new file mode 100644 index 0000000..712264f Binary files /dev/null and b/packs/pregens/000003.log differ diff --git a/packs/pregens/000005.ldb b/packs/pregens/000005.ldb deleted file mode 100644 index ef0a53e..0000000 Binary files a/packs/pregens/000005.ldb and /dev/null differ diff --git a/packs/pregens/000006.log b/packs/pregens/000006.log deleted file mode 100644 index ddbae86..0000000 Binary files a/packs/pregens/000006.log and /dev/null differ diff --git a/packs/pregens/CURRENT b/packs/pregens/CURRENT index cacca75..1a84852 100644 --- a/packs/pregens/CURRENT +++ b/packs/pregens/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/pregens/LOG b/packs/pregens/LOG index 83ac41a..e6ec8e9 100644 --- a/packs/pregens/LOG +++ b/packs/pregens/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.294604 174adb000 Recovering log #3 -2026/08/11-23:23:08.295663 174adb000 Level-0 table #5: started -2026/08/11-23:23:08.296163 174adb000 Level-0 table #5: 58792 bytes OK -2026/08/11-23:23:08.296520 174adb000 Delete type=0 #3 -2026/08/11-23:23:08.296610 174adb000 Delete type=3 #2 +2026/08/11-23:39:03.892036 16e9af000 Delete type=3 #1 diff --git a/packs/pregens/LOG.old b/packs/pregens/LOG.old deleted file mode 100644 index 46f8755..0000000 --- a/packs/pregens/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.835678 17198b000 Delete type=3 #1 diff --git a/packs/pregens/MANIFEST-000002 b/packs/pregens/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/pregens/MANIFEST-000002 differ diff --git a/packs/pregens/MANIFEST-000004 b/packs/pregens/MANIFEST-000004 deleted file mode 100644 index fb2adca..0000000 Binary files a/packs/pregens/MANIFEST-000004 and /dev/null differ diff --git a/packs/rules/000003.log b/packs/rules/000003.log new file mode 100644 index 0000000..7bc4ddf Binary files /dev/null and b/packs/rules/000003.log differ diff --git a/packs/rules/000005.ldb b/packs/rules/000005.ldb deleted file mode 100644 index aff8ef7..0000000 Binary files a/packs/rules/000005.ldb and /dev/null differ diff --git a/packs/rules/000006.log b/packs/rules/000006.log deleted file mode 100644 index f3c7033..0000000 Binary files a/packs/rules/000006.log and /dev/null differ diff --git a/packs/rules/CURRENT b/packs/rules/CURRENT index cacca75..1a84852 100644 --- a/packs/rules/CURRENT +++ b/packs/rules/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/rules/LOG b/packs/rules/LOG index f872108..b0d13de 100644 --- a/packs/rules/LOG +++ b/packs/rules/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.320015 175af3000 Recovering log #3 -2026/08/11-23:23:08.320173 175af3000 Level-0 table #5: started -2026/08/11-23:23:08.320528 175af3000 Level-0 table #5: 33474 bytes OK -2026/08/11-23:23:08.320923 175af3000 Delete type=0 #3 -2026/08/11-23:23:08.320978 175af3000 Delete type=3 #2 +2026/08/11-23:39:03.924025 1701d3000 Delete type=3 #1 diff --git a/packs/rules/LOG.old b/packs/rules/LOG.old deleted file mode 100644 index 06c8aac..0000000 --- a/packs/rules/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.868156 17117f000 Delete type=3 #1 diff --git a/packs/rules/MANIFEST-000002 b/packs/rules/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/rules/MANIFEST-000002 differ diff --git a/packs/rules/MANIFEST-000004 b/packs/rules/MANIFEST-000004 deleted file mode 100644 index a877353..0000000 Binary files a/packs/rules/MANIFEST-000004 and /dev/null differ diff --git a/packs/skills/000003.log b/packs/skills/000003.log new file mode 100644 index 0000000..2a55440 Binary files /dev/null and b/packs/skills/000003.log differ diff --git a/packs/skills/000005.ldb b/packs/skills/000005.ldb deleted file mode 100644 index eb948ea..0000000 Binary files a/packs/skills/000005.ldb and /dev/null differ diff --git a/packs/skills/000006.log b/packs/skills/000006.log deleted file mode 100644 index 1989ee1..0000000 Binary files a/packs/skills/000006.log and /dev/null differ diff --git a/packs/skills/CURRENT b/packs/skills/CURRENT index cacca75..1a84852 100644 --- a/packs/skills/CURRENT +++ b/packs/skills/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/skills/LOG b/packs/skills/LOG index 7f8b75b..486de35 100644 --- a/packs/skills/LOG +++ b/packs/skills/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.305494 1742cf000 Recovering log #3 -2026/08/11-23:23:08.305911 1742cf000 Level-0 table #5: started -2026/08/11-23:23:08.306128 1742cf000 Level-0 table #5: 7590 bytes OK -2026/08/11-23:23:08.306405 1742cf000 Delete type=0 #3 -2026/08/11-23:23:08.306467 1742cf000 Delete type=3 #2 +2026/08/11-23:39:03.875989 16f9c7000 Delete type=3 #1 diff --git a/packs/skills/LOG.old b/packs/skills/LOG.old deleted file mode 100644 index 1d811f3..0000000 --- a/packs/skills/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.820649 172197000 Delete type=3 #1 diff --git a/packs/skills/MANIFEST-000002 b/packs/skills/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/skills/MANIFEST-000002 differ diff --git a/packs/skills/MANIFEST-000004 b/packs/skills/MANIFEST-000004 deleted file mode 100644 index 90efb97..0000000 Binary files a/packs/skills/MANIFEST-000004 and /dev/null differ diff --git a/packs/slice/000003.log b/packs/slice/000003.log new file mode 100644 index 0000000..4a86fe9 Binary files /dev/null and b/packs/slice/000003.log differ diff --git a/packs/slice/000005.ldb b/packs/slice/000005.ldb deleted file mode 100644 index 4851c77..0000000 Binary files a/packs/slice/000005.ldb and /dev/null differ diff --git a/packs/slice/000006.log b/packs/slice/000006.log deleted file mode 100644 index c7d9b16..0000000 Binary files a/packs/slice/000006.log and /dev/null differ diff --git a/packs/slice/CURRENT b/packs/slice/CURRENT index cacca75..1a84852 100644 --- a/packs/slice/CURRENT +++ b/packs/slice/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/slice/LOG b/packs/slice/LOG index fc3115d..20c5c57 100644 --- a/packs/slice/LOG +++ b/packs/slice/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.328983 1752e7000 Recovering log #3 -2026/08/11-23:23:08.329262 1752e7000 Level-0 table #5: started -2026/08/11-23:23:08.329521 1752e7000 Level-0 table #5: 16892 bytes OK -2026/08/11-23:23:08.329805 1752e7000 Delete type=0 #3 -2026/08/11-23:23:08.329838 1752e7000 Delete type=3 #2 +2026/08/11-23:39:03.917638 16f9c7000 Delete type=3 #1 diff --git a/packs/slice/LOG.old b/packs/slice/LOG.old deleted file mode 100644 index 82360c8..0000000 --- a/packs/slice/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.860796 17117f000 Delete type=3 #1 diff --git a/packs/slice/MANIFEST-000002 b/packs/slice/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/slice/MANIFEST-000002 differ diff --git a/packs/slice/MANIFEST-000004 b/packs/slice/MANIFEST-000004 deleted file mode 100644 index 0552c3a..0000000 Binary files a/packs/slice/MANIFEST-000004 and /dev/null differ diff --git a/packs/starter/000003.log b/packs/starter/000003.log new file mode 100644 index 0000000..380686c Binary files /dev/null and b/packs/starter/000003.log differ diff --git a/packs/starter/000005.ldb b/packs/starter/000005.ldb deleted file mode 100644 index f7db5b4..0000000 Binary files a/packs/starter/000005.ldb and /dev/null differ diff --git a/packs/starter/000006.log b/packs/starter/000006.log deleted file mode 100644 index 68669cb..0000000 Binary files a/packs/starter/000006.log and /dev/null differ diff --git a/packs/starter/CURRENT b/packs/starter/CURRENT index cacca75..1a84852 100644 --- a/packs/starter/CURRENT +++ b/packs/starter/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/starter/LOG b/packs/starter/LOG index d947226..8de9093 100644 --- a/packs/starter/LOG +++ b/packs/starter/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.324024 1752e7000 Recovering log #3 -2026/08/11-23:23:08.325074 1752e7000 Level-0 table #5: started -2026/08/11-23:23:08.325775 1752e7000 Level-0 table #5: 89206 bytes OK -2026/08/11-23:23:08.326188 1752e7000 Delete type=0 #3 -2026/08/11-23:23:08.326248 1752e7000 Delete type=3 #2 +2026/08/11-23:39:03.913120 16f9c7000 Delete type=3 #1 diff --git a/packs/starter/LOG.old b/packs/starter/LOG.old deleted file mode 100644 index 48f3c56..0000000 --- a/packs/starter/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.856844 17117f000 Delete type=3 #1 diff --git a/packs/starter/MANIFEST-000002 b/packs/starter/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/starter/MANIFEST-000002 differ diff --git a/packs/starter/MANIFEST-000004 b/packs/starter/MANIFEST-000004 deleted file mode 100644 index 78b3fb2..0000000 Binary files a/packs/starter/MANIFEST-000004 and /dev/null differ diff --git a/packs/tables/000003.log b/packs/tables/000003.log new file mode 100644 index 0000000..f125b7d Binary files /dev/null and b/packs/tables/000003.log differ diff --git a/packs/tables/000005.ldb b/packs/tables/000005.ldb deleted file mode 100644 index 64baa1c..0000000 Binary files a/packs/tables/000005.ldb and /dev/null differ diff --git a/packs/tables/000006.log b/packs/tables/000006.log deleted file mode 100644 index d5e06f3..0000000 Binary files a/packs/tables/000006.log and /dev/null differ diff --git a/packs/tables/CURRENT b/packs/tables/CURRENT index cacca75..1a84852 100644 --- a/packs/tables/CURRENT +++ b/packs/tables/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/tables/LOG b/packs/tables/LOG index d53aad9..22b41a9 100644 --- a/packs/tables/LOG +++ b/packs/tables/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.330955 1742cf000 Recovering log #3 -2026/08/11-23:23:08.331078 1742cf000 Level-0 table #5: started -2026/08/11-23:23:08.331226 1742cf000 Level-0 table #5: 3739 bytes OK -2026/08/11-23:23:08.331550 1742cf000 Delete type=0 #3 -2026/08/11-23:23:08.331583 1742cf000 Delete type=3 #2 +2026/08/11-23:39:03.906240 1701d3000 Delete type=3 #1 diff --git a/packs/tables/LOG.old b/packs/tables/LOG.old deleted file mode 100644 index 2c994fb..0000000 --- a/packs/tables/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.849798 17117f000 Delete type=3 #1 diff --git a/packs/tables/MANIFEST-000002 b/packs/tables/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/tables/MANIFEST-000002 differ diff --git a/packs/tables/MANIFEST-000004 b/packs/tables/MANIFEST-000004 deleted file mode 100644 index 004ff30..0000000 Binary files a/packs/tables/MANIFEST-000004 and /dev/null differ diff --git a/packs/talents/000003.log b/packs/talents/000003.log new file mode 100644 index 0000000..443b7ea Binary files /dev/null and b/packs/talents/000003.log differ diff --git a/packs/talents/000005.ldb b/packs/talents/000005.ldb deleted file mode 100644 index fb653de..0000000 Binary files a/packs/talents/000005.ldb and /dev/null differ diff --git a/packs/talents/000006.log b/packs/talents/000006.log deleted file mode 100644 index 29003f7..0000000 Binary files a/packs/talents/000006.log and /dev/null differ diff --git a/packs/talents/CURRENT b/packs/talents/CURRENT index cacca75..1a84852 100644 --- a/packs/talents/CURRENT +++ b/packs/talents/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/talents/LOG b/packs/talents/LOG index 80e25cf..5d1a776 100644 --- a/packs/talents/LOG +++ b/packs/talents/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.307829 174adb000 Recovering log #3 -2026/08/11-23:23:08.308163 174adb000 Level-0 table #5: started -2026/08/11-23:23:08.308314 174adb000 Level-0 table #5: 5770 bytes OK -2026/08/11-23:23:08.308647 174adb000 Delete type=0 #3 -2026/08/11-23:23:08.308699 174adb000 Delete type=3 #2 +2026/08/11-23:39:03.879030 16f1bb000 Delete type=3 #1 diff --git a/packs/talents/LOG.old b/packs/talents/LOG.old deleted file mode 100644 index 54aea62..0000000 --- a/packs/talents/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.823417 172197000 Delete type=3 #1 diff --git a/packs/talents/MANIFEST-000002 b/packs/talents/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/talents/MANIFEST-000002 differ diff --git a/packs/talents/MANIFEST-000004 b/packs/talents/MANIFEST-000004 deleted file mode 100644 index f8c6b47..0000000 Binary files a/packs/talents/MANIFEST-000004 and /dev/null differ diff --git a/packs/vehicles/000003.log b/packs/vehicles/000003.log new file mode 100644 index 0000000..9950ce5 Binary files /dev/null and b/packs/vehicles/000003.log differ diff --git a/packs/vehicles/000005.ldb b/packs/vehicles/000005.ldb deleted file mode 100644 index f6b2cd4..0000000 Binary files a/packs/vehicles/000005.ldb and /dev/null differ diff --git a/packs/vehicles/000006.log b/packs/vehicles/000006.log deleted file mode 100644 index 47800e2..0000000 Binary files a/packs/vehicles/000006.log and /dev/null differ diff --git a/packs/vehicles/CURRENT b/packs/vehicles/CURRENT index cacca75..1a84852 100644 --- a/packs/vehicles/CURRENT +++ b/packs/vehicles/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/vehicles/LOG b/packs/vehicles/LOG index 58fcb45..f261c92 100644 --- a/packs/vehicles/LOG +++ b/packs/vehicles/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.318258 1752e7000 Recovering log #3 -2026/08/11-23:23:08.318423 1752e7000 Level-0 table #5: started -2026/08/11-23:23:08.318619 1752e7000 Level-0 table #5: 6939 bytes OK -2026/08/11-23:23:08.318944 1752e7000 Delete type=0 #3 -2026/08/11-23:23:08.319006 1752e7000 Delete type=3 #2 +2026/08/11-23:39:03.887719 16e9af000 Delete type=3 #1 diff --git a/packs/vehicles/LOG.old b/packs/vehicles/LOG.old deleted file mode 100644 index 6ec0926..0000000 --- a/packs/vehicles/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.831389 170973000 Delete type=3 #1 diff --git a/packs/vehicles/MANIFEST-000002 b/packs/vehicles/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/vehicles/MANIFEST-000002 differ diff --git a/packs/vehicles/MANIFEST-000004 b/packs/vehicles/MANIFEST-000004 deleted file mode 100644 index d4d73b7..0000000 Binary files a/packs/vehicles/MANIFEST-000004 and /dev/null differ diff --git a/packs/weapons/000003.log b/packs/weapons/000003.log new file mode 100644 index 0000000..e1488ed Binary files /dev/null and b/packs/weapons/000003.log differ diff --git a/packs/weapons/000005.ldb b/packs/weapons/000005.ldb deleted file mode 100644 index 742beba..0000000 Binary files a/packs/weapons/000005.ldb and /dev/null differ diff --git a/packs/weapons/000006.log b/packs/weapons/000006.log deleted file mode 100644 index 4d427a6..0000000 Binary files a/packs/weapons/000006.log and /dev/null differ diff --git a/packs/weapons/CURRENT b/packs/weapons/CURRENT index cacca75..1a84852 100644 --- a/packs/weapons/CURRENT +++ b/packs/weapons/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000002 diff --git a/packs/weapons/LOG b/packs/weapons/LOG index f4adbf3..8e81423 100644 --- a/packs/weapons/LOG +++ b/packs/weapons/LOG @@ -1,5 +1 @@ -2026/08/11-23:23:08.311931 174adb000 Recovering log #3 -2026/08/11-23:23:08.312527 174adb000 Level-0 table #5: started -2026/08/11-23:23:08.312793 174adb000 Level-0 table #5: 14767 bytes OK -2026/08/11-23:23:08.313217 174adb000 Delete type=0 #3 -2026/08/11-23:23:08.313275 174adb000 Delete type=3 #2 +2026/08/11-23:39:03.880963 16e9af000 Delete type=3 #1 diff --git a/packs/weapons/LOG.old b/packs/weapons/LOG.old deleted file mode 100644 index b9e9eaa..0000000 --- a/packs/weapons/LOG.old +++ /dev/null @@ -1 +0,0 @@ -2026/08/11-23:22:30.825501 172197000 Delete type=3 #1 diff --git a/packs/weapons/MANIFEST-000002 b/packs/weapons/MANIFEST-000002 new file mode 100644 index 0000000..bbbc585 Binary files /dev/null and b/packs/weapons/MANIFEST-000002 differ diff --git a/packs/weapons/MANIFEST-000004 b/packs/weapons/MANIFEST-000004 deleted file mode 100644 index 6a582af..0000000 Binary files a/packs/weapons/MANIFEST-000004 and /dev/null differ diff --git a/tools/build-packs.mjs b/tools/build-packs.mjs index 6565b1f..25649ff 100644 --- a/tools/build-packs.mjs +++ b/tools/build-packs.mjs @@ -555,6 +555,23 @@ await writePack("armour", ARMOURS.map(a => { // The case file, already at the scenario's opening state. const C = S.STARTER_CASE; const caseId = idFor(`actor:${C.key}`); + // Group ITEMS from the scenario data. resolveContact looks these up and returns null + // without one, so a standing with no group silently switches off READ/SIGNAL/OFFER. + const groupDocs = S.STARTER_GROUPS.map(g => ({ + _id: idFor(`owned:${C.key}:group_${g.groupId}`), + name: g.name, type: "group", img: ICON.actor, + system: { + description: g.description, + groupId: g.groupId, speciesId: "baseline", population: g.population, + npcTemplateId: g.npcTemplateId, + taboos: g.taboos, desires: g.desires, + correctOfferForm: g.correctOfferForm, + rewardsByStanding: g.rewardsByStanding, + standing: 0, impression: 0 + }, + effects: [], ...BASE() + })); + const caseDoc = { _id: caseId, name: C.name, type: "expedition", img: ICON.caseFile ?? ICON.actor, system: { @@ -568,18 +585,21 @@ await writePack("armour", ARMOURS.map(a => { destinationKnowledge: "briefed", currentLeg: 0, elapsedDays: 0, siteTableId: "sites", hazardTableId: "hazards", returnClock: 0, legs: C.legs.map((l, i) => ({ - index: i, terrain: l.label, mode: "foot", kindId: l.kindId, + // `kind`, not `kindId` — resolveLegDialog reads leg.kind and falls back to a + // regex on the terrain text. Writing the wrong field worked only because + // "Extraction — closing the register" happens to start with the word. + index: i, terrain: l.label, mode: "foot", kind: l.kindId, difficulty: l.difficulty, modifier: l.mod, days: 0, explored: true, resolved: false, forcedEncounterId: "", costSupply: 1, costPower: 0 })) }, - standings: [{ groupId: "returned_clerks", value: 0, impression: 0, encounters: 0, - knownTaboos: [], knownDesires: [], pidginEstablished: false, obligations: [] }], + standings: C.standings.map(id => ({ groupId: id, value: 0, impression: 0, encounters: 0, + knownTaboos: [], knownDesires: [], pidginEstablished: false, obligations: [] })), across: false, crossingModifier: 0, salvageEra: "modern", notes: C.notes }, - items: [], effects: [], + items: groupDocs, effects: [], prototypeToken: { name: C.name, displayName: 20, actorLink: true, width: 1, height: 1, texture: { src: ICON.actor }, sight: { enabled: false }, disposition: 1, bar1: { attribute: "integrity" }, bar2: { attribute: "supply" }, flags: {} }, diff --git a/tools/check-behaviour.mjs b/tools/check-behaviour.mjs index 96a0ed4..d1eff2f 100644 --- a/tools/check-behaviour.mjs +++ b/tools/check-behaviour.mjs @@ -27,12 +27,19 @@ import { strict as assert } from "node:assert"; import * as RULES from "../rules.mjs"; import { ROLES, TRADES, INDUCTION, TIERS, TRADE_BANDS, CHARACTERISTIC_DICE } from "../postings.mjs"; +import { STARTER_AUTHORITY, STARTER_GROUPS, STARTER_CASE } from "./scenario-starter.mjs"; let passed = 0, failed = 0; +// Async tests are awaited in order rather than fired off — a failure that lands after +// the summary has printed is a failure nobody sees. +const pending = []; const test = (name, fn) => { - try { fn(); passed++; } - catch (e) { failed++; console.error(` FAIL ${name}\n ${e.message}`); } + pending.push(async () => { + try { await fn(); passed++; } + catch (e) { failed++; console.error(` FAIL ${name}\n ${e.message}`); } + }); }; +const runAll = async () => { for (const t of pending) await t(); }; /* ---------------------------------------------------------------- * * Contact — R-246: a fumbled greeting used to cost nothing @@ -174,8 +181,66 @@ test("a success against a critical still lands, one step down", () => { test("a critical against a critical turns it aside", () => assert.equal(RULES.defenceOutcomeFor("critical", "critical").turnedAside, true)); +/* ---------------------------------------------------------------- * + * Borrowed Authority — a bad scope fails silently, which is the worst way + * ---------------------------------------------------------------- */ + +test("an in-scope action is in scope", () => + assert.equal(RULES.scopeStanceFor("routine", "routine"), "in-scope")); +test("one tier beyond is a stretch", () => + assert.equal(RULES.scopeStanceFor("routine", "privileged"), "stretch")); +test("two tiers beyond is impossible at any skill", () => + assert.equal(RULES.scopeStanceFor("routine", "administrative"), "impossible")); +// An unrecognised scope ranks 0, so EVERYTHING becomes impossible and nothing says so. +test("an unrecognised scope makes everything impossible", () => + assert.equal(RULES.scopeStanceFor("operate", "routine"), "impossible")); +test("the starter's credential names a real scope tier", async () => { + assert.ok(RULES.SCOPE_TIERS.includes(STARTER_AUTHORITY.scope), + `scope "${STARTER_AUTHORITY.scope}" is not a tier`); +}); + +/* ---------------------------------------------------------------- * + * Shipped case files — a standing with no group is an unreachable subsystem + * ---------------------------------------------------------------- */ + +// resolveContact looks up a GROUP ITEM and returns null without one, so a case file +// carrying a standing with no matching group has READ, SIGNAL and OFFER silently +// switched off. That is how PAPER WINDOW first shipped, with the contact scene as its +// centrepiece and no error anywhere. Asserted against the scenario DATA rather than the +// built pack, because the pack is a LevelDB that Foundry holds open while it runs — and +// a test that cannot read its subject must fail loudly, not skip quietly. +test("every standing on the starter case file has a group behind it", () => { + const groups = new Set(STARTER_GROUPS.map(g => g.groupId)); + for (const id of STARTER_CASE.standings ?? []) { + assert.ok(groups.has(id), + `case file has a standing for "${id}" with no group — READ/SIGNAL/OFFER cannot run`); + } +}); +// resolveLegDialog reads `leg.kind`. A case file that writes `kindId` falls through to +// a regex on the terrain prose, which works right up until somebody renames a phase. +test("starter phases name a kind the engine will read", () => { + const kinds = ["approach", "cordon", "containment", "extraction"]; + for (const l of STARTER_CASE.legs) { + assert.ok(kinds.includes(l.kindId), `phase "${l.label}" has kind "${l.kindId}"`); + } + assert.equal(STARTER_CASE.legs.at(-1).kindId, "extraction", + "the last phase must be the extraction, or the return clock never moves"); +}); +test("every starter group is usable by the contact engine", () => { + for (const g of STARTER_GROUPS) { + assert.ok(g.groupId && g.name, "a group needs an id and a name"); + assert.ok(g.desires?.length, `${g.groupId}: a group with no desire cannot be offered anything`); + assert.ok(g.correctOfferForm, `${g.groupId}: no correct offer form`); + for (const t of g.taboos ?? []) { + assert.ok(t.id && t.text, `${g.groupId}: a taboo needs an id and text`); + } + } +}); + /* ---------------------------------------------------------------- */ +await runAll(); + if (failed) { console.error(`check-behaviour: ${failed} failure(s), ${passed} passed`); process.exit(1); diff --git a/tools/check-kits.mjs b/tools/check-kits.mjs index 44c95ba..0b52348 100644 --- a/tools/check-kits.mjs +++ b/tools/check-kits.mjs @@ -9,7 +9,7 @@ * node tools/check-kits.mjs */ import { SKILL_CATALOGUE, TALENTS, GEAR, WEAPONS, ARMOURS, DEVICES } from "./content.mjs"; -import { SHIELD } from "../rules.mjs"; +import { SHIELD, SCOPE_TIERS } from "../rules.mjs"; // Imported, not regexed out of the engine source. See postings.mjs. import { ROLES, TRADES, INDUCTION, CHARACTERISTIC_DICE } from "../postings.mjs"; @@ -64,6 +64,19 @@ for (const [id, r] of Object.entries({ ...ROLES, ...TRADES })) { kitSets.set(sig, id); } +// A Borrowed Authority whose scope is not a real tier reads as rank 0 — "nothing" — +// and every single action through it comes back "impossible" with no error anywhere. +// The starter scenario shipped with scope "operate", which is not a tier, and the only +// symptom was a credential that silently did not work. +{ + const S = await import("./scenario-starter.mjs").catch(() => null); + const auth = S?.STARTER_AUTHORITY; + if (auth && !SCOPE_TIERS.includes(auth.scope)) { + problems.push(`starter authority "${auth.name}": scope "${auth.scope}" is not a ` + + `scope tier (have: ${SCOPE_TIERS.join(", ")})`); + } +} + // INDUCTION is handed to every trade character, so its keys are checked once here // rather than ten times above. for (const k of INDUCTION.skills) { diff --git a/tools/scenario-starter.mjs b/tools/scenario-starter.mjs index 7511e91..693492c 100644 --- a/tools/scenario-starter.mjs +++ b/tools/scenario-starter.mjs @@ -351,12 +351,21 @@ export const STARTER_PAGES = [ }, { name: "10 · Extraction and debrief", content: - P("Use the normal return procedure and Transposition rolls in every ending. A clean " - + "settlement leaves the window clock at zero and adds no case-specific penalty.") - + UL(["Another agent may aim the return for someone else.", + P("Use the normal return procedure in every ending. A clean settlement leaves the " + + "window clock at zero and adds no case-specific penalty.") + + UL(["Another agent may aim the return for someone else — the team's best Transposition.", "Failure gets an agent home near the target; it never strands them.", "A fumble costs Coherence and may grant a Quiet Art.", "PAPER WINDOW is Near: no classification penalty."]) + + P("This team has no Anchor Officer, and that is deliberate. " + + "Transposition is trained by exactly one posting in the register, and none of " + + "these six has it: every one of them aims the return at the printed 1%. " + + "Do not roll six dice to discover that. Narrate it: they all get home, " + + "and none of them gets home neatly — wrong street, wrong hour, one of them in the " + + "wrong coat. Roll only if an agent has a reason to want a clean arrival, or if the " + + "window clock has moved and you want the fumble on the table.") + + P("It is worth saying out loud at the debrief that the department sent six people to " + + "a crossing and no anchor. That is the campaign, not an oversight.") + P("When everyone is home, close the case and resolve experience.") + H(2, "Debrief — ask each player one") + OL(["Field Lead: at what moment did this stop being the case in your orders?", @@ -660,7 +669,7 @@ export const STARTER_AUTHORITY = { holderName: "Imogen Price", holderRole: "Senior Asbestos Surveyor", issuer: "Halcyon Environmental Compliance Ltd", - scope: "operate", + scope: "routine", scopeNote: "Routine site inspection at a controlled demolition site.", trust: 2, redFlags: [ @@ -676,6 +685,54 @@ export const STARTER_AUTHORITY = { + "
A fumble burns it: the real Imogen Price telephones the site manager.
" }; +/** + * The groups the team can talk to, as DATA rather than as something the pack builder + * invents. `resolveContact` looks up a group ITEM on the case file and returns null + * without one — a standing record alone leaves READ, SIGNAL and OFFER silently switched + * off, which is how this scenario first shipped, with the contact scene as its + * centrepiece. The pairing is asserted in check-behaviour against this file. + */ +export const STARTER_GROUPS = [{ + groupId: "returned_clerks", + name: "The Returned Clerks", + population: 6, + npcTemplateId: "pw_evelyn", + description: + "Six clerks in 1987 uniforms under green lamps, none of them aged. They have been " + + "on the same shift for thirty-nine years, and they are not invaders — they are " + + "waiting to be relieved.
", + taboos: [ + { id: "sealed_mail", + text: "Never open, read aloud or name the addressee of mail that is not yours. A sealed identity belongs to its recipient.", + penaltyIfViolated: -30 }, + { id: "the_counter", + text: "The public side of the counter is the public side. Speaking from behind it is not rudeness — it is not speaking at all.", + penaltyIfViolated: -20 } + ], + desires: [ + { id: "relief", + text: "To be relieved. A recognised authority to receipt the disputed folio so the shift can close.", + offerBonusStep: "easy" } + ], + correctOfferForm: + "A signed receipt taking the disputed folio into recognised custody, passed through " + + "Window Six from the public side of the counter, quoting case R-143.", + rewardsByStanding: { + "1": [{ id: "pw1_explain", + text: "Evelyn explains that the register needs custody and certification, and what that means.", + effect: { type: "reveal", note: "The folio needs a custodian, a medical certification that the duplicates are living persons, and a current date stamp." } }], + "2": [{ id: "pw2_folio", + text: "Evelyn explains the clean closure and will release the folio once the six requirements are met.", + effect: { type: "reveal", note: "R-143-A: a pending inter-jurisdictional register. Six signatures, one per agent." } }, + { id: "pw2_stamp", + text: "She says which drawer holds the crown master stamp, and that it opens from the public side.", + effect: { type: "skillBonus", skillFamilyId: "sleight_of_hand", value: 20, phases: [3] } }], + "3": [{ id: "pw3_help", + text: "The night shift helps. Two clerks hold the folio steady while the engineer works.", + effect: { type: "waiveCost", phase: 3 } }] + } +}]; + /** The case file, already set to the scenario's opening state. */ export const STARTER_CASE = { key: "pw_case", @@ -687,6 +744,7 @@ export const STARTER_CASE = { + "minutes of argument without action, a loud weapon fired in the mundane building, the " + "credential burned, or the clerks' taboo violated after it has been learned." + "Not for careful investigation. Never for careful investigation.
", + standings: ["returned_clerks"], legs: [ { label: "Approach — the demolition cordon", kindId: "approach", difficulty: "average", mod: 0 }, { label: "Investigation — the dead-letter cage", kindId: "cordon", difficulty: "average", mod: -5 },