@cratis/pi 7.103.3 → 7.103.5

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.
@@ -24,7 +24,9 @@ exact commands.
24
24
 
25
25
  - Read the `go` directive, build constraints and CI before choosing a feature.
26
26
  The minimum is not the newest locally installed compiler; a `toolchain`
27
- preference does not replace minimum-version testing. Do not raise it incidentally.
27
+ preference does not replace minimum-version testing. Do not raise it incidentally
28
+ or rewrite unrelated code to modernize syntax. Verify unfamiliar APIs against the
29
+ documentation for that minimum, and keep experimental features opt-in.
28
30
  - Iterators require Go 1.23; `T.Context` and `B.Loop` require 1.24;
29
31
  stable `testing/synctest` and `WaitGroup.Go` require 1.25.
30
32
  - Prefer the standard library when it meets the contract. Review dependency
@@ -33,6 +35,10 @@ exact commands.
33
35
  including indirect minimum-version changes; keep sums consistent. A consumer
34
36
  must not need a developer's workspace or local replacement.
35
37
  - Never edit generated code; change its authoritative inputs and pinned generator.
38
+ - Start with a small public package surface aligned with caller workflows; put
39
+ implementation-only packages in `internal/` and keep optional adapters apart from
40
+ core behavior. Do not mandate `pkg/`. Avoid package initialization that performs
41
+ I/O, starts goroutines or mutates globals.
36
42
 
37
43
  ## Names, public APIs and values
38
44
 
@@ -44,11 +50,23 @@ exact commands.
44
50
  - Document exported declarations with comments beginning with their names.
45
51
  Explain nil/zero semantics, concurrency, ownership, cancellation, error identities
46
52
  and cleanup. Add executable examples for important public workflows.
47
- - Make zero values useful where possible; reject invalid construction early.
48
- Document option defaults, validation, ordering and duplicates.
53
+ - Design exported APIs from realistic caller examples first and export only what
54
+ the library will support. Make zero values useful where possible; reject invalid
55
+ construction early. Use plain parameters or config structs for simple
56
+ configuration and functional options when extensibility outweighs the added
57
+ namespace; document option defaults, validation, ordering and duplicates.
58
+ - Reuse standard interfaces such as `io.Reader` and `http.Handler`; prefer concrete
59
+ returns unless an abstraction is part of the API. Use pointer receivers for
60
+ mutation or values that must not be copied, and avoid public embedding that
61
+ promotes dependency methods. Mark retired API with a `Deprecated:` paragraph
62
+ naming the replacement.
49
63
  - Use named domain values instead of interchangeable primitives. Defined types
50
64
  do not inherit codec methods; explicitly forward text/JSON codecs and test wire
51
65
  formats. See `cratis-fundamentals-concept-go` when using Fundamentals.Go.
66
+ - Specify `Close` ownership, repeated-close behavior and use after close, and
67
+ document concurrent-use guarantees for clients, handles and callbacks.
68
+ - Use generics for meaningful type-safe reuse, not speculative abstraction; do not
69
+ replace domain types with `any` for plumbing convenience.
52
70
  - Document whether slices, maps, config and results are owned, copied or borrowed.
53
71
  Copying a slice/map header is not a detached copy. Do not copy a used mutex,
54
72
  wait group or atomic value, or expose pooled bytes after returning their buffer.
@@ -62,7 +80,9 @@ exact commands.
62
80
  return an `error` interface containing a typed nil.
63
81
  - Add useful operation context. Handle/log an error at one boundary rather than
64
82
  repeatedly logging and returning it. A partial or ambiguous write is not success
65
- and must not trigger a blind retry.
83
+ and must not trigger a blind retry. Use sentinels for stable categories and typed
84
+ errors for structured details; translate dependency errors whose identity must
85
+ stay internal, and explain intentional suppression.
66
86
  - Put `context.Context` first for blocking/cancelable work and propagate it through
67
87
  RPCs, HTTP, storage and callbacks. Never escape caller cancellation by replacing
68
88
  it with `Background`. Do not retain request contexts in long-lived clients.
@@ -73,6 +93,9 @@ exact commands.
73
93
 
74
94
  ## Goroutines, streams and iterators
75
95
 
96
+ - Prefer synchronous APIs and let callers place concurrency. A saturated
97
+ `errgroup.SetLimit` can block `Go`; use `errgroup` only when its cancellation
98
+ and error behavior fits.
76
99
  - Each goroutine needs an owner, termination condition and observable join path.
77
100
  Cancellation requests termination; it does not join workers.
78
101
  - Bound workers, queues, subscriptions, buffers and retries; define backpressure.
@@ -85,6 +108,8 @@ exact commands.
85
108
  - Preserve protocol metadata, tenancy, checkpoints and duplicate-delivery semantics.
86
109
  No generic retry or stream helper may promise exactly-once effects.
87
110
  - Validate remote TLS identities. Development exceptions must be explicit.
111
+ Bound untrusted payload sizes, fan-out and retained subscription state, and keep
112
+ long-lived subscription lifetimes apart from unary-call deadlines.
88
113
  Use cryptographic randomness for secrets, never `math/rand`.
89
114
 
90
115
  ## Specifications and checks
@@ -98,10 +123,23 @@ exact commands.
98
123
  - Cover error identity, nil/zero input, cancellation/deadlines, partial outcomes,
99
124
  early stream exit and resource ownership. Bound fuzz duration and preserve
100
125
  failing seeds. Use race checks where supported; race-free does not mean leak-free.
126
+ - Add a regression test for each corrected behavior, including error and boundary
127
+ cases. Use `httptest` or `bufconn` plus real-transport tests where needed, and
128
+ protobuf-aware comparison for generated types.
129
+ - Profile or benchmark a demonstrated problem before optimizing; add no pools,
130
+ caches or `unsafe` without measured justification.
101
131
  - Run the repository's build, tests, formatting, vet and pinned golangci-lint gates,
102
132
  with race and vulnerability scanning as separate checks. Respect the declared
103
133
  minimum without silent toolchain upgrades. Report absent tools honestly.
104
134
 
135
+ ## Compatibility and releases
136
+
137
+ - Prefer additive change: exported signature changes break callers, and adding a
138
+ method to an exported interface breaks its external implementations. Check struct comparability, embedding, defaults, errors and wire shape;
139
+ API-diff tools aid but cannot prove behavioral compatibility.
140
+ - Introduce `/v2` only with a migration and parallel-support plan. Never move a
141
+ published tag; issue a corrective release and retract when needed.
142
+
105
143
  ## Adaptation and attribution
106
144
 
107
145
  This condensed rule adapts the repository-owned Go baseline at
@@ -128,6 +128,22 @@ ignored records. Other ignored files (`node_modules`, build output) go with a de
128
128
  `--include-work-records` only after preserving any records you still need: it permits deleting
129
129
  `.ai-work/` content, but never overrides locks or other safety checks. Hook mode ignores this flag;
130
130
  automatic hooks never opt in.
