@junghanacs/entwurf 0.15.0 → 0.16.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 (90) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +299 -0
  3. package/DELIVERY.md +4 -3
  4. package/README.md +99 -67
  5. package/VERIFY.md +13 -7
  6. package/docs/acp-backend-rail.md +1 -1
  7. package/docs/external-mcp-host.md +147 -9
  8. package/docs/setup-clean-host.md +221 -16
  9. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +65 -20
  10. package/mcp/entwurf-bridge/dist/pi-extensions/entwurf-capabilities.json +1 -0
  11. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +17 -6
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +1 -1
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +172 -5
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +152 -17
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/omp-fresh-preflight.js +271 -0
  16. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-omp.js +988 -0
  17. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-receive-omp.js +574 -0
  18. package/mcp/entwurf-bridge/dist/scripts/omp-receive-facts.js +84 -0
  19. package/mcp/entwurf-bridge/src/index.ts +65 -19
  20. package/mcp/entwurf-bridge/tsconfig.build.json +19 -3
  21. package/mcp/tsconfig.json +10 -0
  22. package/package.json +14 -4
  23. package/pi/entwurf-capabilities.json +1 -0
  24. package/pi/meta-bridge-omp/entwurf-meta-omp/package.json +7 -0
  25. package/pi/omp-receive/entwurf-receive-omp/package.json +7 -0
  26. package/pi-extensions/entwurf-control.ts +12 -9
  27. package/pi-extensions/lib/entwurf-self-address.ts +18 -7
  28. package/pi-extensions/lib/meta-sender-identity.ts +1 -1
  29. package/pi-extensions/lib/meta-session.ts +219 -5
  30. package/pi-extensions/lib/mux-fresh-call.ts +171 -17
  31. package/pi-extensions/lib/omp-fresh-preflight.ts +275 -0
  32. package/pi-extensions/meta-bridge-omp.ts +1244 -0
  33. package/pi-extensions/meta-bridge-receive-omp.ts +666 -0
  34. package/run.sh +1041 -174
  35. package/scripts/agy-bridge.sh +4 -2
  36. package/scripts/check-copilot-birth-hook.ts +700 -23
  37. package/scripts/check-entwurf-self-address.ts +31 -0
  38. package/scripts/check-fresh-cut-gate.sh +12 -4
  39. package/scripts/check-gate-qualification.ts +8 -2
  40. package/scripts/check-harness-admission-parity.ts +143 -0
  41. package/scripts/check-meta-doctor-oracle.sh +20 -0
  42. package/scripts/check-omp-birth-hook.ts +1049 -0
  43. package/scripts/check-omp-fresh-preflight.ts +181 -0
  44. package/scripts/check-omp-receive-arm.ts +516 -0
  45. package/scripts/check-setup-qualification.sh +126 -0
  46. package/scripts/copilot-bridge-doctor.sh +104 -71
  47. package/scripts/copilot-bridge-install.sh +180 -20
  48. package/scripts/copilot-bridge-oracle.sh +223 -0
  49. package/scripts/copilot-bridge-uninstall.sh +137 -0
  50. package/scripts/dev-bin.sh +50 -9
  51. package/scripts/fake-copilot-vendor.sh +67 -0
  52. package/scripts/inventory-verification-surface.ts +1 -1
  53. package/scripts/meta-bridge-hook-log.sh +9 -1
  54. package/scripts/mutants/copilot-birth.json +96 -5
  55. package/scripts/mutants/mux-fresh-call.json +22 -22
  56. package/scripts/mutants/omp-birth.json +173 -0
  57. package/scripts/mutants/omp-fresh.json +300 -0
  58. package/scripts/mutants/omp-receive.json +135 -0
  59. package/scripts/mutants/pi-package-ownership.json +92 -0
  60. package/scripts/mutants/self-address.json +34 -0
  61. package/scripts/mutants/setup-verdict.json +148 -0
  62. package/scripts/mutants/source-install.json +32 -0
  63. package/scripts/omp-bridge-doctor.sh +315 -0
  64. package/scripts/omp-bridge-install.sh +221 -0
  65. package/scripts/omp-bridge-oracle.sh +154 -0
  66. package/scripts/omp-bridge-uninstall.sh +57 -0
  67. package/scripts/omp-mcp-bridge.sh +320 -0
  68. package/scripts/omp-mcp-config.py +392 -0
  69. package/scripts/omp-receive-doctor.sh +246 -0
  70. package/scripts/omp-receive-facts.ts +106 -0
  71. package/scripts/omp-receive-install.sh +228 -0
  72. package/scripts/omp-receive-uninstall.sh +60 -0
  73. package/scripts/omp-tool-surface.py +349 -0
  74. package/scripts/pi_settings_io.py +22 -0
  75. package/scripts/raw-omp-measure/README.md +420 -0
  76. package/scripts/raw-omp-measure/probe-extension.ts +76 -0
  77. package/scripts/raw-omp-measure/probe-receive-surface.ts +250 -0
  78. package/scripts/raw-omp-measure/source-audit.md +414 -0
  79. package/scripts/register-pi-package.py +525 -7
  80. package/scripts/register-pi-provider.py +162 -12
  81. package/scripts/smoke-agy-install-state.sh +86 -30
  82. package/scripts/smoke-agy-statusline-state.sh +9 -6
  83. package/scripts/smoke-omp-bridge-state.sh +221 -0
  84. package/scripts/smoke-omp-fresh-live.ts +497 -0
  85. package/scripts/smoke-omp-mcp-state.sh +327 -0
  86. package/scripts/smoke-omp-receive-live.ts +340 -0
  87. package/scripts/smoke-omp-receive-state.sh +196 -0
  88. package/scripts/smoke-setup-verdict.sh +291 -0
  89. package/scripts/smoke-user-scope-citizen.sh +388 -1
  90. package/scripts/tsconfig.json +2 -0
