@cratis/pi 7.118.0 → 7.119.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/package/corpus/agents/screenplay-modeler.md +1 -0
  2. package/package/corpus/harnesses/copilot/instructions/profiles.instructions.md +1 -1
  3. package/package/corpus/harnesses/pi/agents/screenplay-modeler.md +1 -0
  4. package/package/corpus/hooks/scripts/cratis-cleanup-worktrees.sh +4 -4
  5. package/package/corpus/hooks/scripts/cratis-slice-scope-report.sh +2 -1
  6. package/package/corpus/hooks/scripts/validate-type-references.sh +2 -2
  7. package/package/corpus/rules/profiles.md +1 -1
  8. package/package/corpus/skills/cratis-engineering-review-rounds/SKILL.md +22 -0
  9. package/package/corpus/skills/cratis-engineering-review-rounds/verification.json +2 -1
  10. package/package/corpus/skills/cratis-orchestration-merge-gates/LICENSE +2 -0
  11. package/package/corpus/skills/cratis-orchestration-merge-gates/SKILL.md +100 -0
  12. package/package/corpus/skills/cratis-orchestration-merge-gates/references/merge-queue.md +69 -0
  13. package/package/corpus/skills/cratis-orchestration-merge-gates/references/unattended-guards.md +66 -0
  14. package/package/corpus/skills/cratis-orchestration-merge-gates/verification.json +17 -0
  15. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/capture-map-and-example.md +7 -0
  16. package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +5 -1
  17. package/package/corpus/skills/cratis-screenplay-command-surface/references/date-comparisons.md +16 -0
  18. package/package/corpus/skills/cratis-screenplay-command-surface/references/protected-reads.md +2 -0
  19. package/package/corpus/skills/cratis-screenplay-event-modeling/SKILL.md +5 -3
  20. package/package/corpus/skills/cratis-screenplay-event-modeling/verification.json +4 -0
  21. package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-tools.md +1 -0
  22. package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/SKILL.md +1 -1
  23. package/package/corpus/skills/cratis-screenplay-projections/SKILL.md +4 -1
  24. package/package/corpus/skills/cratis-screenplay-read-surface/SKILL.md +1 -1
  25. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +8 -0
  26. package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +2 -0
  27. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/consistency-and-concurrency.md +5 -0
  28. package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +5 -0
  29. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +13 -2
  30. package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +3 -0
  31. package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +1 -1
  32. package/package/profile-catalog.json +2 -1
  33. package/package.json +1 -1
@@ -35,6 +35,7 @@ After reading these instructions, read each file listed under `process.agents.sc
35
35
 
36
36
  - Reuse existing model/workspace roots. Code-only `Source/` or `src/` is not a model root; absent model/workspace state, use repository-root `Screenplay/`, never `.cratis/`. Read model-authoring's MCP root-selection/version guidance before switching roots.
37
37
  - Load `cratis-screenplay-modeling-lifecycle`, then exactly one phase skill per step: discovery, slice design, streams and consistency, automations and translations, scenario coverage. A legacy system enters through `cratis-screenplay-legacy-extraction` instead of discovery and modeling; later runs re-enter by recorded source identity, widen the candidate in layered passes, and promote locators, decisions and open questions into notes and `documentation` before acceptance (`references/re-entry-and-passes.md` there). Syntax, versions and verdict commands: `cratis-screenplay-toolchain`. Load the phase skill before authoring a construct family.
38
+ - A new model starts its application root with `command reads protected`; leave the preamble out only when the model's reads are not admissible (PLAY0781/PLAY0786, `cratis-screenplay-command-surface` `references/protected-reads.md`).
38
39
  - For a change to an existing model, start from an impact walkthrough (`cratis-screenplay-model-review` `references/walkthrough.md`) so the brief names every affected slice.
39
40
  - Write declarations in story order, one slice after another, never batched by kind. After each batch read `PLAY0516` and `PLAY0517` and repair, or record why the order stays (`cratis-screenplay-slice-design` `references/slicing.md`).
40
41
  - Slices under delivery: where a delivery plan exists (`cratis-screenplay-delivery-planning`), a slice that is `in progress`, `blocked` or `done` is read-only unless the request names it; naming it approves exactly those declarations. Do the rest of the request, return an edit request naming the slice, its status and the intended change, and open the report with that part as NOT done. Changing a `done` slice reopens its delivery: tell the plan owner (`cratis-screenplay-modeling-lifecycle` `references/phases.md`).
@@ -99,7 +99,7 @@ profile includes neither Screenplay nor Stage.
99
99
  | `cratis/engineering/go` | Go framework parity and immutable module releases | `cratis/engineering/core`, `cratis/language/go` |
100
100
  | `cratis/engineering/typescript` | TypeScript engineering conventions | `cratis/engineering/core` |
101
101
  | `cratis/engineering/react` | React engineering conventions | `cratis/engineering/core` |
102
- | `cratis/orchestration` | Multi-session lane coordination: `cratis-orchestration-lanes` | `cratis/engineering/core` |
102
+ | `cratis/orchestration` | Multi-session lane coordination: `cratis-orchestration-lanes`, `cratis-orchestration-merge-gates` | `cratis/engineering/core` |
103
103
 
104
104
  The `cratis/orchestration` profile is opt-in: select it explicitly for work with two or more autonomous lanes; `cratis/engineering` and `cratis` do not include it.
105
105
 
@@ -30,6 +30,7 @@ After reading these instructions, read each file listed under `process.agents.sc
30
30
 
31
31
  - Reuse existing model/workspace roots. Code-only `Source/` or `src/` is not a model root; absent model/workspace state, use repository-root `Screenplay/`, never `.cratis/`. Read model-authoring's MCP root-selection/version guidance before switching roots.
32
32
  - Load `cratis-screenplay-modeling-lifecycle`, then exactly one phase skill per step: discovery, slice design, streams and consistency, automations and translations, scenario coverage. A legacy system enters through `cratis-screenplay-legacy-extraction` instead of discovery and modeling; later runs re-enter by recorded source identity, widen the candidate in layered passes, and promote locators, decisions and open questions into notes and `documentation` before acceptance (`references/re-entry-and-passes.md` there). Syntax, versions and verdict commands: `cratis-screenplay-toolchain`. Load the phase skill before authoring a construct family.
33
+ - A new model starts its application root with `command reads protected`; leave the preamble out only when the model's reads are not admissible (PLAY0781/PLAY0786, `cratis-screenplay-command-surface` `references/protected-reads.md`).
33
34
  - For a change to an existing model, start from an impact walkthrough (`cratis-screenplay-model-review` `references/walkthrough.md`) so the brief names every affected slice.