131
+ - **GitHub lookups.** The complete worktree and branch sweep is planned before any removal. Git
132
+ ancestry is checked first; only a plan needing more evidence triggers the single REST batch. It
133
+ reads the latest 100 closed pull requests, so older merged branches absent from that page are simply
134
+ kept. Only merged entries with the exact branch and head commit qualify. Hook runs share an atomic
135
+ stamp and cache under the Git common directory, with at most one request per repository every
136
+ 15 minutes, including failed attempts. A fresh successful cache is reused. A failed request, invalid
137
+ response, or unavailable lock without a fresh successful cache aborts **all** removals in that sweep,
138
+ including ancestry-proven worktrees and branches, with a one-line notice. Failed attempts are marked
139
+ for the full window: later plans needing GitHub also abort all removals without retrying, while plans
140
+ needing only ancestry evidence proceed without GitHub. Locks older than 15 minutes can be reclaimed.
141
+ Manual runs are not throttled, but also use at most one request per run and abort all removals if
142
+ that request fails.
143
+ - **Disable GitHub only.** Set `CRATIS_CLEANUP_NO_GH=1` to avoid all GitHub lookups while keeping
144
+ cleanup based on Git ancestry enabled. Missing `gh` or `jq`, a non-GitHub origin, or an invalid
145
+ repository slug also select ancestry-only cleanup before planning: unproven items are kept, with
146
+ no GitHub call, abort, or failed-attempt marker.
131
147
  - **Pin a long-lived worktree.** Use `git worktree lock <path>` to keep it out of cleanup; release the
132
148
  pin with `git worktree unlock <path>` when ready.
133
149
  - **Self-test.** `--self-test` plants delivered, dirty, unmerged, brand-new, work-record and locked cases
@@ -139,34 +139,121 @@ REMOVED=(); KEPT=(); FREED_KB=0
139
139
  note_removed() { REMOVED+=("$1"); }
140
140
  note_kept() { KEPT+=("$1"); }
141
141
 
142
- # delivered <sha> <branch|""> <upstream-track> → prints the evidence, returns 0 when delivered
143
- delivered() {
144
- local sha="$1" br="$2" track="$3"
142
+ # The cache is available only after a successful, valid batch. Failed attempts also stamp the window.
143
+ GH_PULLS=''
144
+ valid_pulls() {
145
+ jq -e -s 'length == 1 and (.[0] | type == "array" and all(.[];
146
+ type == "object" and has("merged_at") and (.merged_at == null or (.merged_at | type == "string")) and
147
+ (.head | type == "object" and (.ref | type == "string") and (.sha | type == "string"))))' "$1" >/dev/null 2>&1
148
+ }
149
+ lock_stat() { stat -c '%i %Y' "$1" 2>/dev/null || stat -f '%i %m' "$1" 2>/dev/null; }
150
+ fresh_stamp() {
151
+ local stamp
152
+ stamp=$(cat "$state/stamp" 2>/dev/null || true)
153
+ [[ "$stamp" =~ ^[0-9]+$ ]] && [ "$now" -lt "$((stamp + 900))" ]
154
+ }
155
+ cached_pulls() {
156
+ fresh_stamp && [ ! -e "$state/failed" ] && valid_pulls "$state/pulls.json" || return 1
157
+ cat "$state/pulls.json"
158
+ }
159
+ take_lock() {
160
+ mkdir "$state/lock" 2>/dev/null && return 0
161
+ local modified retired acquired
162
+ read -r _ modified < <(lock_stat "$state/lock")
163
+ [[ "$modified" =~ ^[0-9]+$ ]] && [ "$now" -ge "$((modified + 900))" ] || return 1
164
+ # Rename atomically: a killed reclaimer can leave only a retired directory, never a blocking marker.
165
+ retired="$state/lock.stale.$$.$RANDOM"
166
+ mv "$state/lock" "$retired" 2>/dev/null || return 1
167
+ acquired=1
168
+ mkdir "$state/lock" 2>/dev/null && acquired=0
169
+ rm -rf "$retired"
170
+ return "$acquired"
171
+ }
172
+ hook_pulls() (
173
+ local repo="$1" common state now temporary lock_inode current
174
+ common=$(git rev-parse --git-common-dir) || exit 1
175
+ state="$common/cratis-cleanup-gh/$repo"
176
+ now=$(date +%s)
177
+ mkdir -p "$state" 2>/dev/null || exit 1
178
+ if ! take_lock; then cached_pulls; exit $?; fi
179
+ read -r lock_inode _ < <(lock_stat "$state/lock")
180
+ temporary=''
181
+ # A retired owner must never remove its replacement's lock.
182
+ trap '[[ -z "$temporary" ]] || rm -f "$temporary"; read -r current _ < <(lock_stat "$state/lock"); [ "$current" != "$lock_inode" ] || rmdir "$state/lock" 2>/dev/null' EXIT
183
+ if fresh_stamp; then cached_pulls; exit $?; fi
184
+ temporary=$(mktemp "$state/pulls.XXXXXX") || exit 1
185
+ printf '%s\n' "$now" > "$temporary" && mv "$temporary" "$state/failed" || exit 1
186
+ printf '%s\n' "$now" > "$temporary" && mv "$temporary" "$state/stamp" || exit 1
187
+ read -r current _ < <(lock_stat "$state/lock")
188
+ [ "$current" = "$lock_inode" ] || exit 1
189
+ # Only the latest 100 closed PRs are searched; older merged branches are simply kept.
190
+ if gh api "repos/$repo/pulls?state=closed&per_page=100" > "$temporary" 2>/dev/null && valid_pulls "$temporary"; then
191
+ read -r current _ < <(lock_stat "$state/lock")
192
+ [ "$current" = "$lock_inode" ] || exit 1
193
+ mv "$temporary" "$state/pulls.json" && rm -f "$state/failed" || exit 1
194
+ cat "$state/pulls.json"
195
+ else exit 1; fi
196
+ )
197
+ GH_POSSIBLE=0; GH_REPO=''
198
+ configure_github() {
199
+ [ "${CRATIS_CLEANUP_NO_GH:-}" != 1 ] || return 0
200
+ command -v gh >/dev/null 2>&1 && command -v jq >/dev/null 2>&1 || return 0
201
+ local remote repo
202
+ remote=$(git remote get-url origin 2>/dev/null) || return 0
203
+ case "$remote" in
204
+ https://github.com/*) repo=${remote#https://github.com/} ;;
205
+ git@github.com:*) repo=${remote#git@github.com:} ;;
206
+ ssh://git@github.com/*) repo=${remote#ssh://git@github.com/} ;;
207
+ *) return 0 ;;
208
+ esac
209
+ repo=${repo%.git}
210
+ [[ "$repo" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]] || return 0
211
+ GH_REPO=$repo; GH_POSSIBLE=1
212
+ }
213
+ configure_github
214
+ load_pulls() {
215
+ if [ "$HOOK" = 1 ]; then GH_PULLS=$(hook_pulls "$GH_REPO") || return 1
216
+ else GH_PULLS=$(gh api "repos/$GH_REPO/pulls?state=closed&per_page=100" 2>/dev/null) || return 1; fi
217
+ printf '%s' "$GH_PULLS" | valid_pulls /dev/stdin
218
+ }
219
+
220
+ # Ancestry evidence is resolved during planning; GitHub evidence only after the complete plan exists.
221
+ ancestry_delivered() {
222
+ local sha="$1" track="$3"
145
223
  if git merge-base --is-ancestor "$sha" "$default" 2>/dev/null; then
146
- if ! grep -qx "$sha" "$firstparent"; then echo "merged into $default"; return 0; fi
147
- if [ "$track" = "[gone]" ]; then echo "merged into $default, upstream gone"; return 0; fi
148
- fi
149
- if [ -n "$br" ] && [ "${CRATIS_CLEANUP_NO_GH:-}" != 1 ] && command -v gh >/dev/null 2>&1; then
150
- if gh pr list --head "$br" --state merged --json headRefOid -q '.[].headRefOid' 2>/dev/null | grep -qx "$sha"; then
151
- echo "pull request merged at this commit"; return 0
152
- fi
224
+ if ! grep -qx "$sha" "$firstparent"; then EVIDENCE="merged into $default"; return 0; fi
225
+ if [ "$track" = "[gone]" ]; then EVIDENCE="merged into $default, upstream gone"; return 0; fi
153
226
  fi
154
227
  return 1
155
228
  }
