Repository navigation
Expand file tree
/
Copy pathjustfile
More file actions
763 lines (719 loc) · 44.7 KB
/
Copy pathjustfile
File metadata and controls
763 lines (719 loc) · 44.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
# Elohim developer CLI — one discoverable root entrypoint.
#
# Public surface: gate · test · dev · mesh · seed · look · status · codegen
# Project-specific mechanics stay in private recipes and build-manifest.json.
set dotenv-load := false
root := justfile_directory()
app_dir := root / "app" / "elohim-app"
a2o_dir := root / "genesis" / "a2o"
seeder_dir := root / "genesis" / "seeder"
[private]
default:
@just --list
# Run the manifest-declared quality gate for changed files, a project name, or a path.
gate target="changed" base="origin/dev":
#!/usr/bin/env bash
set -euo pipefail
if [[ "{{ target }}" != "changed" ]]; then
exec node "{{ root }}/genesis/orchestrator/gate-runner.mjs" --target "{{ target }}"
fi
changes="$(mktemp)"
trap 'rm -f "$changes"' EXIT
if git rev-parse --verify "{{ base }}" >/dev/null 2>&1; then
merge_base="$(git merge-base HEAD "{{ base }}")"
git diff --name-only "$merge_base"...HEAD >> "$changes"
else
git diff-tree --no-commit-id --name-only -r HEAD >> "$changes"
fi
git diff --name-only >> "$changes"
git diff --cached --name-only >> "$changes"
git ls-files --others --exclude-standard >> "$changes"
sort -u "$changes" | node "{{ root }}/genesis/orchestrator/gate-runner.mjs" --changed-file-list
# Run one test family; `mesh` is the Act I a2o lane, optionally scoped to a path or tag expression.
test target="changed" scope="":
#!/usr/bin/env bash
set -euo pipefail
case "{{ target }}" in
changed) exec just --justfile "{{ root }}/justfile" gate ;;
app) cd "{{ app_dir }}"; exec pnpm test ;;
a2o) cd "{{ a2o_dir }}"; exec pnpm run test:unit ;;
mesh|mesh-browser)
# Act I lane — the a2o `mesh` cucumber profile against the household mesh THIS host owns.
# `mesh-browser` is the same act, same mesh, through a real browser: it selects the
# `mesh-browser` profile (@browser/@browser-only, which `mesh` excludes) and points the
# app URL at the doorway, which serves the app AND proxies the sign-in portal, so both
# live on one origin and a portal return-URL is an ordinary same-origin redirect.
# Env comes from the same two sources the CI mesh stage uses: hc-mesh.sh's `mesh_seed_env`
# (seed/probe block) and hc-mesh-prologue.sh's "a2o env" block, so a local run and the
# pipeline read the same names. Bring the mesh up first: `just mesh start && just mesh prologue`.
# THE BERTH LEASE IS THE ROUTER (plan R4): the household is one per workspace, so this lane
# claims it as `verify` (or a declared `measure`) for a bounded ttl before anything else
# runs — a second session is refused in under a second (exit 3) with the holder named, never
# queued. BERTH_CLASS=measure is refused naming `just measure <scope>`; MEASURE_ON_DEV_BERTH=1
# declares an override that puts dev-berth-held-by-measure@1 on the record. Only exit 4 (no
# session resolvable, e.g. a bare non-Claude shell) proceeds, unleased; every other non-zero
# code is propagated. A renew or a lane covered by this session's own `mesh start` daemon
# lease keeps that hold, so only a claim this lane made is given back on exit.
# DEADLINE FENCE: the lane body re-enters this recipe under `timeout` at the lease's ttl (its
# own process group; INT, then KILL 30 s later), so an EXPIRED lane lease implies a dead lane
# and a takeover is safe.
if [[ -z "${BERTH_FENCED:-}" ]]; then
berth="{{ root }}/genesis/agentic/bin/berth"
lane_class="${BERTH_CLASS:-verify}"
lane_ttl="${BERTH_TTL:-1800}"
case "$lane_class" in
verify|measure) ;;
*) echo "REFUSED: BERTH_CLASS=$lane_class — a test lane claims verify|measure (\`mesh\` is the daemon lease \`just mesh start\` holds)" >&2; exit 2 ;;
esac
berth_rc=0
berth_out="$("$berth" claim mesh --class "$lane_class" --ttl "$lane_ttl" --note "test {{ target }} {{ scope }}")" || berth_rc=$?
if [[ -n "$berth_out" ]]; then echo "$berth_out"; fi
if [[ "$berth_rc" -ne 0 && "$berth_rc" -ne 4 ]]; then exit "$berth_rc"; fi
if [[ "$berth_rc" -eq 0 && "$berth_out" != *renewed* ]]; then
trap '"$berth" release mesh >/dev/null 2>&1 || true' EXIT
fi
lane_rc=0
BERTH_FENCED=1 timeout --signal=INT --kill-after=30 "$lane_ttl" \
just --justfile "{{ root }}/justfile" app_dir="{{ app_dir }}" a2o_dir="{{ a2o_dir }}" \
test "{{ target }}" "{{ scope }}" || lane_rc=$?
if [[ "$lane_rc" -eq 124 || "$lane_rc" -eq 137 ]]; then
echo "BUDGET-EXCEEDED: $lane_class lane ran past its ${lane_ttl}s lease" >&2
exit 3
fi
exit "$lane_rc"
fi
# `set +e` around the source because hc-mesh.sh is `set -u` only and its optional-binary
# probes (mongod, the conductor fork) legitimately exit non-zero at load.
set +e
# shellcheck source=/dev/null
source "{{ app_dir }}/scripts/hc-mesh.sh"
set -e
mesh_seed_env
DOORWAY_B_PORT="${DOORWAY_B_PORT:-8889}"
export E2E_DOORWAY_ALPHA="$DOORWAY_URL"
export E2E_DOORWAY_B="http://localhost:$DOORWAY_B_PORT"
export E2E_DOORWAY_BETA="$E2E_DOORWAY_B"
# Gamma (story 3.1's second "garden" holder, name-routing.feature scenario 5,
# still @wip) is OPTIONAL — only export when it is actually up, mirroring
# hc-mesh-prologue.sh's "a2o env" block exactly. An unconditional export here
# would out-rank the household fixture's honest absentReason
# (household-mesh.ts::applyDoorwayEnvironment: an env var always wins over the
# manifest) and turn a clear named absence into a bare connection-refused.
if [[ "${MESH_DOORWAY_GAMMA:-1}" = "1" ]] && curl -s -m 2 "http://localhost:$DOORWAY_C_PORT/health" >/dev/null; then
export E2E_DOORWAY_GAMMA="http://localhost:$DOORWAY_C_PORT"
else
unset E2E_DOORWAY_GAMMA
fi
export E2E_STORAGE_URL="$STORAGE_URL"
i=0
for peer in "${PEERS[@]}"; do
peer_url="http://localhost:$(http_port $i)"
if [[ "$i" -eq 1 ]]; then export E2E_STORAGE_B="$peer_url"; fi
export "E2E_STORAGE_$(echo "$peer" | tr '[:lower:]' '[:upper:]')=$peer_url"
i=$((i+1))
done
export E2E_DOORWAY_POOL_STORAGE_URLS="$(peer_url_csv)"
household_fixture="$MESH_DIR/household-fixture.json"
if [[ -f "$household_fixture" ]]; then
export E2E_HOUSEHOLD_FIXTURE_PATH="$household_fixture"
else
unset E2E_HOUSEHOLD_FIXTURE_PATH
fi
# CAST PREFLIGHT — refuse before launch, the same contract the portal check below
# holds for browser lanes. Every hosted-human / humans-served scenario logs in as a
# cast member the prologue registered in the doorway archive; a cold start drops that
# archive (hc-mesh.sh) and a lane run without a fresh prologue fails as sixteen
# opaque `Invalid credentials` 401s with nothing naming the cause (measured
# 2026-09-11, run 20260911T223432Z). The roster file is written by the prologue and
# removed with the archive, so "present and newer than the archive's birth" is the whole
# precondition. The archive's birth is storage.bson (written once when mongod initialises
# the dbpath, never touched again) — NOT the mongo directory, whose mtime moves on every
# collection file mongod creates. MESH_ALLOW_NO_PROLOGUE=1 runs anyway (a scoped lane
# that casts no one).
roster="$MESH_DIR/prologue-hosted-humans.json"
archive_birth="$MESH_DIR/mongo/storage.bson"
if [[ "${MESH_ALLOW_NO_PROLOGUE:-0}" != "1" ]]; then
if [[ ! -f "$roster" ]]; then
echo "REFUSED: no hosted-human roster at $roster — the doorway archive has no cast." >&2
echo " Run \`just mesh prologue\` first (or MESH_ALLOW_NO_PROLOGUE=1 for a lane that casts nobody)." >&2
exit 2
fi
if [[ -f "$archive_birth" && "$archive_birth" -nt "$roster" ]]; then
echo "REFUSED: the doorway archive was (re)created after the hosted-human roster ($roster)." >&2
echo " The cast it names was dropped by a cold start; run \`just mesh prologue\` before this lane." >&2
exit 2
fi
fi
wait_for_lamad_call_readiness 75
export ELOHIM_CLUSTER_STATE_PATH_OVERRIDE="{{ root }}/genesis/manifests/cluster-state.act1-household.yaml"
# One home: the runtime signal is DERIVED from the lane's cluster-state (the household file
# declares no remote compute, so `unavailable`), never typed beside it; no `epr` reads unavailable.
eval "$(epr flow hold --scope --env --cluster-state "$ELOHIM_CLUSTER_STATE_PATH_OVERRIDE" 2>/dev/null || echo 'export ELOHIM_REMOTE_COMPUTE_STATUS=unavailable')"
# DURABLE TRACE. Reports live under the REPO (genesis/a2o/reports/, gitignored),
# not under $MESH_DIR: /tmp is wiped on container restart, so every honest local
# run's evidence died with the container and counted for nothing. See
# genesis/docs/superpowers/specs/2026-08-22-verification-as-memoized-derivation-guidestar.md
# (§S1/§S4: the lane with the highest discovery value produced the least durable
# evidence — this lane is the ONLY one where destructive chapters can run at all).
reports_dir="{{ a2o_dir }}/reports"
mkdir -p "$reports_dir"
# Default, not a force: a caller-supplied CUCUMBER_JSON_REPORT survives, so a
# scoped run's report isn't clobbered by a later full-lane run.
cucumber_json_report_supplied="${CUCUMBER_JSON_REPORT:+1}"
# Law II env input: the peer count this run addressed. The household fixture also
# carries it, but the fixture is written by `just mesh prologue` and can be absent,
# while the mesh roster is always in scope here. Nothing else is forced from this
# recipe on purpose — the fixture declares processControl, and an undeclared
# network stage / DNA hash is reported `unknown` by the builder rather than guessed.
export A2O_PEER_COUNT="${#PEERS[@]}"
# The transport-parity story must name its mode inside Gherkin. A matrix
# caller pins the requested mode; an ordinary mesh run derives it from
# every peer's live status, so neither path trusts a launcher variable.
export E2E_EXPECTED_TRANSPORT="${E2E_EXPECTED_TRANSPORT:-$(mesh_transport_backend_from_status)}"
# Run id: sortable UTC stamp + the commit measured. Lexicographic order IS
# chronological order, and a mesh run takes minutes, so one second is collision-free.
run_id="${A2O_RUN_ID:-$(date -u +%Y%m%dT%H%M%SZ)-$(git -C "{{ root }}" rev-parse --short=8 HEAD 2>/dev/null || echo nogit)}"
export A2O_RUN_ID="$run_id"
a2o_profile=mesh
if [[ "{{ target }}" == "mesh-browser" ]]; then
a2o_profile=mesh-browser
export E2E_DEVICE_MODE=playwright
export E2E_APP_URL="${E2E_APP_URL:-$DOORWAY_URL}"
# PORTAL PREFLIGHT — refuse before launch, the same contract `just mesh preflight`
# holds for the mesh itself. The portal is a bare `ng serve` with no supervisor;
# the workspace RAM guard sheds it and the only symptom the lane produced was a
# step timeout inside `threshold-register-display-name` with nothing naming the
# cause (measured 2026-09-11, run 20260911T0326Z — every browser scenario timed
# out, ~1 wasted run). Every browser scenario signs in through
# <doorway>/threshold/login, so a single probe of exactly that URL is the whole
# precondition: a 502 there is the portal upstream gone.
portal_url="$E2E_APP_URL/threshold/login"
# curl already writes 000 on a transport failure, so do NOT append another
# fallback code — `|| echo 000` concatenated with it and printed "000000".
portal_code="$(curl -s -m 10 -o /dev/null -w '%{http_code}' "$portal_url" 2>/dev/null)"
[[ -n "$portal_code" ]] || portal_code=000
if [[ "$portal_code" != "200" ]]; then
echo "REFUSED: the sign-in portal does not answer at $portal_url (HTTP $portal_code)." >&2
echo " Every @browser scenario signs in there; without it they all time out in" >&2
echo " 'threshold-register-display-name' with no hint. Bring it back with:" >&2
echo " just mesh portal-restart # then re-run this lane" >&2
echo " (502 = the doorway is up but its THRESHOLD_URL upstream is gone — the" >&2
echo " usual case, a RAM-guard shed. 000 = the doorway itself is down: just mesh status.)" >&2
exit 2
fi
echo "portal preflight ok: $portal_url -> 200"
fi
if [[ -z "$cucumber_json_report_supplied" ]]; then
export CUCUMBER_JSON_REPORT="$reports_dir/cucumber-$a2o_profile-$run_id.json"
fi
mkdir -p "$(dirname "$CUCUMBER_JSON_REPORT")"
cd "{{ a2o_dir }}"
# NO `exec`: exec replaces the shell, so nothing after cucumber ever ran and a run
# left no report. Capture the verdict instead and propagate it at the end.
rc=0
if [[ -z "{{ scope }}" ]]; then
"{{ a2o_dir }}/node_modules/.bin/cucumber-js" --profile "$a2o_profile" || rc=$?
else
# SCOPING: cucumber MERGES a profile's `paths` with CLI positionals instead of replacing
# them, so a bare `--profile mesh features/x.feature` runs the WHOLE tree plus that file.
# Generate a config carrying the mesh profile MINUS `paths` so the positional (or --tags)
# actually narrows. cucumber does `path.join(cwd, configFile)`, so --config must be a path
# RELATIVE to genesis/a2o — an absolute one is silently mangled.
export A2O_PROFILE="$a2o_profile"
cfg="$reports_dir/cucumber-$a2o_profile-scoped.mjs"
printf '%s\n' \
'// GENERATED by `just test mesh <scope>`: the mesh profile MINUS `paths`, so a CLI' \
'// positional or tag expression scopes the run instead of merging with the whole' \
'// feature tree. Regenerated every run; never commit it.' \
"import profiles from 'file://{{ a2o_dir }}/cucumber.mjs';" \
'export default function () {' \
' const name = process.env.A2O_PROFILE || "mesh";' \
' const { paths: _paths, ...profile } = profiles()[name];' \
' // A2O_RUN_WIP=1 must reach the SCENARIO FILTER, not just the step hook in' \
' // steps/common.steps.ts. cucumber ANDs a CLI --tags with the profile tags, so' \
' // the profile`s own `not @wip` survived every override and a scoped @wip run' \
' // reported "0 scenarios" as a GREEN no-op (measured 2026-09-07 on the' \
' // accountable-correction feature). Drop the clause here, at the one place the' \
' // profile is rewritten, so the documented local red loop can actually run.' \
' if (process.env.A2O_RUN_WIP === "1" && typeof profile.tags === "string") {' \
' profile.tags = profile.tags.split(" and not @wip").join("");' \
' }' \
' return { [name]: profile };' \
'}' > "$cfg"
cfg_rel="$(realpath --relative-to="{{ a2o_dir }}" "$cfg")"
case "{{ scope }}" in
@*|*" and "*|*" or "*|*"not "*)
"{{ a2o_dir }}/node_modules/.bin/cucumber-js" --config "$cfg_rel" --profile "$a2o_profile" --tags "{{ scope }}" || rc=$? ;;
*)
# REFUSE-BEFORE-LAUNCH: a path scope is resolved by cucumber-js
# relative to genesis/a2o (this recipe already `cd`'d there) — a
# repo-relative scope like `genesis/a2o/features/x.feature` matches
# nothing, and cucumber silently reports "0 scenarios" with exit 0
# (the previous silent-no-op class this guard exists to catch).
# `compgen -G` is glob-aware, so a bare path AND a glob scope both
# resolve the same way a positional argument to cucumber-js would.
if ! compgen -G "{{ scope }}" >/dev/null 2>&1; then
hint=""
case "{{ scope }}" in
genesis/a2o/*)
candidate="{{ scope }}"
candidate="${candidate#genesis/a2o/}"
if compgen -G "$candidate" >/dev/null 2>&1; then
hint=" — did you mean '${candidate}'? (scope is relative to genesis/a2o, not the repo root)"
fi
;;
esac
echo "REFUSED: scope '{{ scope }}' selects nothing relative to genesis/a2o (cwd for this run)${hint}. Pass a path relative to genesis/a2o (e.g. 'features/dataplane/x.feature') or a tag expression (e.g. '@concern:foo')." >&2
exit 2
fi
"{{ a2o_dir }}/node_modules/.bin/cucumber-js" --config "$cfg_rel" --profile "$a2o_profile" "{{ scope }}" || rc=$? ;;
esac
fi
# Built REGARDLESS of the verdict: a red run that leaves no evidence is the exact
# defect this slice exists to fix. Run-identified under the stable glob
# reports/sprint-report-household-*.json, so no run overwrites another. A scoped run
# still reports every unexercised DECLARED concern as NOT MEASURED (Law I) — a
# re-scope must not make missing coverage vanish.
# --console-dir / --coverage-gap are LANE-OWNED slots, not the builder's ambient
# defaults (reports/console, reports/coverage-gap.json). Those two paths accumulate
# across every lane and are never cleared per run: with the defaults, this household
# report attributed 22 console-error findings from an Aug-20 BROWSER run to a
# 1-scenario mesh run. A report may under-count its own findings; it may not carry
# another run's. (The steps hardcode `reports/console`, so wiring the household lane's
# own capture into this slot is a genesis/a2o/steps change, not a justfile one.)
report_rc=0
# Stamp what every running peer proves, not the launcher selection. A
# partial dual restart resolves to unknown rather than forging a dual
# evidence key from MESH_TRANSPORT_BACKEND alone.
observed_transport="$(mesh_transport_backend_from_status)"
# --scope (empty string when unscoped, parsed as absent by build-sprint-report.ts):
# an empty-selection receipt (a scoped run that measured 0 scenarios) fails
# THIS step, not just cucumber's own exit code — see its --scope handling.
node --import tsx scripts/build-sprint-report.ts \
--cucumber "$CUCUMBER_JSON_REPORT" \
--console-dir "$reports_dir/console-household" \
--coverage-gap "$reports_dir/coverage-gap-household.json" \
--out-json "${A2O_SPRINT_REPORT_JSON:-$reports_dir/sprint-report-household-$run_id.json}" \
--out-md "${A2O_SPRINT_REPORT_MD:-$reports_dir/sprint-report-household-$run_id.md}" \
--profile mesh \
--lane household \
--transport "$observed_transport" \
--run-id "$run_id" \
--scope "{{ scope }}" \
--doorway "$E2E_DOORWAY_ALPHA" || report_rc=$?
# Cucumber's code wins so a red run stays red; a GREEN run whose evidence could not
# be written is not a green run either, so the builder's code is the fallback.
if [[ "$rc" -ne 0 ]]; then exit "$rc"; fi
exit "$report_rc"
;;
seeder) cd "{{ seeder_dir }}"; exec pnpm test ;;
storage) exec node "{{ root }}/genesis/orchestrator/gate-runner.mjs" --target elohim-storage ;;
doorway) exec node "{{ root }}/genesis/orchestrator/gate-runner.mjs" --target doorway ;;
node) exec node "{{ root }}/genesis/orchestrator/gate-runner.mjs" --target steward-node ;;
sophia) cd "{{ root }}/sophia"; exec pnpm test --ci ;;
*) echo "test target must be changed|app|a2o|mesh|seeder|storage|doorway|node|sophia" >&2; exit 2 ;;
esac
# Manage the single-peer local stack. Safe default: status.
dev action="status" profile="isolated" seed="false" build="false":
#!/usr/bin/env bash
set -euo pipefail
case "{{ action }}" in
start)
args=()
[[ "{{ seed }}" == "true" ]] && args+=(--seed)
[[ "{{ build }}" == "true" ]] && args+=(--build)
case "{{ profile }}" in
isolated) export NETWORK_PROFILE=isolated ;;
alpha) export NETWORK_PROFILE=join-alpha ;;
*) echo "dev profile must be isolated|alpha" >&2; exit 2 ;;
esac
exec "{{ app_dir }}/scripts/hc-start.sh" "${args[@]}"
;;
conductor)
# The T3 hybrid rung: `just dev conductor profile=alpha` = a workspace conductor joined to
# alpha's network (sovereign peer). The profile mapping is the same as `start` — before
# 2026-08-28 this arm ignored `profile`, so profile=alpha silently started an isolated node.
# Usage: just dev conductor alpha [CONDUCTOR_RELEASE_CHANNELS=<channel>=observe]
# Sprint 2026-09-08 (T2): when the household mesh's own peers are live, hc-start.sh
# auto-offsets this peer's STORAGE_PORT/DOORWAY_PORT and sandbox name so it runs beside
# the mesh without a port collision — no flags needed here, straight passthrough.
case "{{ profile }}" in
isolated) export NETWORK_PROFILE=isolated ;;
alpha) export NETWORK_PROFILE=join-alpha ;;
*) echo "dev profile must be isolated|alpha" >&2; exit 2 ;;
esac
exec "{{ app_dir }}/scripts/hc-start.sh" --conductor
;;
app) cd "{{ app_dir }}"; exec pnpm start ;;
package)
package_app="{{ profile }}"
[[ "$package_app" == "isolated" ]] && package_app="{{ app_dir }}"
package_args=("$package_app" --build)
[[ -n "${EPR_APP_ADAPTER:-}" ]] && package_args+=(--adapter "$EPR_APP_ADAPTER")
[[ -n "${EPR_APP_TARGET:-}" ]] && package_args+=(--target "$EPR_APP_TARGET")
exec node "{{ root }}/elohim/sdk/scripts/package-app.mjs" "${package_args[@]}"
;;
stop)
# Sprint 2026-09-08 follow-up: was `pkill -x holochain` + `fuser -k` on
# fixed ports — beside a running household mesh (hc-mesh.sh) that killed
# the mesh too (its conductors are also named `holochain`; its doorway A
# / storage matthew sit on exactly 8888/8090). hc-start.sh --stop reaps
# only the pids it recorded for THIS workspace stack's own sandbox.
exec "{{ app_dir }}/scripts/hc-start.sh" --stop
;;
status) just --justfile "{{ root }}/justfile" status runtime ;;
*) echo "dev action must be start|conductor|app|package|stop|status" >&2; exit 2 ;;
esac
# Manage or measure the local multi-peer mesh. Safe default: status.
mesh action="status" *args:
#!/usr/bin/env bash
set -euo pipefail
case "{{ action }}" in
# start holds the household's DAEMON lease (class `mesh`: no ttl, never taken over by expiry,
# only when its holder's mooring is dead): a start while another live session holds the mesh
# is refused (exit 3) with the holder named. Only exit 4 (no session resolvable) proceeds,
# unleased; every other non-zero code is propagated. A failed start gives the lease back.
start)
berth="{{ root }}/genesis/agentic/bin/berth"
berth_rc=0
"$berth" claim mesh --class mesh --note "mesh start" || berth_rc=$?
if [[ "$berth_rc" -ne 0 && "$berth_rc" -ne 4 ]]; then exit "$berth_rc"; fi
start_rc=0
"{{ app_dir }}/scripts/hc-mesh.sh" start || start_rc=$?
if [[ "$start_rc" -ne 0 && "$berth_rc" -eq 0 ]]; then "$berth" release mesh >/dev/null 2>&1 || true; fi
exit "$start_rc" ;;
# stop is destructive to whoever holds the household: refused (exit 3, holder named) while
# another live session holds `mesh`; MESH_STOP_FORCE=1 overrides with an `override` row and
# gives back the overridden lease once the household is down.
stop)
berth="{{ root }}/genesis/agentic/bin/berth"
force=()
if [[ "${MESH_STOP_FORCE:-0}" == "1" ]]; then force=(--force); fi
owner_rc=0
"$berth" owner-check mesh --action stop --note "just mesh stop" "${force[@]}" || owner_rc=$?
if [[ "$owner_rc" -ne 0 ]]; then exit "$owner_rc"; fi
stop_rc=0
"{{ app_dir }}/scripts/hc-mesh.sh" stop || stop_rc=$?
if [[ "$stop_rc" -eq 0 ]]; then "$berth" release mesh "${force[@]}" >/dev/null 2>&1 || true; fi
exit "$stop_rc" ;;
status|probe|prologue) exec "{{ app_dir }}/scripts/hc-mesh.sh" "{{ action }}" ;;
# preflight/wait (sprint 2026-09-08, T1): `start` already runs preflight itself and
# launches detached — these are for checking readiness/refusals independently (a fresh
# shell polling a `start` someone else kicked off, or a dry-run binary/port check).
preflight) exec "{{ app_dir }}/scripts/hc-mesh.sh" preflight ;;
# build the mesh's OWN storage (p2p p2p-iroh) + doorway binaries and install them into the
# pool's mesh-bin/ paths, which the gate never writes; MESH_BUILD_DRY_RUN=1 prints the commands.
build) exec "{{ app_dir }}/scripts/hc-mesh.sh" build {{ args }} ;;
wait) exec "{{ app_dir }}/scripts/hc-mesh.sh" wait {{ args }} ;;
quiesce) exec "{{ app_dir }}/scripts/hc-mesh-quiesce.sh" ;;
monitor) exec python3 "{{ app_dir }}/scripts/hc-mesh-monitor.py" ;;
# matrix/recovery/recovery-matrix are MEASURE-class runs (windows, restarts, repeated shapes):
# they claim `mesh --class measure` first, so on the dev berth they are refused (exit 3, naming
# `just measure <scope>`) unless MEASURE_ON_DEV_BERTH=1 declares the override (ttl BERTH_TTL,
# default 3600 s) and puts dev-berth-held-by-measure@1 on the record.
matrix|recovery|recovery-matrix)
berth="{{ root }}/genesis/agentic/bin/berth"
berth_rc=0
berth_out="$("$berth" claim mesh --class measure --ttl "${BERTH_TTL:-3600}" --note "mesh {{ action }} {{ args }}")" || berth_rc=$?
if [[ -n "$berth_out" ]]; then echo "$berth_out"; fi
if [[ "$berth_rc" -ne 0 && "$berth_rc" -ne 4 ]]; then exit "$berth_rc"; fi
if [[ "$berth_rc" -eq 0 && "$berth_out" != *renewed* ]]; then
trap '"$berth" release mesh >/dev/null 2>&1 || true' EXIT
fi
case "{{ action }}" in
matrix) "{{ app_dir }}/scripts/hc-mesh-transport-matrix.sh" ;;
recovery) "{{ app_dir }}/scripts/hc-mesh-recovery.sh" {{ args }} ;;
recovery-matrix) "{{ app_dir }}/scripts/hc-mesh-recovery-matrix.sh" ;;
esac ;;
# Restart arms (ratchet lane D, rung D2 pawls — 2026-08-28): the same hc-mesh.sh actions the
# recovery harness drives, reachable through the verb so a shift never has to know the script.
conductors-restart) exec "{{ app_dir }}/scripts/hc-mesh.sh" conductors-restart ;;
storage-restart) exec "{{ app_dir }}/scripts/hc-mesh.sh" storage-restart {{ args }} ;;
# Re-exec one doorway (a | b | c) on the binary now at its path, with its captured env —
# how a rebuilt doorway reaches the running household without a full mesh restart.
doorway-restart) exec "{{ app_dir }}/scripts/hc-mesh.sh" doorway-restart {{ args }} ;;
# The sign-in portal (doorway-app `ng serve` on THRESHOLD_PORT) is shed by the
# workspace RAM guard like any other fat node process and nothing supervises it.
# `just test mesh-browser` refuses to start without it, and this is the arm that
# brings it back — no other mesh component is touched.
portal-restart) exec "{{ app_dir }}/scripts/hc-mesh.sh" portal-restart ;;
join-peer) exec "{{ app_dir }}/scripts/hc-mesh.sh" join-peer {{ args }} ;;
*) echo "mesh action must be start|preflight|build [storage|doorway|beacon]|wait [--timeout N]|stop|status|probe|prologue|quiesce|monitor|matrix|recovery|recovery-matrix|conductors-restart|storage-restart [peer...]|doorway-restart <a|b|c>|portal-restart|join-peer <fresh-name>" >&2; exit 2 ;;
esac
# Seed content or validate a corpus facet (profile: local|alpha|mesh). False content dry-run modes are intentionally absent.
seed action="validate" profile="local" scope="content" limit="":
#!/usr/bin/env bash
set -euo pipefail
cd "{{ seeder_dir }}"
export CONDUCTOR_URLS="${CONDUCTOR_URLS:-ws://localhost:4445}"
case "{{ profile }}" in
local) ;;
alpha)
export DOORWAY_URL=https://doorway-alpha.elohim.host
export DOORWAY_API_KEY=dev-elohim-auth-2024
export STORAGE_URL=https://storage-alpha.elohim.host
export HOLOCHAIN_ADMIN_URL='wss://doorway-alpha.elohim.host?apiKey=dev-elohim-auth-2024'
export ADMIN_PROXY_URL=https://doorway-alpha.elohim.host
;;
mesh)
# The household mesh THIS host owns (`just mesh start`): the seed-chain env comes from
# hc-mesh.sh's `mesh_seed_env` — the one source of truth `just test mesh` and the CI mesh
# stage already read (DOORWAY_URL/STORAGE_URL/DOORWAY_API_KEY/ADMIN_PROXY_URL + the cast's
# CONDUCTOR_URLS). `set +e` around the source: hc-mesh.sh is `set -u` only and its
# optional-binary probes exit non-zero at load.
set +e
# shellcheck source=/dev/null
source "{{ app_dir }}/scripts/hc-mesh.sh"
set -e
mesh_seed_env
export ADMIN_PROXY_URL="${ADMIN_PROXY_URL:-$DOORWAY_URL}"
;;
*) echo "seed profile must be local|alpha|mesh" >&2; exit 2 ;;
esac
case "{{ action }}" in
validate)
case "{{ scope }}" in
content) exec pnpm exec tsx src/schema-validation.ts ../data/lamad/content ;;
all) exec pnpm run validate:all ;;
collectives|humans|presences|account-packages|devices|deployments|corpora)
exec pnpm run "validate:{{ scope }}"
;;
*) echo "validation scope must be content|all|collectives|humans|presences|account-packages|devices|deployments|corpora" >&2; exit 2 ;;
esac
;;
apply)
case "{{ scope }}" in
content)
args=()
if [[ -n "{{ limit }}" ]]; then
[[ "{{ limit }}" =~ ^[0-9]+$ ]] || { echo "seed limit must be a positive integer" >&2; exit 2; }
args+=(--limit "{{ limit }}")
fi
exec pnpm exec tsx src/seed.ts "${args[@]}"
;;
conductors) exec pnpm exec tsx src/seed-conductor-identities.ts ;;
agent-bindings) exec pnpm exec tsx src/seed-agent-bindings.ts ;;
humans) exec pnpm exec tsx src/seed-humans.ts ;;
collectives) exec pnpm exec tsx src/seed-collectives.ts ;;
presences) exec pnpm exec tsx src/seed-presences.ts ;;
accounts) exec pnpm exec tsx src/seed-accounts.ts ;;
nodes) exec pnpm exec tsx src/seed-nodes.ts ;;
epr-atoms) exec pnpm exec tsx src/seed-epr-atom.ts ;;
commitments) exec pnpm exec tsx src/seed-commitments.ts ;;
household) exec pnpm exec tsx src/seed-household-formation.ts ;;
delegates) exec pnpm exec tsx src/seed-delegates-compute.ts ;;
test-admin) exec pnpm exec tsx src/seed-test-admin.ts ;;
*) echo "apply scope must be content|conductors|agent-bindings|humans|collectives|presences|accounts|nodes|epr-atoms|commitments|household|delegates|test-admin" >&2; exit 2 ;;
esac
;;
stats) exec pnpm exec tsx src/stats.ts ;;
diagnose) exec pnpm exec tsx src/diagnose.ts ;;
*) echo "seed action must be validate|apply|stats|diagnose" >&2; exit 2 ;;
esac
# Render a page or the Graphos component system.
look kind="page" target="":
#!/usr/bin/env bash
set -euo pipefail
cd "{{ a2o_dir }}"
case "{{ kind }}" in
page) [[ -n "{{ target }}" ]] || { echo "usage: just look page <url>" >&2; exit 2; }; exec pnpm look "{{ target }}" ;;
graphos) [[ -n "{{ target }}" ]] || { echo "usage: just look graphos <list|story|sheet>" >&2; exit 2; }; exec pnpm graphos "{{ target }}" ;;
*) echo "look kind must be page|graphos" >&2; exit 2 ;;
esac
# Show the runtime, habits, saga, CI preview, seed, or RAM-guard state.
status view="all":
#!/usr/bin/env bash
set -euo pipefail
runtime() {
for endpoint in 'Doorway|http://localhost:8888/health' 'Storage|http://localhost:8090/health'; do
name="${endpoint%%|*}"; url="${endpoint#*|}"
if curl -sf -m 2 "$url" >/dev/null; then printf '%-10s UP\n' "$name"; else printf '%-10s down\n' "$name"; fi
done
"{{ app_dir }}/scripts/hc-mesh.sh" status 2>/dev/null || true
}
case "{{ view }}" in
runtime) runtime ;;
habits) python3 "{{ root }}/.claude/scripts/habits-status.py" --full ;;
saga) python3 "{{ root }}/.claude/scripts/saga-status.py" ;;
ci) node "{{ root }}/genesis/orchestrator/preview.mjs" origin/dev ;;
seed) cd "{{ seeder_dir }}"; exec pnpm exec tsx src/stats.ts ;;
ram) exec python3 "{{ root }}/genesis/agentic/bin/ram-guard" status ;;
# device: has this workspace ARRIVED as one of its human's devices — six ok/REFUSED lines
# (epr binary · device key · roster bound · embed model · fold attested · berth moored), each
# REFUSED naming its fix; exit 1 on any REFUSED. Spec: elohim/lvi/docs/specs/2026-10-10-workspace-arrival-as-declared-device.md
device) exec python3 "{{ root }}/genesis/agentic/bin/device-preflight" ;;
all) runtime; python3 "{{ root }}/genesis/agentic/bin/ram-guard" status --brief || true; python3 "{{ root }}/genesis/agentic/bin/device-preflight" || true; python3 "{{ root }}/.claude/scripts/habits-status.py" ;;
*) echo "status view must be all|runtime|habits|saga|ci|seed|ram|device" >&2; exit 2 ;;
esac
# Generate or verify derived interfaces. Safe default: verify.
codegen target="all" mode="verify":
#!/usr/bin/env bash
set -euo pipefail
[[ "{{ mode }}" == "verify" || "{{ mode }}" == "write" ]] || { echo "codegen mode must be verify|write" >&2; exit 2; }
run_target() {
case "$1:{{ mode }}" in
schema:verify) pnpm run schema:codegen:ts -- --verify; pnpm run schema:codegen:rs -- --verify ;;
schema:write) pnpm run schema:codegen:ts; pnpm run schema:codegen:rs ;;
domains:verify) pnpm run manifest:codegen:verify; pnpm run lamad:codegen:verify; pnpm run imagodei:codegen:verify; pnpm run shefa:codegen:verify; pnpm run qahal:codegen:verify; pnpm run avodah:codegen:verify ;;
domains:write) pnpm run lamad:codegen; pnpm run imagodei:codegen; pnpm run shefa:codegen; pnpm run qahal:codegen; pnpm run avodah:codegen ;;
routes:verify) pnpm run route-claims:codegen:verify ;;
routes:write) pnpm run route-claims:codegen ;;
agents:verify) node elohim/sdk/domains/elohim-agent/scripts/package-projections.mjs verify ;;
agents:write) node elohim/sdk/domains/elohim-agent/scripts/package-projections.mjs project --write-fixtures --write-runtime ;;
wire-types:verify) pnpm run wire-types:generate; git diff --exit-code -- elohim/sdk/storage-client-ts/src/generated ;;
wire-types:write) pnpm run wire-types:generate ;;
elements:verify) pnpm run elements:codegen:verify ;;
elements:write) pnpm run elements:codegen ;;
rakia:verify) pnpm run rakia:codegen:rs:verify ;;
rakia:write) pnpm run rakia:codegen:rs ;;
*) echo "codegen target must be all|schema|domains|routes|agents|wire-types|elements|rakia" >&2; exit 2 ;;
esac
}
if [[ "{{ target }}" == all ]]; then
for target in schema domains routes agents elements rakia; do run_target "$target"; done
else
run_target "{{ target }}"
fi
# ---- Private manifest runners -------------------------------------------------
# Executable contract probe for run-local-gate.sh's env handling. Not registered
# in any manifest; invoked directly by gate-runner.test.mjs so that
# `rustflags: ""` collapsing back to inherit can never regress silently.
_gate-selftest-env:
@echo "RUSTFLAGS=[${RUSTFLAGS-<unset>}] CARGO_TARGET_DIR=[${CARGO_TARGET_DIR-<unset>}]"
@echo "CARGO_BUILD_JOBS=[${CARGO_BUILD_JOBS-<unset>}] RUST_TEST_THREADS=[${RUST_TEST_THREADS-<unset>}] GATE_CARGO_ENV=[${GATE_CARGO_ENV-<unset>}]"
_gate-elohim-library:
cd app/elohim-library && pnpm exec eslint projects/elohim-service/src projects/lamad-ui/src projects/html5-app-plugin/src
cd app/elohim-library/projects/elohim-service && pnpm exec tsc --noEmit && pnpm exec tsc --noEmit -p tsconfig.spec.json && pnpm exec vitest run
_gate-elohim-storybook:
cd app/elohim-library && pnpm run build-storybook && pnpm run test-storybook:ci
_gate-elements-codegen:
pnpm run elements:codegen:verify
pnpm --filter elohim-core test
_gate-elohim-compute:
cd elohim/elohim-compute && cargo fmt --check && cargo clippy -- -D warnings && cargo test
_gate-elohim-epr:
cd elohim && cargo fmt --check && cargo clippy -p elohim-epr -p elohim-epr-rea -p elohim-epr-index -- -D warnings && cargo test -p elohim-epr -p elohim-epr-rea -p elohim-epr-index --all-targets
_gate-elohim-ark:
cd elohim && cargo fmt --check -p elohim-ark-core -p elohim-ark-supervisor -p elohim-ark && cargo clippy -p elohim-ark-core -p elohim-ark-supervisor -p elohim-ark -- -D warnings && cargo test -p elohim-ark-core -p elohim-ark-supervisor -p elohim-ark --all-targets
# `pnpm build` first: @elohim/epr ships no dist/ in the tree, so a consumer's
# import fails at module resolution rather than at type-check. Testing a package
# that cannot be imported proves the tests, not the package.
_gate-epr-ts:
cd elohim/sdk/epr-ts && pnpm build && pnpm test
# elohim/eprfs is its own native workspace with no per-project justfile; the
# recipe lives here so the manifest's typed contract has a real target.
_gate-eprfs:
cd elohim/eprfs && cargo fmt --check
cd elohim/eprfs && cargo clippy --workspace --all-targets -- -D warnings
cd elohim/eprfs && cargo test --workspace
# Exercise the agent journey against the same native binary just built in the
# manifest-selected pool slot; the Cucumber profile owns isolated local fixtures.
_gate-memory-ceremony:
# Station six round (a) (2026-09-11): genesis/scripts/memory_balance.py, its shell wrapper
# and its unittest are deleted. The paired burden/benefit measure is native —
# elohim/eprfs/epr-cli/src/flow/memory/footprint.rs (METHOD_VERSION bounded-memory-balance-v1),
# gated below by --test flow_memory_footprint, whose pinned normalized digest is asserted
# unconditionally and does not need the Python oracle to be present.
cargo build --manifest-path elohim/eprfs/Cargo.toml -p elohim-epr-cli
# Station five (2026-09-10): the recall executor and the identity-closed corrections view are
# native. These two binaries carry the 60 Python recall cases (54 counterparts + 6 retired as
# out-of-process artefacts); the Python suite and its scripts are gone.
cargo test --manifest-path elohim/eprfs/Cargo.toml -p elohim-epr-cli --test flow_memory_recall --test flow_concerns_corrections --test flow_memory_footprint --test flow_memory_recall_golden --test flow_memory_recall_lens --test flow_memory_recall_sample --test flow_report --test flow_report_fold_lag
# Governed-discovery station 4 (final review, ruling I3): the native semantic provider's own
# suites — the fold, the semantic and lexical routes, first-screen fusion, the pinned embedder
# and the index declarations — run in the gate that covers the station.
cargo test --manifest-path elohim/eprfs/Cargo.toml -p elohim-epr-cli --test flow_memory_recall_fold --test flow_memory_recall_semantic --test flow_memory_recall_fusion --test flow_memory_recall_lexical --test flow_memory_recall_embedder --test flow_memory_recall_index
# Station four (2026-09-10): the memory-index projection router and the relocated memory
# lenses. Station six round (b) (2026-09-11) removed the kit leg from every hook, so these
# now pin the INVERTED contract: a drift signal is a fold and only a fold, and the index
# projection STANDS DOWN rather than falling back. Nothing else ran .claude/hooks/__tests__ —
# the same verification-that-never-runs shape pre-push names for .claude/scripts/_lib/__tests__.
EPR_BIN="$CARGO_TARGET_DIR/debug/epr" python3 -m unittest discover -s .claude/hooks/__tests__ -p '*_test.py'
python3 .epr-meta/elohim/lenses/memory/__tests__/memory_coherence_audit_test.py
cd genesis/a2o && EPR_BIN="$CARGO_TARGET_DIR/debug/epr" pnpm exec cucumber-js --profile ceremony
cd genesis/a2o && EPR_BIN="$CARGO_TARGET_DIR/debug/epr" pnpm exec cucumber-js --profile collective-memory
_gate-seam-contracts:
cd crates/seam-contracts && cargo test --all-features
cd crates/seam-contracts && cargo clippy --all-features -- -D warnings
cd crates/seam-contracts && cargo fmt --check
cd crates/seam-contracts && cargo build --target wasm32-unknown-unknown --no-default-features
_gate-consent-grant:
cd crates/consent-grant && cargo test
cd crates/consent-grant && cargo clippy --all-targets -- -D warnings
cd crates/consent-grant && cargo fmt --check
_gate-hc-dbtool:
cd elohim/holochain/tools/hc-dbtool && cargo test
cd elohim/holochain/tools/hc-dbtool && cargo clippy --all-targets -- -D warnings
cd elohim/holochain/tools/hc-dbtool && cargo fmt --check
_gate-epr-storage:
cd elohim/elohim-storage && cargo build && cargo test --test schema_contract && cargo test --test schema_contract_diesel_epr
cd elohim/sdk/storage-client-ts && pnpm test
_gate-elohim-sdk:
bash scripts/ci/elohim-sdk-feature-matrix.sh
_gate-schema-dna:
pnpm run schema:check-dna
_gate-manifest-hygiene:
cargo test --manifest-path elohim/holochain/tests/manifest-hygiene/Cargo.toml
_gate-sweettest-check:
#!/usr/bin/env bash
set -euo pipefail
clang_include="$(ls -1d /usr/lib/clang/*/include 2>/dev/null | sort -V | tail -1)"
BINDGEN_EXTRA_CLANG_ARGS="${BINDGEN_EXTRA_CLANG_ARGS:--I$clang_include}" OPENSSL_NO_VENDOR=1 \
cargo check --manifest-path elohim/holochain/tests/sweettest/Cargo.toml --tests
# extern-fails-loud, enforced (elohim/holochain/dna/.epr-meta/manifest.md): each DNA
# builds in its own in-tree ./target with its own justfile-exported RUSTFLAGS (the
# documented DNA exception — no CARGO_TARGET_DIR override here), so this just calls
# each DNA's own `lint-externs` recipe in turn rather than re-declaring RUSTFLAGS.
_gate-dna-extern-lints:
#!/usr/bin/env bash
set -euo pipefail
for dna in elohim imagodei infrastructure node-registry mishpat; do
echo "[dna-extern-lints] $dna"
just --justfile "elohim/holochain/dna/$dna/justfile" \
--working-directory "elohim/holochain/dna/$dna" lint-externs
done
_gate-schema-validate:
pnpm run schema:validate
_gate-schema-codegen:
pnpm run schema:codegen:ts -- --verify
pnpm run schema:codegen:rs -- --verify
pnpm run route-claims:codegen:verify
_gate-constants-sync:
pnpm run schema:codegen:ts -- --verify
cd genesis/seeder && pnpm exec vitest run src/__tests__/constants-sync.test.ts
_gate-genesis-a2o:
cd genesis/a2o && pnpm run lint && pnpm run format:check && pnpm run typecheck
_gate-gherkin-prepush-lint:
cd genesis/a2o && pnpm run lint:gherkin
_gate-reach-drift:
node genesis/seeder/scripts/check-reach-drift.mjs
_gate-domain-types:
#!/usr/bin/env bash
set -euo pipefail
for domain in imagodei infrastructure lamad qahal shefa avodah; do
cargo check --manifest-path "elohim/sdk/domains/$domain/types/Cargo.toml"
done
_gate-rakia-codegen:
pnpm run rakia:codegen:rs:verify
_gate-rakia-validate:
pnpm run rakia:schema:validate
_gate-cargo-coverage:
pnpm run validate:cargo-coverage
_gate-pipeline-list-fresh:
node genesis/orchestrator/scripts/generate-pipeline-list.mjs
git diff --exit-code -- genesis/orchestrator/pipeline-list.json
# SDK archive checks shared by local EPR-app packaging and CI staging, plus the
# staging ladder's own classification tests (fake curl/node, no network).
[private]
_gate-epr-app-package:
node --test "{{ root }}/elohim/sdk/scripts/package-app.test.mjs"
bash "{{ root }}/scripts/ci/stage-spa-blob.test.sh"
# Measure-class work leaves the dev berth: author ONE feature path as a peer-executed stage,
# submit it to the provider that holds the stores, detach, and read the receipt back into the
# ledger. Wraps genesis/agentic/compute/measure.sh (grant | worker | <feature-path> | status |
# poll | fixture). The dev berth refuses `berth claim mesh --class measure`; this is the verb the
# refusal names. MEASURE_DRY_RUN=1 prints the env block and the commands without running them.
measure *args:
#!/usr/bin/env bash
set -euo pipefail
exec bash "{{ justfile_directory() }}/genesis/agentic/compute/measure.sh" {{ args }}