@junghanacs/entwurf 0.41.2 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/AGENTS.md +4 -2
  2. package/BASELINE.md +110 -1
  3. package/CHANGELOG.md +328 -0
  4. package/CONTRIBUTING.md +1 -1
  5. package/ENTWURF-CLI.json +1229 -0
  6. package/ENTWURF.json +284 -0
  7. package/FAQ.md +4 -4
  8. package/README.md +125 -184
  9. package/VERIFY.md +2 -2
  10. package/docs/external-mcp-host.md +3 -3
  11. package/docs/setup-clean-host.md +37 -12
  12. package/mcp/entwurf-bridge/dist/ENTWURF.json +284 -0
  13. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +46 -196
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/agent-guidance.js +299 -0
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +21 -25
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +498 -29
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-dispatch.js +47 -10
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +613 -33
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-resume-call.js +497 -0
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +3 -1
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +23 -20
  22. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-resume-call.js +68 -21
  23. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-fresh-preflight.js +7 -1
  24. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-location.js +347 -0
  25. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-owner-fence.js +1132 -0
  26. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-runtime.js +1 -0
  27. package/mcp/entwurf-bridge/dist/pi-extensions/lib/remote-pair-send.js +7 -4
  28. package/mcp/entwurf-bridge/dist/pi-extensions/lib/resume-launch-identity.js +18 -11
  29. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +53 -60
  30. package/mcp/entwurf-bridge/dist/scripts/herdr-rails.mjs +40 -7
  31. package/mcp/entwurf-bridge/dist/scripts/meta-bridge-fresh-cut.js +1 -27
  32. package/mcp/entwurf-bridge/dist/scripts/meta-bridge-prune.js +1 -1
  33. package/mcp/entwurf-bridge/dist/scripts/meta-facts.js +1 -1
  34. package/mcp/entwurf-bridge/dist/scripts/peer-facts.js +1 -1
  35. package/mcp/entwurf-bridge/src/index.ts +149 -327
  36. package/mcp/entwurf-bridge/tsconfig.build.json +7 -1
  37. package/native/win32-x64/manifest.json +1 -1
  38. package/package.json +8 -4
  39. package/pi/pi-durable/bootstrap.mjs +179 -6
  40. package/pi/pi-durable/carrier/runtime.js +108 -9
  41. package/pi/pi-durable/carrier/session-name.js +11 -0
  42. package/pi/pi-durable/carrier/sessions.js +96 -20
  43. package/pi/pi-durable/overlay/upstream-pin.json +11 -5
  44. package/pi-extensions/lib/agent-guidance.ts +341 -0
  45. package/pi-extensions/lib/entwurf-v2-surface.ts +25 -31
  46. package/pi-extensions/lib/entwurf-v2-visible-resume.ts +725 -54
  47. package/pi-extensions/lib/fresh-call-dispatch.ts +64 -12
  48. package/pi-extensions/lib/herdr-fresh-call.ts +919 -40
  49. package/pi-extensions/lib/herdr-resume-call.ts +810 -0
  50. package/pi-extensions/lib/meta-session.ts +13 -8
  51. package/pi-extensions/lib/mux-fresh-call.ts +23 -26
  52. package/pi-extensions/lib/mux-resume-call.ts +95 -23
  53. package/pi-extensions/lib/pi-durable-fresh-preflight.ts +9 -2
  54. package/pi-extensions/lib/pi-durable-location.ts +446 -0
  55. package/pi-extensions/lib/pi-durable-owner-fence.ts +1461 -0
  56. package/pi-extensions/lib/pi-durable-runtime.ts +4 -0
  57. package/pi-extensions/lib/remote-pair-send.ts +7 -4
  58. package/pi-extensions/lib/resume-launch-identity.ts +31 -12
  59. package/pi-extensions/meta-bridge-pi-durable.ts +52 -79
  60. package/run.sh +417 -654
  61. package/scripts/build-bridge.sh +10 -0
  62. package/scripts/check-capability-bundle-reach.ts +86 -0
  63. package/scripts/check-claude-launch.ts +341 -0
  64. package/scripts/check-entwurf-self-address.ts +3 -3
  65. package/scripts/check-entwurf-v2-surface.ts +94 -98
  66. package/scripts/check-fresh-call-dispatch.ts +70 -9
  67. package/scripts/check-fresh-cut-gate.sh +23 -9
  68. package/scripts/check-gate-qualification.ts +24 -17
  69. package/scripts/check-herdr-activation.ts +301 -23
  70. package/scripts/check-herdr-fresh-call.ts +161 -25
  71. package/scripts/check-herdr-plugin-build.ts +173 -1
  72. package/scripts/check-herdr-plugin.ts +28 -2
  73. package/scripts/check-herdr-runtime-bootstrap.ts +136 -0
  74. package/scripts/check-install-surface.ts +1236 -6
  75. package/scripts/check-meta-doctor-oracle.sh +1 -1
  76. package/scripts/check-meta-facts.ts +20 -1
  77. package/scripts/check-mux-resume-call.ts +48 -3
  78. package/scripts/check-peer-facts.ts +39 -2
  79. package/scripts/cli-help.mjs +222 -0
  80. package/scripts/dev-bin.sh +39 -2
  81. package/scripts/herdr-activation.mjs +28 -6
  82. package/scripts/herdr-operator-link.mjs +389 -0
  83. package/scripts/herdr-plugin-activate.mjs +5 -0
  84. package/scripts/herdr-plugin-deactivate.mjs +18 -5
  85. package/scripts/herdr-rails.mjs +43 -7
  86. package/scripts/herdr-runtime.mjs +27 -0
  87. package/scripts/meta-bridge-fresh-cut.ts +1 -27
  88. package/scripts/meta-bridge-prune.ts +1 -1
  89. package/scripts/meta-facts.ts +1 -1
  90. package/scripts/mutants/agent-guidance.json +160 -0
  91. package/scripts/mutants/bridge-boot-resume.json +6 -8
  92. package/scripts/mutants/capability-bundle-reach.json +124 -0
  93. package/scripts/mutants/claude-launch.json +142 -0
  94. package/scripts/mutants/cli-help-source.json +420 -0
  95. package/scripts/mutants/control-send-receipt.json +21 -4
  96. package/scripts/mutants/dev-gate-dispatch.json +109 -0
  97. package/scripts/mutants/fresh-call-dispatch.json +38 -2
  98. package/scripts/mutants/fresh-cut.json +15 -0
  99. package/scripts/mutants/herdr-activation.json +128 -0
  100. package/scripts/mutants/herdr-fresh-call.json +278 -5
  101. package/scripts/mutants/herdr-operator-link.json +318 -0
  102. package/scripts/mutants/herdr-plugin-build.json +55 -0
  103. package/scripts/mutants/herdr-plugin.json +17 -0
  104. package/scripts/mutants/herdr-resume-call.json +288 -0
  105. package/scripts/mutants/herdr-runtime-bootstrap.json +48 -0
  106. package/scripts/mutants/meta-facts.json +15 -0
  107. package/scripts/mutants/mux-fresh-call.json +14 -3
  108. package/scripts/mutants/mux-resume-call.json +89 -3
  109. package/scripts/mutants/peer-facts.json +15 -0
  110. package/scripts/mutants/pi-durable.json +996 -6
  111. package/scripts/mutants/remote-pair-send.json +21 -2
  112. package/scripts/mutants/self-address.json +10 -10
  113. package/scripts/mutants/source-install.json +35 -0
  114. package/scripts/mutants/v2-surface.json +50 -64
  115. package/scripts/mutants/v2-visible-resume.json +266 -6
  116. package/scripts/peer-facts.ts +1 -1
  117. package/scripts/smoke-agy-install-state.sh +66 -0
  118. package/scripts/smoke-meta-prune.sh +23 -0
  119. package/scripts/smoke-omp-fresh-live.ts +12 -3
  120. package/scripts/smoke-omp-receive-live.ts +7 -1
  121. package/scripts/smoke-pi-durable-fresh-live.ts +12 -2
  122. package/team.json.example +39 -0
