Apply ground-game's rulings: mastery in points, four boards, and a
Some checks failed
ci / check (push) Failing after 4s

vendor tool that covers what the gate checks

They ruled on all seven items the same day. Two were actionable here.

F28 RULED: points. Modes.csv MODE_COOP clarified upstream to say
"penalties apply to points, not card count"; mastery is now
total - blame - denied. A recorded scenario went red on it --
gr-e02-shared-ground pinned 0 (2 claimed CARDS - 1 - 1) and now expects
2 (4 POINTS - 1 - 1). The number moved because the rule was decided, not
because the engine drifted, and the scenario records both rulings; its
schema has no field for a second one, so both live in ruled_note with
`ruled` carrying the LATEST date.

F29 RULED not-intended and APPLIED upstream: SCN_02's suits re-tuned the
same day. The characterisation test is how we found out -- it pinned the
duplication, went red on the re-tune, and that red WAS the notification.
It now asserts every pair distinct, the stronger statement the
duplication had made unavailable. SCN_02 re-measures at 73 at 2p, not
67: its own board now.

F26/F30 ruled and recorded. F30's ruling incidentally confirms our
reading -- they name priority-2's suit as the first lever, which is the
difference we identified without having measured causation.

vendor-editions grew twice, both times because it covered less than the
gate it exists to satisfy:

  - It refused to touch ground-darvo-r0/ on the reasoning that the
    baseline is "a separate record". That was wrong within the hour:
    ground-game clarified Modes.csv and `make vendor` reported a clean
    sync while edition-check went red. A sync tool that covers less than
    its check reports success into a red gate.
  - Its two-block rewrite DETECTED which fence held which set and
    preserved the arrangement -- faithfully preserving a swap an earlier
    write had introduced, leaving each fence under a heading describing
    the other. edition-check reads every sha256 line flat and passed
    throughout: a document can be self-consistently wrong and green.
    Order is now asserted, with a control that goes red on a swap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-09 00:15:14 +02:00
parent 98f600b1d3
commit 704b99975b
15 changed files with 373 additions and 154 deletions

View file

@ -55,8 +55,8 @@
| workplan | CB-WP-0045 | done | — | workplans/CB-WP-0045-the-table-names-what-it-shows.md |
| workplan | CB-WP-0046 | done | — | workplans/CB-WP-0046-the-rule-the-placement-encodes.md |
| workplan | CB-WP-0047 | done | — | workplans/CB-WP-0047-all-four-boards-and-all-three-modes.md |
| workplan | CB-WP-0048 | in_progress | — | workplans/CB-WP-0048-a-configuration-not-a-variant.md |
| workplan | CB-WP-0049 | in_progress | — | workplans/CB-WP-0049-a-seat-that-plays-its-own-objective.md |
| workplan | CB-WP-0048 | active | — | workplans/CB-WP-0048-a-configuration-not-a-variant.md |
| workplan | CB-WP-0049 | active | — | workplans/CB-WP-0049-a-seat-that-plays-its-own-objective.md |
| task | CB-WP-0001-T01 | done | — | workplans/CB-WP-0001-inner-loop.md |
| task | CB-WP-0001-T02 | done | — | workplans/CB-WP-0001-inner-loop.md |
| task | CB-WP-0001-T03 | done | — | workplans/CB-WP-0001-inner-loop.md |

View file

@ -93,6 +93,11 @@ profile: scoped_plus_attack_soothe
- Each module: apply `rules_delta` + optional `data_overlays` from its `path`.
- Apply modules in **aspect order** listed in `catalog.yaml` `aspects:` (stable, documented).
- Conflict: refuse composition rather than last-write-wins.
- **`consumed_files` (RPT-0006):** when present on a module, a consumer that
has not read those paths is in a **detectable** incomplete state — not
silence. Freshness/edition-check should fail or warn if a listed file is
unread or undigested. Modules without the field still work; new modules
should list it.
---

View file

@ -4,6 +4,7 @@
schema_version: 2
# terminology: aspect (human) = former axis; modules remain module_id
# packages declare files consumers must read (consumed_files / data_overlays)
updated: "2026-08-08"
default_baseline: ground-darvo-r0
default_profile: baseline
@ -97,6 +98,12 @@ modules:
status: measured
rules_delta: editions/modules/problem_stress/scoped/rules_delta.yaml
data_overlays: [Problems.csv, Rules_Text.csv]
# files a consumer must open to implement this module (RPT-0006 §5b)
consumed_files:
- editions/modules/problem_stress/scoped/rules_delta.yaml
- editions/modules/problem_stress/scoped/Problems.csv
- editions/modules/problem_stress/scoped/Rules_Text.csv
- editions/modules/problem_stress/scoped/MODULE.md
legacy_experiment_ids: [h2-scoped-problem-stress]
measurement_ref: reports/260808-clay-borg-h2-measured.md
hypothesis_ref: history/260808-h2-scoped-problem-stress.md

View file