34
35
  - Write declarations in story order, one slice after another, never batched by kind. After each batch read `PLAY0516` and `PLAY0517` and repair, or record why the order stays (`cratis-screenplay-slice-design` `references/slicing.md`).
35
36
  - Slices under delivery: where a delivery plan exists (`cratis-screenplay-delivery-planning`), a slice that is `in progress`, `blocked` or `done` is read-only unless the request names it; naming it approves exactly those declarations. Do the rest of the request, return an edit request naming the slice, its status and the intended change, and open the report with that part as NOT done. Changing a `done` slice reopens its delivery: tell the plan owner (`cratis-screenplay-modeling-lifecycle` `references/phases.md`).
@@ -98,16 +98,16 @@ if [ "$SELFTEST" = 1 ]; then
98
98
  chk "fresh worktree kept" '[ -d "$t/wt-fresh" ]'
99
99
  chk "fresh branch kept" 'git rev-parse -q --verify refs/heads/fresh >/dev/null'
100
100
  chk "main kept" 'git rev-parse -q --verify refs/heads/main >/dev/null'
101
- chk "report names the removal" 'printf "%s" "$out" | grep -q "removed worktree"'
101
+ chk "report names the removal" 'grep -q "removed worktree" <<<"$out"'
102
102
  chk "work records kept" '[ -f "$t/wt-records/.ai-work/.handoff" ]'
103
103
  chk "work records branch kept" 'git rev-parse -q --verify refs/heads/records >/dev/null'
104
- chk "work records reason reported" 'printf "%s" "$out" | grep -Fq "has untracked work records (.ai-work/)"'
104
+ chk "work records reason reported" 'grep -Fq "has untracked work records (.ai-work/)" <<<"$out"'
105
105
  chk "empty work records removed" '[ ! -d "$t/wt-empty-records" ]'
106
106
  chk "locked worktree kept" '[ -d "$t/wt-locked" ]'
107
107
  chk "locked branch kept" 'git rev-parse -q --verify refs/heads/locked >/dev/null'
108
- chk "locked reason reported" 'printf "%s" "$out" | grep -Fq "worktree $t/wt-locked (locked): locked"'
108
+ chk "locked reason reported" 'grep -Fq "worktree $t/wt-locked (locked): locked" <<<"$out"'
109
109
  chk "locked detached kept" '[ -d "$t/wt-locked-detached" ]'
110
- chk "locked detached reported" 'printf "%s" "$out" | grep -Fq "worktree $t/wt-locked-detached (detached): locked"'
110
+ chk "locked detached reported" 'grep -Fq "worktree $t/wt-locked-detached (detached): locked" <<<"$out"'
111
111
  out=$(printf '%s' '{"hook_event_name":"SessionStart"}' | "$self" --no-fetch --include-work-records --hook 2>&1) || { echo "FAIL: hook exit $?"; echo "$out"; exit 1; }
112
112
  chk "hook ignores opt-in" '[ -f "$t/wt-records/.ai-work/.handoff" ]'
113
113
  out=$("$self" --no-fetch --include-work-records 2>&1) || { echo "FAIL: opt-in exit $?"; echo "$out"; exit 1; }
@@ -32,7 +32,8 @@ while IFS= read -r slice; do
32
32
  done <<EOF
33
33
  $changed
34
34
  EOF
35
- if printf '%s\n' "$changed" | LC_ALL=C grep -Fxq "$anchor"; then
35
+ # A here-string, never `printf … | grep -q`: under `pipefail` the early-exiting `grep -q` can SIGPIPE `printf`.
36
+ if LC_ALL=C grep -Fxq "$anchor" <<<"$changed"; then
36
37
  spec_paths="$(printf '%s\n' "$paths" | CRATIS_SLICE="$slice/" awk '
37
38
  index($0, ENVIRON["CRATIS_SLICE"]) == 1 && /\/when_[^\/]+(\/|\.cs$)/ { print }
38
39
  ')"
@@ -270,9 +270,9 @@ AWK
270
270
 
271
271
  if [[ "$self_test" == 1 ]]; then
272
272
  flags="$(grep '^FLAG' "$tmp/out.txt" 2>/dev/null || true)"
273
- printf '%s\n' "$flags" | grep -q $'\tReactorSideEffect\t' \
273
+ grep -q $'\tReactorSideEffect\t' <<<"$flags" \
274
274
  || { printf 'ai-corpus type-references self-test: FAILED - the seeded ReactorSideEffect fabrication was not flagged\n' >&2; exit 1; }
275
- if printf '%s\n' "$flags" | grep -qE $'\t(EventForEventSourceId|IReactor|ReactorSideEffectFailure)\t'; then
275
+ if grep -qE $'\t(EventForEventSourceId|IReactor|ReactorSideEffectFailure)\t' <<<"$flags"; then
276
276
  printf 'ai-corpus type-references self-test: FAILED - a real Cratis type was flagged as unresolved\n' >&2; exit 1
277
277
  fi
278
278
  printf 'ai-corpus type-references self-test: passed - the seeded fabrication is named and the real types stay silent\n' >&2
@@ -98,7 +98,7 @@ profile includes neither Screenplay nor Stage.
98
98
  | `cratis/engineering/go` | Go framework parity and immutable module releases | `cratis/engineering/core`, `cratis/language/go` |
99
99
  | `cratis/engineering/typescript` | TypeScript engineering conventions | `cratis/engineering/core` |
100
100
  | `cratis/engineering/react` | React engineering conventions | `cratis/engineering/core` |
101
- | `cratis/orchestration` | Multi-session lane coordination: `cratis-orchestration-lanes` | `cratis/engineering/core` |
101
+ | `cratis/orchestration` | Multi-session lane coordination: `cratis-orchestration-lanes`, `cratis-orchestration-merge-gates` | `cratis/engineering/core` |
102
102
 
103
103
  The `cratis/orchestration` profile is opt-in: select it explicitly for work with two or more autonomous lanes; `cratis/engineering` and `cratis` do not include it.
104
104
 
@@ -94,6 +94,28 @@ change addressing the failure class or ask the user about the approach. Use
94
94
  A structural change does not authorize an automatic fourth round or waive any
95
95
  required review; report the remaining blocker or required decision.
96
96
 