229
+ github_delivered() {
230
+ printf '%s' "$GH_PULLS" | jq -e --arg br "$1" --arg sha "$2" \
231
+ 'any(.[]; .merged_at != null and .head.ref == $br and .head.sha == $sha)' >/dev/null 2>&1
232
+ }
233
+ PLAN_KIND=(); PLAN_PATH=(); PLAN_SHA=(); PLAN_BRANCH=(); PLAN_EVIDENCE=(); NEEDS_GH=0
234
+ plan_item() {
235
+ local kind="$1" path="$2" tip="$3" branch="$4" evidence=''
236
+ if ancestry_delivered "$tip" "$branch" "$([ -n "$branch" ] && track_of "$branch")"; then evidence=$EVIDENCE
237
+ elif [ -n "$branch" ] && [ "$GH_POSSIBLE" = 1 ]; then NEEDS_GH=1; fi
238
+ PLAN_KIND+=("$kind"); PLAN_PATH+=("$path"); PLAN_SHA+=("$tip")
239
+ PLAN_BRANCH+=("$branch"); PLAN_EVIDENCE+=("$evidence")
240
+ }
156
241
  track_of() { git for-each-ref --format='%(upstream:track)' "refs/heads/$1" 2>/dev/null; }
157
242
 
158
- # ── Worktrees ─────────────────────────────────────────────────────────────────
159
- git worktree prune >/dev/null 2>&1
243
+ # ── Plan the entire sweep without removing worktrees or branches ──────────────
160
244
  wt=""; sha=""; br=""; locked=0; first=1