@@ -697,6 +697,72 @@ if bash "$DEVBIN" expose entwurf-bridge >/dev/null 2>&1; then die "dev-bin migra
697
697
  ok "dev-bin migrate: foreign legacy refused (linkPath basename != entwurf-bridge)"
698
698
  rm -f "$LEGACY" "$DLINK" "$DSTATE"
699
699
  bash "$DEVBIN" remove >/dev/null 2>&1
700
+ # J-6 (#153): dev-bin mutation is a SOURCE checkout's authority. The moved-checkout rule lets a
701
+ # developer's link follow its own checkout (D1 → D2); an INSTALLED package must not inherit it —
702
+ # measured before this guard: a node_modules-shaped root's public expose-dev-bin retargeted every
703
+ # managed link and state a dev checkout had made. The installed root is judged by where dev-bin.sh
704
+ # itself lives (symlinks and directory aliases resolved), never by cwd or a target override. The
705
+ # copies below carry THIS checkout's run.sh/dev-bin.sh/package.json bytes, so the cells test them.
706
+ OVERRIDES=(-u ENTWURF_OPERATOR_TARGET -u ENTWURF_BRIDGE_TARGET -u ENTWURF_AGY_STATUSLINE_TARGET -u ENTWURF_AGY_IMPRINT_TARGET -u ENTWURF_COPILOT_STATUSLINE_TARGET)
707
+ make_root() { # $1 = root dir: the three real files plus no-op helper targets
708
+ mkdir -p "$1/scripts" "$1/mcp/entwurf-bridge"
709
+ cp "$REPO_DIR/run.sh" "$1/run.sh"; cp "$DEVBIN" "$1/scripts/dev-bin.sh"; cp "$REPO_DIR/package.json" "$1/package.json"
710
+ for _t in mcp/entwurf-bridge/start.sh scripts/agy-statusline.sh scripts/agy-imprint.sh scripts/copilot-statusline.sh; do
711
+ printf '#!/bin/sh\nexit 0\n' > "$1/$_t"; chmod +x "$1/$_t"
712
+ done
713
+ chmod +x "$1/run.sh" "$1/scripts/dev-bin.sh"; unset _t
714
+ }
715
+ devbin_world() { # every link in the bin dir, every dev-bin state body, and the profile bytes
716
+ { for _f in "$DBIN_DIR"/* "$XDG_DATA_HOME"/entwurf/dev-bin/*; do
717
+ [ -e "$_f" ] || [ -L "$_f" ] || continue
718
+ if [ -L "$_f" ]; then printf 'L %s -> %s\n' "$_f" "$(readlink "$_f")"; else printf 'F %s %s\n' "$_f" "$(sha256sum < "$_f")"; fi
719
+ done
720
+ printf 'P %s\n' "$(sha256sum < "$HOME/.profile")"; } 2>/dev/null; unset _f
721
+ }
722
+ D1="$SB/src-d1"; D2="$SB/src-d2"; INST="$SB/inst/node_modules/@junghanacs/entwurf"
723
+ make_root "$D1"; make_root "$D2"; make_root "$INST"
724
+ printf '# smoke profile seed\n' > "$HOME/.profile"
725
+ env "${OVERRIDES[@]}" bash "$D1/scripts/dev-bin.sh" expose >/dev/null 2>&1 # a dev checkout's five links + states
726
+ printf '{"schemaVersion":1,"linkPath":"%s","target":"%s","detectMode":"created-new","stampedAt":"x"}\n' \
727
+ "$DBIN_DIR/entwurf-bridge" "$D1/mcp/entwurf-bridge/start.sh" > "$XDG_DATA_HOME/entwurf/dev-bin/install-state.json" # a legacy state migration would act on
728
+ ln -s "$INST" "$SB/inst-alias"; ln -s "$INST/scripts/dev-bin.sh" "$SB/dev-bin-link.sh"
729
+ WORLD_BEFORE="$(devbin_world)"
730
+ set +e
731
+ bash "$INST/scripts/dev-bin.sh" expose >"$SB/j6-direct.out" 2>&1; RC_DIRECT=$? # target overrides still set
732
+ env "${OVERRIDES[@]}" bash "$SB/inst-alias/scripts/dev-bin.sh" expose entwurf >/dev/null 2>&1; RC_ALIAS=$?
733
+ env "${OVERRIDES[@]}" bash "$SB/dev-bin-link.sh" expose entwurf >/dev/null 2>&1; RC_LINK=$?
734
+ set -e
735
+ WORLD_AFTER_EXPOSE="$(devbin_world)"
736
+ # an installed-root link and state that DO match the installed target: remove still refuses
737
+ rm -f "$OLINK"; ln -s "$INST/run.sh" "$OLINK"
738
+ printf '{"schemaVersion":1,"linkPath":"%s","target":"%s","detectMode":"created-new","stampedAt":"x"}\n' "$OLINK" "$INST/run.sh" > "$OSTATE"
739
+ WORLD_BEFORE_REMOVE="$(devbin_world)"
740
+ set +e; env "${OVERRIDES[@]}" bash "$INST/scripts/dev-bin.sh" remove entwurf >/dev/null 2>&1; RC_REMOVE=$?; set -e
741
+ want "installed dev-bin: expose (direct, alias, symlinked script) and remove refuse with 4 before any write — no link, state, legacy migration or profile change, even for a link the installed root's own target matches [QK:INSTALLED-DEVBIN-MUTATION-REFUSED]" \
742
+ "[ '$RC_DIRECT' -eq 4 ] && [ '$RC_ALIAS' -eq 4 ] && [ '$RC_LINK' -eq 4 ] && [ '$RC_REMOVE' -eq 4 ] && grep -qF 'REFUSE expose: this dev-bin.sh belongs to an installed package' '$SB/j6-direct.out' && [ \"\$WORLD_BEFORE\" = \"\$WORLD_AFTER_EXPOSE\" ] && [ \"\$WORLD_BEFORE_REMOVE\" = \"\$(devbin_world)\" ] && [ -f '$XDG_DATA_HOME/entwurf/dev-bin/install-state.json' ]"
743
+ rm -f "$OLINK"; ln -s "$D1/run.sh" "$OLINK"
744
+ printf '{"schemaVersion":1,"linkPath":"%s","target":"%s","detectMode":"created-new","stampedAt":"x"}\n' "$OLINK" "$D1/run.sh" > "$OSTATE"
745
+ rm -f "$XDG_DATA_HOME/entwurf/dev-bin/install-state.json"
746
+ # the public verbs: the refusal propagates, and nothing after it runs — no verify, no exclusive,
747
+ # no package-manager query (a recording pnpm/npm in front of the fixture ones).
748
+ PM_TRACE="$SB/j6-pm.trace"; : > "$PM_TRACE"; PM_REC="$SB/j6-pm"; mkdir -p "$PM_REC"
749
+ for _pm in pnpm npm; do printf '#!/usr/bin/env bash\necho "%s $*" >> "%s"\nexec "%s/%s" "$@"\n' "$_pm" "$PM_TRACE" "$FAKE_PM" "$_pm" > "$PM_REC/$_pm"; chmod +x "$PM_REC/$_pm"; done; unset _pm
750
+ WORLD_BEFORE="$(devbin_world)"
751
+ set +e
752
+ OUT="$(env "${OVERRIDES[@]}" PATH="$PM_REC:$DBIN_DIR:$PATH" bash "$INST/run.sh" expose-dev-bin 2>&1)"; RC=$?
753
+ env "${OVERRIDES[@]}" PATH="$PM_REC:$DBIN_DIR:$PATH" bash "$INST/run.sh" remove-dev-bin >/dev/null 2>&1; RC_PREMOVE=$?
754
+ set -e
755
+ want "installed public expose-dev-bin/remove-dev-bin exit 4 with the named refusal, and nothing follows it: no verify, no exclusive, no package-manager query, no change [QK:INSTALLED-DEVBIN-PUBLIC-STOPS]" \
756
+ "[ '$RC' -eq 4 ] && [ '$RC_PREMOVE' -eq 4 ] && printf '%s' \"\$OUT\" | grep -qF 'REFUSE expose: this dev-bin.sh belongs to an installed package' && ! printf '%s' \"\$OUT\" | grep -qE 'dev-bin verify|dev-bin exclusive|PATH winner' && [ ! -s '$PM_TRACE' ] && [ \"\$WORLD_BEFORE\" = \"\$(devbin_world)\" ]"
757
+ # the developer's own authority is kept: a link a source checkout made follows it to another one
758
+ set +e; env "${OVERRIDES[@]}" bash "$D2/scripts/dev-bin.sh" expose entwurf >"$SB/j6-d2.out" 2>&1; RC=$?; set -e
759
+ want "source dev-bin keeps the moved-checkout rule: the D1 link and state move to D2 as refresh-ours [QK:SOURCE-DEVBIN-MOVED-CHECKOUT]" \
760
+ "[ '$RC' -eq 0 ] && [ \"\$(readlink '$OLINK')\" = '$D2/run.sh' ] && grep -q 'refresh-ours' '$SB/j6-d2.out' && python3 -c 'import json,sys; sys.exit(0 if json.load(open(sys.argv[1]))[\"target\"]==sys.argv[2] else 1)' '$OSTATE' '$D2/run.sh'"
761
+ env "${OVERRIDES[@]}" bash "$D2/scripts/dev-bin.sh" remove entwurf >/dev/null 2>&1
762
+ env "${OVERRIDES[@]}" bash "$D1/scripts/dev-bin.sh" remove >/dev/null 2>&1
763
+ rm -rf "$D1" "$D2" "$SB/inst" "$SB/inst-alias" "$SB/dev-bin-link.sh" "$PM_REC" "$PM_TRACE" "$HOME/.profile"
764
+ want "installed dev-bin cells leave no managed link or state behind" "[ -z \"\$(ls -A '$DBIN_DIR' 2>/dev/null)\" ] && [ ! -d '$XDG_DATA_HOME/entwurf/dev-bin' ]"
765
+
700
766
  unset ENTWURF_DEV_BIN_DIR ENTWURF_OPERATOR_TARGET ENTWURF_BRIDGE_TARGET ENTWURF_AGY_STATUSLINE_TARGET
701
767
  export PATH="$DEVBIN_ORIG_PATH"
702
768
  unset ENTWURF_AGY_IMPRINT_TARGET ENTWURF_COPILOT_STATUSLINE_TARGET
@@ -166,6 +166,29 @@ OUT3="$(node --experimental-strip-types "$PRUNE" "$STORE" --ttl-days 100 2>&1)"
166
166
  set -e
167
167
  echo "$OUT3" | grep -q "STALE recordUpdatedAt>100d (0):" && echo "$OUT3" | grep -q "KEEP (live/recent): 2 record" && ok "--ttl-days widens keep window" || bad "--ttl-days did not move stale boundary"
168
168
 
169
+ # the leaf's usage is now only the address of the description (#153): --help keeps exit 0 and an
170
+ # unknown flag keeps exit 2 with its cause line, both with nothing on stdout. These two children get
171
+ # their own scratch HOME, XDG roots, PI dir and store under $TMP, never the operator's.
172
+ PRUNE_HOME="$TMP/help-home"
173
+ prune_env=(HOME="$PRUNE_HOME" XDG_DATA_HOME="$PRUNE_HOME/.local/share" XDG_STATE_HOME="$PRUNE_HOME/.local/state"
174
+ XDG_CACHE_HOME="$PRUNE_HOME/.cache" XDG_CONFIG_HOME="$PRUNE_HOME/.config" PI_CODING_AGENT_DIR="$PRUNE_HOME/.pi/agent"
175
+ ENTWURF_META_SESSIONS_DIR="$PRUNE_HOME/store")
176
+ PRUNE_POINTER='meta-bridge-prune: see `entwurf help meta-bridge-prune` (from that checkout'"'"'s root: `./run.sh help meta-bridge-prune`)'
177
+ set +e
178
+ env "${prune_env[@]}" node --experimental-strip-types "$PRUNE" --help >"$TMP/help.out" 2>"$TMP/help.err"
179
+ HELP_CODE=$?
180
+ env "${prune_env[@]}" node --experimental-strip-types "$PRUNE" --bogus >"$TMP/bogus.out" 2>"$TMP/bogus.err"
181
+ BOGUS_CODE=$?
182
+ set -e
183
+ if [ "$HELP_CODE" = "0" ] && [ ! -s "$TMP/help.out" ] && [ "$(cat "$TMP/help.err")" = "$PRUNE_POINTER" ] \
184
+ && [ "$(wc -l <"$TMP/help.err")" = 1 ] \
185
+ && [ "$BOGUS_CODE" = "2" ] && [ ! -s "$TMP/bogus.out" ] \
186
+ && [ "$(cat "$TMP/bogus.err")" = "unknown flag: --bogus"$'\n'"$PRUNE_POINTER" ] && [ "$(wc -l <"$TMP/bogus.err")" = 2 ]; then
187
+ ok "--help (exit 0) and --bogus (exit 2, after its cause line) print nothing on stdout and point at \`entwurf help meta-bridge-prune\`"
188
+ else
189
+ bad "[QK:PRUNE-HELP-POINTER] the leaf's usage is not exactly the pointer line: help rc=$HELP_CODE stderr=$(head -c 300 "$TMP/help.err") stdout=$(head -c 200 "$TMP/help.out") | bogus rc=$BOGUS_CODE stderr=$(head -c 300 "$TMP/bogus.err") stdout=$(head -c 200 "$TMP/bogus.out")"
190
+ fi
191
+
169
192
  if [ "$fail" = "0" ]; then
170
193
  echo "smoke-meta-prune PASS"
171
194
  else
@@ -221,8 +221,12 @@ ok("the caller is a record-backed citizen with an armed mailbox and a sender mar
221
221
 
222
222
  const citizensBefore = new Set(
223
223
  (
224
- JSON.parse(execFileSync("bash", [path.join(REPO, "run.sh"), "meta-facts"], { encoding: "utf8" }))
225
- .citizens as Array<{
224
+ JSON.parse(
225
+ execFileSync("bash", [path.join(REPO, "run.sh"), "meta-facts"], {
226
+ encoding: "utf8",
227
+ maxBuffer: 64 * 1024 * 1024,
228
+ }),
229
+ ).citizens as Array<{
226
230
  gardenId: string;
227
231
  }>
228
232
  ).map((c) => c.gardenId),
@@ -356,7 +360,12 @@ ok(
356
360
  );
357
361
 
358
362
  // ── 7. that id is a real omp citizen, and the ONLY one this step minted ──────
359
- const facts = JSON.parse(execFileSync("bash", [path.join(REPO, "run.sh"), "meta-facts"], { encoding: "utf8" }));
363
+ const facts = JSON.parse(
364
+ execFileSync("bash", [path.join(REPO, "run.sh"), "meta-facts"], {
365
+ encoding: "utf8",
366
+ maxBuffer: 64 * 1024 * 1024,
367
+ }),
368
+ );
360
369
  const citizen = (facts.citizens as Array<Record<string, unknown>>).find((c) => c.gardenId === siblingGid);
361
370
  ok(
362
371
  "the callback id resolves to a V3 record whose backend is omp",
@@ -279,7 +279,13 @@ ok(
279
279
  // This closes a real gap rather than a cosmetic one. `entwurf_inbox_read` takes a
280
280
  // CALLER-SUPPLIED garden id and does not verify it against the caller's identity, so
281
281
  // `lastReadAt` alone proves a read happened — not that THIS session performed it.
282
- const record = JSON.parse(sh("bash", [path.join(REPO, "run.sh"), "meta-facts"]));
282
+ const record = JSON.parse(
283
+ execFileSync("bash", [path.join(REPO, "run.sh"), "meta-facts"], {
284
+ encoding: "utf8",
285
+ stdio: ["ignore", "pipe", "pipe"],
286
+ maxBuffer: 64 * 1024 * 1024,
287
+ }),
288
+ );
283
289
  const citizen = (record.citizens as Array<Record<string, unknown>>).find((c) => c.gardenId === gardenId);
284
290
  ok("the citizen's V3 record names a transcript for this session", typeof citizen?.transcriptPath === "string");
285
291
  const transcriptPath = citizen?.transcriptPath as string;
@@ -258,7 +258,12 @@ receipts["1-fixture"] = `gardenId=${fixtureGid} backend=claude-code (collector o
258
258
 
259
259
  const citizensBefore = new Set(
260
260
  (
261
- JSON.parse(execFileSync("bash", [path.join(REPO, "run.sh"), "meta-facts"], { encoding: "utf8" })) as {
261
+ JSON.parse(
262
+ execFileSync("bash", [path.join(REPO, "run.sh"), "meta-facts"], {
263
+ encoding: "utf8",
264
+ maxBuffer: 64 * 1024 * 1024,
265
+ }),
266
+ ) as {
262
267
  citizens: Array<{ gardenId: string }>;
263
268
  }
264
269
  ).citizens.map((c) => c.gardenId),
@@ -453,7 +458,12 @@ ok(
453
458
  JSON.stringify(pdMarker),
454
459
  );
455
460
 
456
- const facts = JSON.parse(execFileSync("bash", [path.join(REPO, "run.sh"), "meta-facts"], { encoding: "utf8" })) as {
461
+ const facts = JSON.parse(
462
+ execFileSync("bash", [path.join(REPO, "run.sh"), "meta-facts"], {
463
+ encoding: "utf8",
464
+ maxBuffer: 64 * 1024 * 1024,
465
+ }),
466
+ ) as {
457
467
  citizens: Array<{ gardenId: string }>;
458
468
  };
459
469
  // Other siblings may mint citizens in the operator's garden meanwhile; this step's are the ones in its scratch cwd.
@@ -0,0 +1,39 @@
1
+ {
2
+ "version": 1,
3
+ "project": "example-project",
4
+ "cwd": "/absolute/path/to/project",
5
+ "notes": [
6
+ "Illustrative caller-maintained sibling bookmarks, not a runtime standard. All identities below are fictional.",
7
+ "Copy this file to team.json at the repository root and ignore /team.json in that repository's .gitignore.",
8
+ "Everyone is a sibling, including the coordinator. Tasks are agreed with the human for each piece of work, not fixed identities.",
9
+ "The role field is only a descriptive form of address: coordinating sibling or sibling. It assigns no task, standing duty or permission.",
10
+ "A garden ID marks a sibling's birth and remains its delivery address across supported same-ID returns. The native session ID identifies that harness's conversation.",
11
+ "The top-level cwd is shared by the members shown in this single-project example; consult each citizen's record for its actual cwd.",
12
+ "Read both IDs, backend and cwd from Entwurf's current record facts. This bookmark does not replace the record or certify current liveness. If they disagree, the record wins; reconcile the bookmark, never rewrite the record to match it.",
13
+ "Keep entries after retirement. Membership is not permission to send, resume or retire; use explicit operator requests and the owning lifecycle tools.",
14
+ "No program loads this example as configuration. It owns no authentication, transcript, model, placement, role assignment or lifecycle automation."
15
+ ],
16
+ "members": [
17
+ {
18
+ "name": "Coordinator",
19
+ "role": "coordinating sibling",
20
+ "backend": "pi-durable",
21
+ "garden_id": "20260101T090000-a1b2c3",
22
+ "native_session_id": "1767225600000-00000000-0000-4000-8000-000000000001"
23
+ },
24
+ {
25
+ "name": "Sibling A",
26
+ "role": "sibling",
27
+ "backend": "pi",
28
+ "garden_id": "20260101T090100-b2c3d4",
29
+ "native_session_id": "019b76da-b260-7000-8000-000000000002"
30
+ },
31
+ {
32
+ "name": "Sibling B",
33
+ "role": "sibling",
34
+ "backend": "claude-code",
35
+ "garden_id": "20260101T090200-c3d4e5",
36
+ "native_session_id": "00000000-0000-4000-8000-000000000003"
37
+ }
38
+ ]
39
+ }