@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.
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +299 -0
- package/DELIVERY.md +4 -3
- package/README.md +99 -67
- package/VERIFY.md +13 -7
- package/docs/acp-backend-rail.md +1 -1
- package/docs/external-mcp-host.md +147 -9
- package/docs/setup-clean-host.md +221 -16
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +65 -20
- package/mcp/entwurf-bridge/dist/pi-extensions/entwurf-capabilities.json +1 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +17 -6
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +1 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +172 -5
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +152 -17
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/omp-fresh-preflight.js +271 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-omp.js +988 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-receive-omp.js +574 -0
- package/mcp/entwurf-bridge/dist/scripts/omp-receive-facts.js +84 -0
- package/mcp/entwurf-bridge/src/index.ts +65 -19
- package/mcp/entwurf-bridge/tsconfig.build.json +19 -3
- package/mcp/tsconfig.json +10 -0
- package/package.json +14 -4
- package/pi/entwurf-capabilities.json +1 -0
- package/pi/meta-bridge-omp/entwurf-meta-omp/package.json +7 -0
- package/pi/omp-receive/entwurf-receive-omp/package.json +7 -0
- package/pi-extensions/entwurf-control.ts +12 -9
- package/pi-extensions/lib/entwurf-self-address.ts +18 -7
- package/pi-extensions/lib/meta-sender-identity.ts +1 -1
- package/pi-extensions/lib/meta-session.ts +219 -5
- package/pi-extensions/lib/mux-fresh-call.ts +171 -17
- package/pi-extensions/lib/omp-fresh-preflight.ts +275 -0
- package/pi-extensions/meta-bridge-omp.ts +1244 -0
- package/pi-extensions/meta-bridge-receive-omp.ts +666 -0
- package/run.sh +1041 -174
- package/scripts/agy-bridge.sh +4 -2
- package/scripts/check-copilot-birth-hook.ts +700 -23
- package/scripts/check-entwurf-self-address.ts +31 -0
- package/scripts/check-fresh-cut-gate.sh +12 -4
- package/scripts/check-gate-qualification.ts +8 -2
- package/scripts/check-harness-admission-parity.ts +143 -0
- package/scripts/check-meta-doctor-oracle.sh +20 -0
- package/scripts/check-omp-birth-hook.ts +1049 -0
- package/scripts/check-omp-fresh-preflight.ts +181 -0
- package/scripts/check-omp-receive-arm.ts +516 -0
- package/scripts/check-setup-qualification.sh +126 -0
- package/scripts/copilot-bridge-doctor.sh +104 -71
- package/scripts/copilot-bridge-install.sh +180 -20
- package/scripts/copilot-bridge-oracle.sh +223 -0
- package/scripts/copilot-bridge-uninstall.sh +137 -0
- package/scripts/dev-bin.sh +50 -9
- package/scripts/fake-copilot-vendor.sh +67 -0
- package/scripts/inventory-verification-surface.ts +1 -1
- package/scripts/meta-bridge-hook-log.sh +9 -1
- package/scripts/mutants/copilot-birth.json +96 -5
- package/scripts/mutants/mux-fresh-call.json +22 -22
- package/scripts/mutants/omp-birth.json +173 -0
- package/scripts/mutants/omp-fresh.json +300 -0
- package/scripts/mutants/omp-receive.json +135 -0
- package/scripts/mutants/pi-package-ownership.json +92 -0
- package/scripts/mutants/self-address.json +34 -0
- package/scripts/mutants/setup-verdict.json +148 -0
- package/scripts/mutants/source-install.json +32 -0
- package/scripts/omp-bridge-doctor.sh +315 -0
- package/scripts/omp-bridge-install.sh +221 -0
- package/scripts/omp-bridge-oracle.sh +154 -0
- package/scripts/omp-bridge-uninstall.sh +57 -0
- package/scripts/omp-mcp-bridge.sh +320 -0
- package/scripts/omp-mcp-config.py +392 -0
- package/scripts/omp-receive-doctor.sh +246 -0
- package/scripts/omp-receive-facts.ts +106 -0
- package/scripts/omp-receive-install.sh +228 -0
- package/scripts/omp-receive-uninstall.sh +60 -0
- package/scripts/omp-tool-surface.py +349 -0
- package/scripts/pi_settings_io.py +22 -0
- package/scripts/raw-omp-measure/README.md +420 -0
- package/scripts/raw-omp-measure/probe-extension.ts +76 -0
- package/scripts/raw-omp-measure/probe-receive-surface.ts +250 -0
- package/scripts/raw-omp-measure/source-audit.md +414 -0
- package/scripts/register-pi-package.py +525 -7
- package/scripts/register-pi-provider.py +162 -12
- package/scripts/smoke-agy-install-state.sh +86 -30
- package/scripts/smoke-agy-statusline-state.sh +9 -6
- package/scripts/smoke-omp-bridge-state.sh +221 -0
- package/scripts/smoke-omp-fresh-live.ts +497 -0
- package/scripts/smoke-omp-mcp-state.sh +327 -0
- package/scripts/smoke-omp-receive-live.ts +340 -0
- package/scripts/smoke-omp-receive-state.sh +196 -0
- package/scripts/smoke-setup-verdict.sh +291 -0
- package/scripts/smoke-user-scope-citizen.sh +388 -1
- 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
|
-
|
|
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.
|
package/scripts/tsconfig.json
CHANGED
|
@@ -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
|
}
|