97
+ ## Contract
98
+
99
+ A caller that schedules a round supplies these inputs. Resolve every SHA with
100
+ `git rev-parse`; never expand a short prefix by hand.
101
+
102
+ | Input | Meaning | Required |
103
+ | --- | --- | --- |
104
+ | `target` | The pull request, branch or work item under review | Always |
105
+ | `round` | Round number within the work item's cap of 3 | Always |
106
+ | `baseSha` | Full SHA of the original base | Always |
107
+ | `headSha` | Full SHA of the head being reviewed | Always |
108
+ | `since` | Full SHA of the head last reviewed | Delta rounds |
109
+ | `prior` | The complete previous report, with dismissals and limits | Delta rounds |
110
+ | `cachedReview` | An earlier review to reuse | Only for the exact same SHAs and scope |
111
+ | `mode` | `whole-change` or `delta`; quick, ordinary or deep depth | Always |
112
+ | `deepReason` | One named risk class and a one-line justification | Required when the depth is deep |
113
+
114
+ The result is one verdict from the canonical vocabulary in `review-reports.md`:
115
+ **Approved**, **Approved with suggestions**, **Changes requested** or
116
+ **Incomplete**. A provider or tool error yields **Incomplete**, never an
117
+ approval and never an invented verdict.
118
+
97
119
  ## What breaks
98
120
 
99
121
  - **A whole-change restart after every correction:** repeats work while losing
@@ -11,6 +11,7 @@
11
11
  { "kind": "skill-contains", "value": "3 rounds per work item" },
12
12
  { "kind": "skill-contains", "value": "Never file an issue merely to dispose of advisory feedback" },
13
13
  { "kind": "skill-contains", "value": "single-provider" },
14
- { "kind": "skill-contains", "value": "**cross-cutting**" }
14
+ { "kind": "skill-contains", "value": "**cross-cutting**" },
15
+ { "kind": "skill-contains", "value": "A provider or tool error yields **Incomplete**" }
15
16
  ]
16
17
  }
