@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.
- package/package/corpus/agents/screenplay-modeler.md +1 -0
- package/package/corpus/harnesses/copilot/instructions/profiles.instructions.md +1 -1
- package/package/corpus/harnesses/pi/agents/screenplay-modeler.md +1 -0
- package/package/corpus/hooks/scripts/cratis-cleanup-worktrees.sh +4 -4
- package/package/corpus/hooks/scripts/cratis-slice-scope-report.sh +2 -1
- package/package/corpus/hooks/scripts/validate-type-references.sh +2 -2
- package/package/corpus/rules/profiles.md +1 -1
- package/package/corpus/skills/cratis-engineering-review-rounds/SKILL.md +22 -0
- package/package/corpus/skills/cratis-engineering-review-rounds/verification.json +2 -1
- package/package/corpus/skills/cratis-orchestration-merge-gates/LICENSE +2 -0
- package/package/corpus/skills/cratis-orchestration-merge-gates/SKILL.md +100 -0
- package/package/corpus/skills/cratis-orchestration-merge-gates/references/merge-queue.md +69 -0
- package/package/corpus/skills/cratis-orchestration-merge-gates/references/unattended-guards.md +66 -0
- package/package/corpus/skills/cratis-orchestration-merge-gates/verification.json +17 -0
- package/package/corpus/skills/cratis-screenplay-captures-and-reactions/references/capture-map-and-example.md +7 -0
- package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +5 -1
- package/package/corpus/skills/cratis-screenplay-command-surface/references/date-comparisons.md +16 -0
- package/package/corpus/skills/cratis-screenplay-command-surface/references/protected-reads.md +2 -0
- package/package/corpus/skills/cratis-screenplay-event-modeling/SKILL.md +5 -3
- package/package/corpus/skills/cratis-screenplay-event-modeling/verification.json +4 -0
- package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-tools.md +1 -0
- package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/SKILL.md +1 -1
- package/package/corpus/skills/cratis-screenplay-projections/SKILL.md +4 -1
- package/package/corpus/skills/cratis-screenplay-read-surface/SKILL.md +1 -1
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +8 -0
- package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +2 -0
- package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/consistency-and-concurrency.md +5 -0
- package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +5 -0
- package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +13 -2
- package/package/corpus/skills/cratis-screenplay-toolchain/references/language-admission.md +3 -0
- package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +1 -1
- package/package/profile-catalog.json +2 -1
- 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" '
|
|
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" '
|
|
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" '
|
|
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" '
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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,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.
|
package/package/corpus/skills/cratis-orchestration-merge-gates/references/unattended-guards.md
ADDED
|
@@ -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
|
package/package/corpus/skills/cratis-screenplay-command-surface/references/date-comparisons.md
CHANGED
|
@@ -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.
|
package/package/corpus/skills/cratis-screenplay-command-surface/references/protected-reads.md
CHANGED
|
@@ -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.
|
|
119
|
-
Stage, `cratis render` or Studio refusal as a platform gap
|
|
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.**
|
|
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`).
|
|
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.
|
|
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
|
-
|
|
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
|