@@ -15,6 +15,7 @@
15
15
  # repo actually commits was never registered against — and `setup` duplicated and
16
16
  # restyled the tracked file for four cuts without a single gate seeing it.
17
17
  set -euo pipefail
18
+ export PYTHONDONTWRITEBYTECODE=1 # snapshot purity: no ignored scripts/__pycache__ writes under qualification
18
19
 
19
20
  HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
20
21
  REPO="$(cd "$HERE/.." && pwd)"
@@ -331,7 +332,15 @@ else
331
332
  ck_rc=$?
332
333
  set -e
333
334
  if [ "$ck_rc" != 0 ]; then
334
- bad "14 SETUP MISS: the stand-in \`run.sh install\` drive did not complete (exit $ck_rc) no byte verdict from a drive that failed for its own reasons" "$ck_out"
335
+ if printf '%s' "$ck_out" | grep -q 'repo dependency integrity check failed'; then
336
+ # Snapshot honesty: the stand-in drive needs the bundled runtime deps to
337
+ # resolve (node_modules), which a tracked-files-only checkout — e.g. the
338
+ # gate-qualification snapshot — does not have. The byte-identity property is
339
+ # untestable there, not violated: a named skip, never a FAIL and never an ok.
340
+ echo " skip 14 stand-in \`run.sh install\` drive skipped: bundled deps unresolvable in this checkout (no node_modules — snapshot shape); byte verdict untestable here"
341
+ else
342
+ bad "14 SETUP MISS: the stand-in \`run.sh install\` drive did not complete (exit $ck_rc) — no byte verdict from a drive that failed for its own reasons" "$ck_out"
343
+ fi
335
344
  else
336
345
  ok "14 the stand-in \`run.sh install\` drive completed (seed: $ck_seed)"
337
346
  if [ "$CK_BEFORE" = "$(sha256sum "$CKS" | cut -d' ' -f1)" ] && [ "$CK_MT" = "$(stat -c %Y "$CKS")" ]; then
@@ -353,6 +362,384 @@ else
353
362
  fi
354
363
  fi
355
364
 