@@ -0,0 +1,2 @@
1
+ Copyright (c) Cratis. All rights reserved.
2
+ Licensed under the MIT license. See LICENSE file in the canonical Cratis/AI repository for the full license text.
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: cratis-orchestration-merge-gates
3
+ description: Decide when an assembled candidate may merge during multi-lane work, using tier names, GitHub state for serial merge turns, a stale-head check, the review budget and an unattended no-prompt contract. Use when naming the gate tier for a lane, deciding whether it is this pull request's turn to merge, checking that a green run belongs to the current head, bounding review rounds for a lane, or making a command safe to run unattended. Not for ordinary single-session merging (use cratis-engineering-ci-gates), lane claims and briefs (use cratis-orchestration-lanes), review rounds themselves (use cratis-engineering-review-rounds), or grouping a release candidate (use cratis-engineering-release-trains).
4
+ license: LICENSE
5
+ compatibility: Requires git and the GitHub CLI (gh).
6
+ ---
7
+
8
+ <!-- Copyright (c) Cratis. All rights reserved. -->
9
+ <!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
10
+
11
+ # Merge in turn, on evidence
12
+
13
+ This skill applies to multi-lane work where several pull requests merge into
14
+ one repository. A single session follows `cratis-engineering-ci-gates`.
15
+ Merging, like any external effect, needs the user's request or brief to
16
+ authorize it: read
17
+ [capability-is-not-authority.md](../../rules/capability-is-not-authority.md).
18
+ Placeholders such as `<coordinator>` and the default time boxes come from
19
+ `cratis-orchestration-lanes` and its
20
+ [placeholders.md](../cratis-orchestration-lanes/references/placeholders.md);
21
+ they are not redefined here.
22
+
23
+ ## Tier names
24
+
25
+ Lanes use short names for the gates already defined in
26
+ `cratis-engineering-ci-gates`. That skill owns the gate content; this table only
27
+ maps names.
28
+
29
+ | Lane term | Gate | When |
30
+ |---|---|---|
31
+ | Iteration | Affected checks | While editing, per lane |
32
+ | Ready to merge | Tier 1 on the assembled candidate | Before asking for a merge turn |
33
+ | Integration | Tier 2 or CI | On the pushed head, before merge |
34
+
35
+ A lane's own green iteration result is never ready-to-merge evidence for the
36
+ assembled candidate.
37
+
38
+ ## Serial merge is decided by GitHub state
39
+
40
+ Merge turns are decided by GitHub state, never by a chat or inbox message
41
+ saying "go". Merge only when all three hold, each read from GitHub or git just
42
+ before the merge:
43
+
44
+ 1. **Predecessors are merged.** Every predecessor pull request the candidate
45
+ depends on is `MERGED`, not merely approved or green.
46
+ 2. **No publish is running.** No publish run of the repository is queued or
47
+ in progress. A merge during a publish can race the release or be released
48
+ under an unexpected version.
49
+ 3. **No overlap since CI ran.** Main has no changes touching the candidate's
50
+ paths since the commit its CI ran on:
51
+ `git log <ci-sha>..origin/main -- <paths>` prints nothing.
52
+
53
+ If any check fails, do not merge and do not wait in a loop: report which check
54
+ failed and the evidence, then hand the turn back to `<coordinator>`. Read
55
+ [references/merge-queue.md](references/merge-queue.md) for the `gh api`
56
+ commands and a worked example.
57
+
58
+ ## Green but stale
59
+
60
+ A green run on an older head is not evidence for the current head. Before
61
+ merging, compare the full SHA of the pull request head with the head SHA of the
62
+ run you rely on. Different SHAs mean the run proves nothing: wait for or start
63
+ the run for the current head, following `cratis-engineering-ci-gates`. The same
64
+ applies after a base update: a run on the pre-update head is stale.
65
+
66
+ ## Review budget
67
+
68
+ Review rounds follow `cratis-engineering-review-rounds`, including its
69
+ **Contract** table of round inputs and result states. The cap is 3 rounds per
70
+ work item; a brief may lower it, never raise it. A review that fails on a
71
+ provider or tool error is Incomplete, not approval, and does not open an extra
72
+ round.
73
+
74
+ ## Unattended contract
75
+
76
+ Unattended lanes have nobody to answer a question. No hook or tool may wait for
77
+ interactive input.
78
+
79
+ - Make every command non-interactive: pass explicit flags, close stdin, and
80
+ provide values rather than prompting for them.
81
+ - Time boxes for a targeted check, a build or test phase and the detach
82
+ threshold are the defaults in the lanes skill's
83
+ [placeholders.md](../cratis-orchestration-lanes/references/placeholders.md);
84
+ the queue wait is set by the brief.
85
+ - A silent command is diagnosed, not given more time: check the process, its
86
+ output and what it waits on, then fix or report.
87
+ - Work beyond the detach threshold runs detached and reports through a
88
+ completion notification; the lane does not poll it.
89
+ - Never loosen a hook, allowlist or guard to get past a prompt. A prompt that
90
+ cannot be answered is a blocker: send a `blocked` message and stop.
91
+
92
+ Read [references/unattended-guards.md](references/unattended-guards.md) for the
93
+ checkable form of this contract.
94
+
95
+ ## Verify
96
+
97
+ - Each merge records the three state checks with the commands and results.
98
+ - The run relied on names the same full SHA as the pull request head.
99
+ - The ready-to-merge gate ran on the assembled candidate, not a lane branch.
100
+ - No command in the lane's brief waits for input or runs without a time box.
@@ -0,0 +1,69 @@
1
+ <!-- Copyright (c) Cratis. All rights reserved. -->
2
+ <!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
3
+
4
+ # Merge queue state checks
5
+
6
+ Each check reads GitHub or git state immediately before the merge. Use the REST
7
+ API through `gh api`. `owner/repo` is the repository, `<n>` a pull request
8
+ number, `<sha>` a full SHA from `git rev-parse`. Gate content and run watching
9
+ stay in `cratis-engineering-ci-gates`.
10
+
11
+ ## 1. Predecessors are merged
12
+
13
+ ```bash
14
+ gh api repos/owner/repo/pulls/<predecessor> --jq '{state: .state, merged: .merged}'
15
+ ```
16
+
17
+ Proceed only when `merged` is `true`. A closed pull request with `merged:
18
+ false` was abandoned, not delivered: stop and report it.
19
+
20
+ ## 2. No publish run is queued or in progress
21
+
22
+ ```bash
23
+ gh api "repos/owner/repo/actions/workflows/<publish-workflow>.yml/runs?status=queued" --jq '.total_count'
24
+ gh api "repos/owner/repo/actions/workflows/<publish-workflow>.yml/runs?status=in_progress" --jq '.total_count'
25
+ ```
26
+
27
+ Proceed only when both print `0`. Use the repository's own publish workflow
28
+ file name. A nonzero count is a stop: report the run ids, never cancel another
29
+ owner's publish run (see `cratis-engineering-ci-gates`).
30
+
31
+ ## 3. No overlapping change on main since CI ran
32
+
33
+ Find the commit the relied-on run used, then compare:
34
+
35
+ ```bash
36
+ ci_sha=$(gh api repos/owner/repo/actions/runs/<run-id> --jq '.head_sha')
37
+ git fetch origin main
38
+ git log --oneline "$ci_sha"..origin/main -- <candidate paths>
39
+ ```
40
+
41
+ Proceed only when `git log` prints nothing. If the CI sha is not an ancestor
42
+ of the pull request head, the run is stale; see below.
43
+
44
+ ## 4. The run belongs to the current head
45
+
46
+ ```bash
47
+ pr_head=$(gh api repos/owner/repo/pulls/<n> --jq '.head.sha')
48
+ run_head=$(gh api repos/owner/repo/actions/runs/<run-id> --jq '.head_sha')
49
+ test "$pr_head" = "$run_head"
50
+ ```
51
+
52
+ A nonzero exit means the green run is stale.
53
+
54
+ ## Worked example
55
+
56
+ Candidate pull request 12 depends on pull request 10. Its CI run 900 was green.
57
+
58
+ 1. Predecessor: `pulls/10` reports `merged: true`. Passes.
59
+ 2. Publish: both workflow queries print `0`. Passes.
60
+ 3. Overlap: run 900 used `aaa111…`; `git log aaa111…..origin/main -- Source/Api`
61
+ prints one commit, which changed `Source/Api`. Fails.
62
+
63
+ The lane does not merge. It reports "turn blocked: main changed `Source/Api`
64
+ after the CI commit" with the commit id, then hands the turn back to
65
+ `<coordinator>`. After updating the branch it needs a new run on the new head;
66
+ the old green run proves nothing for it. The merge proceeds only when the three
67
+ state checks (predecessors merged, no publish running, no overlap since CI ran)
68
+ all hold and the stale-head check confirms the run belongs to the current head.
69
+ The lane records the commands and their results with the merge.
@@ -0,0 +1,66 @@
1
+ <!-- Copyright (c) Cratis. All rights reserved. -->
2
+ <!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
3
+
4
+ # Unattended guards
5
+
6
+ An unattended lane has nobody to answer a question. The contract is checkable:
7
+ no hook or tool may wait for interactive input, and every command has a time
8
+ box.
9
+
10
+ ## The no-prompt contract
11
+
12
+ - Every command runs without a terminal prompt: explicit flags, values passed
13
+ by argument or environment, stdin closed (`< /dev/null`).
14
+ - Every command has a deadline. A hung command is killed by its box, not
15
+ waited on.
16
+ - A hook that would ask is a blocker, not an obstacle. Never loosen a hook,
17
+ allowlist or guard to avoid a prompt; report it. See
18
+ [hooks/README.md](../../../hooks/README.md) for how denials behave when no human
19
+ is present.
20
+ - Secrets are never typed into a prompt: see
21
+ [secrets.md](../../../rules/secrets.md).
22
+
23
+ ## Time boxes
24
+
25
+ The values and override bounds for the first three boxes are the defaults in
26
+ [placeholders.md](../../cratis-orchestration-lanes/references/placeholders.md);
27
+ a brief may override within those bounds. The queue wait is set by the brief.
28
+
29
+ | Box | Value from | Action at the limit |
30
+ |---|---|---|
31
+ | Targeted check | placeholders.md | Stop and diagnose |
32
+ | Build or test phase | placeholders.md | Stop and diagnose; longer needs approval |
33
+ | Detach threshold | placeholders.md | Run detached; do not wait |
34
+ | Queue wait | the brief | Send a `blocked` message |
35
+
36
+ ## A silent command is diagnosed
37
+
38
+ A command that prints nothing is not "still working". Inspect: is the process
39
+ alive, what is it waiting on (a prompt, a lock, the network), what changed in
40
+ its output directory. Fix the cause or report it; do not extend the box.
41
+
42
+ ## Detach rule
43
+
44
+ Work expected to exceed the detach threshold runs detached, with output going
45
+ to a file under `<work-root>`, and reports through a completion notification.
46
+ The lane does not poll it by hand. Where the harness has no notification, the
47
+ blocking watch described in `cratis-engineering-ci-gates` holds the wait.
48
+
49
+ ## Checkable example
50
+
51
+ A command that would prompt, made non-interactive and boxed:
52
+
53
+ ```bash
54
+ # Would prompt: gh pr merge <n> (asks how to merge)
55
+ # Non-interactive, explicit strategy, stdin closed, targeted-check box (120 seconds by default):
56
+ timeout 120 gh pr merge <n> --repo owner/repo --merge < /dev/null
57
+ echo "exit=$?"
58
+ ```
59
+
60
+ Verify it behaves: the command must return within the box and the exit code
61
+ must be explicit. Exit `124` means the box expired: diagnose, do not rerun
62
+ with a longer box. Any other nonzero exit is the command's own failure.
63
+ To prove that nothing waits on input, run the same command with stdin
64
+ closed and confirm it fails fast rather than hanging.
65
+ This example shows the form only; merging still needs the authorization and
66
+ the three state checks in the skill.
@@ -0,0 +1,17 @@
1
+ {
2
+ "skill": "cratis-orchestration-merge-gates",
3
+ "input": "Decide whether a lane's pull request may merge now, given predecessors, a running publish and a green run.",
4
+ "fixtures": [],
5
+ "assertions": [
6
+ { "kind": "skill-contains", "value": "Merge turns are decided by GitHub state" },
7
+ { "kind": "skill-contains", "value": "Every predecessor pull request the candidate" },
8
+ { "kind": "skill-contains", "value": "No publish run of the repository is queued or" },
9
+ { "kind": "skill-contains", "value": "git log <ci-sha>..origin/main -- <paths>" },
10
+ { "kind": "skill-contains", "value": "A green run on an older head is not evidence for the current head" },
11
+ { "kind": "skill-contains", "value": "3 rounds per" },
12
+ { "kind": "skill-contains", "value": "No hook or tool may wait for" },
13
+ { "kind": "skill-contains", "value": "A silent command is diagnosed, not given more time" },
14
+ { "kind": "skill-contains", "value": "references/merge-queue.md" },
15
+ { "kind": "skill-contains", "value": "references/unattended-guards.md" }
16
+ ]
17
+ }
@@ -63,6 +63,13 @@ reference is handed records (`given capture`, `when capture`) and never contacts
63
63
  (PLAY0700). Events append to the event source the key names, and