161
245
  process_worktree() {
162
246
  [ -n "$wt" ] || return 0
163
247
  if [ "$first" = 1 ]; then first=0; return 0; fi # the main worktree is never removed
164
- local name="${br:-detached}" ev
248
+ local name="${br:-detached}"
165
249
  if [ "$locked" = 1 ]; then note_kept "worktree $wt ($name): locked"; return 0; fi
166
250
  case "$here/" in "$wt"/*) note_kept "worktree $wt ($name): it is the current directory - run the sweep from the main checkout"; return 0 ;; esac
167
- if ! ev=$(delivered "$sha" "$br" "$([ -n "$br" ] && track_of "$br")"); then
168
- note_kept "worktree $wt ($name): work not delivered to $default"; return 0
169
- fi
251
+ plan_item worktree "$wt" "$sha" "$br"
252
+ }
253
+ execute_worktree() {
254
+ local name="${br:-detached}" ev="$1" current
255
+ current=$(git -C "$wt" rev-parse HEAD 2>/dev/null) || return 0
256
+ [ "$current" = "$sha" ] || { note_kept "worktree $wt ($name): tip changed since planning"; return 0; }
170
257
  if [ "$INCLUDE_WORK_RECORDS" = 0 ] && [ -d "$wt/.ai-work" ]; then
171
258
  local records
172
259
  if ! records=$(find "$wt/.ai-work/." -mindepth 1 -maxdepth 1 -print -quit); then
@@ -191,20 +278,49 @@ while IFS= read -r line; do
191
278
  done < <(git worktree list --porcelain; echo)
192
279
  process_worktree
193
280
 
194
- # ── Local branches ────────────────────────────────────────────────────────────
195
281
  in_use=$(git worktree list --porcelain | sed -n 's#^branch refs/heads/##p')
282
+ planned_branches=$(printf '%s\n' "${PLAN_BRANCH[@]+"${PLAN_BRANCH[@]}"}")
196
283
  while IFS='|' read -r b bsha; do
197
284
  if [ -z "$b" ] || [ "$b" = "$default_local" ]; then continue; fi
198
- printf '%s\n' "$in_use" | grep -qx "$b" && continue
199
- if ev=$(delivered "$bsha" "$b" "$(track_of "$b")"); then
200
- if [ "$DRY" = 1 ]; then note_removed "branch $b: would delete, $ev"
201
- elif git branch -D "$b" >/dev/null 2>&1; then note_removed "branch $b: $ev"
202
- else note_kept "branch $b: git refused to delete it"; fi
203
- else
204
- note_kept "branch $b: work not delivered to $default"
285
+ if printf '%s\n' "$in_use" | grep -qx "$b"; then
286
+ [ "$DRY" = 0 ] || continue
287
+ printf '%s\n' "$planned_branches" | grep -qx "$b" || continue
205
288
  fi
289
+ plan_item branch "$b" "$bsha" "$b"
206
290
  done < <(git for-each-ref --format='%(refname:short)|%(objectname)' refs/heads)
207
291
 
292
+ abort_sweep() {
293
+ echo "cratis-cleanup-worktrees: GitHub evidence unavailable; 0 removed, keeping the entire sweep" >&2
294
+ exit 0
295
+ }
296
+ # Resolve every item's evidence before any deletion, including ancestry-proven items.
297
+ if [ "$NEEDS_GH" = 1 ] && ! load_pulls; then abort_sweep; fi
298
+ for ((i=0; i<${#PLAN_KIND[@]}; i++)); do
299
+ if [ -z "${PLAN_EVIDENCE[i]}" ] && [ -n "${PLAN_BRANCH[i]}" ] && [ -n "$GH_PULLS" ]; then
300
+ if github_delivered "${PLAN_BRANCH[i]}" "${PLAN_SHA[i]}"; then PLAN_EVIDENCE[i]="pull request merged at this commit"
301
+ else result=$?; [ "$result" = 1 ] || abort_sweep; fi
302
+ fi
303
+ done
304
+
305
+ # ── Execute the resolved plan, rechecking tips and worktree safety ─────────────
306
+ git worktree prune >/dev/null 2>&1
307
+ for ((i=0; i<${#PLAN_KIND[@]}; i++)); do
308
+ kind=${PLAN_KIND[i]}; path=${PLAN_PATH[i]}; sha=${PLAN_SHA[i]}; br=${PLAN_BRANCH[i]}; ev=${PLAN_EVIDENCE[i]}
309
+ if [ "$kind" = branch ]; then
310
+ git worktree list --porcelain | sed -n 's#^branch refs/heads/##p' | grep -qx "$br" && continue
311
+ fi
312
+ if [ -z "$ev" ]; then
313
+ if [ "$kind" = worktree ]; then note_kept "worktree $path (${br:-detached}): work not delivered to $default"
314
+ else note_kept "branch $br: work not delivered to $default"; fi
315
+ continue
316
+ fi
317
+ if [ "$kind" = worktree ]; then wt=$path; execute_worktree "$ev"; continue; fi
318
+ [ "$(git rev-parse -q --verify "refs/heads/$br")" = "$sha" ] || { note_kept "branch $br: tip changed since planning"; continue; }
319
+ if [ "$DRY" = 1 ]; then note_removed "branch $br: would delete, $ev"
320
+ elif git branch -D "$br" >/dev/null 2>&1; then note_removed "branch $br: $ev"
321
+ else note_kept "branch $br: git refused to delete it"; fi
322
+ done
323
+
208
324
  # ── Report ────────────────────────────────────────────────────────────────────
209
325
  summary="cratis-cleanup-worktrees: ${#REMOVED[@]} removed, ${#KEPT[@]} kept"
210
326
  [ "$FREED_KB" -gt 0 ] && summary="$summary, $((FREED_KB / 1024)) MB freed"
@@ -23,7 +23,9 @@ exact commands.
23
23
 
24
24
  - Read the `go` directive, build constraints and CI before choosing a feature.
25
25
  The minimum is not the newest locally installed compiler; a `toolchain`
26
- preference does not replace minimum-version testing. Do not raise it incidentally.
26
+ preference does not replace minimum-version testing. Do not raise it incidentally
27
+ or rewrite unrelated code to modernize syntax. Verify unfamiliar APIs against the
28
+ documentation for that minimum, and keep experimental features opt-in.
27
29
  - Iterators require Go 1.23; `T.Context` and `B.Loop` require 1.24;
28
30
  stable `testing/synctest` and `WaitGroup.Go` require 1.25.
29
31
  - Prefer the standard library when it meets the contract. Review dependency
@@ -32,6 +34,10 @@ exact commands.
32
34
  including indirect minimum-version changes; keep sums consistent. A consumer
33
35
  must not need a developer's workspace or local replacement.
34
36
  - Never edit generated code; change its authoritative inputs and pinned generator.
37
+ - Start with a small public package surface aligned with caller workflows; put
38
+ implementation-only packages in `internal/` and keep optional adapters apart from
39
+ core behavior. Do not mandate `pkg/`. Avoid package initialization that performs
40
+ I/O, starts goroutines or mutates globals.
35
41
 
36
42
  ## Names, public APIs and values
37
43
 
@@ -43,11 +49,23 @@ exact commands.
43
49
  - Document exported declarations with comments beginning with their names.
44
50
  Explain nil/zero semantics, concurrency, ownership, cancellation, error identities
45
51
  and cleanup. Add executable examples for important public workflows.
46
- - Make zero values useful where possible; reject invalid construction early.
47
- Document option defaults, validation, ordering and duplicates.
52
+ - Design exported APIs from realistic caller examples first and export only what
53
+ the library will support. Make zero values useful where possible; reject invalid
54
+ construction early. Use plain parameters or config structs for simple
55
+ configuration and functional options when extensibility outweighs the added
56
+ namespace; document option defaults, validation, ordering and duplicates.
57
+ - Reuse standard interfaces such as `io.Reader` and `http.Handler`; prefer concrete
58
+ returns unless an abstraction is part of the API. Use pointer receivers for
59
+ mutation or values that must not be copied, and avoid public embedding that
60
+ promotes dependency methods. Mark retired API with a `Deprecated:` paragraph
61
+ naming the replacement.
48
62
  - Use named domain values instead of interchangeable primitives. Defined types
49
63
  do not inherit codec methods; explicitly forward text/JSON codecs and test wire
50
64
  formats. See `cratis-fundamentals-concept-go` when using Fundamentals.Go.
65
+ - Specify `Close` ownership, repeated-close behavior and use after close, and
66
+ document concurrent-use guarantees for clients, handles and callbacks.
67
+ - Use generics for meaningful type-safe reuse, not speculative abstraction; do not
68
+ replace domain types with `any` for plumbing convenience.
51
69
  - Document whether slices, maps, config and results are owned, copied or borrowed.
52
70
  Copying a slice/map header is not a detached copy. Do not copy a used mutex,
53
71
  wait group or atomic value, or expose pooled bytes after returning their buffer.
@@ -61,7 +79,9 @@ exact commands.
61
79
  return an `error` interface containing a typed nil.
62
80
  - Add useful operation context. Handle/log an error at one boundary rather than
63
81
  repeatedly logging and returning it. A partial or ambiguous write is not success
64
- and must not trigger a blind retry.
82
+ and must not trigger a blind retry. Use sentinels for stable categories and typed
83
+ errors for structured details; translate dependency errors whose identity must
84
+ stay internal, and explain intentional suppression.
65
85
  - Put `context.Context` first for blocking/cancelable work and propagate it through
66
86
  RPCs, HTTP, storage and callbacks. Never escape caller cancellation by replacing
67
87
  it with `Background`. Do not retain request contexts in long-lived clients.
@@ -72,6 +92,9 @@ exact commands.
72
92
 
73
93
  ## Goroutines, streams and iterators
74
94
 
95
+ - Prefer synchronous APIs and let callers place concurrency. A saturated
96
+ `errgroup.SetLimit` can block `Go`; use `errgroup` only when its cancellation
97
+ and error behavior fits.
75
98
  - Each goroutine needs an owner, termination condition and observable join path.
76
99
  Cancellation requests termination; it does not join workers.
77
100
  - Bound workers, queues, subscriptions, buffers and retries; define backpressure.
@@ -84,6 +107,8 @@ exact commands.
84
107
  - Preserve protocol metadata, tenancy, checkpoints and duplicate-delivery semantics.
85
108
  No generic retry or stream helper may promise exactly-once effects.
86
109
  - Validate remote TLS identities. Development exceptions must be explicit.
110
+ Bound untrusted payload sizes, fan-out and retained subscription state, and keep
111
+ long-lived subscription lifetimes apart from unary-call deadlines.
87
112
  Use cryptographic randomness for secrets, never `math/rand`.
88
113
 
89
114
  ## Specifications and checks
@@ -97,10 +122,23 @@ exact commands.
97
122
  - Cover error identity, nil/zero input, cancellation/deadlines, partial outcomes,
98
123
  early stream exit and resource ownership. Bound fuzz duration and preserve
99
124
  failing seeds. Use race checks where supported; race-free does not mean leak-free.
125
+ - Add a regression test for each corrected behavior, including error and boundary
126
+ cases. Use `httptest` or `bufconn` plus real-transport tests where needed, and
127
+ protobuf-aware comparison for generated types.
128
+ - Profile or benchmark a demonstrated problem before optimizing; add no pools,
129
+ caches or `unsafe` without measured justification.
100
130
  - Run the repository's build, tests, formatting, vet and pinned golangci-lint gates,
101
131
  with race and vulnerability scanning as separate checks. Respect the declared
102
132
  minimum without silent toolchain upgrades. Report absent tools honestly.
103
133
 
134
+ ## Compatibility and releases
135
+
136
+ - Prefer additive change: exported signature changes break callers, and adding a
137
+ method to an exported interface breaks its external implementations. Check struct comparability, embedding, defaults, errors and wire shape;
138
+ API-diff tools aid but cannot prove behavioral compatibility.
139
+ - Introduce `/v2` only with a migration and parallel-support plan. Never move a
140
+ published tag; issue a corrective release and retract when needed.
141
+
104
142
  ## Adaptation and attribution
105
143
 
106
144
  This condensed rule adapts the repository-owned Go baseline at
@@ -55,12 +55,13 @@ commands before choosing the build, regression spec and full gate commands.
55
55
  ## Copy this checklist
56
56
 
57
57
  - [ ] Reproduce the consumer bug and select its regression spec/app action.
58
- - [ ] Generate one stamp; build and pack the producer's full dependency closure.
58
+ - [ ] Read [references/dependency-map.md](references/dependency-map.md) for the chain between the named repositories, generate one stamp, then pack each producer in upstream order.
59
59
  - [ ] If needed, publish the kernel and assets, then build a matching local image.
60
60
  - [ ] Activate the consumer overlay and select the local image.
61
61
  - [ ] Build the consumer, run its regression specs/app action and required gates.
62
62
  - [ ] On failure, diagnose, fix the producer, create a distinct stamp and repeat.
63
- - [ ] Run `check` before every consumer commit and push, and on the producer.
63
+ - [ ] Run `check` before every consumer commit and push, and on the producer; it must report 0 leaks.
64
+ - [ ] Upstream first: a downstream ships only after the upstream has released and its pin is bumped to the released version.
64
65
  - [ ] Restore overlays, unset environment overrides, and run `check` again.
65
66
  - [ ] Review stamp-scoped `clean` dry-run targets, then apply cleanup.
66
67
 
@@ -92,7 +93,10 @@ For npm, complete the repository build before
92
93
  exit `0`. Inspect package dependencies: every locally changed dependency ID must
93
94
  resolve to the stamp, not a published fallback. Chronicle's client solution filter
94
95
  can omit `Cratis.Chronicle.CodeAnalysis`; pack its code-analysis package project
95
- separately. A successful pack alone does not prove dependency closure.
96
+ separately. The package IDs a producer should ship are listed in
97
+ [dependency-map.tsv](scripts/dependency-map.tsv) (a reference, see
98
+ [references/dependency-map.md](references/dependency-map.md)); compare them with the feed by hand.
99
+ A successful pack alone does not prove dependency closure.
96
100
 
97
101
  ### 3. Build an image when needed
98
102
 
@@ -237,7 +241,7 @@ minutes, instead of after a release and a pin bump.
237
241
  - Read [references/npm-yarn.md](references/npm-yarn.md) when packing frontend libraries or restoring Yarn overlays.
238
242
  - Read [references/docker-images.md](references/docker-images.md) when publishing a kernel or selecting images in a consumer.
239
243
  - Read [references/go-jvm-python-elixir.md](references/go-jvm-python-elixir.md) when the boundary uses another language toolchain.
240
- - Read [references/worked-examples.md](references/worked-examples.md) when following Chronicle → Studio, Fundamentals → Arc or Components → Studio.
244
+ - Read [references/worked-examples.md](references/worked-examples.md) when following Chronicle → Studio, Fundamentals → Arc, Components → Studio, Chronicle → Direct, Screenplay → Stage and Studio, Arc → Chronicle, or Fundamentals → Arc → Chronicle.
241
245
  - Read [references/other-environments.md](references/other-environments.md) when running on another developer machine or an agent host.
242
246
 
243
247
  Read `scripts/npm-restore-check.cjs` when inspecting the read-only npm restoration
@@ -0,0 +1,59 @@
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
+ # Dependency map
5
+
6
+ `scripts/dependency-map.tsv` is a reference table of the producer-to-consumer edges between
7
+ Cratis repositories, the pack targets of each producer and the package IDs each ships.
8
+ `cratis-local-packages.sh` does not read it: use it to decide which repositories to pack,
9
+ in which order, and which IDs to expect in the feed. It holds no versions; read pins live
10
+ from the consumer manifests (`Directory.Packages.props`, `package.json`, `Dockerfile`).
11
+
12
+ ## Rows
13
+
14
+ Tab-separated, `#` starts a comment.
15
+
16
+ | Row | Fields | Meaning |
17
+ | --- | --- | --- |
18
+ | `pack` | repo, eco, target, `PROP=VAL,...` | A pack target; the optional MSBuild properties are the `-p:` arguments the producer's own publish workflow passes |
19
+ | `ids` | repo, eco, comma-separated IDs | The packages the producer ships in that ecosystem |
20
+ | `uses` | consumer, producer, eco, manifest | An edge; the manifest is the pin file, or the Yarn project directory for npm |
21
+ | `image` | repo, dockerfile, tag suffix | A producer image a consumer builds on |
22
+
23
+ `eco` is `nuget`, `npm` or `image`. For npm, `.` means the repository root.
24
+
25
+ ## Using it
26
+
27
+ - Find every `uses` row whose producer is the repository you changed; those consumers
28
+ pin its packages. A consumer may also reach the producer through another repository
29
+ (Fundamentals reaches Chronicle through Arc as well as directly).
30
+ - Pack upstream first. Overlay the earlier producer into the next repository with
31
+ `use-nuget`, pack that, then `restore` it. Use one stamp for the whole chain: `stamp`
32
+ takes one producer, so generate it once and reuse the string.
33
+ - Pack properties from a `pack` row are not accepted by `pack-nuget`. When a row has them,
34
+ run `dotnet pack TARGET -c Release -p:PackageVersion=$stamp -p:Version=$stamp -p:PROP=VAL
35
+ -o "$CRATIS_LOCAL_FEED/nuget"` yourself, with the properties as `-p:` arguments and never
36
+ as exported environment variables (an exported `IsPackaging=true` reaches Chronicle's
37
+ nested `dotnet run` code generator and fails with a multi-target error).
38
+ - After packing, list the feed for the stamp and compare it with the `ids` row; a missing ID
39
+ is a silent partial overlay. Open the nuspec of each packed ID and check that every locally
40
+ changed dependency is at the stamp.
41
+
42
+ ## Facts about the chains
43
+
44
+ - Arc and Chronicle depend on each other. Arc's Chronicle-facing packages are built against
45
+ a released Chronicle, and Chronicle's clients against a released Arc. The same holds for
46
+ Chronicle and Orleans. Record the nuspec dependencies and do not break the cycle.
47
+ - Image and package pins are coupled. A consumer that builds `FROM` a producer image may
48
+ derive the tag from the producer's NuGet pin; check its publish workflow before tagging a
49
+ local image.
50
+ - A repository you did not name keeps its released version: Stage reaches Arc, Chronicle
51
+ reaches Orleans. A binary break through that hop is a finding about the consumer's pins.
52
+ - The current Screenplay rows list only npm IDs although Stage and Studio consume its NuGet
53
+ packages; read the IDs from the producer's publish workflow.
54
+
55
+ ## Extend it
56
+
57
+ Add `pack` rows only from the producer's publish workflow on the default branch, not a
58
+ stale clone. Add `ids` for every package a consumer must resolve. Add one `uses` row per
59
+ consumer manifest that pins the producer.
@@ -3,16 +3,28 @@
3
3
 
4
4
  # Worked examples
5
5
 
6
+ ## Contents
7
+
8
+ - Chronicle kernel → Studio integration specs
9
+ - Fundamentals → Arc (NuGet)
10
+ - Components → Studio frontend (npm)
11
+ - Chronicle clients → Direct (NuGet)
12
+ - Screenplay → Stage and Studio (NuGet and npm)
13
+ - Arc → Chronicle (NuGet)
14
+ - Fundamentals → Arc → Chronicle under one stamp
15
+
16
+ Run times below are rounded from one measured run on a shared machine; queue wait is not included.
6
17
  Use absolute producer/consumer paths for your checkouts and the entry point's
7
18
  `local` helper variable. These recipes define work to execute, not pre-verified
8
19
  results. Substitute actual regression filters and CI commands; stop on a failed
9
20
  step. Apply the entry point's check/restore/cleanup sequence to both repositories.
10
21
 
22
+
11
23
  ## Chronicle kernel → Studio integration specs
12
24
 
13
25
  1. Reproduce Studio's integration bug against its released client/kernel. Record
14
26
  the regression filter and inspect Studio's CI build/test commands.
15
- 2. Generate the stamp and pack client packages plus their full dependency closure.
27
+ 2. Generate the stamp and pack client packages plus their dependencies.
16
28
  A client solution filter can omit CodeAnalysis. Include its package explicitly:
17
29
 
18
30
  ```bash
@@ -60,38 +72,160 @@ requirement the consumer's container setup does not satisfy yet), that is a
60
72
  real finding about the consumer, not about the overlay: read the container log
61
73
  before changing the producer.
62
74
 
63
- ## Fundamentals → Arc
75
+ ## Fundamentals → Arc (NuGet)
76
+
77
+ ```bash
78
+ stamp=$(bash "$local" stamp "$fundamentals")
79
+ (cd "$fundamentals" && bash "$local" pack-nuget . "$stamp" Fundamentals.slnx)
80
+ bash "$local" use-nuget "$arc" "$stamp"
81
+ ```
82
+
83
+ Gates (Arc `dotnet-build.yml`), run in this order after sourcing the printed env:
84
+ `yarn install --immutable`; in `Source/DotNET/Screenplay.Embedded`: `npm ci --workspaces=false`,
85
+ `npm run typecheck`, `npm test`, `npm run build`; `dotnet build --configuration Release
86
+ -p:CratisSpecsTargetFramework=net10.0`; then `dotnet test <project> --no-build --configuration
87
+ Release --framework net10.0` for each project that `python3 scripts/ci-test-shards.py projects
88
+ --shard specs-N` prints. Finish by listing Arc's `obj/project.assets.json` files for the stamp.
89
+
90
+ - Pass: the Fundamentals IDs in `project.assets.json` are at the stamp, build has 0 warnings and 0 errors, 18 spec projects run and none fail.
91
+ - Time: pack about 4 min, build about 6 min, the spec projects about 18 min.
92
+ - Pitfall: skipping the embedded viewer build makes four `Screenplay.Embedded.Specs` fail
93
+ with a 404 for the viewer. It is the missing step, not the overlay.
94
+ - Pitfall: Arc's own `@cratis/fundamentals` npm line is out of scope for the NuGet stamp.
95
+ - Skip producer specs when the producer is unchanged `origin/main`; its CI covered that SHA.
96
+
97
+ For a JavaScript Fundamentals fix, run the producer's build and `pack-npm`, then `use-npm` in
98
+ Arc and install. Include every affected workspace tarball so no transitive copy stays released.
99
+
100
+ ## Components → Studio frontend (npm)
101
+
102
+ ```bash
103
+ (cd "$components" && yarn install --immutable && yarn workspace @cratis/components run ci && yarn build)
104
+ stamp=$(bash "$local" stamp "$components")
105
+ (cd "$components" && bash "$local" pack-npm . "$stamp")
106
+ bash "$local" use-npm "$studio" "$stamp"
107
+ (cd "$studio" && yarn install) # not --immutable: the overlay edits the lock
108
+ yarn why @cratis/components
109
+ ```
110
+
111
+ Gates: from `Source/<App>` run `yarn ci` for each Studio application that uses
112
+ `@cratis/components` (Core, Admin, Editor, EventModels, Viewer, ScreenMigration), `node
113
+ scripts/generate-scene-package-catalog.mjs --check`, then in Core `yarn build` and the
114
+ `initial-bundle-guard.mjs` budget check, and `yarn build-storybook` where the script exists.
64
115
 
65
- For a .NET Fundamentals fix, build/spec the producer, generate its stamp and
66
- `pack-nuget` the affected projects and dependency closure. In Arc, run `use-nuget`
67
- with the required Fundamentals package IDs, source the printed env/config, restore,
68
- then build/spec Arc with its CI configuration. Inspect `project.assets.json` to
69
- confirm the actual stamp. No image is required unless the reproducer needs one.
116
+ - Pass: every installed `@cratis/components*` copy is at the stamp (`yarn why` and the installed `package.json` files),
117
+ `yarn why` shows one resolution, and every gate above exits 0.
118
+ - Time: Components `ci` about 7 min, all-workspace build about 1 min, pack about 2 min,
119
+ Studio install under 30 s, Studio gates about 8 min.
120
+ - Pitfall: `yarn workspace @cratis/components run ci` builds only the core package. Run
121
+ `yarn build` at the Components root before `pack-npm`, or the adapter tarballs have no
122
+ `dist` and Studio fails with `Failed to resolve entry for package
123
+ "@cratis/components.primereact"`.
124
+ - Pitfall: the root `package.json` version is a placeholder, so the stamp base comes from tags.
125
+ Resolutions bypass the prerelease ranges that npm would otherwise ignore.
70
126
 
71
- For a JavaScript Fundamentals fix, run the producer's normal build and
72
- `pack-npm`, then `use-npm` in Arc and install. Run Arc frontend build/specs and the
73
- reproducer. Include all affected workspace tarballs so a transitive dependency
74
- cannot silently remain released. A green producer-only spec is not consumer proof.
75
- Finish with the entry point's commit checks, restoration and cleanup.
127
+ ## Chronicle clients → Direct (NuGet)
76
128
 
77
- ## Components → Studio frontend
129
+ ```bash
130
+ stamp=$(bash "$local" stamp "$chronicle")
131
+ (cd "$chronicle" && dotnet pack Source/Clients/Packages.slnf -c Release -p:PackageVersion=$stamp -p:Version=$stamp \
132
+ -p:IsPackaging=true -p:DisableProxyGenerator=true -p:DisableDockerBuild=true -o "$CRATIS_LOCAL_FEED/nuget")
133
+ bash "$local" use-nuget "$direct" "$stamp"
134
+ ```
135
+
136
+ Gates (Direct `build.yml`): `dotnet build Source/Direct/Direct.csproj -c Release
137
+ -p:DisableProxyGenerator=true`, the same in Debug with `-warnaserror`, `dotnet test` of that
138
+ project with `--no-build`, and `dotnet test Source/Assurance/Assurance.csproj`. Then
139
+ check `project.assets.json`. Image-based specs also need the producer image tag.
140
+
141
+ - Pass for a consumer whose pins lag the producer: every Chronicle ID is in the feed at the
142
+ stamp, the Release build with the owner's floors passes, and `project.assets.json` shows every
143
+ stamped ID at the stamp. The Debug `-warnaserror` build and the specs are gated on the consumer owner's pin
144
+ bump (Arc, Orleans, Screenplay, MongoDB.Driver) and on the analyzer fixes the newer pins
145
+ bring. Record that dependency; do not edit the consumer's source or tracked pins.
146
+ - Time: pack about 5 min; the Release build about 2 min.
147
+ - Pitfall: pass pack properties as `-p:` arguments to `dotnet pack`, never
148
+ as environment variables; `pack-nuget` takes none. An exported `IsPackaging=true` reaches Chronicle's nested
149
+ `dotnet run` code generator and fails with a multi-target error.
150
+ - Pitfall: a consumer whose pins lag the producer's own pins fails with NU1109 or NU1605.
151
+ That is the upgrade the consumer would need anyway; record the bump list.
152
+ - Pitfall: a released umbrella package can pull in a released package that is also stamped
153
+ (here an AspNetCore package). Pin it with a direct reference or treat it as a finding.
154
+
155
+ ## Screenplay → Stage and Studio (NuGet and npm)
156
+
157
+ ```bash
158
+ stamp=$(bash "$local" stamp "$screenplay")
159
+ (cd "$screenplay" && yarn install && yarn workspaces foreach -Rt --from @cratis/screenplay-mcp-app run build \
160
+ && bash "$local" pack-nuget . "$stamp" Screenplay.slnx && yarn build && bash "$local" pack-npm . "$stamp")
161
+ bash "$local" use-nuget "$stage" "$stamp"; bash "$local" use-nuget "$studio" "$stamp"
162
+ bash "$local" use-npm "$studio" "$stamp" # at the workspace root, not the nested app
163
+ ```
164
+
165
+ Gates: Stage's frontend `npm ci`, test and build, then `dotnet build` in Debug and the repository's
166
+ own spec-shard helper; skip probes that need a live kernel or database and say so. Studio:
167
+ `dotnet build` of its solution in Debug with warnings as errors, then the frontend `yarn ci` and
168
+ `yarn build` of every workspace that consumes the language package.
78
169
 
79
- Build/spec Components using its own package scripts, including any required
80
- Storybook gate. Then:
170
+ - Pass: `project.assets.json` shows the stamp in both NuGet consumers and `yarn why` at the Studio workspace root shows one resolution; specs executed > 0.
171
+ - Pitfall: a repository without a committed lockfile fails `yarn install --immutable`; use plain
172
+ `yarn install` there.
173
+ - Pitfall: yarn hoists to the root `node_modules`; check and install at the root.
174
+ - Pitfall: the packed language tarball must contain its built bundles. `pack-npm` uses `yarn pack`;
175
+ a package whose `files` lists a gitignored folder can ship only part of it. Compare the
176
+ tarball file list with the package's `dist` folder.
177
+ - Pitfall: multi-hop. Studio keeps its released Stage; a binary break is a finding.
178
+
179
+ ## Arc → Chronicle (NuGet)
81
180
 
82
181
  ```bash
83
- stamp=$(bash "$local" stamp "$producer")
84
- bash "$local" pack-npm "$producer" "$stamp"
85
- bash "$local" use-npm "$consumer" "$stamp"
86
- cd "$consumer"
87
- yarn install
182
+ stamp=$(bash "$local" stamp "$arc")
183
+ (cd "$arc" && bash "$local" pack-nuget . "$stamp" Arc.slnx)
184
+ bash "$local" use-nuget "$chronicle" "$stamp"
88
185
  ```
89
186
 
90
- Confirm the Components `file:` tarball resolutions. Run Studio's frontend build,
91
- lint/specs and exercise the broken dialog/page. If Vite serves stale assets, stop
92
- the dev server, clear only its `.vite` prebundle and restart. Avoid `link:` and
93
- `portal:` because duplicate React/context instances distort the reproduction.
94
- Overlay-only lockfile changes from Yarn install are restored automatically.
95
- Review npm backups if unrelated changes cause `restore` to refuse; preserve
96
- that work, restore only local changes and retry. Reinstall released packages,
97
- run `check`, and review/apply cleanup for this stamp.
187
+ Gates: Chronicle `dotnet build` in Release with `DisableProxyGenerator=true` and
188
+ `DisableDockerBuild=true`, the non-integration specs; Workbench `yarn install` then `yarn ci`
189
+ with `NODE_OPTIONS=--max-old-space-size=4096`.
190
+
191
+ - Pass: Release build clean; every spec assembly passes; `project.assets.json` shows the stamp for
192
+ every Arc ID.
193
+ - Finding when the consumer's other pins lag: the build passes, but the specs fail with
194
+ `MissingMethodException` on a Fundamentals method the newer Arc calls, because Chronicle pins an
195
+ older Fundamentals than Arc was built against. Record it; do not edit the consumer's pins.
196
+ - Pitfall: build the Arc embedded viewer before the .NET build, or the Arc build fails.
197
+ - Pitfall: Chronicle resolves Arc packages to the stamp only where its manifests pin them; a
198
+ released package that depends on a released Arc package keeps that version. Record it.
199
+ - Pitfall: `use-npm` overlays only the consumer repository root `package.json` and has no option to
200
+ target `Source/Workbench`, so this recipe does not put the Arc npm packages under the Workbench.
201
+ To verify them there, run `pack-npm` in Arc, then add `file:` resolutions to the Workbench
202
+ manifest by hand and run `yarn install`; do not claim the Workbench result without that step.
203
+ - Pitfall: the Workbench is its own Yarn project with its own lockfile. `restore` refuses to
204
+ put back a changed lockfile; in a throwaway worktree check out the two manifests and remove the
205
+ helper's backup folder.
206
+
207
+ ## Fundamentals → Arc → Chronicle under one stamp
208
+
209
+ ```bash
210
+ stamp=$(bash "$local" stamp "$arc") # one stamp, reused for every layer
211
+ (cd "$fundamentals" && bash "$local" pack-nuget . "$stamp" Fundamentals.slnx)
212
+ bash "$local" use-nuget "$arc" "$stamp" # Arc builds against the new Fundamentals
213
+ (cd "$arc" && bash "$local" pack-nuget . "$stamp" Arc.slnx)
214
+ bash "$local" restore "$arc"
215
+ bash "$local" use-nuget "$chronicle" "$stamp" # no IDs: every stamped Fundamentals and Arc ID
216
+ ```
217
+
218
+ Gates: Chronicle Release build and the non-integration specs, as above.
219
+
220
+ Without package IDs `use-nuget` overrides every package in the feed carrying the stamp, so Chronicle
221
+ resolves Fundamentals at the stamp both directly and through Arc; naming only the Arc IDs would leave
222
+ its direct Fundamentals pin at the release and bring back the `MissingMethodException`.
223
+
224
+ - Pass: every spec assembly passes (no `MissingMethodException`), which the two-repository run does
225
+ not achieve. A binary mismatch between layers disappears only when every layer carries the same stamp.
226
+ - Order: pack the upstream first, overlay it into the next repository, pack that, and so on;
227
+ inspect the nuspec of each pack before overlaying it.
228
+ - A stamp is tied to the commit of the repository it was generated from. After changing any
229
+ layer, generate a new stamp and repeat the chain.
230
+ - Time: each pack 15–30 minutes with queue waits; the Chronicle build and specs about 5 minutes
231
+ of run time each.
@@ -0,0 +1,68 @@
1
+ # Reference table of producer/consumer dependencies between Cratis repositories. cratis-local-packages.sh does not read it.
2
+ # Tab-separated; # starts a comment; no versions (pins are read live from consumer manifests).
3
+ # pack <repo> <eco> <target> [PROP=VAL,...] pack targets; PROP is a -p:PROP=VAL argument (never an environment variable)
4
+ # ids <repo> <eco> <comma-separated expected package IDs>
5
+ # uses <consumer> <producer> <eco> <manifest path relative to consumer>
6
+ # image <repo> <dockerfile> <tag-suffix>
7
+ # A target of "." means the repository root (npm workspaces).
8
+
9
+ # Fundamentals
10
+ pack Fundamentals nuget Fundamentals.slnx
11
+ ids Fundamentals nuget Cratis.Fundamentals,Cratis.Metrics.Roslyn,Cratis.OpenTelemetry
12
+ pack Fundamentals npm .
13
+
14
+ # Orleans (edges only)
15
+ pack Orleans nuget Orleans.slnx
16
+
17
+ # Arc
18
+ pack Arc nuget Arc.slnx CratisSpecsTargetFramework=net10.0
19
+ ids Arc nuget Cratis.Arc,Cratis.Arc.Core,Cratis.Arc.MongoDB,Cratis.Arc.EntityFrameworkCore,Cratis.Arc.Swagger,Cratis.Arc.Connections.Azure,Cratis.Arc.ProxyGenerator.Build,Cratis.Arc.Testing
20
+ pack Arc npm .
21
+ ids Arc npm @cratis/arc,@cratis/arc.react,@cratis/arc.react.mvvm,@cratis/arc.vite
22
+
23
+ # Chronicle (clients only; the kernel ships as an image)
24
+ pack Chronicle nuget Source/Clients/Packages.slnf IsPackaging=true,DisableProxyGenerator=true,DisableDockerBuild=true
25
+ ids Chronicle nuget Cratis.Chronicle,Cratis.Chronicle.AspNetCore,Cratis.Chronicle.Aspire,Cratis.Chronicle.CodeAnalysis,Cratis.Chronicle.Connections,Cratis.Chronicle.Contracts,Cratis.Chronicle.Testing,Cratis.Chronicle.XUnit.Integration
26
+ image Chronicle Docker/Production/Dockerfile (none)
27
+
28
+ # Components
29
+ pack Components npm .
30
+ ids Components npm @cratis/components,@cratis/components.primereact,@cratis/components.mui
31
+
32
+ # Screenplay
33
+ pack Screenplay nuget Screenplay.slnx
34
+ pack Screenplay npm .
35
+ ids Screenplay npm @cratis/screenplay-language
36
+
37
+ # Stage
38
+ pack Stage nuget Stage.slnx
39
+
40
+ # Edges (consumer, producer, ecosystem, manifest)
41
+ uses Arc Fundamentals nuget Directory.Packages.props
42
+ uses Arc Chronicle nuget Directory.Packages.props
43
+ uses Arc Screenplay nuget Directory.Packages.props
44
+ uses Chronicle Fundamentals nuget Directory.Packages.props
45
+ uses Chronicle Arc nuget Directory.Packages.props
46
+ uses Chronicle Orleans nuget Directory.Packages.props
47
+ uses Chronicle Arc npm Source/Workbench
48
+ uses Orleans Arc nuget Directory.Packages.props
49
+ uses Orleans Chronicle nuget Directory.Packages.props
50
+ uses Orleans Fundamentals nuget Directory.Packages.props
51
+ uses Stage Fundamentals nuget Directory.Packages.props
52
+ uses Stage Arc nuget Directory.Packages.props
53
+ uses Stage Chronicle nuget Directory.Packages.props
54
+ uses Stage Screenplay nuget Directory.Packages.props
55
+ uses Studio Fundamentals nuget Directory.Packages.props
56
+ uses Studio Arc nuget Directory.Packages.props
57
+ uses Studio Chronicle nuget Directory.Packages.props
58
+ uses Studio Orleans nuget Directory.Packages.props
59
+ uses Studio Stage nuget Directory.Packages.props
60
+ uses Studio Screenplay nuget Directory.Packages.props
61
+ uses Studio Components npm .
62
+ uses Studio Screenplay npm .
63
+ uses Direct Fundamentals nuget Directory.Packages.props
64
+ uses Direct Arc nuget Directory.Packages.props
65
+ uses Direct Chronicle nuget Directory.Packages.props
66
+ uses Direct Orleans nuget Directory.Packages.props
67
+ uses Direct Screenplay nuget Directory.Packages.props
68
+ uses Direct Chronicle image Source/Watchdog/Dockerfile.full
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cratis/pi",
3
- "version": "7.103.3",
3
+ "version": "7.103.5",
4
4
  "description": "Configuration-aware Cratis AI integration for Pi",
5
5
  "type": "module",
6
6
  "files": [