365
+ # ── 16–25. #86 C2: user-scope OWNERSHIP — explicit takeover, same-owner inverse ──
366
+ # Axes fixed here (literal cells, no matrix framework): first/same root · legacy
367
+ # same-root adoption · legacy other-root refuse · live-other normal-install refuse
368
+ # · operator-explicit takeover · old-root inverse refusal · missing-owner normal
369
+ # refusal + doctor verdict · aligned orphan remove (run.sh path) · package/provider
370
+ # state mismatch refusal · ATOMIC two-writer refusals for install/remove/takeover
371
+ # (cells 26–29: the refusing half leaves the other half byte-identical) ·
372
+ # provider-absent orphan refusal (30) · doctor ownership-coupling mismatch (31) ·
373
+ # exact-owner classifier vs a second entwurf-shaped root: install/inverse/takeover
374
+ # refuse + doctor red (32–33, B blockers 1–2) · typed installerRoot corrupt
375
+ # fail-closed across install/remove/doctor (34, B blocker 3) ·
376
+ # look-alike + settings-relative + project-local preservation (cells 3/8/11 above
377
+ # keep owning those three). EXCLUDED by design: C3/Copilot, credentials,
378
+ # platform/Windows, provider RUNTIME verdicts (doctor-pi-provider owns those).
379
+ # Every cell builds its own fixtures so one planted production defect fails
380
+ # exactly its own cell.
381
+ US_ROOT_A="$TMP/own/checkout-a/entwurf"; mkdir -p "$US_ROOT_A"
382
+ US_ROOT_B="$TMP/own/checkout-b/entwurf"; mkdir -p "$US_ROOT_B"
383
+ c2_reset() { # $1=cell tag → sets OS (settings), OST (pkg state) fresh
384
+ OS="$TMP/own/$1-settings.json"; OST="$TMP/own/$1-pkg-state.json"
385
+ rm -f "$OS" "$OST"
386
+ }
387
+
388
+ # 16. first root: fresh install writes the owner state (packageRoot + managedSettingsPath)
389
+ c2_reset c16
390
+ python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" >/dev/null
391
+ if python3 -c "
392
+ import json,sys
393
+ st=json.load(open('$OST'))
394
+ assert st['packageRoot']=='$US_ROOT_A', st
395
+ assert st['managedSettingsPath'].endswith('c16-settings.json'), st
396
+ p=json.load(open('$OS'))['packages']; assert '$US_ROOT_A' in p, p
397
+ " 2>/dev/null; then ok "16 fresh user-scope install records the owner (packageRoot + managedSettingsPath)"; else bad "16 owner state missing/wrong after fresh install"; fi
398
+
399
+ # 17. same root re-run: no-op, mtime stable, state intact
400
+ MT16="$(stat -c %Y "$OS")"; sleep 1
401
+ OUT17="$(python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST")"
402
+ if printf '%s' "$OUT17" | grep -q 'no-op' && [ "$MT16" = "$(stat -c %Y "$OS")" ]; then ok "17 same-owner re-install is a no-op (mtime stable)"; else bad "17 same-owner re-install rewrote or refused: $OUT17"; fi
403
+
404
+ # 18. legacy no-state entry EXACTLY this root → adoption: state written, settings bytes/mtime untouched
405
+ c2_reset c18
406
+ printf '{"packages": ["%s", "../../repos/gh/andenken"]}\n' "$US_ROOT_A" > "$OS"
407
+ SHA18="$(sha256sum "$OS" | cut -d' ' -f1)"; MT18="$(stat -c %Y "$OS")"; sleep 1
408
+ OUT18="$(python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST")"
409
+ if printf '%s' "$OUT18" | grep -q 'adopted legacy' && [ -f "$OST" ] \
410
+ && [ "$SHA18" = "$(sha256sum "$OS" | cut -d' ' -f1)" ] && [ "$MT18" = "$(stat -c %Y "$OS")" ]; then
411
+ ok "18 legacy same-root entry is ADOPTED (state written; settings bytes+mtime untouched)"
412
+ else bad "18 legacy same-root adoption failed or touched settings: $OUT18"; fi
413
+
414
+ # 19. legacy no-state entries that do NOT exactly name this root → refuse, zero write
415
+ c2_reset c19
416
+ printf '{"packages": ["/old/moved/entwurf", "../../repos/gh/andenken"]}\n' > "$OS"
417
+ SHA19="$(sha256sum "$OS" | cut -d' ' -f1)"
418
+ if python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" >/dev/null 2>&1; then
419
+ bad "19 ambiguous legacy entries were silently normalized (must refuse)"
420
+ elif [ "$SHA19" = "$(sha256sum "$OS" | cut -d' ' -f1)" ] && [ ! -e "$OST" ]; then
421
+ ok "19 ambiguous/other legacy no-state entries REFUSE (zero settings write, no state minted)"
422
+ else bad "19 the legacy refusal wrote settings or state"; fi
423
+
424
+ # 20. live other owner: NORMAL install from root B refuses — zero write, takeover named
425
+ c2_reset c20
426
+ python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" >/dev/null
427
+ SHA20="$(sha256sum "$OS" | cut -d' ' -f1)"
428
+ set +e; OUT20="$(python3 "$REG" "$OS" "$US_ROOT_B" --scope user --state "$OST" 2>&1)"; RC20=$?; set -e
429
+ L20="20 a LIVE other owner makes normal install a zero-write refusal, never a silent replace [QK:SILENT-TAKEOVER]"
430
+ if [ "$RC20" -ne 0 ] && [ "$SHA20" = "$(sha256sum "$OS" | cut -d' ' -f1)" ] \
431
+ && [ "$(python3 -c "import json;print(json.load(open('$OST'))['packageRoot'])")" = "$US_ROOT_A" ]; then
432
+ ok "$L20"
433
+ else bad "$L20 — violated (rc=$RC20): $OUT20"; fi
434
+ if printf '%s' "$OUT20" | grep -q 'takeover-user-scope'; then ok "20b the refusal names the explicit takeover action"; else bad "20b refusal does not point at takeover-user-scope: $OUT20"; fi
435
+
436
+ # 21. operator-explicit takeover: old→new replace, both roots reported, state moves
437
+ OUT21="$(python3 "$REG" "$OS" "$US_ROOT_B" --scope user --state "$OST" --takeover)"
438
+ if printf '%s' "$OUT21" | grep -q "moved $US_ROOT_A -> $US_ROOT_B" \
439
+ && [ "$(python3 -c "import json;print(json.load(open('$OST'))['packageRoot'])")" = "$US_ROOT_B" ] \
440
+ && python3 -c "
441
+ import json;p=json.load(open('$OS'))['packages']
442
+ assert '$US_ROOT_B' in p and '$US_ROOT_A' not in p, p" 2>/dev/null; then
443
+ ok "21 explicit takeover replaces old→new and REPORTS both roots"
444
+ else bad "21 takeover did not replace/report correctly: $OUT21 / $(cat "$OS")"; fi
445
+
446
+ # 22. old root's inverse after takeover: LIVE foreign owner → remove refuses, zero write
447
+ SHA22="$(sha256sum "$OS" | cut -d' ' -f1)"
448
+ set +e; OUT22="$(python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" --remove 2>&1)"; RC22=$?; set -e
449
+ L22="22 an old root's inverse cannot remove the LIVE current owner's registration [QK:FOREIGN-INVERSE-REMOVE]"
450
+ if [ "$RC22" -ne 0 ] && [ "$SHA22" = "$(sha256sum "$OS" | cut -d' ' -f1)" ] && [ -f "$OST" ]; then
451
+ ok "$L22"
452
+ else bad "$L22 — violated (rc=$RC22): $OUT22"; fi
453
+
454
+ # 23. missing owner: normal install still refuses; doctor names missing-owner
455
+ c2_reset c23
456
+ MISSING_ROOT="$TMP/own/gone/entwurf"; mkdir -p "$MISSING_ROOT"
457
+ python3 "$REG" "$OS" "$MISSING_ROOT" --scope user --state "$OST" >/dev/null
458
+ rm -rf "$TMP/own/gone"
459
+ SHA23="$(sha256sum "$OS" | cut -d' ' -f1)"
460
+ set +e; OUT23="$(python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" 2>&1)"; RC23=$?; set -e
461
+ L23="23 a MISSING owner still refuses a normal install — no auto-takeover of an orphan [QK:MISSING-OWNER-AUTO-TAKEOVER]"
462
+ if [ "$RC23" -ne 0 ] && [ "$SHA23" = "$(sha256sum "$OS" | cut -d' ' -f1)" ] \
463
+ && [ "$(python3 -c "import json;print(json.load(open('$OST'))['packageRoot'])")" = "$MISSING_ROOT" ]; then
464
+ ok "$L23"
465
+ else bad "$L23 — violated (rc=$RC23): $OUT23"; fi
466
+ set +e; OUT23D="$(python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" --doctor)"; RC23D=$?; set -e
467
+ if [ "$RC23D" -ne 0 ] && printf '%s' "$OUT23D" | grep -q 'missing-owner'; then ok "23b doctor verdict names missing-owner (nonzero)"; else bad "23b doctor missing-owner verdict wrong (rc=$RC23D): $OUT23D"; fi
468
+
469
+ # 24. aligned orphan remove through run.sh: entry + package state + provider installerRoot
470
+ # all name the same MISSING root → reported cleanup; then idempotent
471
+ AG24="$TMP/own/agent24"; XD24="$TMP/own/xdg24"; mkdir -p "$AG24" "$XD24"
472
+ GONE24="$TMP/own/gone24/entwurf"; mkdir -p "$GONE24"
473
+ PKGST24="$XD24/entwurf/pi-package/install-state.json"; PPST24="$XD24/entwurf/pi-provider/install-state.json"
474
+ python3 "$REG" "$AG24/settings.json" "$GONE24" --scope user --state "$PKGST24" >/dev/null
475
+ python3 "$REPO/scripts/register-pi-provider.py" install "$AG24/settings.json" "$GONE24" --scope user --state "$PPST24" >/dev/null
476
+ rm -rf "$TMP/own/gone24"
477
+ set +e; OUT24="$(HOME="$TMP/home" XDG_DATA_HOME="$XD24" XDG_STATE_HOME="$TMP/state" XDG_CACHE_HOME="$TMP/cache" PI_CODING_AGENT_DIR="$AG24" bash "$RUN" remove-user-scope 2>&1)"; RC24=$?; set -e
478
+ if [ "$RC24" -eq 0 ] && printf '%s' "$OUT24" | grep -q 'orphan cleanup' \
479
+ && [ ! -e "$PKGST24" ] \
480
+ && python3 -c "
481
+ import json;p=json.load(open('$AG24/settings.json'))['packages']
482
+ assert not any(isinstance(x,str) and x.endswith('gone24/entwurf') for x in p), p" 2>/dev/null; then
483
+ ok "24 remove-user-scope performs the ALIGNED orphan cleanup (missing owner; reported; states cleared)"
484
+ else bad "24 aligned orphan cleanup failed (rc=$RC24): $OUT24"; fi
485
+
486
+ # 25. mismatch: package state names a missing owner but provider installerRoot names a DIFFERENT root → refuse
487
+ AG25="$TMP/own/agent25"; XD25="$TMP/own/xdg25"; mkdir -p "$AG25" "$XD25"
488
+ GONE25="$TMP/own/gone25/entwurf"; mkdir -p "$GONE25"
489
+ PKGST25="$XD25/entwurf/pi-package/install-state.json"; PPST25="$XD25/entwurf/pi-provider/install-state.json"
490
+ python3 "$REG" "$AG25/settings.json" "$GONE25" --scope user --state "$PKGST25" >/dev/null
491
+ python3 "$REPO/scripts/register-pi-provider.py" install "$AG25/settings.json" "$US_ROOT_B" --scope user --state "$PPST25" --takeover >/dev/null
492
+ rm -rf "$TMP/own/gone25"
493
+ SHA25="$(sha256sum "$AG25/settings.json" | cut -d' ' -f1)"
494
+ set +e; OUT25="$(HOME="$TMP/home" XDG_DATA_HOME="$XD25" XDG_STATE_HOME="$TMP/state" XDG_CACHE_HOME="$TMP/cache" PI_CODING_AGENT_DIR="$AG25" bash "$RUN" remove-user-scope 2>&1)"; RC25=$?; set -e
495
+ if [ "$RC25" -ne 0 ] && [ "$SHA25" = "$(sha256sum "$AG25/settings.json" | cut -d' ' -f1)" ] && [ -e "$PKGST25" ]; then
496
+ ok "25 package/provider owner MISMATCH refuses the orphan path (no cleanup without full alignment)"
497
+ else bad "25 mismatched states were cleaned up anyway (rc=$RC25): $OUT25"; fi
498
+
499
+ # ── 26–31. #86 C2 amendment: ATOMIC two-writer operations + coupling doctor ──
500
+ PROV="$REPO/scripts/register-pi-provider.py"
501
+
502
+ # 26. install atomicity through the PUBLIC drive: provider owned by another LIVE
503
+ # root → the whole `run.sh install` user-scope step refuses and the PACKAGE
504
+ # half is byte-identical (no entry, no state minted). Needs resolvable bundled
505
+ # deps like cell 14 — a dep-unresolvable checkout (qualification snapshot) gets
506
+ # the same NAMED skip; the atomic decision itself stays covered snapshot-safe
507
+ # by the SSOT preflights cells 27/29/30 drive through remove-user-scope.
508
+ AG26="$TMP/own/agent26"; XD26="$TMP/own/xdg26"; PROJ26="$TMP/own/proj26"; mkdir -p "$AG26" "$XD26" "$PROJ26"
509
+ python3 "$PROV" install "$AG26/settings.json" "$US_ROOT_A" --scope user --state "$XD26/entwurf/pi-provider/install-state.json" >/dev/null
510
+ set +e
511
+ OUT26="$(HOME="$TMP/home" XDG_DATA_HOME="$XD26" XDG_STATE_HOME="$TMP/state" XDG_CACHE_HOME="$TMP/cache" PI_CODING_AGENT_DIR="$AG26" bash "$RUN" install "$PROJ26" 2>&1)"
512
+ RC26=$?
513
+ set -e
514
+ if [ "$RC26" -eq 0 ]; then
515
+ bad "26 install completed although the provider half is owned by another root: $OUT26"
516
+ elif printf '%s' "$OUT26" | grep -q 'repo dependency integrity check failed'; then
517
+ echo " skip 26 public install drive skipped: bundled deps unresolvable in this checkout (snapshot shape); atomicity stays covered by cells 27/29/30"
518
+ elif [ -e "$XD26/entwurf/pi-package/install-state.json" ] \
519
+ || python3 -c "
520
+ import json,sys
521
+ try: p=json.load(open('$AG26/settings.json')).get('packages',[])
522
+ except FileNotFoundError: sys.exit(1)
523
+ sys.exit(0 if any(isinstance(x,str) and x=='$REPO' for x in p) else 1)"; then
524
+ # EITHER leak is a broken atomic contract: a minted package state OR a written
525
+ # packages[] entry before the provider-side refusal.
526
+ bad "26 refusal was not atomic — the package half (state and/or entry) was written before the provider refusal"
527
+ else
528
+ ok "26 install is ATOMIC: a provider-side owner refusal leaves the package half byte-identical (no entry, no state)"
529
+ fi
530
+
531
+ # 27. remove atomicity: package owned by the CALLING root (run.sh's own checkout),
532
+ # provider owned by another LIVE root → remove-user-scope refuses ON THE
533
+ # PROVIDER SIDE and the package entry + state stay intact.
534
+ AG27="$TMP/own/agent27"; XD27="$TMP/own/xdg27"; mkdir -p "$AG27" "$XD27"
535
+ python3 "$REG" "$AG27/settings.json" "$REPO" --scope user --state "$XD27/entwurf/pi-package/install-state.json" >/dev/null
536
+ python3 "$PROV" install "$AG27/settings.json" "$US_ROOT_B" --scope user --state "$XD27/entwurf/pi-provider/install-state.json" --takeover >/dev/null
537
+ set +e
538
+ OUT27="$(HOME="$TMP/home" XDG_DATA_HOME="$XD27" XDG_STATE_HOME="$TMP/state" XDG_CACHE_HOME="$TMP/cache" PI_CODING_AGENT_DIR="$AG27" bash "$RUN" remove-user-scope 2>&1)"
539
+ RC27=$?
540
+ set -e
541
+ if [ "$RC27" -ne 0 ] && printf '%s' "$OUT27" | grep -q 'register-pi-provider' \
542
+ && [ -e "$XD27/entwurf/pi-package/install-state.json" ] \
543
+ && python3 -c "
544
+ import json,sys;p=json.load(open('$AG27/settings.json'))['packages']
545
+ sys.exit(0 if any(isinstance(x,str) and x=='$REPO' for x in p) else 1)"; then
546
+ ok "27 remove is ATOMIC: a provider-side owner refusal leaves the package entry + state intact"
547
+ else bad "27 remove was not atomic or refused on the wrong side (rc=$RC27): $OUT27"; fi
548
+ # 27b (final amendment): provider SAME-owner but its managedSettingsPath names a
549
+ # DIFFERENT settings file → the provider preflight is RED (binding check runs
550
+ # before any green) and the package entry + state stay byte-identical.
551
+ printf '{"schemaVersion":1,"managedSettingsPath":"%s","ownership":"managed-current","installerRoot":"%s"}\n' \
552
+ "$TMP/own/elsewhere-settings.json" "$REPO" > "$XD27/entwurf/pi-provider/install-state.json"
553
+ SHA27B="$(sha256sum "$AG27/settings.json" | cut -d' ' -f1)"
554
+ set +e
555
+ OUT27B="$(HOME="$TMP/home" XDG_DATA_HOME="$XD27" XDG_STATE_HOME="$TMP/state" XDG_CACHE_HOME="$TMP/cache" PI_CODING_AGENT_DIR="$AG27" bash "$RUN" remove-user-scope 2>&1)"
556
+ RC27B=$?
557
+ set -e
558
+ if [ "$RC27B" -ne 0 ] && printf '%s' "$OUT27B" | grep -q 'ownership record and target disagree' \
559
+ && [ "$SHA27B" = "$(sha256sum "$AG27/settings.json" | cut -d' ' -f1)" ] \
560
+ && [ -e "$XD27/entwurf/pi-package/install-state.json" ]; then
561
+ ok "27b a provider managedSettingsPath mismatch is preflight-RED with the package half byte-identical"
562
+ else bad "27b provider binding mismatch was not fail-closed atomically (rc=$RC27B): $OUT27B"; fi
563
+
564
+ # 28. takeover over a provider USER-OVERRIDE: split verdict — package moved,
565
+ # override preserved and UNOWNED, stale provider ownership state cleared.
566
+ AG28="$TMP/own/agent28"; XD28="$TMP/own/xdg28"; mkdir -p "$AG28" "$XD28"
567
+ python3 "$REG" "$AG28/settings.json" "$US_ROOT_A" --scope user --state "$XD28/entwurf/pi-package/install-state.json" >/dev/null
568
+ python3 - "$AG28/settings.json" <<'PY'
569
+ import json,sys
570
+ p=sys.argv[1]
571
+ d=json.load(open(p))
572
+ d["entwurfProvider"]={"mcpServers":{"entwurf-bridge":{"command":"/custom/operator-bridge"}}}
573
+ open(p,"w").write(json.dumps(d,indent=2)+"\n")
574
+ PY
575
+ mkdir -p "$XD28/entwurf/pi-provider"
576
+ printf '{"schemaVersion":1,"managedSettingsPath":"%s","ownership":"absent","installerRoot":"%s"}\n' "$AG28/settings.json" "$US_ROOT_A" > "$XD28/entwurf/pi-provider/install-state.json"
577
+ set +e
578
+ OUT28="$(HOME="$TMP/home" XDG_DATA_HOME="$XD28" XDG_STATE_HOME="$TMP/state" XDG_CACHE_HOME="$TMP/cache" PI_CODING_AGENT_DIR="$AG28" bash "$RUN" takeover-user-scope 2>&1)"
579
+ RC28=$?
580
+ set -e
581
+ if [ "$RC28" -eq 0 ] && printf '%s' "$OUT28" | grep -q 'provider override preserved' \
582
+ && printf '%s' "$OUT28" | grep -q 'package owner moved' \
583
+ && ! printf '%s' "$OUT28" | grep -q 'now owns the user-scope registration' \
584
+ && [ ! -e "$XD28/entwurf/pi-provider/install-state.json" ] \
585
+ && grep -q '/custom/operator-bridge' "$AG28/settings.json"; then
586
+ ok "28 takeover over a provider override is a SPLIT verdict (package moved; override preserved, unowned; stale state cleared; no false both-owned)"
587
+ else bad "28 takeover override split verdict wrong (rc=$RC28): $OUT28"; fi
588
+
589
+ # 29. legacy provider state (no installerRoot): the inverse is FAIL-CLOSED and the
590
+ # package half stays intact (atomic) — adoption is install-only.
591
+ AG29="$TMP/own/agent29"; XD29="$TMP/own/xdg29"; mkdir -p "$AG29" "$XD29/entwurf/pi-provider"
592
+ python3 "$REG" "$AG29/settings.json" "$REPO" --scope user --state "$XD29/entwurf/pi-package/install-state.json" >/dev/null
593
+ printf '{"schemaVersion":1,"managedSettingsPath":"%s","ownership":"managed-current"}\n' "$AG29/settings.json" > "$XD29/entwurf/pi-provider/install-state.json"
594
+ set +e
595
+ OUT29="$(HOME="$TMP/home" XDG_DATA_HOME="$XD29" XDG_STATE_HOME="$TMP/state" XDG_CACHE_HOME="$TMP/cache" PI_CODING_AGENT_DIR="$AG29" bash "$RUN" remove-user-scope 2>&1)"
596
+ RC29=$?
597
+ set -e
598
+ if [ "$RC29" -ne 0 ] && printf '%s' "$OUT29" | grep -qi 'LEGACY' \
599
+ && [ -e "$XD29/entwurf/pi-package/install-state.json" ] \
600
+ && python3 -c "
601
+ import json,sys;p=json.load(open('$AG29/settings.json'))['packages']
602
+ sys.exit(0 if any(isinstance(x,str) and x=='$REPO' for x in p) else 1)"; then
603
+ ok "29 a LEGACY provider state fail-closes the inverse (adopt via install/setup first) and the package half stays intact"
604
+ else bad "29 legacy provider inverse did not fail closed atomically (rc=$RC29): $OUT29"; fi
605
+
606
+ # 30. orphan alignment REQUIRES the provider state: package owner missing + entry
607
+ # aligned but NO provider state → refuse, zero write.
608
+ AG30="$TMP/own/agent30"; XD30="$TMP/own/xdg30"; mkdir -p "$AG30" "$XD30"
609
+ GONE30="$TMP/own/gone30/entwurf"; mkdir -p "$GONE30"
610
+ python3 "$REG" "$AG30/settings.json" "$GONE30" --scope user --state "$XD30/entwurf/pi-package/install-state.json" >/dev/null
611
+ rm -rf "$TMP/own/gone30"
612
+ SHA30="$(sha256sum "$AG30/settings.json" | cut -d' ' -f1)"
613
+ set +e
614
+ OUT30="$(HOME="$TMP/home" XDG_DATA_HOME="$XD30" XDG_STATE_HOME="$TMP/state" XDG_CACHE_HOME="$TMP/cache" PI_CODING_AGENT_DIR="$AG30" bash "$RUN" remove-user-scope 2>&1)"
615
+ RC30=$?
616
+ set -e
617
+ if [ "$RC30" -ne 0 ] && [ "$SHA30" = "$(sha256sum "$AG30/settings.json" | cut -d' ' -f1)" ] \
618
+ && [ -e "$XD30/entwurf/pi-package/install-state.json" ]; then
619
+ ok "30 an ABSENT provider state is NOT orphan alignment — remove refuses with zero writes"
620
+ else bad "30 orphan cleanup ran without a provider state (rc=$RC30): $OUT30"; fi
621
+
622
+ # 31. doctor ownership coupling: package state and provider installerRoot disagree → FAIL naming the mismatch.
623
+ AG31="$TMP/own/agent31"; XD31="$TMP/own/xdg31"; mkdir -p "$AG31" "$XD31/entwurf/pi-provider"
624
+ python3 "$REG" "$AG31/settings.json" "$US_ROOT_A" --scope user --state "$XD31/entwurf/pi-package/install-state.json" >/dev/null
625
+ printf '{"schemaVersion":1,"managedSettingsPath":"%s","ownership":"absent","installerRoot":"%s"}\n' "$AG31/settings.json" "$US_ROOT_B" > "$XD31/entwurf/pi-provider/install-state.json"
626
+ set +e
627
+ OUT31="$(HOME="$TMP/home" XDG_DATA_HOME="$XD31" XDG_STATE_HOME="$TMP/state" XDG_CACHE_HOME="$TMP/cache" PI_CODING_AGENT_DIR="$AG31" bash "$RUN" doctor-pi-package 2>&1)"
628
+ RC31=$?
629
+ set -e
630
+ if [ "$RC31" -ne 0 ] && printf '%s' "$OUT31" | grep -q 'coupling mismatch'; then
631
+ ok "31 doctor-pi-package FAILs on a packageRoot↔installerRoot coupling mismatch"
632
+ else bad "31 doctor coupling mismatch verdict wrong (rc=$RC31): $OUT31"; fi
633
+ # 31b (final amendment): a package state whose managedSettingsPath names a DIFFERENT
634
+ # settings file is an ownership FAIL for the doctor too (runtime never probed).
635
+ python3 - "$XD31/entwurf/pi-package/install-state.json" <<'PY'
636
+ import json,sys
637
+ p=sys.argv[1]; st=json.load(open(p))
638
+ st["managedSettingsPath"]="/somewhere/else/settings.json"
639
+ open(p,"w").write(json.dumps(st,indent=2)+"\n")
640
+ PY
641
+ set +e
642
+ OUT31B="$(HOME="$TMP/home" XDG_DATA_HOME="$XD31" XDG_STATE_HOME="$TMP/state" XDG_CACHE_HOME="$TMP/cache" PI_CODING_AGENT_DIR="$AG31" bash "$RUN" doctor-pi-package 2>&1)"
643
+ RC31B=$?
644
+ set -e
645
+ if [ "$RC31B" -ne 0 ] && printf '%s' "$OUT31B" | grep -q 'managedSettingsPath mismatch'; then
646
+ ok "31b doctor-pi-package FAILs on a package managedSettingsPath mismatch"
647
+ else bad "31b doctor package managed-path mismatch verdict wrong (rc=$RC31B): $OUT31B"; fi
648
+
649
+ # ── 32–34. #86 C2 corrective amendment (B review blockers, 2026-08-27): the ONE
650
+ # exact-owner classifier across install/takeover/inverse/doctor, and the ONE typed
651
+ # provider installerRoot verdict. Each cell replants a transition B reproduced
652
+ # OUTSIDE the original C2 gate space.
653
+ # 32. B blocker 1: recorded owner A, packages [A, another-entwurf-shaped root B].
654
+ # A's NORMAL install must refuse with zero writes — never route through the
655
+ # broad register() collapse that silently deletes B's entry.
656
+ c2_reset c32
657
+ python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" >/dev/null
658
+ python3 - "$OS" "$US_ROOT_B" <<'PY'
659
+ import json,sys
660
+ d=json.load(open(sys.argv[1])); d["packages"].append(sys.argv[2])
661
+ open(sys.argv[1],"w").write(json.dumps(d,indent=2)+"\n")
662
+ PY
663
+ SHA32="$(sha256sum "$OS" | cut -d' ' -f1)"
664
+ set +e; OUT32="$(python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" 2>&1)"; RC32=$?; set -e
665
+ L32="32 owner A + another entwurf-shaped root: A's NORMAL install refuses zero-write, B's entry survives [QK:BROAD-INSTALL-COLLAPSE]"
666
+ if [ "$RC32" -ne 0 ] && [ "$SHA32" = "$(sha256sum "$OS" | cut -d' ' -f1)" ] \
667
+ && python3 -c "
668
+ import json;p=json.load(open('$OS'))['packages']
669
+ assert '$US_ROOT_B' in p and '$US_ROOT_A' in p, p" 2>/dev/null; then
670
+ ok "$L32"
671
+ else bad "$L32 — violated (rc=$RC32): $OUT32 / $(cat "$OS")"; fi
672
+ # 32b. the SAME ambiguous store refuses the owned inverse (one classifier, not a
673
+ # broad-install/exact-inverse double standard) …
674
+ set +e; OUT32B="$(python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" --remove 2>&1)"; RC32B=$?; set -e
675
+ if [ "$RC32B" -ne 0 ] && [ "$SHA32" = "$(sha256sum "$OS" | cut -d' ' -f1)" ] && [ -f "$OST" ]; then
676
+ ok "32b the ambiguous store refuses the owned inverse too (zero writes, state kept)"
677
+ else bad "32b owned inverse proceeded over an ambiguous store (rc=$RC32B): $OUT32B"; fi
678
+ # 32c. … and refuses the explicit takeover: takeover licenses moving THE exact
679
+ # entry, never collateral deletion of an unattributed second root.
680
+ set +e; OUT32C="$(python3 "$REG" "$OS" "$US_ROOT_B" --scope user --state "$OST" --takeover 2>&1)"; RC32C=$?; set -e
681
+ if [ "$RC32C" -ne 0 ] && [ "$SHA32" = "$(sha256sum "$OS" | cut -d' ' -f1)" ] \
682
+ && [ "$(python3 -c "import json;print(json.load(open('$OST'))['packageRoot'])")" = "$US_ROOT_A" ]; then
683
+ ok "32c even explicit takeover refuses the ambiguous store (no collateral license)"
684
+ else bad "32c takeover proceeded over an ambiguous store (rc=$RC32C): $OUT32C"; fi
685
+
686
+ # 33. B blocker 2: owner state records A, A's exact entry is GONE and only another
687
+ # entwurf-shaped root remains → the doctor must be RED naming the mismatch,
688
+ # never "owned" through the broad shape matcher (while the inverse refuses the
689
+ # very same state — contradictory verdicts on one store).
690
+ c2_reset c33
691
+ python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" >/dev/null
692
+ python3 - "$OS" "$US_ROOT_A" "$US_ROOT_B" <<'PY'
693
+ import json,sys
694
+ d=json.load(open(sys.argv[1]))
695
+ d["packages"]=[sys.argv[3] if x==sys.argv[2] else x for x in d["packages"]]
696
+ open(sys.argv[1],"w").write(json.dumps(d,indent=2)+"\n")
697
+ PY
698
+ set +e; OUT33="$(python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" --doctor)"; RC33=$?; set -e
699
+ L33="33 doctor: owner A recorded, only another entwurf-shaped root present → RED mismatch, never owned [QK:BROAD-DOCTOR-GREEN]"
700
+ if [ "$RC33" -ne 0 ] && printf '%s' "$OUT33" | grep -q 'mismatch' \
701
+ && ! printf '%s' "$OUT33" | grep -q 'doctor-pi-package: owned '; then
702
+ ok "$L33"
703
+ else bad "$L33 — violated (rc=$RC33): $OUT33"; fi
704
+
705
+ # 34. B blocker 3: a wrong-TYPE provider installerRoot (number / empty string /
706
+ # bool / object / array) is CORRUPT and fail-closed for install AND remove —
707
+ # zero settings writes, state never rebound — instead of falling between the
708
+ # isinstance(str) arm and the is-None legacy arm and proceeding unattributed.
709
+ AG34="$TMP/own/agent34"; XD34="$TMP/own/xdg34"; mkdir -p "$AG34" "$XD34/entwurf/pi-provider"
710
+ PPST34="$XD34/entwurf/pi-provider/install-state.json"
711
+ QK34='[QK:PROVIDER-ROOT-TYPE-FAIL-OPEN]'
712
+ fail34=0
713
+ for bad_root in '7' '""' 'true' '{}' '[]'; do
714
+ printf '{"entwurfProvider":{"mcpServers":{"entwurf-bridge":{"command":"entwurf-bridge"}}}}\n' > "$AG34/settings.json"
715
+ printf '{"schemaVersion":1,"managedSettingsPath":"%s","ownership":"managed-current","command":"entwurf-bridge","installerRoot":%s}\n' \
716
+ "$AG34/settings.json" "$bad_root" > "$PPST34"
717
+ SHA34="$(sha256sum "$AG34/settings.json" | cut -d' ' -f1)"
718
+ ST34="$(sha256sum "$PPST34" | cut -d' ' -f1)"
719
+ set +e
720
+ python3 "$PROV" install "$AG34/settings.json" "$US_ROOT_A" --scope user --state "$PPST34" >/dev/null 2>&1; RCI=$?
721
+ python3 "$PROV" remove "$AG34/settings.json" "$US_ROOT_A" --scope user --state "$PPST34" >/dev/null 2>&1; RCR=$?
722
+ set -e
723
+ if [ "$RCI" -eq 0 ] || [ "$RCR" -eq 0 ] \
724
+ || [ "$SHA34" != "$(sha256sum "$AG34/settings.json" | cut -d' ' -f1)" ] \
725
+ || [ "$ST34" != "$(sha256sum "$PPST34" | cut -d' ' -f1)" ]; then
726
+ bad "34 installerRoot=$bad_root not fail-closed (install rc=$RCI, remove rc=$RCR) $QK34"; fail34=1
727
+ fi
728
+ done
729
+ if [ "$fail34" -eq 0 ]; then
730
+ ok "34 wrong-type provider installerRoot (number/empty-string/bool/object/array) is CORRUPT: install+remove refuse, zero writes, state never rebound $QK34"
731
+ fi
732
+ # 34b. the doctor coupling asks the SAME typed classifier: package owner A + a
733
+ # wrong-type provider installerRoot → FAIL naming CORRUPT, never silence.
734
+ c2_reset c34b
735
+ python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" >/dev/null
736
+ printf '{"schemaVersion":1,"managedSettingsPath":"%s","ownership":"managed-current","command":"entwurf-bridge","installerRoot":7}\n' \
737
+ "$OS" > "$PPST34"
738
+ set +e; OUT34B="$(python3 "$REG" "$OS" "$US_ROOT_A" --scope user --state "$OST" --doctor --provider-state "$PPST34")"; RC34B=$?; set -e
739
+ if [ "$RC34B" -ne 0 ] && printf '%s' "$OUT34B" | grep -q 'CORRUPT'; then
740
+ ok "34b doctor coupling FAILs on a wrong-type provider installerRoot (named CORRUPT) $QK34"
741
+ else bad "34b doctor stayed green/silent over a corrupt installerRoot (rc=$RC34B): $OUT34B $QK34"; fi
742
+
356
743
  # 15. WIRING: both writers of this one file must share the serializer, not copy it.
357
744
  # A duplicated indent-detector is how the provider writer stayed open after the
358
745
  # package writer was closed; a parity check is cheaper than a third round.
@@ -31,6 +31,8 @@
31
31
  "../pi-extensions/model-lock.ts",
32
32
  "../pi-extensions/meta-bridge-hook.ts",
33
33
  "../pi-extensions/meta-bridge-hook-copilot.ts",
34
+ "../pi-extensions/meta-bridge-omp.ts",
35
+ "../pi-extensions/meta-bridge-receive-omp.ts",
34
36
  "../mcp/entwurf-bridge/src/resume-mode.ts"
35
37
  ]
36
38
  }