64
64
  `$context.occurred` is supplied by the scenario's `given clock`.
65
65
 
66
+ When every consumed event declares the key as one required scalar property of the same
67
+ type (for example a concept over Uuid), the appended event's identity carries that type
68
+ instead of Text, and `for` in specifications binds as that type. A model that uses this
69
+ selects ESM v32 (Requires Screenplay 4.241.0; `screenplay --version`); untyped, non-scalar or
70
+ disagreeing keys keep Text and the earlier version. Rendering needs a Stage that admits v32:
71
+ see toolchain [language admission](../../cratis-screenplay-toolchain/references/language-admission.md).
72
+
66
73
  For a producer that sources every event by this key, declare
67
74
  `key <property> is event source` (ESM v33, Screenplay 4.242.0).
68
75
  See [Keying by the event source](#keying-by-the-event-source) below for the promise, fixture `for`
@@ -212,6 +212,8 @@ comparisons; older binders report PLAY0268. Read [date comparisons](references/d
212
212
  when ordering a retention window with `require to >= from`, comparing instants
213
213
  across offsets, or rejecting offset-less inputs before rules. It covers admitted
214
214
  positions, PLAY0268/0273, ordinal `then` matching and Stage's STAGE-ESM-046 renderer refusal.
215
+ The same file lists the parsed-but-not-runnable calendar and clock forms (`time zone`, `calendar`,
216
+ `today - 7 days`, `date of occurred`; PLAY0812 to PLAY0814): do not author them into executable models.
215
217
 
216
218
  Requires Screenplay 4.205.0 (ESM v28; `screenplay --version`) for `==`/`!=` between Uuid
217
219
  values (properties, concepts, identities, canonical literals, and read paths in `require`);
@@ -220,7 +222,9 @@ rule, PLAY0268/0273 and the refused shapes (ordering, Uuid validation rules, Uui
220
222
 
221
223
  **Rules whose logic is code.** A bare `rule <Name>` has no portable meaning (`PLAY0268`) and a bodied rule binds only as
222
224
  opaque code. Read [references/validate-rules.md](references/validate-rules.md) when a rule's logic must live in a `file`
223
- or fenced code body.
225
+ or fenced code body. Built-in inline languages are `csharp`, `typescript`, `react`, `html`, `sql` and `java`;
226
+ the body is opaque and travels unchanged, and the Cratis render target refuses `java` bodies.
227
+ Requires Screenplay 4.244.0 (`screenplay --version`) for that refusal.
224
228
 
225
229
  **Put format rules on the `concept`, not the command** (except date comparisons,
226
230
  which bind only on command properties, not as concept rules). A concept carries its own
@@ -7,6 +7,7 @@
7
7
 
8
8
  - Retention window and rejection specifications
9
9
  - Missing-offset input rejection
10
+ - Clock operands and calendars (parsed, not runnable)
10
11
 
11
12
  Requires Screenplay 4.199.0 (ESM v26; `screenplay --version`); older binders refuse date comparisons with PLAY0268. Upgrade the compiler without weakening the rule.
12
13
 
@@ -109,3 +110,18 @@ Include a skipped-condition case where applicable. A typed `.play` fixture with
109
110
  that invalid value refuses binding with PLAY0273; `then error` does not turn it
110
111
  into an executed runtime rejection. Record the target test separately, not as a
111
112
  passing `.play` specification or a `given clock` workaround.
113
+
114
+ ## Clock operands and calendars (parsed, not runnable)
115
+
116
+ Both compilers parse these forms, but executable binding refuses each with PLAY0268 and
117
+ none selects an ESM version. Do not author them into an executable model:
118
+
119
+ - application root: `time zone "<id>"` or `time zone configurable default "<id>"`;
120
+ - command: `calendar "<id>"` or `calendar from $context.<member>`;
121
+ - specification: `given time zone "<id>"`;
122
+ - condition operands: clock offsets such as `today - 7 days` and `now + 2 hours`, and
123
+ `date of occurred` or `date of now`.
124
+
125
+ Bare `today` and `now` stay ordinary property paths. PLAY0812, PLAY0813 and PLAY0814 report
126
+ a repeated or malformed time zone, command calendar and specification time zone.
127
+ Requires Screenplay 4.242.0 (`screenplay --version`) to parse them.
@@ -154,6 +154,8 @@ Stage's [protected reads rendering](https://github.com/Cratis/Stage/blob/main/Do
154
154
  for the rendered shape and where it differs from the reference (a race is an Arc
155
155
  validation failure, not `DecisionStateChanged`; only the first failing requirement is reported).
156
156
 
157
+ When the same commit also violates a uniqueness constraint, the constraint refusal is the one observed, not the concurrency conflict; see the concurrency scenarios section of [consistency and concurrency](../../cratis-screenplay-streams-and-consistency/references/consistency-and-concurrency.md).
158
+
157
159
  Requires Stage 4.129.0 for semantic Host/specification-executor protected reads;
158
160
  older engines refuse STAGE-ESM-044. They require presence before requirements or
159
161
  generation and use stored read properties in requirements and produced mappings,
@@ -115,8 +115,8 @@ result are in [references/parsed-not-runnable.md](references/parsed-not-runnable
115
115
  and `cratis-screenplay-toolchain` (`references/executable-subset.md`). Read `references/parsed-not-runnable.md` when determining the required ESM version or interpreting binding dispositions. Read `cratis-screenplay-toolchain`'s `references/executable-subset.md` when checking binder admission or reference-execution limits. Model the wider
116
116
  language freely when the `.play` file **is** the deliverable - documentation,
117
117
  review, a shared description of a system. Never read a clean `screenplay` run as
118
- evidence a construct works downstream. The language is frozen at ESM v1–v28 ([the freeze decision](https://github.com/Cratis/Screenplay/blob/main/decisions/0092-the-language-is-frozen-at-esm-v28.md)): model with it, and report a typed
119
- Stage, `cratis render` or Studio refusal as a platform gap rather than waiting for new constructs.
118
+ evidence a construct works downstream. New constructs can be admitted, each byte-changing one with its own ESM version, and count as delivered once Stage admits it or refuses it with a typed refusal. Model with what the installed compiler admits, and report a typed
119
+ Stage, `cratis render` or Studio refusal as a platform gap.
120
120
 
121
121
  ## Locate the model
122
122
 
@@ -168,7 +168,9 @@ Read [references/parsed-not-runnable.md](references/parsed-not-runnable.md) (sec
168
168
  Two divergences matter, and getting them wrong produces a model that will not
169
169
  compile or will not be safe. Both are deliberate.
170
170
 
171
- - **A command may read state.** The generic method forbids `ReadModel -> Command`
171
+ - **A command may read state.** A newly scaffolded model starts its application root
172
+ with `command reads protected`; leave the preamble out only for a model whose reads are
173
+ not admissible (PLAY0781/PLAY0786). The generic method forbids `ReadModel -> Command`
172
174
  edges. Screenplay ships `reads <ReadModel> [as <alias>] [by <property>]` so the
173
175
  model shows what a state-dependent decision consulted. Application-root
174
176
  `command reads protected` admits eligible command reads as v25: absent state
@@ -50,6 +50,10 @@
50
50
  "kind": "skill-contains",
51
51
  "value": "command reads protected"
52
52
  },
53
+ {
54
+ "kind": "skill-contains",
55
+ "value": "A newly scaffolded model starts its application root"
56
+ },
53
57
  {
54
58
  "kind": "skill-contains",
55
59
  "value": "Legacy reads remain PLAY0271"
@@ -82,6 +82,7 @@ A declaration move follows these rules:
82
82
 
83
83
  - A specification that covers only the moved declaration moves with it. A specification covers a declaration when it is a matching specification of one of its `find-specification-obligations` obligations, or when its `when` step names it; a `given` or `then` reference alone is not coverage.
84
84
  - The move is refused when a specification also covers a declaration that stays, when an obligation the source slice met would no longer be met or the move would introduce an unmet obligation, on a name collision, for an inline declaration (such as an inline `produces event`), a declaration written in more than one fragment, a standalone specification, screen, constraint or module, and when an unqualified reference would resolve differently. Qualify that reference first.
85
+ - The C# workspace API refuses the same cases as `propose-move`; a refusal in either surface reports the standard `ProposalRejected` failure kind with the usual rejection fields. Carried specifications are computed automatically; a supplied list must match them (Requires Screenplay 4.241.0, `screenplay --version`).
85
86
  - Screen `execute`, `refresh` and `navigate to` targets that name the declaration are repaired, not moved.
86
87
  - Slice-level events named by `produces` do not travel with a command, and a projection's `from` may name an event declared in another slice; move such an event with its own `propose-move` only when it should change slices. A command's inline events go with it.
87
88
  - Event names and pins stay untouched, and assigned identities follow the declaration.
@@ -45,7 +45,7 @@ an unproven pass.
45
45
  | Situation | Level | Where the work goes |
46
46
  |---|---|---|
47
47
  | An accepted model covers the scope | **Model** | Change the `.play`, verify V1-V3, review, then render or gap-fill |
48
- | Opted in, but this scope has no model yet | **Model** | New behavior starts in discovery, then slice design |
48
+ | Opted in, but this scope has no model yet | **Model** | New behavior starts in discovery, then slice design; a new model's application root starts with `command reads protected` (omit it only when the reads are not admissible, PLAY0781/PLAY0786) |
49
49
  | A computed rule inside a modeled slice | **Model + code attachment** | `csharp`/`file` block; it binds only as the construct allows (`cratis-screenplay-model-authoring`) |
50
50
  | Scope Stage cannot render yet (Stage renders supported event-triggered Automation and bounded source-event capture/outbound Translate paths; refused shapes remain gap-fill. Mixed effects stay one reaction, `STAGE-ESM-037`; a hand-written realization must prove retry safety) | **Gap-fill code** | Hand-written; the `.play` slice and specs are the contract. `cratis-screenplay-render-and-gap-fill` separates an authorized existing generated base from fully hand-written delivery |
51
51
  | Outside call, transport or credentials | **Adapter code** | `Customizations/` or the host, applying `cratis-engineering-effect-boundaries` |
@@ -255,7 +255,10 @@ reducer Balance => AccountBalance
255
255
  ````
256
256
 
257
257
  Inline code uses a tagged fence (` ```csharp `); a `csharp` line above a bare
258
- fence still parses but warns (`PLAY0397`). Reach for a reducer only when the next
258
+ fence still parses but warns (`PLAY0397`). Built-in inline languages are `csharp`,
259
+ `typescript`, `react`, `html`, `sql` and `java`; the body is opaque and travels unchanged
260
+ to the target, and the Cratis render target refuses `java` bodies.
261
+ Requires Screenplay 4.244.0 (`screenplay --version`) for that refusal. Reach for a reducer only when the next
259
262
  state depends on the current one — a running balance, a state machine.
260
263
  `context.State` is **null for the first event** and is the only nullable member;
261
264
  `Event`, `Key`, `Tenant`, `Occurred`, `SequenceNumber` and `IsFirst` are always
@@ -164,7 +164,7 @@ A query is **complete without a performer** — it is realization metadata, not
164
164
  precondition. It takes a `file` reference or an inline block in a tagged fence
165
165
  (` ```csharp `, ` ```sql `), and is the query's counterpart to a command's
166
166
  `handler`. The parser accepts any registered inline language and does not reject
167
- a nonsensical one, so the choice is yours to get right. Performer code is opaque:
167
+ a nonsensical one, so the choice is yours to get right. Built-in inline languages are `csharp`, `typescript`, `react`, `html`, `sql` and `java`. A performer query refuses a `by` or `filter` argument sourced from `$context` with PLAY0810 (C# binding; Requires Screenplay 4.244.0, `screenplay --version`; older compilers silently drop it): take a caller-supplied argument instead. Performer code is opaque:
168
168
  Screenplay never runs it. It is reported as information `PLAY0270` and left out of the executable model; a specification that reads it is left out while every other specification still runs. Older compilers refuse it with PLAY0268: see the [version gate](../cratis-screenplay-toolchain/references/executable-subset.md#code-attachments-what-binds-what-never-does).
169
169
 
170
170
  A read model a performer composes needs no projection, and no event builds it.
@@ -48,6 +48,11 @@ in code, not by waiting for ESM admission. Requires Screenplay 4.210.0
48
48
  older binders use PLAY0268. Read [renderability gate](references/renderability-gate.md)
49
49
  when classifying a handler or other binding refusal; never parse message text.
50
50
 
51
+ Inline bodies (`csharp`, `typescript`, `react`, `html`, `sql`, `java`) are opaque and reach the target
52
+ unchanged; each target decides which it realizes. The Cratis target refuses `java` bodies: gap-fill
53
+ that scope in code and record the refusal.
54
+ Requires Screenplay 4.244.0 (`screenplay --version`) for the `java` refusal.
55
+
51
56
  ## Interview phase
52
57
  Ask only for missing inputs: accepted model/root, stable `--name`, destination,
53
58
  non-renderable-scope decision and seams. Read [references/delivery-protocol.md](references/delivery-protocol.md)
@@ -176,6 +181,9 @@ Adapters and non-renderable scope follow the contract rules of `cratis-applicati
176
181
  - The `cratis run` sandbox's legacy EventModel engine (the default engine before CLI 3.73.0) enforces only simple literal validation rules and no
177
182
  authorization; it is no evidence for denial behaviour or for any other rule.
178
183
  - Never remove `pii`, `secret`, authorization or rules to get a render through; report the gap.
184
+ - Generated .NET apps validate concept `matches` rules at runtime with the `Cratis.Screenplay.Matching` package (`PortableMatcher`),
185
+ the matcher the compiler admitted; reference it at the same version as the Screenplay compiler.
186
+ Requires Screenplay 4.241.0 (`screenplay --version`) for that package.
179
187
  - Stop and ask only on a genuine contradiction between model, specs, descriptions and declared
180
188
  contracts, after reading the slice fully (`cratis-screenplay-modeling-lifecycle` `references/stop-or-assume.md`).
181
189
  - Commit set after a delivery the user accepts: the destination's `.cratis-render.json`,
@@ -141,6 +141,8 @@ Rules the binder enforces:
141
141
  needs one of them, `then denied` or a sole validation `then error` (`PLAY0465`). Each argument is a `by` or
142
142
  `filter` parameter of the query (`PLAY0468`).
143
143
  - **A clock instant is ISO 8601 with an offset or `Z`** (PLAY0461); one `given clock` maximum.
144
+ - **`given time zone "<id>"` is parsed, not runnable.** Executable binding refuses it with PLAY0268;
145
+ a repeated or malformed line is PLAY0814. Do not author it into an executable model.
144
146
  - **`then` contains either events or an error — never both.** A rejection
145
147
  specification has exactly one rejection and no success outcome.
146
148
  - **`then denied` stands alone**: not with events, errors or state assertions
@@ -139,6 +139,11 @@ For each enforced or recorded rule write three short scenarios:
139
139
  checks uniqueness before the commit and updates the index after it; index update failures
140
140
  are logged, not rolled back (Screenplay `constraints.md`, Chronicle#4123, open). Do not call it an
141
141
  atomic index-and-append guarantee.
142
+ When a command's protected read changed and its uniqueness constraint is violated in the same
143
+ commit, the observable refusal is the constraint refusal, not the concurrency conflict: assert
144
+ the constraint's message in the `then` expectation.
145
+ Requires Screenplay 4.245.0 (`screenplay --version`);
146
+ older reference evaluators report the concurrency conflict.
142
147
  - **retry** (same request and operation identity, after a lost reply) -> must not record a
143
148
  second occurrence, without blocking a different legitimate operation. A once-only fact uses
144
149
  `unique event`; a repeatable operation needs an operation identity and target-side
@@ -149,6 +149,11 @@ with ordered imports means future files need explicit imports.
149
149
  `references/diagnostics.md` for proof/support failures. Binding is not rendering.
150
150
  Tool/renderer authors: read [references/generation-checks.md](references/generation-checks.md)
151
151
  when discovering strategy options, checking one concept or value, or consuming rule proofs.
152
+ - **v32:** a `source events` capture with a typed scalar key carries the key's type onto
153
+ the appended event's identity.
154
+ Requires Screenplay 4.241.0 (`screenplay --version`);
155
+ older compilers keep the key as Text. Read
156
+ [language admission](references/language-admission.md) for the Stage boundary.
152
157
  - **v28:** `==`/`!=` between Uuid values in `require` and `produces when` select v28
153
158
  (Requires Screenplay 4.205.0; `screenplay --version`; older binders refuse PLAY0268).
154
159
  Read [language admission](references/language-admission.md) and command-surface
@@ -13,6 +13,7 @@
13
13
  - Chronological command date comparisons (ESM v26)
14
14
  - Flat composite read-model keys (ESM v27)
15
15
  - Uuid equality in command conditions (ESM v28)
16
+ - Parsed, not runnable: clocks, calendars and time zones
16
17
  - Code attachments (what binds, what never does)
17
18
  - Refused (code, reason): fix, or record as a mode gap
18
19
  - Not refused, but do not rely on it
@@ -45,7 +46,7 @@ Complete examples that bind live in `executable-example.md`, `pdl-example.md` (p
45
46
  For atomic batches (v22), described handlers (v23), ordinal text rules (v24) and
46
47
  protected reads (v25), chronological command dates (v26), composite keys (v27) and Uuid equality (v28), read
47
48
  [language admission](language-admission.md). A later
48
- version alone does not enable either application opt-in. The language is frozen at ESM v1–v28 ([the freeze decision](https://github.com/Cratis/Screenplay/blob/main/decisions/0092-the-language-is-frozen-at-esm-v28.md)): no new versions, constructs, keywords or grammar, except a construct for a real model that is blocked with no model-side alternative, accepted in its own record. Model with what v1–v28 offers; when Stage, `cratis render` or Studio does not support a construct yet, treat the typed refusal as a platform gap to report, since consumers are catching up to v28, not a reason to wait for new language.
49
+ version alone does not enable either application opt-in. New constructs can be admitted, each byte-changing one with its own ESM version, and count as delivered once Stage admits it or refuses it with a typed refusal. Model with what the installed compiler admits; when Stage, `cratis render` or Studio does not support a construct yet, treat the typed refusal as a platform gap to report.
49
50
 
50
51
  ## Caller and compliance boundary
51
52
 
@@ -307,6 +308,16 @@ binding and reference execution. Read command-surface
307
308
  [Uuid equality](../../cratis-screenplay-command-surface/references/uuid-equality.md) for the
308
309
  complete example.
309
310
 
311
+ ## Parsed, not runnable: clocks, calendars and time zones
312
+
313
+ Application-root `time zone` / `time zone configurable default`, command `calendar` /
314
+ `calendar from $context.<member>`, specification `given time zone`, and the condition
315
+ operands `today - 7 days`, `now + 2 hours`, `date of occurred` and `date of now` parse and
316
+ print, but executable binding refuses them with PLAY0268 and they select no ESM version.
317
+ Do not author them into executable models. PLAY0812, PLAY0813 and PLAY0814 are the
318
+ syntax diagnostics (Requires Screenplay 4.242.0; `screenplay --version`). Bare `today` and
319
+ `now` remain ordinary paths. Detail: command-surface `references/date-comparisons.md`.
320
+
310
321
  ## Code attachments (what binds, what never does)
311
322
 
312
323
  Pending `handler implementation` beside unconditional `produces` binds as a described
@@ -315,7 +326,7 @@ denial/validation specs still run. Read [language admission](language-admission.
315
326
  v22–v28 and [described handlers](../../cratis-screenplay-command-surface/references/described-handlers.md)
316
327
  for the result contract. Attached handlers remain unbound.
317
328
 
318
- Inline fences (`csharp`, `typescript`, `react`, `html`, `sql`) and `file <path>` attach
329
+ Inline fences (`csharp`, `typescript`, `react`, `html`, `sql`, `java`) and `file <path>` attach
319
330
  code to an owner. Two kinds block binding (V3 blocked, no specification runs):
320
331
  the attached command `handler` (PLAY0800) and the `file` constraint (PLAY0268, see below).
321
332
  A query `performer` does not block: it is an opaque read, reported as information
@@ -28,6 +28,7 @@ exact language/semantic pairs; binding, reference execution and rendering are se
28
28
  | v29 | `decimals <= N`; `add`/`subtract` by `a * b`; a concept mapped to another concept over the same primitive (decision 0098) | Decimal-places rule on a Decimal concept or property; the exact decimal product; the conversion is admitted only when the target declares no rule or compliance the source does not, never for enums, composites or optional into required | Stage admits v29; numeric projection arithmetic and admitted decimal/concept validation have target-specific paths |
29
29
  | v30 | A command `produces ... for <required scalar property>` (several event sources); a specification `given generated <Command>.<property> = <value>` (decision 0098) | Several sources in one accepted command; pinned generated values for reaction-invoked commands, taken in authored order | Stage admits v30; generated backends preserve per-production destinations. CLI render admits v30 with an admitting bundle |
30
30
  | v31 | A policy `require anonymous` for a public command or query | A deliberately public surface; the policy is the whole effective authorization | v31 refused until Stage admits it |
31
+ | v32 | A `source events` capture whose key is a typed scalar (for example a concept over Uuid) | The appended event's event-source identity keeps the key's type instead of Text (see the compiler minimums); other models keep their version and bytes | Stage admits v32 through a direct caller of the reviewed baseline; see [Stage admission](#stage-admission-and-execution) |
31
32
  | v33 | `key <property> is event source` on a single-property `source events` capture (Screenplay 4.242.0; PLAY0809) | Serializes `keyIsEventSource` beside `sourceEvents`. Promises every incoming event is sourced by that key; explicit fixture `for` must equal it, while omission takes the key before projections/reactions. Checks also run on givens without an action. Unmarked captures keep earlier behavior/version/bytes | An admitting renderer may narrow history reads by event source id; binding alone does not prove target realization |
32
33
 
33
34
  Constructs of decision 0098 with no executable-model content need no version: application-level toolbar buttons in the layout's `navigation topbar` region (`button <id> title "..." slice <Slice>` with an optional indented `authorize <Policy>`), a command specification that states the public event its outbound Translate slice publishes (no more false `PLAY0285`), and a capture over events that copies a list (`lines = $.lines`) or fans out with `children lines identified by sku`. Check `screenplay --version` against the release that admitted v29 and v30 before relying on them.
@@ -42,6 +43,8 @@ Requires Screenplay 4.184.0 or later (`screenplay --version`) for literal text r
42
43
 
43
44
  Requires Screenplay 4.193.0 or later (`screenplay --version`) for protected reads; older binders retain PLAY0271/PLAY0268.
44
45
 
46
+ Requires Screenplay 4.241.0 or later (`screenplay --version`) for v32 typed scalar `source events` keys; older compilers keep the key as Text on the appended event's identity.
47
+
45
48
  Requires Screenplay 4.199.0 (ESM v26; `screenplay --version`) for date comparisons; older binders report PLAY0268.
46
49
 
47
50
  Requires Screenplay 4.204.0 (ESM v27; `screenplay --version`) for composite read-model keys; older binders report PLAY0268.
@@ -22,7 +22,7 @@ and concept compliance (v13) render.
22
22
 
23
23
  ## Current admission
24
24
 
25
- The language is frozen at ESM v1–v28 ([the freeze decision](https://github.com/Cratis/Screenplay/blob/main/decisions/0092-the-language-is-frozen-at-esm-v28.md)): no new versions, constructs, keywords or grammar, except a construct for a real model that is blocked with no model-side alternative, accepted in its own record. Model with what v1–v28 offers; when Stage, `cratis render` or Studio does not support a construct yet, treat the typed refusal as a platform gap to report, since consumers are catching up to v28, not a reason to wait for new language.
25
+ New constructs can be admitted, each byte-changing one with its own ESM version, and count as delivered once Stage admits it or refuses it with a typed refusal. Model with what the installed compiler admits; when Stage, `cratis render` or Studio does not support a construct yet, treat the typed refusal as a platform gap to report.
26
26
 
27
27
  Stage v4.197.0 admits matched language/ESM **1.0–30.0 and 32.0**, not 31.0,
28
28
  mixed or unknown pairs (`STAGE-ESM-016`). CLI v3.100.0 render checks only the
@@ -1162,7 +1162,8 @@
1162
1162
  "cratis/engineering/core"
1163
1163
  ],
1164
1164
  "availableTargets": [
1165
- "cratis-orchestration-lanes"
1165
+ "cratis-orchestration-lanes",
1166
+ "cratis-orchestration-merge-gates"
1166
1167
  ],
1167
1168
  "languages": [
1168
1169
  "language-agnostic"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cratis/pi",
3
- "version": "7.118.0",
3
+ "version": "7.119.1",
4
4
  "description": "Configuration-aware Cratis AI integration for Pi",
5
5
  "type": "module",
6
6
  "files": [