@ -5,10 +5,10 @@ PRB_01_2,SCN_01,Hidden,personal,2,Unspoken Overload,The work required more capac
PRB_01_3,SCN_01,Hidden,bond,3,Bad News Was Delayed,A warning was withheld until the remaining options became worse.,Repair,SYM_REPAIR,3,Resolve with Repair. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=bond (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_01_4,SCN_01,Hidden,personal,4,No Checkpoint Process,The group had no reliable moment for testing progress and changing course.,Change,SYM_CHANGE,3,Resolve with Change. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_S,SCN_02,Surface,global,0,Shared Task Left Undone,"A recurring responsibility was not completed, and others absorbed the impact.",Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=global (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM_SURFACE
PRB_02_1,SCN_02,Hidden,personal,1,Different Standards,"Players were using different definitions of complete, timely, or fair.",Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_2,SCN_02,Hidden,personal,2,Invisible Workload,Some contributions and constraints were not visible to the group.,Boundary,SYM_BOUNDARY,2,Resolve with Boundary. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_3,SCN_02,Hidden,bond,3,Resentment Never Raised,Frustration accumulated without a direct request or acknowledgement.,Repair,SYM_REPAIR,3,Resolve with Repair. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=bond (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_4,SCN_02,Hidden,personal,4,No Ownership Routine,The group relied on goodwill instead of a dependable allocation method.,Change,SYM_CHANGE,3,Resolve with Change. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_1,SCN_02,Hidden,personal,1,Different Standards,"Players were using different definitions of complete, timely, or fair.",Change,SYM_CHANGE,2,Resolve with Change. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_2,SCN_02,Hidden,personal,2,Invisible Workload,Some contributions and constraints were not visible to the group.,Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_3,SCN_02,Hidden,bond,3,Resentment Never Raised,Frustration accumulated without a direct request or acknowledgement.,Boundary,SYM_BOUNDARY,3,Resolve with Boundary. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=bond (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_4,SCN_02,Hidden,personal,4,No Ownership Routine,The group relied on goodwill instead of a dependable allocation method.,Repair,SYM_REPAIR,3,Resolve with Repair. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_03_S,SCN_03,Surface,global,0,Decision Announced as Settled,A group-affecting choice was presented as final before meaningful agreement.,Boundary,SYM_BOUNDARY,2,Resolve with Boundary. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=global (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM_SURFACE
PRB_03_1,SCN_03,Hidden,personal,1,Mandate Was Ambiguous,"It was unclear who could decide, advise, consent, or veto.",Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_03_2,SCN_03,Hidden,personal,2,Contributions Were Dismissed,Relevant input was ignored or treated as less legitimate.,Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM

1 problem_id scenario_id visibility stress_scope hidden_priority title problem_text required_solution symbol_id point_value front_rules reveal_effect unresolved_effect back_design_id
5 PRB_01_3 SCN_01 Hidden bond 3 Bad News Was Delayed A warning was withheld until the remaining options became worse. Repair SYM_REPAIR 3 Resolve with Repair. Value: 3. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=bond (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
6 PRB_01_4 SCN_01 Hidden personal 4 No Checkpoint Process The group had no reliable moment for testing progress and changing course. Change SYM_CHANGE 3 Resolve with Change. Value: 3. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
7 PRB_02_S SCN_02 Surface global 0 Shared Task Left Undone A recurring responsibility was not completed, and others absorbed the impact. Repair SYM_REPAIR 2 Resolve with Repair. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=global (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM_SURFACE
8 PRB_02_1 SCN_02 Hidden personal 1 Different Standards Players were using different definitions of complete, timely, or fair. Clarify Change SYM_CLARIFY SYM_CHANGE 2 Resolve with Clarify. Value: 2. Resolve with Change. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
9 PRB_02_2 SCN_02 Hidden personal 2 Invisible Workload Some contributions and constraints were not visible to the group. Boundary Clarify SYM_BOUNDARY SYM_CLARIFY 2 Resolve with Boundary. Value: 2. Resolve with Clarify. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
10 PRB_02_3 SCN_02 Hidden bond 3 Resentment Never Raised Frustration accumulated without a direct request or acknowledgement. Repair Boundary SYM_REPAIR SYM_BOUNDARY 3 Resolve with Repair. Value: 3. Resolve with Boundary. Value: 3. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=bond (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
11 PRB_02_4 SCN_02 Hidden personal 4 No Ownership Routine The group relied on goodwill instead of a dependable allocation method. Change Repair SYM_CHANGE SYM_REPAIR 3 Resolve with Change. Value: 3. Resolve with Repair. Value: 3. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
12 PRB_03_S SCN_03 Surface global 0 Decision Announced as Settled A group-affecting choice was presented as final before meaningful agreement. Boundary SYM_BOUNDARY 2 Resolve with Boundary. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=global (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM_SURFACE
13 PRB_03_1 SCN_03 Hidden personal 1 Mandate Was Ambiguous It was unclear who could decide, advise, consent, or veto. Clarify SYM_CLARIFY 2 Resolve with Clarify. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
14 PRB_03_2 SCN_03 Hidden personal 2 Contributions Were Dismissed Relevant input was ignored or treated as less legitimate. Repair SYM_REPAIR 2 Resolve with Repair. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM

View file

@ -1,4 +1,4 @@
mode_id,title,mode_type,tagline,rules_text,scoring_tiebreak,back_design_id
MODE_COOP,SHARED GROUND,Cooperative,The group succeeds or fails together.,"All claimed Problem cards form one shared score. Meet the Scenario threshold by the end of Round 5. Playable at 26 players — not a high-seat-only mode. No individual winner is declared. For a mastery rating, subtract 1 for each Blame token still in play and 1 for each Denied Problem.",Not applicable.,BACK_MODE
MODE_COOP,SHARED GROUND,Cooperative,The group succeeds or fails together.,"All claimed Problem cards form one shared score equal to the sum of their point values. Meet the Scenario threshold by the end of Round 5. Playable at 26 players — not a high-seat-only mode. No individual winner is declared. For a mastery rating, start from that shared point total and subtract 1 point for each Blame token still in play and 1 point for each Denied Problem (penalties apply to points, not card count).",Not applicable.,BACK_MODE
MODE_SEMI,"COMMON PROBLEM, PERSONAL EDGE",Semi-cooperative,The group must succeed before anyone can win.,"The group succeeds only if the total value of all claimed Problems meets the Scenario threshold (always ≤ available points for the seat band). If it succeeds, each player scores the value of Problems they claimed minus 1 per Blame token they hold. Highest score wins.","Lower Stress, then more Bonds, then shared victory.",BACK_MODE
MODE_COALITION,BONDED COALITIONS,Dynamic teams,Bonds decide the sides at the end.,"The group must first meet the Scenario threshold (always ≤ available points for the seat band). At game end, each connected network of Bonds is a coalition; unbonded players are one-player coalitions. Sum the personal scores of coalition members. The highest-scoring coalition wins. Rivalries do not connect players.","Lower combined Stress, then fewer Blame tokens, then shared victory.",BACK_MODE

1 mode_id title mode_type tagline rules_text scoring_tiebreak back_design_id
2 MODE_COOP SHARED GROUND Cooperative The group succeeds or fails together. All claimed Problem cards form one shared score. Meet the Scenario threshold by the end of Round 5. Playable at 2–6 players — not a high-seat-only mode. No individual winner is declared. For a mastery rating, subtract 1 for each Blame token still in play and 1 for each Denied Problem. All claimed Problem cards form one shared score equal to the sum of their point values. Meet the Scenario threshold by the end of Round 5. Playable at 2–6 players — not a high-seat-only mode. No individual winner is declared. For a mastery rating, start from that shared point total and subtract 1 point for each Blame token still in play and 1 point for each Denied Problem (penalties apply to points, not card count). Not applicable. BACK_MODE
3 MODE_SEMI COMMON PROBLEM, PERSONAL EDGE Semi-cooperative The group must succeed before anyone can win. The group succeeds only if the total value of all claimed Problems meets the Scenario threshold (always ≤ available points for the seat band). If it succeeds, each player scores the value of Problems they claimed minus 1 per Blame token they hold. Highest score wins. Lower Stress, then more Bonds, then shared victory. BACK_MODE
4 MODE_COALITION BONDED COALITIONS Dynamic teams Bonds decide the sides at the end. The group must first meet the Scenario threshold (always ≤ available points for the seat band). At game end, each connected network of Bonds is a coalition; unbonded players are one-player coalitions. Sum the personal scores of coalition members. The highest-scoring coalition wins. Rivalries do not connect players. Lower combined Stress, then fewer Blame tokens, then shared victory. BACK_MODE

View file

@ -57,16 +57,42 @@ Vendored 2026-08-08 from `ground-game` `8886543` (CB-WP-0038). These are
the adversarial review ([CB-REV-0001](../../reviews/CB-REV-0001-h1.md))
reported it unverified and it was a real gap.
```
sha256 7a7a302aabecdeb419c562a029bec3e3576a306b0bd1175d1200de60d9530073 Actions.csv
sha256 0afb882dc8001f03bc48a152c9d8c36ad492ceeff2d30ef6a3a690937317f77b DARVO.csv
sha256 d06924a19f805feb9e2557fd5c06254ae2054e1f865265f45c26eb293f53bf12 Glossary.csv
sha256 4b8e795fbbc93646230f666f8c139dfbd3375af7a12c2968f1674ec83b05b21d Modes.csv
sha256 ad2bfbf897bbb3878691cbdbfec739adc58d28cad3923a989dd46b426cce1395 Player_Mats.csv
sha256 62e4ae3f4a3c29cf8bdd13f09d3a8866aa98b1716b8e72e49a4aba874c9e9fcb Problems.csv
sha256 cd84c3b131c1b7a541e9e42529fdce2b7911f0832cce8c50cfcb8462d01dc551 Relations.csv
sha256 f830de9ca44417a7510e04a39ea24a070a81969b33a31fa68361fba132ad40cd Scenarios.csv
sha256 0bda1ee97de726b5e8c4404ab15ecc53a359e6c23db74fb41ecb51d78f9884ad Solutions.csv
sha256 25273bb6e74c9ad545c5e89dfe0f76b294d0a6cbef51f80d548039d5f0943484 Tokens.csv
```
**H2 vendored 2026-08-08** (CB-WP-0042). Its `Problems.csv` is r0's with
**one column added** — `stress_scope` — and **nothing else changed**: same
rows, same `point_value`, `required_solution`, `visibility` and
`hidden_priority`. That is checked, not assumed, because the delta's
`unchanged:` list claims `deal_and_thresholds` and a silent change there
would move every baseline hash.
**`rules_delta.yaml` is the load-bearing one**: it is the executable
statement of H1, and the kernel implements it. A silent change there is a
silent change to what we measured.
## Digests
```
sha256 536ad836991804e8d96eff20ae549654ecb82e28cdd884914730b70e3c387ee3 ../ASPECTS.md
sha256 5b5f1b73a6fa0f7a8d9ef2061670efc1c309d69774dea9e0deeb3fbce0a399b9 ../CATALOG.md
sha256 2adedb8c28570c33e126484c472d8b097067f50358f2ac523f1b3c976e66947a ../catalog.yaml
sha256 269db010edfbf9331a3e3bc07fa3949138b2f20adf77ba2c11925bcb8579f997 ../CATALOG.md
sha256 5f12bbdc180efd89a5a27750a01d763018044309a629e8437bf8b65373a685ca ../catalog.yaml
sha256 7b1cc0149122b855e827bc930576ed165bf7dd8d62707e845a9e514ce3521f8e ../experiments/h1-problem-stress/Actions.csv
sha256 62785f5e7e245c60171624d15de2f40187a44fec54f93c7d9705cf52584b1078 ../experiments/h1-problem-stress/Rules_Text.csv
sha256 49897a68056643a8cfccff32c9e4a9811018b4e4689b90a85124a487f2318369 ../experiments/h1-problem-stress/VARIANT.md
sha256 443199db94601cc889557e5e86823f374dbfdf875962fc84f95c01865605101c ../experiments/h1-problem-stress/metadata.json
sha256 f58e81f84ea2b0d16e39932261eb3f3d9890345cdf37ad6f0b3abc00636840be ../experiments/h1-problem-stress/rules_delta.yaml
sha256 4c81bae21d2ecb70c7424fa17445246a9b551b10e258d448634816c564e28f09 ../experiments/h2-scoped-problem-stress/Problems.csv
sha256 959872910d7824629afe34fb7135a2670d699444001f2eb72b33ba3102c3b82f ../experiments/h2-scoped-problem-stress/Problems.csv
sha256 8ed8deb7ad142de1bda70dc11add339f742e8c12ac1f02d5f7c7ec8f17f77b1d ../experiments/h2-scoped-problem-stress/Rules_Text.csv
sha256 b0ffea41820ef35960d8c75ff0a734370a29a738e49fda74851fe5c2daafe53e ../experiments/h2-scoped-problem-stress/VARIANT.md
sha256 abf994f585fdfa9b2822614a7961e98141cded6a91c446916ff7fd48642de0a7 ../experiments/h2-scoped-problem-stress/metadata.json
@ -84,37 +110,11 @@ sha256 a5e66fd60abef1cf965b0b20892548c65f4005c45f4d44c025e4756eff579897 ../mod
sha256 95fa5d4ad811407eda1cf31d99d5dd984e9d1d9af8c284e10df598874d0f06e3 ../modules/problem_stress/flat_any_open/rules_delta.yaml
sha256 1e9cb6e2dac046a9f48beccb0ddc09c41608306711320159ecdce3572562e454 ../modules/problem_stress/none/MODULE.md
sha256 aae98322a70e51b639b8c39ac45604807f5311ae55edc75b47199056a483c963 ../modules/problem_stress/scoped/MODULE.md
sha256 4c81bae21d2ecb70c7424fa17445246a9b551b10e258d448634816c564e28f09 ../modules/problem_stress/scoped/Problems.csv
sha256 959872910d7824629afe34fb7135a2670d699444001f2eb72b33ba3102c3b82f ../modules/problem_stress/scoped/Problems.csv
sha256 8ed8deb7ad142de1bda70dc11add339f742e8c12ac1f02d5f7c7ec8f17f77b1d ../modules/problem_stress/scoped/Rules_Text.csv
sha256 960e8a35f5f214ff9936ea95c4ca9a9145e2a01a8258b1c873251b89ee23972f ../modules/problem_stress/scoped/rules_delta.yaml
```
**H2 vendored 2026-08-08** (CB-WP-0042). Its `Problems.csv` is r0's with
**one column added** — `stress_scope` — and **nothing else changed**: same
rows, same `point_value`, `required_solution`, `visibility` and
`hidden_priority`. That is checked, not assumed, because the delta's
`unchanged:` list claims `deal_and_thresholds` and a silent change there
would move every baseline hash.
**`rules_delta.yaml` is the load-bearing one**: it is the executable
statement of H1, and the kernel implements it. A silent change there is a
silent change to what we measured.
## Digests
```
sha256 7a7a302aabecdeb419c562a029bec3e3576a306b0bd1175d1200de60d9530073 Actions.csv
sha256 0afb882dc8001f03bc48a152c9d8c36ad492ceeff2d30ef6a3a690937317f77b DARVO.csv
sha256 d06924a19f805feb9e2557fd5c06254ae2054e1f865265f45c26eb293f53bf12 Glossary.csv
sha256 565431571bc06adafb67edefd4b368839b6b94134c2289877384688cc643390b Modes.csv
sha256 ad2bfbf897bbb3878691cbdbfec739adc58d28cad3923a989dd46b426cce1395 Player_Mats.csv
sha256 0a04830c93b62dcb2f4411a9fbde576368a7427fe9e63c5015e606e4d42d23a0 Problems.csv
sha256 cd84c3b131c1b7a541e9e42529fdce2b7911f0832cce8c50cfcb8462d01dc551 Relations.csv
sha256 f830de9ca44417a7510e04a39ea24a070a81969b33a31fa68361fba132ad40cd Scenarios.csv
sha256 0bda1ee97de726b5e8c4404ab15ecc53a359e6c23db74fb41ecb51d78f9884ad Solutions.csv
sha256 25273bb6e74c9ad545c5e89dfe0f76b294d0a6cbef51f80d548039d5f0943484 Tokens.csv
```
`make edition-check` compares this against `../ground-game` when that
repository is present, and reports **`upstream not checked out`** as a
distinct outcome when it is not — never a pass. An absent check is

View file

@ -1,21 +1,21 @@
problem_id,scenario_id,visibility,hidden_priority,title,problem_text,required_solution,symbol_id,point_value,front_rules,reveal_effect,unresolved_effect,back_design_id
PRB_01_S,SCN_01,Surface,0,Deadline Missed,A promised result was not delivered when expected.,Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM_SURFACE
PRB_01_1,SCN_01,Hidden,1,Unclear Ownership,Responsibility for the commitment and the work was never made explicit.,Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_01_2,SCN_01,Hidden,2,Unspoken Overload,The work required more capacity than someone could safely or fairly provide.,Boundary,SYM_BOUNDARY,2,Resolve with Boundary. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_01_3,SCN_01,Hidden,3,Bad News Was Delayed,A warning was withheld until the remaining options became worse.,Repair,SYM_REPAIR,3,Resolve with Repair. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_01_4,SCN_01,Hidden,4,No Checkpoint Process,The group had no reliable moment for testing progress and changing course.,Change,SYM_CHANGE,3,Resolve with Change. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_02_S,SCN_02,Surface,0,Shared Task Left Undone,"A recurring responsibility was not completed, and others absorbed the impact.",Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM_SURFACE
PRB_02_1,SCN_02,Hidden,1,Different Standards,"Players were using different definitions of complete, timely, or fair.",Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_02_2,SCN_02,Hidden,2,Invisible Workload,Some contributions and constraints were not visible to the group.,Boundary,SYM_BOUNDARY,2,Resolve with Boundary. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_02_3,SCN_02,Hidden,3,Resentment Never Raised,Frustration accumulated without a direct request or acknowledgement.,Repair,SYM_REPAIR,3,Resolve with Repair. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_02_4,SCN_02,Hidden,4,No Ownership Routine,The group relied on goodwill instead of a dependable allocation method.,Change,SYM_CHANGE,3,Resolve with Change. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_03_S,SCN_03,Surface,0,Decision Announced as Settled,A group-affecting choice was presented as final before meaningful agreement.,Boundary,SYM_BOUNDARY,2,Resolve with Boundary. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM_SURFACE
PRB_03_1,SCN_03,Hidden,1,Mandate Was Ambiguous,"It was unclear who could decide, advise, consent, or veto.",Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_03_2,SCN_03,Hidden,2,Contributions Were Dismissed,Relevant input was ignored or treated as less legitimate.,Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_03_3,SCN_03,Hidden,3,One Voice Spoke for Others,A player claimed authority to represent people who had not agreed.,Boundary,SYM_BOUNDARY,3,Resolve with Boundary. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_03_4,SCN_03,Hidden,4,No Decision Rule,The group had no shared method for turning discussion into a legitimate choice.,Change,SYM_CHANGE,3,Resolve with Change. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_04_S,SCN_04,Surface,0,Private Information Spread,Information moved beyond the circle in which it was originally shared.,Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM_SURFACE
PRB_04_1,SCN_04,Hidden,1,Confidentiality Was Assumed,The players never made the scope of confidentiality explicit.,Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_04_2,SCN_04,Hidden,2,Exposure Caused Harm,"The sharing changed another player's safety, reputation, or freedom to choose.",Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_04_3,SCN_04,Hidden,3,Consent Boundary Was Ignored,A clear or reasonably expected limit on sharing was crossed.,Boundary,SYM_BOUNDARY,3,Resolve with Boundary. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_04_4,SCN_04,Hidden,4,No Sharing Protocol,"The group lacked a repeatable rule for consent, need-to-know, and escalation.",Change,SYM_CHANGE,3,Resolve with Change. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
problem_id,scenario_id,visibility,hidden_priority,title,problem_text,required_solution,symbol_id,point_value,front_rules,reveal_effect,unresolved_effect,back_design_id
PRB_01_S,SCN_01,Surface,0,Deadline Missed,A promised result was not delivered when expected.,Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM_SURFACE
PRB_01_1,SCN_01,Hidden,1,Unclear Ownership,Responsibility for the commitment and the work was never made explicit.,Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_01_2,SCN_01,Hidden,2,Unspoken Overload,The work required more capacity than someone could safely or fairly provide.,Boundary,SYM_BOUNDARY,2,Resolve with Boundary. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_01_3,SCN_01,Hidden,3,Bad News Was Delayed,A warning was withheld until the remaining options became worse.,Repair,SYM_REPAIR,3,Resolve with Repair. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_01_4,SCN_01,Hidden,4,No Checkpoint Process,The group had no reliable moment for testing progress and changing course.,Change,SYM_CHANGE,3,Resolve with Change. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_02_S,SCN_02,Surface,0,Shared Task Left Undone,"A recurring responsibility was not completed, and others absorbed the impact.",Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM_SURFACE
PRB_02_1,SCN_02,Hidden,1,Different Standards,"Players were using different definitions of complete, timely, or fair.",Change,SYM_CHANGE,2,Resolve with Change. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_02_2,SCN_02,Hidden,2,Invisible Workload,Some contributions and constraints were not visible to the group.,Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_02_3,SCN_02,Hidden,3,Resentment Never Raised,Frustration accumulated without a direct request or acknowledgement.,Boundary,SYM_BOUNDARY,3,Resolve with Boundary. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_02_4,SCN_02,Hidden,4,No Ownership Routine,The group relied on goodwill instead of a dependable allocation method.,Repair,SYM_REPAIR,3,Resolve with Repair. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_03_S,SCN_03,Surface,0,Decision Announced as Settled,A group-affecting choice was presented as final before meaningful agreement.,Boundary,SYM_BOUNDARY,2,Resolve with Boundary. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM_SURFACE
PRB_03_1,SCN_03,Hidden,1,Mandate Was Ambiguous,"It was unclear who could decide, advise, consent, or veto.",Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_03_2,SCN_03,Hidden,2,Contributions Were Dismissed,Relevant input was ignored or treated as less legitimate.,Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_03_3,SCN_03,Hidden,3,One Voice Spoke for Others,A player claimed authority to represent people who had not agreed.,Boundary,SYM_BOUNDARY,3,Resolve with Boundary. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_03_4,SCN_03,Hidden,4,No Decision Rule,The group had no shared method for turning discussion into a legitimate choice.,Change,SYM_CHANGE,3,Resolve with Change. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_04_S,SCN_04,Surface,0,Private Information Spread,Information moved beyond the circle in which it was originally shared.,Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM_SURFACE
PRB_04_1,SCN_04,Hidden,1,Confidentiality Was Assumed,The players never made the scope of confidentiality explicit.,Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_04_2,SCN_04,Hidden,2,Exposure Caused Harm,"The sharing changed another player's safety, reputation, or freedom to choose.",Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_04_3,SCN_04,Hidden,3,Consent Boundary Was Ignored,A clear or reasonably expected limit on sharing was crossed.,Boundary,SYM_BOUNDARY,3,Resolve with Boundary. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM
PRB_04_4,SCN_04,Hidden,4,No Sharing Protocol,"The group lacked a repeatable rule for consent, need-to-know, and escalation.",Change,SYM_CHANGE,3,Resolve with Change. Value: 3.,None in the core set.,No card-specific effect; it simply remains unsolved.,BACK_PROBLEM

1 problem_id scenario_id visibility hidden_priority title problem_text required_solution symbol_id point_value front_rules reveal_effect unresolved_effect back_design_id
2 PRB_01_S SCN_01 Surface 0 Deadline Missed A promised result was not delivered when expected. Repair SYM_REPAIR 2 Resolve with Repair. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM_SURFACE
3 PRB_01_1 SCN_01 Hidden 1 Unclear Ownership Responsibility for the commitment and the work was never made explicit. Clarify SYM_CLARIFY 2 Resolve with Clarify. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
4 PRB_01_2 SCN_01 Hidden 2 Unspoken Overload The work required more capacity than someone could safely or fairly provide. Boundary SYM_BOUNDARY 2 Resolve with Boundary. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
5 PRB_01_3 SCN_01 Hidden 3 Bad News Was Delayed A warning was withheld until the remaining options became worse. Repair SYM_REPAIR 3 Resolve with Repair. Value: 3. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
6 PRB_01_4 SCN_01 Hidden 4 No Checkpoint Process The group had no reliable moment for testing progress and changing course. Change SYM_CHANGE 3 Resolve with Change. Value: 3. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
7 PRB_02_S SCN_02 Surface 0 Shared Task Left Undone A recurring responsibility was not completed, and others absorbed the impact. Repair SYM_REPAIR 2 Resolve with Repair. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM_SURFACE
8 PRB_02_1 SCN_02 Hidden 1 Different Standards Players were using different definitions of complete, timely, or fair. Clarify Change SYM_CLARIFY SYM_CHANGE 2 Resolve with Clarify. Value: 2. Resolve with Change. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
9 PRB_02_2 SCN_02 Hidden 2 Invisible Workload Some contributions and constraints were not visible to the group. Boundary Clarify SYM_BOUNDARY SYM_CLARIFY 2 Resolve with Boundary. Value: 2. Resolve with Clarify. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
10 PRB_02_3 SCN_02 Hidden 3 Resentment Never Raised Frustration accumulated without a direct request or acknowledgement. Repair Boundary SYM_REPAIR SYM_BOUNDARY 3 Resolve with Repair. Value: 3. Resolve with Boundary. Value: 3. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
11 PRB_02_4 SCN_02 Hidden 4 No Ownership Routine The group relied on goodwill instead of a dependable allocation method. Change Repair SYM_CHANGE SYM_REPAIR 3 Resolve with Change. Value: 3. Resolve with Repair. Value: 3. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
12 PRB_03_S SCN_03 Surface 0 Decision Announced as Settled A group-affecting choice was presented as final before meaningful agreement. Boundary SYM_BOUNDARY 2 Resolve with Boundary. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM_SURFACE
13 PRB_03_1 SCN_03 Hidden 1 Mandate Was Ambiguous It was unclear who could decide, advise, consent, or veto. Clarify SYM_CLARIFY 2 Resolve with Clarify. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
14 PRB_03_2 SCN_03 Hidden 2 Contributions Were Dismissed Relevant input was ignored or treated as less legitimate. Repair SYM_REPAIR 2 Resolve with Repair. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
15 PRB_03_3 SCN_03 Hidden 3 One Voice Spoke for Others A player claimed authority to represent people who had not agreed. Boundary SYM_BOUNDARY 3 Resolve with Boundary. Value: 3. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
16 PRB_03_4 SCN_03 Hidden 4 No Decision Rule The group had no shared method for turning discussion into a legitimate choice. Change SYM_CHANGE 3 Resolve with Change. Value: 3. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
17 PRB_04_S SCN_04 Surface 0 Private Information Spread Information moved beyond the circle in which it was originally shared. Repair SYM_REPAIR 2 Resolve with Repair. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM_SURFACE
18 PRB_04_1 SCN_04 Hidden 1 Confidentiality Was Assumed The players never made the scope of confidentiality explicit. Clarify SYM_CLARIFY 2 Resolve with Clarify. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
19 PRB_04_2 SCN_04 Hidden 2 Exposure Caused Harm The sharing changed another player's safety, reputation, or freedom to choose. Repair SYM_REPAIR 2 Resolve with Repair. Value: 2. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
20 PRB_04_3 SCN_04 Hidden 3 Consent Boundary Was Ignored A clear or reasonably expected limit on sharing was crossed. Boundary SYM_BOUNDARY 3 Resolve with Boundary. Value: 3. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM
21 PRB_04_4 SCN_04 Hidden 4 No Sharing Protocol The group lacked a repeatable rule for consent, need-to-know, and escalation. Change SYM_CHANGE 3 Resolve with Change. Value: 3. None in the core set. No card-specific effect; it simply remains unsolved. BACK_PROBLEM

View file

@ -5,10 +5,10 @@ PRB_01_2,SCN_01,Hidden,personal,2,Unspoken Overload,The work required more capac
PRB_01_3,SCN_01,Hidden,bond,3,Bad News Was Delayed,A warning was withheld until the remaining options became worse.,Repair,SYM_REPAIR,3,Resolve with Repair. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=bond (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_01_4,SCN_01,Hidden,personal,4,No Checkpoint Process,The group had no reliable moment for testing progress and changing course.,Change,SYM_CHANGE,3,Resolve with Change. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_S,SCN_02,Surface,global,0,Shared Task Left Undone,"A recurring responsibility was not completed, and others absorbed the impact.",Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=global (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM_SURFACE
PRB_02_1,SCN_02,Hidden,personal,1,Different Standards,"Players were using different definitions of complete, timely, or fair.",Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_2,SCN_02,Hidden,personal,2,Invisible Workload,Some contributions and constraints were not visible to the group.,Boundary,SYM_BOUNDARY,2,Resolve with Boundary. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_3,SCN_02,Hidden,bond,3,Resentment Never Raised,Frustration accumulated without a direct request or acknowledgement.,Repair,SYM_REPAIR,3,Resolve with Repair. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=bond (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_4,SCN_02,Hidden,personal,4,No Ownership Routine,The group relied on goodwill instead of a dependable allocation method.,Change,SYM_CHANGE,3,Resolve with Change. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_1,SCN_02,Hidden,personal,1,Different Standards,"Players were using different definitions of complete, timely, or fair.",Change,SYM_CHANGE,2,Resolve with Change. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_2,SCN_02,Hidden,personal,2,Invisible Workload,Some contributions and constraints were not visible to the group.,Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_3,SCN_02,Hidden,bond,3,Resentment Never Raised,Frustration accumulated without a direct request or acknowledgement.,Boundary,SYM_BOUNDARY,3,Resolve with Boundary. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=bond (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_02_4,SCN_02,Hidden,personal,4,No Ownership Routine,The group relied on goodwill instead of a dependable allocation method.,Repair,SYM_REPAIR,3,Resolve with Repair. Value: 3.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_03_S,SCN_03,Surface,global,0,Decision Announced as Settled,A group-affecting choice was presented as final before meaningful agreement.,Boundary,SYM_BOUNDARY,2,Resolve with Boundary. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=global (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM_SURFACE
PRB_03_1,SCN_03,Hidden,personal,1,Mandate Was Ambiguous,"It was unclear who could decide, advise, consent, or veto.",Clarify,SYM_CLARIFY,2,Resolve with Clarify. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM
PRB_03_2,SCN_03,Hidden,personal,2,Contributions Were Dismissed,Relevant input was ignored or treated as less legitimate.,Repair,SYM_REPAIR,2,Resolve with Repair. Value: 2.,None in the core set.,"H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all).",BACK_PROBLEM

1 problem_id scenario_id visibility stress_scope hidden_priority title problem_text required_solution symbol_id point_value front_rules reveal_effect unresolved_effect back_design_id
5 PRB_01_3 SCN_01 Hidden bond 3 Bad News Was Delayed A warning was withheld until the remaining options became worse. Repair SYM_REPAIR 3 Resolve with Repair. Value: 3. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=bond (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
6 PRB_01_4 SCN_01 Hidden personal 4 No Checkpoint Process The group had no reliable moment for testing progress and changing course. Change SYM_CHANGE 3 Resolve with Change. Value: 3. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
7 PRB_02_S SCN_02 Surface global 0 Shared Task Left Undone A recurring responsibility was not completed, and others absorbed the impact. Repair SYM_REPAIR 2 Resolve with Repair. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=global (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM_SURFACE
8 PRB_02_1 SCN_02 Hidden personal 1 Different Standards Players were using different definitions of complete, timely, or fair. Clarify Change SYM_CLARIFY SYM_CHANGE 2 Resolve with Clarify. Value: 2. Resolve with Change. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
9 PRB_02_2 SCN_02 Hidden personal 2 Invisible Workload Some contributions and constraints were not visible to the group. Boundary Clarify SYM_BOUNDARY SYM_CLARIFY 2 Resolve with Boundary. Value: 2. Resolve with Clarify. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
10 PRB_02_3 SCN_02 Hidden bond 3 Resentment Never Raised Frustration accumulated without a direct request or acknowledgement. Repair Boundary SYM_REPAIR SYM_BOUNDARY 3 Resolve with Repair. Value: 3. Resolve with Boundary. Value: 3. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=bond (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
11 PRB_02_4 SCN_02 Hidden personal 4 No Ownership Routine The group relied on goodwill instead of a dependable allocation method. Change Repair SYM_CHANGE SYM_REPAIR 3 Resolve with Change. Value: 3. Resolve with Repair. Value: 3. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
12 PRB_03_S SCN_03 Surface global 0 Decision Announced as Settled A group-affecting choice was presented as final before meaningful agreement. Boundary SYM_BOUNDARY 2 Resolve with Boundary. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=global (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM_SURFACE
13 PRB_03_1 SCN_03 Hidden personal 1 Mandate Was Ambiguous It was unclear who could decide, advise, consent, or veto. Clarify SYM_CLARIFY 2 Resolve with Clarify. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM
14 PRB_03_2 SCN_03 Hidden personal 2 Contributions Were Dismissed Relevant input was ignored or treated as less legitimate. Repair SYM_REPAIR 2 Resolve with Repair. Value: 2. None in the core set. H2: while unclaimed, +1 Stress at Round End to stress_scope=personal (personal=owner; bond=owner's Bond network; global=all). BACK_PROBLEM

View file

@ -25,7 +25,34 @@ a sample nobody chose (CB-REV-0002 #1).
vary only face-down Problems and other seats' hands, and neither changes
its move. The control is proven against a deliberate peeker first.
## 1 — SCN_01 and SCN_02 are the same board
## 0 — what happened after this was reported
**ground-game ruled on all seven items the same day** (GROUND-RPT-0006
§"disposition"). Two changed the engine or the edition, and the numbers
below are therefore **superseded where noted**:
| item | ruling |
|---|---|
| SCN_01 ≡ SCN_02 | **not intended** — SCN_02 re-tuned upstream, §1 below is now history |
| SCN_04 harder at 2p | acceptable variety; first lever would be priority-2's suit, **not** thresholds — which confirms our reading of the operative difference without our having measured it |
| 6p formality | known (F17 line) |
| modes change who wins | accepted as a design property, not a defect |
| 2 relation slots | **intentional cap**; a third slot stays an extension, so our proposed sensitivity run would measure an extension and not the shipped game |
| mastery: points or cards | **RULED: points.** Applied — see below |
| package file manifest | accepted process ask, tracked as GROUND-WP-0008 |
**Mastery is now `total blame denied`.** `Modes.csv` was clarified
upstream to say *"penalties apply to points, not card count"* and the
engine follows. `gr-e02-shared-ground` went red on it — it pinned 0
(2 claimed cards 1 1) and now expects 2 (4 points 1 1). The
number moved because the rule was decided, not because the engine
drifted, and the scenario records both rulings.
**SCN_02 re-measured after the re-tune:** 2p group success **73**, not 67
— it is now its own board and matches SCN_03's difficulty rather than
SCN_01's. §1 below describes the state that prompted the report.
## 1 — SCN_01 and SCN_02 were the same board (superseded)
Identical suit and value at **every** priority. Every cell matches
exactly, in both policies, at all three seat bands.

View file

@ -1056,16 +1056,20 @@ mod card_text_tests {
}
}
/// **Two of the four scenarios are the same board** (CB-WP-0047).
/// **The four scenarios are four boards** (F29).
///
/// SCN_01 and SCN_02 have identical suit-and-value profiles at every
/// priority, so they play identically and differ only in prose. Not
/// a defect — a designed reskin is a legitimate choice — but it is a
/// fact about what "four scenarios" buys, and measuring them as four
/// independent boards would be measuring two of them twice.
/// They were not. SCN_01 and SCN_02 had identical suit-and-value
/// profiles at every priority — they played identically and differed
/// only in prose, so "four scenarios" bought three boards.
///
/// This is a **characterisation** test: it pins what is true today so
/// that a change to either deck is a decision rather than a drift.
/// Reported as F29; ground-game ruled it **unintended** and re-tuned
/// SCN_02's suits the same day. **This test is how we found out**: it
/// was a characterisation pinning the duplication, it went red on the
/// re-tune, and that red was the notification, not a defect.
///
/// It now asserts the property that should hold from here — every
/// pair distinct — which is the stronger statement the duplication
/// had made unavailable.
#[test]
fn which_scenarios_are_mechanically_distinct() {
let profile = |id: &str| -> Vec<(u8, String, u8)> {
@ -1077,24 +1081,17 @@ mod card_text_tests {
v.sort();
v
};
assert_eq!(
profile("SCN_01"),
profile("SCN_02"),
"SCN_01 and SCN_02 diverged — they were identical boards; \
if this is intended, the panel now measures four real boards"
);
for pair in [
("SCN_01", "SCN_03"),
("SCN_01", "SCN_04"),
("SCN_03", "SCN_04"),
] {
assert_ne!(
profile(pair.0),
profile(pair.1),
"{} and {} became the same board",
pair.0,
pair.1
);
let ids = ["SCN_01", "SCN_02", "SCN_03", "SCN_04"];
for (i, a) in ids.iter().enumerate() {
for b in &ids[i + 1..] {
assert_ne!(
profile(a),
profile(b),
"{a} and {b} are the same board — four scenarios must be \
four boards, or a panel treating them as independent \
samples counts one of them twice"
);
}
}
}

View file

@ -1880,12 +1880,18 @@ impl GroundState {
.map(|p| p.blame_from.len() as i32)
.sum();
let denied = self.problems.values().filter(|p| p.denied).count() as i32;
let claimed = self
.problems
.values()
.filter(|p| p.claimed_by.is_some())
.count() as i32;
let mastery = claimed - blame - denied;
// **Points, not card count** — F28, ruled by ground-game
// 2026-08-08 and clarified in `Modes.csv`: *"start from
// that shared point total and subtract 1 point for each
// Blame token still in play and 1 point for each Denied
// Problem (penalties apply to points, not card count)."*
//
// This counted CLAIMED CARDS. Both readings fit the
// sentence as it stood, and they differ on every game
// where a 3-point Problem is claimed — which is most of
// them. Reported rather than guessed; the card is the
// authority (ADR-0015) and it now says so outright.
let mastery = total as i32 - blame - denied;
let winners = if group_success {
self.players.keys().copied().collect()
} else {
@ -3552,7 +3558,7 @@ mod tests {
/// does today and shows the size of the disagreement, so the ruling
/// has a number in front of it.
#[test]
fn the_mastery_rating_and_the_shared_score_count_different_things() {
fn the_mastery_rating_is_in_points_as_the_mode_card_now_says() {
let mut s = setup_3p(11);
s.mode = ScoringMode::SharedGround;
// Two claimed Problems worth 2 and 3 — five points, two cards.
@ -3587,16 +3593,40 @@ mod tests {
assert_eq!(o.total, 5, "the shared score is claimed VALUE");
assert_eq!(
o.mastery,
Some(2),
"mastery is the claimed COUNT, with no penalties in play"
Some(5),
"mastery starts from the shared POINT total, not the card count"
);
// The disagreement, stated as a number rather than as a worry.
assert_ne!(
i32::try_from(o.total).unwrap(),
o.mastery.unwrap(),
"the two readings agree on this board, so F28 has no bite here \
and the example needs replacing"
// The board is chosen so the two readings disagree — two cards
// worth five points. Without that the test would pass under the
// reading it exists to exclude.
assert_eq!(
s.problems
.values()
.filter(|p| p.claimed_by.is_some())
.count(),
2,
"the fixture must claim a number of CARDS different from the \
POINT total, or it cannot tell the two readings apart"
);
// **The edition's own sentence, not our memory of the ruling.**
// `Modes.csv` was clarified upstream; if that clarification is
// ever reverted this goes red rather than quietly diverging.
let (card, _) = crate::edition::modes()
.expect("Modes.csv")
.into_iter()
.find(|(c, _)| c.id == "MODE_COOP")
.expect("MODE_COOP");
assert!(
card.rules_text.contains("not card count"),
"the Mode card no longer rules out the card-count reading: {:?}",
card.rules_text
);
// And the penalties still bite, in points.
let seat = seats[0];
s.players.get_mut(&seat).unwrap().blame_from = vec![seats[1]];
assert_eq!(s.score().mastery, Some(4), "a Blame token costs 1 POINT");
}
/// **Every scenario is reachable through `setup`** (CB-WP-0047).
@ -3634,14 +3664,13 @@ mod tests {
.collect::<Vec<_>>(),
);
}
// SCN_01 and SCN_02 are the same board by design, so four
// scenarios yield THREE distinct boards. Asserting 4 here would
// be asserting a fact about the edition that is not true.
// Four scenarios, four boards (F29). This asserted THREE until
// 2026-08-08, because SCN_01 and SCN_02 were identical decks;
// ground-game ruled that unintended and re-tuned SCN_02.
assert_eq!(
boards.len(),
3,
"the four scenarios yield {} distinct boards; SCN_01 and SCN_02 \
were identical and the other two differ",
4,
"the four scenarios yield {} distinct boards at 4p",
boards.len()
);
}

View file

@ -4,10 +4,11 @@ description: >
shared total against the player-count threshold, with a Mastery
rating reduced by each Blame token and each Denied Problem.
covers: [GR-R09, GR-E01, GR-E02, GR-P03]
ruled: 2026-08-03
ruled: 2026-08-08
ruled_by: ground-game
ruled_note: >
GROUND-WP-0002 T03, 2026-08-03 — confirm: encode Modes.csv MODE_COOP as printed. Encodes no U-item; it was provisional on the mode data, not on an undetermined rule.
RE-RULED 2026-08-08 (F28 / GROUND-RPT-0006 §5(a)): mastery penalties apply to POINTS, not card count. Modes.csv MODE_COOP was clarified upstream and this scenario's expectation moved from 0 to 2. The schema has no field for a second ruling, so both are recorded here; the `ruled` date is the LATEST, because that is the one a reader must check the edition against.
seed: 42
setup:
players: 3
@ -44,8 +45,15 @@ expect:
"outcome.total": 4
"outcome.threshold": 7
"outcome.group_success": false
# 2 claimed Problems, 1 Blame, 1 Denied.
"outcome.mastery": 0
# POINTS, not card count (F28, ruled by ground-game 2026-08-08):
# start from the shared point total (4), 1 point per Blame token,
# 1 point per Denied Problem.
#
# **This scenario asserted 0** — 2 claimed CARDS 1 1 — which is
# the reading the clarified Modes.csv now rules out. The number moved
# because the rule was decided, not because the engine drifted, and
# the gate went red on exactly this line.
"outcome.mastery": 2
"outcome.winners": []
# GR-R09: the game ended rather than advancing to Round 6.
"round": 5

View file

@ -196,3 +196,57 @@ their own.
§3.1 would now forbid. They were reported on 2026-07-30, before the rule
existed. They are grandfathered rather than rewritten, and the debt is a
reported metric with a target of zero.
- **F28 — SHARED GROUND's mastery rating counts cards where the mode
card counts points.** *"All claimed Problem cards form one shared score.
… For a mastery rating, subtract 1 for each Blame token still in play
and 1 for each Denied Problem."* The shared score is claimed **value**
(`total`); `mastery` subtracts the same penalties from the claimed
**count**. Both readings fit the sentence and they differ on every game
where a 3-point Problem is claimed. Ours to report, theirs to rule.
**Sensitivity:** vary only the point value of the claimed Problems and
the gap moves with `sum(value) - count`. The two readings agree exactly
when every claimed Problem is worth 1 — no Problem in the edition is —
or when nothing is claimed, which is a loss. Everything else is held
fixed: same board, same penalties, same threshold.
**RULED and APPLIED 2026-08-08.** ground-game: *"points."* `Modes.csv`
MODE_COOP clarified upstream to read *"start from that shared point
total and subtract 1 point for each Blame token still in play and 1
point for each Denied Problem (penalties apply to points, not card
count)."* The engine now computes `total blame denied`.
**A recorded scenario went red on it**, which is the gate working:
`gr-e02-shared-ground` pinned mastery 0 (2 claimed cards 1 1) and
now expects 2 (4 points 1 1). The number moved because the rule was
decided, not because the engine drifted, and the scenario says so.
- **F29 — SCN_01 and SCN_02 are the same board.** Identical suit and
value at every priority; every measured cell matches exactly at every
seat band under both policies. **Not called a defect** — a reskin is a
legitimate design choice — but "four scenarios" is three boards, and a
study treating them as four independent samples double-counts one.
`inconsistent` because two artifacts that present as distinct are not;
the register does not have a kind for "intended duplication", and
inventing one before ground-game rules would be answering for them.
**Sensitivity:** none — this is an identity, not a measurement. It
holds for every seed and every seat band by construction, and the test
is a characterisation so a future divergence is a decision.
**RULED 2026-08-08:** *not* an intended reskin. ground-game will
re-tune SCN_02's suits and/or values under a content workplan. The
characterisation test stays as-is until they do — when the decks
diverge it goes red, which is exactly the notification we want.
**APPLIED 2026-08-08, upstream.** SCN_02's suits were re-tuned the same
day: priorities 14 are now Change / Clarify / Boundary / Repair
against SCN_01's Clarify / Boundary / Repair / Change. Re-measured, it
is its own board — 2p group success **73** where it read 67 as SCN_01's
twin.
**The characterisation test is how we found out.** It pinned the
duplication, went red on the re-tune, and that red was the
notification. It now asserts every pair distinct — the stronger
statement the duplication had made unavailable.

View file

@ -53,11 +53,11 @@ kinds, states and metrics: [`GameDesign.md`](GameDesign.md). Reported by
| F21 | degenerate | note | — | — | 2026-08-06 | clay-borg |
| F23 | inconsistent | applied | decisions/ADR-0017-chaos-window-2-verdict.md | counterexample | 2026-08-07 | clay-borg |
| F22 | underdetermined | withdrawn | games_ground::edition::supply_tests::play_never_exceeds_the_components_the_box_holds | counterexample | 2026-08-07 | clay-borg |
| F26 | inert | reported | `crates/cb-render-html/src/lib.rs::a_scoped_table_says_what_a_scope_does` | counterexample | 2026-08-08 | ground-game |
| F26 | inert | ruled | `crates/cb-render-html/src/lib.rs::a_scoped_table_says_what_a_scope_does` | counterexample | 2026-08-08 | ground-game |
| F27 | unplayed | reported | `games/ground/examples/scenario-panel.rs` | counterexample | 2026-08-08 | clay-borg |
| F29 | inconsistent | reported | `games_ground::edition::card_text_tests::which_scenarios_are_mechanically_distinct` | counterexample | 2026-08-08 | ground-game |
| F30 | degenerate | reported | `games/ground/examples/scenario-panel.rs` | counterexample | 2026-08-08 | ground-game |
| F28 | underdetermined | reported | `games_ground::tests::the_mastery_rating_and_the_shared_score_count_different_things` | counterexample | 2026-08-08 | ground-game |
| F29 | inconsistent | applied | `games_ground::edition::card_text_tests::which_scenarios_are_mechanically_distinct` | counterexample | 2026-08-08 | ground-game |
| F30 | degenerate | ruled | `games/ground/examples/scenario-panel.rs` | counterexample | 2026-08-08 | ground-game |
| F28 | underdetermined | applied | `games_ground::tests::the_mastery_rating_and_the_shared_score_count_different_things` | counterexample | 2026-08-08 | ground-game |
<!-- design-register:end -->
@ -66,19 +66,6 @@ Prose for **closed** findings (withdrawn or applied) lives in
are the whole register and `make design` reads them from here.
- **F29 — SCN_01 and SCN_02 are the same board.** Identical suit and
value at every priority; every measured cell matches exactly at every
seat band under both policies. **Not called a defect** — a reskin is a
legitimate design choice — but "four scenarios" is three boards, and a
study treating them as four independent samples double-counts one.
`inconsistent` because two artifacts that present as distinct are not;
the register does not have a kind for "intended duplication", and
inventing one before ground-game rules would be answering for them.
**Sensitivity:** none — this is an identity, not a measurement. It
holds for every seed and every seat band by construction, and the test
is a characterisation so a future divergence is a decision.
- **F30 — SCN_04 is materially harder at 2 players.** 52/100 group
success against 67 and 73, with **every other parameter held by the
edition itself**: same deal shape, same 6 available points, same
@ -95,6 +82,11 @@ are the whole register and `make design` reads them from here.
effect is specific to the 2p deal, which is the band where the deck has
fewest cards to route around a suit it cannot match.
**RULED 2026-08-08:** acceptable variety for now; SCN_04 stands as a
harder board and is monitored. If table feel proves too swingy the
first lever is priority-2's suit (dropping the double Repair), **not**
the global thresholds — which also confirms our reading that the suit
multiset is the operative difference, without our having measured it.
- **F27 — the two competitive modes are scoring lenses over cooperative
play.** `scenario-panel` finds group success *exactly* equal across
SHARED GROUND, COMMON PROBLEM and BONDED COALITIONS in all 36 cells.
@ -135,20 +127,12 @@ are the whole register and `make design` reads them from here.
policy models a *rival* playing their objective, so a competitive mode
in which nobody anticipates an opponent remains a weak test of that
mode (CB-WP-0049 "Not done here").
- **F28 — SHARED GROUND's mastery rating counts cards where the mode
card counts points.** *"All claimed Problem cards form one shared score.
… For a mastery rating, subtract 1 for each Blame token still in play
and 1 for each Denied Problem."* The shared score is claimed **value**
(`total`); `mastery` subtracts the same penalties from the claimed
**count**. Both readings fit the sentence and they differ on every game
where a 3-point Problem is claimed. Ours to report, theirs to rule.
**Sensitivity:** vary only the point value of the claimed Problems and
the gap moves with `sum(value) - count`. The two readings agree exactly
when every claimed Problem is worth 1 — no Problem in the edition is —
or when nothing is claimed, which is a loss. Everything else is held
fixed: same board, same penalties, same threshold.
**The seat-band explanation is answered, 2026-08-08.** ground-game:
the two-relation-slot limit is an **intentional cap** on complexity and
play time; a third slot stays an extension rather than core r0. So the
6p flatness is designed, not a defect — and our sensitivity run is
welcome but would be measuring an extension, not the shipped game.
- **F26 — a package that adds a FILE is invisible, where a package that
adds a column is not.** `h2-scoped-problem-stress` ships
`Rules_Text.csv` — twenty-two passages of player-facing rules, including
@ -169,6 +153,10 @@ are the whole register and `make design` reads them from here.
it needed (CB-WP-0046); the other twenty-one remain unread and that is
the standing evidence.
**RULED 2026-08-08:** accepted as a process ask. Catalog and modules
will declare `consumed_files` / overlays so a consumer reading none of
a package's files is a detectable state. Tracked on their side under
GROUND-WP-0008.
- **F17 — ATTACK cannot affect whether the table succeeds.** Reported
from play as *"there is no incentive to play attacks as long as I have
positive cards"*, and **the artifact now exists**:

View file

@ -28,9 +28,13 @@ precisely the case a maintained list loses.
files upstream does not have. `edition-check` reports both, and a sync
tool that silently resolved them would remove the only signal that the
mirror and upstream disagree about what exists.
- It does not touch `editions/ground-darvo-r0/` except to write the
digest block. That directory is the baseline package (ADR-0011) and its
own provenance is a separate record.
- It does not delete or add; see above. It **does** refresh the baseline
package's CSVs, which the first version refused to do on the reasoning
that `ground-darvo-r0/` is "a separate record". That was wrong within
the hour: ground-game clarified `Modes.csv` and `make vendor` reported
a clean sync while `make edition-check` went red on it. **A sync tool
that covers less than the check it exists to satisfy is a tool that
reports success into a red gate.**
"""
import hashlib
@ -51,6 +55,20 @@ def digest(path):
return hashlib.sha256(open(path, "rb").read()).hexdigest()
def edition_csvs():
"""The baseline package's own CSVs, as bare filenames.
Mirrors `edition-check`'s `vendored_files()`, including its limit:
only `.csv`. A non-CSV added to that directory is invisible to both,
which is recorded as a known hole rather than fixed here.
"""
return sorted(
(n, os.path.join(EDITION_DIR, n))
for n in os.listdir(EDITION_DIR)
if n.endswith(".csv")
)
def siblings():
"""Every file beside the edition directory, as `../`-relative paths.
@ -77,6 +95,16 @@ def refresh():
return 1
copied, missing, extra = [], [], []
# The baseline package first: it is the one `edition-check` checks
# by a different code path, and the one this tool used to skip.
for name, full in edition_csvs():
up = os.path.join(UPSTREAM, "ground-darvo-r0", name)
if not os.path.exists(up):
extra.append(f"ground-darvo-r0/{name}")
continue
if digest(up) != digest(full):
shutil.copy2(up, full)
copied.append(f"ground-darvo-r0/{name}")
for rel, full in siblings():
up = os.path.normpath(os.path.join(UPSTREAM, rel.replace("../", "", 1)))
if not os.path.exists(up):
@ -102,16 +130,57 @@ def refresh():
if not os.path.exists(here):
missing.append(rel)
rows = [(digest(full), rel) for rel, full in siblings()]
rows.sort(key=lambda r: r[1])
block = "\n".join(f"sha256 {h} {r}" for h, r in rows)
# Two digest fences, and **which holds which is fixed by the prose
# above them, not sniffed from their contents.**
#
# The first version detected the current arrangement and preserved
# it — which faithfully preserved a swap an earlier buggy write had
# introduced, leaving each fence under a heading describing the other
# one. `edition-check` reads every `sha256` line and so passed
# throughout: a document can be self-consistently wrong and green.
#
# Order is now asserted. `SIBLING_FENCE` is the fence whose prose is
# about the packages beside the edition; it is the second in the file
# and this refuses to write if that stops being true.
text = open(PROVENANCE, encoding="utf-8").read()
a = text.index("```\nsha256")
b = text.index("```", a + 3) + 3
open(PROVENANCE, "w", encoding="utf-8").write(
text[:a] + "```\n" + block + "\n```" + text[b:]
fences = []
i = 0
while True:
j = text.find("```", i)
if j < 0:
break
fences.append(j)
i = j + 3
if len(fences) < 4:
raise SystemExit(
f"{PROVENANCE}: expected two digest fences, found {len(fences) // 2}"
)
edition_fence, sibling_fence = fences[0], fences[2]
# The heading immediately above the sibling fence must be about
# siblings, or the file has been reorganised and this tool would be
# writing digests under the wrong claim.
lead = text[max(0, sibling_fence - 400) : sibling_fence]
if "Digests" not in lead and "beside" not in lead and "outside" not in lead:
raise SystemExit(
f"{PROVENANCE}: the second fence is not the sibling digest block; "
"the file was reorganised and this tool will not guess"
)
rows_edition = sorted(
((digest(full), name) for name, full in edition_csvs()), key=lambda r: r[1]
)
rows_sibling = sorted(
((digest(full), rel) for rel, full in siblings()), key=lambda r: r[1]
)
rows = rows_edition + rows_sibling
out = text
# Last fence first, so earlier offsets stay valid.
for start, rowset in ((sibling_fence, rows_sibling), (edition_fence, rows_edition)):
end = out.index("```", start + 3) + 3
body = "\n".join(f"sha256 {h} {r}" for h, r in rowset)
out = out[:start] + "```\n" + body + "\n```" + out[end:]
open(PROVENANCE, "w", encoding="utf-8").write(out)
print("vendor-editions — the mirror, and what it now records")
print(f" refreshed from upstream {len(copied)}")
@ -152,6 +221,16 @@ def recorded_paths():
return sorted(out)
def recorded_all():
"""Every path the digest blocks name, siblings and edition alike."""
text = open(PROVENANCE, encoding="utf-8").read()
return sorted(
line.split()[2]
for line in text.splitlines()
if len(line.split()) == 3 and line.split()[0] == "sha256"
)
def self_test():
"""A sync tool that cannot detect an unrecorded file is decoration.
@ -192,6 +271,31 @@ def self_test():
disk = set(found)
check("every vendored file has a recorded digest", not (disk - rec),
f"unrecorded: {sorted(disk - rec)}" if disk - rec else "")
check("the baseline package's CSVs are recorded too",
set(n for n, _ in edition_csvs()) <= set(recorded_all()),
"the first version skipped ground-darvo-r0/ and reported a clean "
"sync while edition-check went red on Modes.csv")
# **Each fence under its own heading** — the control that was
# missing. An earlier write swapped the two blocks and everything
# stayed green, because `edition-check` reads every `sha256` line and
# does not care which fence it came from. A document can be
# self-consistently wrong and pass every check that reads it flat.
text = open(PROVENANCE, encoding="utf-8").read()
fences = []
i = 0
while True:
j = text.find("```", i)
if j < 0:
break
fences.append(j)
i = j + 3
first_body = text[fences[0] : text.index("```", fences[0] + 3)]
second_body = text[fences[2] : text.index("```", fences[2] + 3)]
check("the first digest fence holds the edition's own CSVs",
" ../" not in first_body and "sha256" in first_body)
check("the second digest fence holds the siblings",
all(" ../" in ln for ln in second_body.splitlines() if "sha256" in ln))
check("no digest is recorded for a file that is not here", not (rec - disk),
f"recorded but absent: {sorted(rec - disk)}" if rec - disk else "")