@junghanacs/entwurf 0.14.2 → 0.15.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 +8 -5
- package/CHANGELOG.md +79 -0
- package/DELIVERY.md +72 -59
- package/README.md +55 -4
- package/VERIFY.md +2 -2
- package/demo/README.md +1 -1
- package/docs/acp-backend-rail.md +1 -1
- package/docs/external-mcp-host.md +26 -4
- package/docs/setup-clean-host.md +3 -3
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +8 -6
- package/mcp/entwurf-bridge/dist/pi-extensions/entwurf-capabilities.json +1 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/copilot-fresh-preflight.js +253 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +10 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +102 -28
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +77 -11
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook-copilot.js +288 -0
- package/mcp/entwurf-bridge/src/index.ts +10 -6
- package/mcp/entwurf-bridge/tsconfig.build.json +2 -1
- package/package.json +22 -11
- package/pi/copilot-receive/entwurf-receive/extension.mjs +323 -0
- package/pi/entwurf-capabilities.json +1 -0
- package/pi/meta-bridge-copilot/.claude-plugin/marketplace.json +11 -0
- package/pi/meta-bridge-copilot/entwurf-meta-receive-copilot/.claude-plugin/plugin.json +5 -0
- package/pi/meta-bridge-copilot/entwurf-meta-receive-copilot/hooks/hooks.json +7 -0
- package/pi/meta-bridge-copilot/entwurf-meta-receive-copilot/scripts/copilot-hook-launch.sh +85 -0
- package/pi-extensions/entwurf-control.ts +17 -8
- package/pi-extensions/lib/copilot-fresh-preflight.ts +251 -0
- package/pi-extensions/lib/meta-sender-identity.ts +10 -2
- package/pi-extensions/lib/meta-session.ts +102 -29
- package/pi-extensions/lib/mux-fresh-call.ts +82 -11
- package/pi-extensions/meta-bridge-hook-copilot.ts +323 -0
- package/run.sh +334 -16
- package/scripts/check-copilot-birth-hook.ts +497 -0
- package/scripts/check-copilot-launch.ts +395 -0
- package/scripts/check-copilot-receive-arm.ts +734 -0
- package/scripts/check-copilot-statusline.ts +122 -0
- package/scripts/check-entwurf-capabilities.ts +25 -6
- package/scripts/check-fresh-cut-gate.sh +92 -23
- package/scripts/check-gate-qualification.ts +7 -1
- package/scripts/check-install-container.sh +2 -2
- package/scripts/check-install-surface.ts +1 -1
- package/scripts/check-meta-capability-source.ts +89 -5
- package/scripts/check-meta-doctor-oracle.sh +26 -0
- package/scripts/check-meta-manifest-schema.py +38 -0
- package/scripts/check-meta-receiver-marker.ts +25 -2
- package/scripts/check-meta-session.ts +32 -0
- package/scripts/copilot-bridge-doctor.sh +209 -0
- package/scripts/copilot-bridge-install.sh +224 -0
- package/scripts/copilot-launch.sh +236 -0
- package/scripts/copilot-mcp-bridge.sh +177 -0
- package/scripts/copilot-mcp-config.py +221 -0
- package/scripts/copilot-receive-bridge.sh +483 -0
- package/scripts/copilot-statusline-bridge.sh +149 -0
- package/scripts/copilot-statusline-config.py +201 -0
- package/scripts/copilot-statusline.sh +68 -0
- package/scripts/dev-bin.sh +4 -1
- package/scripts/meta-bridge-hook-log.sh +17 -5
- package/scripts/mutants/capability-cache.json +64 -0
- package/scripts/mutants/copilot-birth.json +155 -0
- package/scripts/mutants/copilot-launch.json +187 -0
- package/scripts/mutants/copilot-receive.json +263 -0
- package/scripts/mutants/fresh-cut.json +17 -0
- package/scripts/mutants/mux-fresh-call.json +216 -2
- package/scripts/mutants/pack-install.json +17 -0
- package/scripts/raw-async-delivery/README.md +170 -125
- package/scripts/raw-async-delivery/copilot-enqueue-addressed.sh +35 -0
- package/scripts/raw-async-delivery/copilot-extension-receive/extension.mjs +123 -0
- package/scripts/smoke-copilot-mcp-state.sh +153 -0
- package/scripts/smoke-copilot-statusline-state.sh +131 -0
- package/scripts/smoke-mux-fresh-call-live.ts +2 -0
- package/scripts/smoke-mux-lifecycle-live.ts +3 -1
- package/scripts/tsconfig.json +1 -0
package/run.sh
CHANGED
|
@@ -130,6 +130,10 @@ Usage:
|
|
|
130
130
|
./run.sh check-meta-session # deterministic gate (#30 step 2, V3-only): fs store — idempotent decideUpsert/upsertMetaSession + mailbox enqueue/read + receipt state, no API
|
|
131
131
|
./run.sh check-meta-v3-record # deterministic gate: the ONE live record schema (v3) — canonical serialize/round-trip/mint, foreign-generation rejections name fresh-cut with the actual version value, strict keyset, no API
|
|
132
132
|
./run.sh check-mailbox-receipt-state # deterministic gate (0.11 Stage 0 step 3B): mailbox receipt state schema + store (stamp→persist→read-back) in a temp mailbox, strict keyset, no API
|
|
133
|
+
./run.sh check-copilot-birth-hook # #82 gate: drives the real Copilot assembler into a temp dir, fires the baked launcher with NO ARGV (the way Copilot's `exec`-string schema forces), and requires a backend:"copilot" v3 record + attach + peer row + a SENDER marker the resolver joins back to that record, and still zero mailbox/receiver marker (who-sent needs a shared parent; a receiver needs a doorbell this backend has not got). Hermetic; no Copilot, no model turn
|
|
134
|
+
./run.sh check-copilot-receive-arm # #82 RAIL 5 gate: the REAL receiver installer + the REAL extension.mjs forked with a stubbed SDK. Arms only after birth, marker owned by the WATCHER pid, self-fetch dispatch answer, doorbell carries the garden id and NOT the body, id-drift/foreign-parent refusals. Hermetic; no Copilot, no model turn
|
|
135
|
+
./run.sh check-copilot-launch # #82 RAIL 7 gate: the MANAGED launch `entwurf copilot`, driven through its public address against a FAKE VENDOR on a sandbox PATH. Receiver precondition refusals, EXTENSIONS token + operator token preservation, injected defaults before the `--` terminator, byte-identical argv, the 11 explicit permission/surface policy overrides that suppress `--yolo`, exec (not fork) pid identity, exit passthrough, recursion refusal. Hermetic; no Copilot, no model turn
|
|
136
|
+
./run.sh check-copilot-statusline # #82 Copilot custom-footer renderer. session_id → ready/?/gid + rail `cop`; exit 0. IN pnpm check. No Copilot, no model turn
|
|
133
137
|
./run.sh check-entwurf-capabilities # deterministic gate (0.11 Stage 0 step 3C): backend capability registry (pi/entwurf-capabilities.json) — coverage==META_CITIZEN_BACKENDS + agrees with live META_BACKEND_DESCRIPTORS + strict keyset, no API
|
|
134
138
|
./run.sh check-capability-bundle-reach # deterministic gate (IN pnpm check): re-ask EVERY shipped copy of meta-session (source + bridge bundle emit) whether metaCapabilitiesFilePath() reaches the registry — the artifact-depth check the source-path gates cannot make; needs a built dist, missing dist FAILS
|
|
135
139
|
./run.sh smoke-pi-attach # deterministic gate (#50 C2 checkpoint + C3 ACP tail): a pi session attaches as a V3 meta-record citizen (backend:"pi"), the gardenId is the RECORD's not pi's session id, the control socket is keyed on it, a re-open ATTACHES to the same address (never a second mint), the BUILT DIST ENTRY driven over MCP stdio lists the citizen + delivers entwurf_v2 to that socket with an RPC ack, and the ACP identity chain lands a send AS the host record (enrichMcpServersWithEnvelope env → bridge sender = host gardenId). mkdtemp-isolated; the live store is never read
|
|
@@ -185,6 +189,8 @@ Usage:
|
|
|
185
189
|
./run.sh check-probe-ordering # §11-7 ordering-probe deterministic gate: raw-client SAMENESS pinned to backend.ts (sequence/args/timeouts/permission policy — the probe may never measure a lookalike), phase attribution incl. set-model, probe-mode fixture wire markers (delay honored, probeRunId REQUIRED, smoke-acp-mcp-live legacy compat), event-log door integrity (reserved keys refused at write; unknown marker name, broken sort axis, or a payload the classifier cannot judge on is MALFORMED, never a quiet event), and the §11-7 paired-verdict truth table (P0/I0 outside the space, phase-qualified D, B promotion ladder, C, A two-delay rule). Offline/deterministic; one product claim (no production prompt cutoff) is replant-qualified via scripts/mutants/probe-ordering.json, while the other assertions are direct [CHECK:*] contracts
|
|
186
190
|
./run.sh check-probe-cli-shim # §11-7-c B-name-snapshot PRODUCER gate: the CLI shim driven as a REAL process against fake CLIs (no API, no cost). Proves what a defect would buy — FABRICATED evidence (a malformed init is never reported as an empty name set; the boot report carries the true target path+sha256 the classifier verifies against the roster), a DESTROYED turn (byte transparency across mid-UTF8/CRLF/oversized/unterminated framing, exit-code fidelity, signal re-raise, inbound signal forwarding, stderr passthrough, stdout backpressure), and LEAKED operator state (exact-allowlist env scrub, no argv/env/prompt body in the log). Offline/deterministic; 20 direct [CHECK:*] contracts, deliberately no longer replant-qualified after #70 subtraction
|
|
187
191
|
./run.sh smoke-agy-statusline-state # agy ambient garden-id statusLine install/doctor/inverse regression. Offline/deterministic
|
|
192
|
+
./run.sh smoke-copilot-statusline-state # Copilot custom-footer install/doctor/inverse regression. Offline/deterministic
|
|
193
|
+
./run.sh smoke-copilot-mcp-state # Copilot MCP install/doctor/inverse regression. Offline/deterministic
|
|
188
194
|
./run.sh smoke-agy-hooks-state # agy PreInvocation birth/sender hook install/doctor/inverse + direct stdin→meta-record regression. Offline/deterministic
|
|
189
195
|
./run.sh smoke-user-scope-citizen # 0.12.6 install-boundary: pi packages[] registration SSOT (register-pi-package.py) — idempotent + preserves unrelated + normalizes stale + remove symmetry + fails loud. Offline/hermetic (deps: bash+python3)
|
|
190
196
|
./run.sh smoke-meta-prune # 1.0.0 meta-bridge Phase 4: listing-only store janitor regression gate — classify keep/orphan/stale/ambiguous, delete nothing. Offline/deterministic (deps: bash+node)
|
|
@@ -195,6 +201,18 @@ Usage:
|
|
|
195
201
|
./run.sh install-meta-bridge # INTERNAL part of `setup` (native-harness plugin) + doctor recovery path — prefer `setup`; stateful GLOBAL install (plugin + USER MCP + settings keyset, honest uninstall state)
|
|
196
202
|
./run.sh uninstall-meta-bridge # 1.0.0 meta-bridge Phase 2: stateful GLOBAL uninstall (restore only keys/items captured in install-state)
|
|
197
203
|
./run.sh doctor-meta-bridge # THE RELEASE ORACLE (#51, Linux-certified repair axis). exit 0 = every required layer was MEASURED on this Linux host: toolchain + state + plugin/MCP + resolved-artifact launch-form classification (all 3 owner hooks + doorbell static contract) + synthetic owner join + store scan + hook errors + SessionStart evidence + REQUIRED live MCP↔marker join + writer-version parity. Missing live evidence is NOT CERTIFIED (open a Claude session and re-run), never a pass; Darwin is not yet verified/certified and stays nonzero for this cut (future validation may reopen it). Detection power is held by check-meta-doctor-oracle
|
|
204
|
+
./run.sh copilot [args...] # #82 RAIL 7: the MANAGED Copilot launch. exec()s the vendor CLI in THIS terminal (cwd/pid/exit preserved) with COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS set for that one invocation — entwurf owns no part of your shell and writes nothing to it, but it owns the process it is about to become. Without that flag Copilot skips the extension scan SILENTLY. Refuses to launch unless the receiver unit is actually installed. Injects `--model auto` when no --model was given and `--yolo` when no explicit permission/surface policy flag was given, both BEFORE any `--`; every argument you pass is forwarded byte-identical. RUNNING THIS IS YOUR CONSENT to that profile — use plain `copilot` for stock vendor behaviour. Not tmux, not fresh-call, mints no citizen (birth is still the first prompt)
|
|
205
|
+
./run.sh install-copilot-bridge # #82: GLOBAL install of the Copilot BIRTH plugin (own marketplace root; node+entry baked into the no-argv exec string). MCP wiring and the RECEIVER extension are separate install surfaces (install-copilot-mcp, install-copilot-receive). Also retires the stale Claude unit (--keep-stale-claude-unit opts out)
|
|
206
|
+
./run.sh doctor-copilot-bridge # #82: fail-loud surface for that unit. Red = a hook that RAN and failed, or a broken/unbaked artifact. "Installed with zero records" is NOT red and is reported as NOT-YET: a Copilot session is born on its FIRST PROMPT, not when the window opens (measured)
|
|
207
|
+
./run.sh install-copilot-statusline # own Copilot statusLine + footer.showCustom with an install-state preimage
|
|
208
|
+
./run.sh uninstall-copilot-statusline # honest inverse of install-copilot-statusline
|
|
209
|
+
./run.sh doctor-copilot-statusline # static ownership/config/bin doctor; never claims a render receipt
|
|
210
|
+
./run.sh install-copilot-mcp # #82 RAIL 5: register ONE entwurf-bridge server in ~/.copilot/mcp-config.json (adopt / create / REFUSE symlink), type:local, install-state under $XDG_DATA_HOME/entwurf/copilot-mcp/
|
|
211
|
+
./run.sh uninstall-copilot-mcp # honest inverse of install-copilot-mcp from install-state
|
|
212
|
+
./run.sh doctor-copilot-mcp # static ownership/config/boot doctor; RED only when install-state exists
|
|
213
|
+
./run.sh install-copilot-receive # #82 RAIL 5: install the RECEIVER extension (user scope ~/.copilot/extensions/entwurf-receive). Owns the artifact and CHECKS the launch flag; it never sets one (a launch does — see `./run.sh copilot`). Arms per session after birth
|
|
214
|
+
./run.sh uninstall-copilot-receive # honest inverse from install-state; never removes a unit it did not install
|
|
215
|
+
./run.sh doctor-copilot-receive # artifact + digest, COPILOT_CLI_ENABLED_FEATURE_FLAGS on the LIVE copilot processes (the silent failure), live receiver markers via the production reader, receiver log. RED only when install-state exists
|
|
198
216
|
./run.sh install-agy-bridge # 봉인 7: agy MCP install adapter — register ONE entwurf-bridge server in the agy mcp_config (adopt file / create / REFUSE symlink), stable bin command, install-state under $XDG_DATA_HOME/entwurf/agy-bridge/
|
|
199
217
|
./run.sh uninstall-agy-bridge # 봉인 7: honest inverse of install-agy-bridge from install-state (restore preimage / remove key; refuse if config became a symlink)
|
|
200
218
|
./run.sh probe-bridge-command <cmd> [args...] # #81: BOOT the given bridge invocation and require the entwurf MCP tool surface back. `--invocation-json '{"command":"…","args":[],"env":{}}'` preserves a harness config exactly. It waits for a valid initialize response, then sends initialized + tools/list only (no tools/call, lock, record, or delivery). exit 0 = it serves the bridge; 1 = it does not. The pi/agy doctors use this leaf.
|
|
@@ -213,6 +231,7 @@ Usage:
|
|
|
213
231
|
./run.sh check-dep-versions # local deterministic check that the pi pin agrees across package.json (devDeps + peer range), run.sh (peer-install pins), and the baseline docs (AGENTS/README/ROADMAP/setup-clean-host/demo)
|
|
214
232
|
./run.sh check-node-floor-coherence # binds the Node floor (24+, single axis) across engines.node, run.sh setup preflight, meta-bridge install/doctor judgment logic, clean-host docs, the bridge launcher header, and the CI runner node-version — engines.node is the SSOT, everything else is derived; sweeps tracked contract text for an unregistered declaration
|
|
215
233
|
./run.sh check-pack # publish gate (dry-run): npm pack --dry-run + tarball invariants (runtime-critical present, dev residue absent)
|
|
234
|
+
./run.sh check-pack-pin-matcher # pure self-test of check-pack-install's pin-leak matcher against synthetic .pnpm lookalikes (version boundary: @0.84.30 must leak, @0.84.3 bare/peer-hash must pass); snapshot-safe qualification oracle, also run first inside check-pack-install
|
|
216
235
|
./run.sh check-fresh-cut-gate # SOURCE cell of the generation-boundary proof (IN pnpm run check:full): drives real install/setup/fresh-cut in a sandbox; certification refusal is pre-write, quiescence is fail-closed, archives preserve bytes, and the #54 exit matrix distinguishes complete / no-move / usage / incomplete transition / complete-with-cleanup-residue. No model/network/cost
|
|
217
236
|
./run.sh check-pack-install # heavy publish gate (prepublishOnly): actual npm pack + tar -tf + fresh-temp install smoke with the pinned pi peers (0.82.x) + the npm-installed bridge BOOTS (tools/list) and DELIVERS (tools/call entwurf_v2 → .msg lands) + the INSTALLED generation lifecycle on a seeded previous-generation host (REFUSE before activation writes / zero Claude invocations → installed fresh-cut archives + opens empty → install-meta-bridge PASSES)
|
|
218
237
|
./run.sh check-install-container # 0.12.8 (#51 C): Linux artifact-CONSUMER gate — one candidate .tgz handed read-only to a checkout-invisible node:<engines-major>-bookworm cell. Default packs once to temp; ENTWURF_CANDIDATE_TGZ=/absolute/preserved.tgz consumes those exact bytes with no re-pack and prints canonical path+sha256 for release. Non-root global PATH install, frozen package, MCP tools/list, fake-Claude install-meta-bridge, path+sha256 fence, strict doctor, and the GENERATION host-state matrix (clean / v3-only store bytes unchanged / previous-generation REFUSE→fresh-cut→retry PASS) seeded inline. Docker missing = honest SKIP; ENTWURF_REQUIRE_DOCKER=1 makes that RED (required CI)
|
|
@@ -738,6 +757,41 @@ check_meta_receiver_marker() {
|
|
|
738
757
|
run_ts scripts/check-meta-receiver-marker.ts
|
|
739
758
|
}
|
|
740
759
|
|
|
760
|
+
check_copilot_birth_hook() {
|
|
761
|
+
# #82 gate: the Copilot BIRTH path, proven without Copilot. Drives the REAL
|
|
762
|
+
# assembler (--assemble-only, into a temp dir), then fires the baked launcher the
|
|
763
|
+
# way Copilot fires it — NO ARGV, envelope on stdin — and requires a v3 record with
|
|
764
|
+
# backend "copilot", an attach on the second event of the same prompt, no
|
|
765
|
+
# mailbox/marker of any kind, and a peer row with liveness `unsupported`. Refusals
|
|
766
|
+
# (disagreeing ids, missing cwd, no id, malformed) must refuse rather than guess.
|
|
767
|
+
# It proves the MECHANISM, never the admission: §6 acceptance is a record minted by
|
|
768
|
+
# a real Copilot session, which costs a model turn.
|
|
769
|
+
run_ts scripts/check-copilot-birth-hook.ts
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
check_copilot_statusline() {
|
|
773
|
+
# #82 Copilot custom-footer renderer. Drives scripts/copilot-statusline.sh with
|
|
774
|
+
# session_id on stdin in an isolated store. ready / ? / exact gid; exit 0.
|
|
775
|
+
run_ts scripts/check-copilot-statusline.ts
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
check_copilot_launch() {
|
|
779
|
+
# #82 RAIL 7. The subject is a process REPLACEMENT, so the oracle is a fake vendor
|
|
780
|
+
# executable on a sandboxed PATH that reports the argv/env/pid/cwd it was handed —
|
|
781
|
+
# never a reading of the launcher's source. HOME/XDG/PATH are all redirected, so the
|
|
782
|
+
# install-state, the extensions root and the resolved binary are the fixture's.
|
|
783
|
+
run_ts scripts/check-copilot-launch.ts
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
check_copilot_receive_arm() {
|
|
787
|
+
# #82 RAIL 5 gate: drives the REAL receiver installer into a temp extensions dir, then
|
|
788
|
+
# forks the REAL extension.mjs with the SDK specifier resolved by a loader hook (the
|
|
789
|
+
# vendor's own mechanism). Binds arm-after-birth, watcher-owned marker, the self-fetch
|
|
790
|
+
# dispatch answer, a doorbell that carries the id and not the body, and every refusal.
|
|
791
|
+
# Needs the compiled bridge closure; hermetic otherwise (no Copilot, no model turn).
|
|
792
|
+
run_ts scripts/check-copilot-receive-arm.ts
|
|
793
|
+
}
|
|
794
|
+
|
|
741
795
|
check_hook_launch_topology() {
|
|
742
796
|
# #51 gate 1, deliberately built only AFTER the B/B2 verdict. Binds the SHIPPED
|
|
743
797
|
# hooks.json to real child topology: every leaf is exec form through the shipped
|
|
@@ -1099,7 +1153,10 @@ check_mux_fresh_call() {
|
|
|
1099
1153
|
# could not see: real bridge boot → tools/list schema/description, Rust-regex-family pattern
|
|
1100
1154
|
# validity on every emitted pattern (the #62 escape), and the schema riding the actual
|
|
1101
1155
|
# anthropic-messages request body. No fake tmux: the real-window axis is smoke-mux-fresh-call-live.
|
|
1102
|
-
|
|
1156
|
+
# copilot-fresh-preflight rides here rather than in its own gate: it exists only as
|
|
1157
|
+
# freshCall's pre-mutation branch (#82 RAIL 9), and splitting it would let the two halves
|
|
1158
|
+
# of one refusal be certified in different runs.
|
|
1159
|
+
run_vitest test/mux-fresh-call.test.ts test/copilot-fresh-preflight.test.ts test/fresh-call-surfaces.contract.test.ts test/fresh-call-provider.contract.test.ts
|
|
1103
1160
|
}
|
|
1104
1161
|
|
|
1105
1162
|
smoke_mux_fresh_call_live() {
|
|
@@ -1629,13 +1686,13 @@ assert.equal(peerTui, piAi,
|
|
|
1629
1686
|
// floor tracks the devDep pin so a consumer can't install against a pi lacking
|
|
1630
1687
|
// the public trust exports the bridge imports at the pinned minor, AND an upper
|
|
1631
1688
|
// bound at the next minor stops a fresh install from silently pulling a future
|
|
1632
|
-
// pi (past the declared ceiling — 0.85+ at the current 0.84.
|
|
1689
|
+
// pi (past the declared ceiling — 0.85+ at the current 0.84.3 pin) whose
|
|
1633
1690
|
// internal export surface has drifted from the one we typecheck against.
|
|
1634
1691
|
// pi moves its public surface every minor (the 0.79→0.80 getModels→provider-
|
|
1635
1692
|
// factory churn is exactly this), so an open `>=` floor is exactly how the next
|
|
1636
1693
|
// installer re-acquires the drift. The floor is also the HARD MINIMUM a consumer
|
|
1637
|
-
// install resolves: at `>=0.84.
|
|
1638
|
-
// Expected shape: `>=<devDep> <0.<minor+1>` (e.g. `>=0.84.
|
|
1694
|
+
// install resolves: at `>=0.84.3` an existing 0.83.x host is upgraded, not kept.
|
|
1695
|
+
// Expected shape: `>=<devDep> <0.<minor+1>` (e.g. `>=0.84.3 <0.85`).
|
|
1639
1696
|
const [piMaj, piMin] = piAi.split('.').map(Number);
|
|
1640
1697
|
assert.equal(piMaj, 0,
|
|
1641
1698
|
`pi pin major must stay 0 for the next-minor ceiling rule (got ${piAi}); revisit check-dep-versions when pi reaches 1.x`);
|
|
@@ -2757,6 +2814,9 @@ check_pack() {
|
|
|
2757
2814
|
# strip-types under node_modules). meta-session.js is shared with the store-doctor
|
|
2758
2815
|
# above; listed here too so the hook axis fails loud if the emit graph drops it.
|
|
2759
2816
|
"mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook.js"
|
|
2817
|
+
# #82 — the Copilot birth entry's compiled closure, for the same node_modules
|
|
2818
|
+
# strip-types refusal that forces the Claude one.
|
|
2819
|
+
"mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook-copilot.js"
|
|
2760
2820
|
"mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js"
|
|
2761
2821
|
"scripts/postinstall-chmod.cjs"
|
|
2762
2822
|
"pi/entwurf-capabilities.json"
|
|
@@ -2769,6 +2829,23 @@ check_pack() {
|
|
|
2769
2829
|
# It rides a per-FILE entry in the files array (not a whole directory), so one
|
|
2770
2830
|
# deleted line drops it from the tarball while every other gate stays green.
|
|
2771
2831
|
"pi/meta-bridge/entwurf-meta-receive/scripts/hook-launch.sh"
|
|
2832
|
+
# #82 — the Copilot BIRTH unit. It is a SECOND marketplace root, not a second
|
|
2833
|
+
# plugin inside the Claude one: the Claude installer assembles one root and copies
|
|
2834
|
+
# one plugin out of it, so a shared marketplace.json would publish a `source` the
|
|
2835
|
+
# assembly does not contain. Same per-FILE listing discipline as the Claude unit.
|
|
2836
|
+
"pi/meta-bridge-copilot/.claude-plugin/marketplace.json"
|
|
2837
|
+
"pi/meta-bridge-copilot/entwurf-meta-receive-copilot/.claude-plugin/plugin.json"
|
|
2838
|
+
"pi/meta-bridge-copilot/entwurf-meta-receive-copilot/hooks/hooks.json"
|
|
2839
|
+
"pi/meta-bridge-copilot/entwurf-meta-receive-copilot/scripts/copilot-hook-launch.sh"
|
|
2840
|
+
"pi-extensions/meta-bridge-hook-copilot.ts"
|
|
2841
|
+
"scripts/copilot-bridge-install.sh"
|
|
2842
|
+
"scripts/copilot-bridge-doctor.sh"
|
|
2843
|
+
# #82 RAIL 5 — the Copilot RECEIVER. A vendor EXTENSION (forked child, stdio
|
|
2844
|
+
# JSON-RPC), not a plugin, so it ships as its own unit and installs into the user
|
|
2845
|
+
# extensions dir. `extension.mjs` is the vendor's required entry NAME: a rename in
|
|
2846
|
+
# the tarball is not a degraded path, it is a unit Copilot never discovers.
|
|
2847
|
+
"pi/copilot-receive/entwurf-receive/extension.mjs"
|
|
2848
|
+
"scripts/copilot-receive-bridge.sh"
|
|
2772
2849
|
"pi-extensions/meta-bridge-hook.ts"
|
|
2773
2850
|
"pi-extensions/lib/meta-session.ts"
|
|
2774
2851
|
"pi-extensions/lib/session-id.js"
|
|
@@ -2836,7 +2913,41 @@ check_pack() {
|
|
|
2836
2913
|
return 1
|
|
2837
2914
|
}
|
|
2838
2915
|
|
|
2916
|
+
# The pin-leak filter for the install tree's .pnpm listing, shared by the real scan and its
|
|
2917
|
+
# self-test below. The version BOUNDARY is load-bearing: a pnpm .pnpm entry is
|
|
2918
|
+
# `<name>@<version>` followed by either `_<peer-hash>` or end-of-name (measured pnpm 11.20.0
|
|
2919
|
+
# on this tree), so an unbounded substring match would bless a lookalike such as `@0.84.30`
|
|
2920
|
+
# while announcing the pinned floor — a false-green oracle (found by independent review,
|
|
2921
|
+
# 2026-08-25).
|
|
2922
|
+
pack_install_leaked_pi() {
|
|
2923
|
+
grep '^@earendil-works+pi-' | grep -Ev '@0\.84\.3(_|$)' || true
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2926
|
+
# Matcher self-test on SYNTHETIC lookalikes: a healthy install tree cannot exercise the
|
|
2927
|
+
# false-green shape (it contains no 0.84.30), so the oracle is proven against a fixture
|
|
2928
|
+
# listing. Expected: the two lookalikes leak, the pinned version passes bare and with a
|
|
2929
|
+
# peer-hash suffix. Exposed as its own snapshot-safe subcommand because the heavy
|
|
2930
|
+
# check-pack-install cannot run inside the qualification snapshot (no install environment),
|
|
2931
|
+
# and a kill-proof needs a control-green gate there; check-pack-install still runs this
|
|
2932
|
+
# first so the heavy gate cannot proceed on a broken oracle.
|
|
2933
|
+
check_pack_pin_matcher() {
|
|
2934
|
+
local matcher_probe
|
|
2935
|
+
matcher_probe=$(printf '%s\n' \
|
|
2936
|
+
'@earendil-works+pi-ai@0.84.3' \
|
|
2937
|
+
'@earendil-works+pi-ai@0.84.3_@modelcontextprotocol+sdk@1.29.0_zod@4.3.6' \
|
|
2938
|
+
'@earendil-works+pi-ai@0.84.30' \
|
|
2939
|
+
'@earendil-works+pi-agent-core@0.84.2' | pack_install_leaked_pi)
|
|
2940
|
+
if [ "$matcher_probe" != '@earendil-works+pi-ai@0.84.30
|
|
2941
|
+
@earendil-works+pi-agent-core@0.84.2' ]; then
|
|
2942
|
+
fail "[QK:PACK-INSTALL-PIN-MATCHER-BOUNDED] the pin-leak matcher must flag the 0.84.30/0.84.2 lookalikes and pass 0.84.3 bare or with a peer-hash — got: ${matcher_probe:-<nothing leaked>}"
|
|
2943
|
+
return 1
|
|
2944
|
+
fi
|
|
2945
|
+
echo "[check-pack-pin-matcher] ok — the pin-leak matcher is version-bounded (lookalikes leak, pinned version passes bare and with a peer-hash)"
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2839
2948
|
_check_pack_install_impl() {
|
|
2949
|
+
check_pack_pin_matcher || return 1
|
|
2950
|
+
|
|
2840
2951
|
# Heavy publish gate. Runs the remaining three checks in #13's
|
|
2841
2952
|
# publish checklist that check_pack (dry-run only) does not cover:
|
|
2842
2953
|
#
|
|
@@ -2954,6 +3065,9 @@ _check_pack_install_impl() {
|
|
|
2954
3065
|
# 0.12.5 — node_modules-safe plugin hook + lib (see check-pack). The installed
|
|
2955
3066
|
# hook regression below runs exactly this compiled JS from under node_modules.
|
|
2956
3067
|
"mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook.js"
|
|
3068
|
+
# #82 — the Copilot birth entry's compiled closure, for the same node_modules
|
|
3069
|
+
# strip-types refusal that forces the Claude one.
|
|
3070
|
+
"mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook-copilot.js"
|
|
2957
3071
|
"mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js"
|
|
2958
3072
|
"scripts/postinstall-chmod.cjs"
|
|
2959
3073
|
"pi/entwurf-capabilities.json"
|
|
@@ -2965,6 +3079,23 @@ _check_pack_install_impl() {
|
|
|
2965
3079
|
# both callers source. The install smoke below asserts the ASSEMBLED launcher is
|
|
2966
3080
|
# executable; this asserts the artifact it is assembled FROM actually shipped.
|
|
2967
3081
|
"pi/meta-bridge/entwurf-meta-receive/scripts/hook-launch.sh"
|
|
3082
|
+
# #82 — the Copilot BIRTH unit. It is a SECOND marketplace root, not a second
|
|
3083
|
+
# plugin inside the Claude one: the Claude installer assembles one root and copies
|
|
3084
|
+
# one plugin out of it, so a shared marketplace.json would publish a `source` the
|
|
3085
|
+
# assembly does not contain. Same per-FILE listing discipline as the Claude unit.
|
|
3086
|
+
"pi/meta-bridge-copilot/.claude-plugin/marketplace.json"
|
|
3087
|
+
"pi/meta-bridge-copilot/entwurf-meta-receive-copilot/.claude-plugin/plugin.json"
|
|
3088
|
+
"pi/meta-bridge-copilot/entwurf-meta-receive-copilot/hooks/hooks.json"
|
|
3089
|
+
"pi/meta-bridge-copilot/entwurf-meta-receive-copilot/scripts/copilot-hook-launch.sh"
|
|
3090
|
+
"pi-extensions/meta-bridge-hook-copilot.ts"
|
|
3091
|
+
"scripts/copilot-bridge-install.sh"
|
|
3092
|
+
"scripts/copilot-bridge-doctor.sh"
|
|
3093
|
+
# #82 RAIL 5 — the Copilot RECEIVER. A vendor EXTENSION (forked child, stdio
|
|
3094
|
+
# JSON-RPC), not a plugin, so it ships as its own unit and installs into the user
|
|
3095
|
+
# extensions dir. `extension.mjs` is the vendor's required entry NAME: a rename in
|
|
3096
|
+
# the tarball is not a degraded path, it is a unit Copilot never discovers.
|
|
3097
|
+
"pi/copilot-receive/entwurf-receive/extension.mjs"
|
|
3098
|
+
"scripts/copilot-receive-bridge.sh"
|
|
2968
3099
|
"pi-extensions/meta-bridge-hook.ts"
|
|
2969
3100
|
"pi-extensions/lib/meta-session.ts"
|
|
2970
3101
|
"pi-extensions/lib/session-id.js"
|
|
@@ -3027,7 +3158,7 @@ _check_pack_install_impl() {
|
|
|
3027
3158
|
printf '%s\n' '{ "name": "entwurf-install-smoke", "version": "0.0.0", "private": true }' > "$tmp/package.json"
|
|
3028
3159
|
|
|
3029
3160
|
# pi-agent-core is pinned even though we never import it: pi-coding-agent depends
|
|
3030
|
-
# on it by CARET (`^0.84.
|
|
3161
|
+
# on it by CARET (`^0.84.3`), so with no lockfile in this fresh temp project it
|
|
3031
3162
|
# floats to whatever pi published last — and that newer core then drags a NESTED
|
|
3032
3163
|
# pi-ai of its own. Measured 2026-07-21: pinning only the three we import left
|
|
3033
3164
|
# pi-agent-core@0.80.10 + pi-ai@0.80.10 in the tree while the gate still announced
|
|
@@ -3046,12 +3177,12 @@ _check_pack_install_impl() {
|
|
|
3046
3177
|
local install_log
|
|
3047
3178
|
install_log=$(cd "$tmp" && pnpm add \
|
|
3048
3179
|
"$tgz_path" \
|
|
3049
|
-
"@earendil-works/pi-ai@0.84.
|
|
3050
|
-
"@earendil-works/pi-coding-agent@0.84.
|
|
3051
|
-
"@earendil-works/pi-tui@0.84.
|
|
3052
|
-
"@earendil-works/pi-agent-core@0.84.
|
|
3053
|
-
"@earendil-works/pi-client@0.84.
|
|
3054
|
-
"@earendil-works/pi-protocol@0.84.
|
|
3180
|
+
"@earendil-works/pi-ai@0.84.3" \
|
|
3181
|
+
"@earendil-works/pi-coding-agent@0.84.3" \
|
|
3182
|
+
"@earendil-works/pi-tui@0.84.3" \
|
|
3183
|
+
"@earendil-works/pi-agent-core@0.84.3" \
|
|
3184
|
+
"@earendil-works/pi-client@0.84.3" \
|
|
3185
|
+
"@earendil-works/pi-protocol@0.84.3" \
|
|
3055
3186
|
"typebox@latest" \
|
|
3056
3187
|
--ignore-workspace --ignore-scripts 2>&1) || {
|
|
3057
3188
|
fail "[check-pack-install] pnpm add failed:"
|
|
@@ -3061,17 +3192,17 @@ _check_pack_install_impl() {
|
|
|
3061
3192
|
|
|
3062
3193
|
# A pin is a wish until the resolved tree is read back. Assert it: EVERY
|
|
3063
3194
|
# @earendil-works pi package present — direct or transitive, top level or nested —
|
|
3064
|
-
# must be the pinned 0.84.
|
|
3195
|
+
# must be the pinned 0.84.3. Anything else means an unpinned caret floated and the
|
|
3065
3196
|
# rest of this gate would be exercising a runtime nobody verified, while still
|
|
3066
|
-
# printing "pinned pi 0.84.
|
|
3197
|
+
# printing "pinned pi 0.84.3". Fail loud instead of proving the wrong floor.
|
|
3067
3198
|
local leaked_pi
|
|
3068
|
-
leaked_pi=$(ls "$tmp/node_modules/.pnpm" 2>/dev/null |
|
|
3199
|
+
leaked_pi=$(ls "$tmp/node_modules/.pnpm" 2>/dev/null | pack_install_leaked_pi)
|
|
3069
3200
|
if [ -n "$leaked_pi" ]; then
|
|
3070
|
-
fail "[check-pack-install] UNVERIFIED pi runtime resolved into the install tree (expected only 0.84.
|
|
3201
|
+
fail "[check-pack-install] UNVERIFIED pi runtime resolved into the install tree (expected only 0.84.3):"
|
|
3071
3202
|
printf '%s\n' "$leaked_pi" | sed 's/^/ /' >&2
|
|
3072
3203
|
return 1
|
|
3073
3204
|
fi
|
|
3074
|
-
echo "[check-pack-install] pi runtime tree pin verified: every @earendil-works pi package is 0.84.
|
|
3205
|
+
echo "[check-pack-install] pi runtime tree pin verified: every @earendil-works pi package is 0.84.3"
|
|
3075
3206
|
|
|
3076
3207
|
# Resolve the installed package.json and confirm pi.extensions
|
|
3077
3208
|
# arrived intact. If pi.extensions is empty or missing, the
|
|
@@ -3224,6 +3355,11 @@ _check_pack_install_impl() {
|
|
|
3224
3355
|
ls -l "$npmroot/node_modules/.bin" 2>/dev/null | sed 's/^/ /' >&2 || true
|
|
3225
3356
|
return 1
|
|
3226
3357
|
fi
|
|
3358
|
+
if [ ! -x "$npmroot/node_modules/.bin/entwurf-copilot-statusline" ]; then
|
|
3359
|
+
fail "[check-pack-install] npm-managed neutral install missing package bin entwurf-copilot-statusline"
|
|
3360
|
+
ls -l "$npmroot/node_modules/.bin" 2>/dev/null | sed 's/^/ /' >&2 || true
|
|
3361
|
+
return 1
|
|
3362
|
+
fi
|
|
3227
3363
|
wire_log=$(HOME="$npmhome" XDG_DATA_HOME="$npmhome/.local/share" XDG_STATE_HOME="$npmhome/.local/state" XDG_CACHE_HOME="$npmhome/.cache" "$npm_pkg/run.sh" install "$npmproj" 2>&1) || {
|
|
3228
3364
|
fail "[check-pack-install] npm-managed run.sh install failed (preflight rejected hoisted deps?):"
|
|
3229
3365
|
echo "$wire_log" | tail -15 | sed 's/^/ /' >&2
|
|
@@ -3394,6 +3530,48 @@ SH
|
|
|
3394
3530
|
fi
|
|
3395
3531
|
rm -rf "$nm_probe"
|
|
3396
3532
|
echo "[check-pack-install] installed hook is node_modules-safe compiled JS (hooks.json points at .js; runs under node_modules with plain node; raw .ts refused there by the strip-types fence)"
|
|
3533
|
+
|
|
3534
|
+
# --- #82: the Copilot birth unit's INSTALLED-PACKAGE branch ------------------
|
|
3535
|
+
# check-copilot-birth-hook drives the installer from a DEV CLONE, so it only ever
|
|
3536
|
+
# exercises the `.ts` branch. The installed-package branch — compiled
|
|
3537
|
+
# meta-bridge-hook-copilot.js, its rewritten `./lib/meta-session.js` import, the
|
|
3538
|
+
# registry copied to the plugin root — was covered by pack LISTS and by nothing that
|
|
3539
|
+
# RUNS it, which is the shape Hard Rule 11 exists to refuse (cross-review, terra +
|
|
3540
|
+
# glm independently, 2026-08-21).
|
|
3541
|
+
#
|
|
3542
|
+
# `--assemble-only` stops before the Copilot CLI, so this needs no Copilot and no fake
|
|
3543
|
+
# of one. A fake Copilot CLI would only prove our script calls our fake the way we
|
|
3544
|
+
# wrote it — the vendor contract is unmeasured, and the first real execution is the
|
|
3545
|
+
# §6 admission itself. This asserts the CITIZEN, not merely that a node process ran.
|
|
3546
|
+
local cop_asm="$npm_tmp/copilot-asm" cop_store cop_log
|
|
3547
|
+
cop_store="$(mktemp -d)"
|
|
3548
|
+
if ! cop_log=$(HOME="$mb_home" XDG_DATA_HOME="$mb_home/.local/share" ENTWURF_COPILOT_ASM="$cop_asm" PATH="$npmroot/node_modules/.bin:$PATH" "$npm_pkg/run.sh" install-copilot-bridge --assemble-only 2>&1); then
|
|
3549
|
+
fail "[check-pack-install] installed install-copilot-bridge --assemble-only failed:"
|
|
3550
|
+
echo "$cop_log" | tail -20 | sed 's/^/ /' >&2
|
|
3551
|
+
return 1
|
|
3552
|
+
fi
|
|
3553
|
+
local cop_unit="$cop_asm/entwurf-meta-receive-copilot"
|
|
3554
|
+
# Branch SELECTION, pinned: an installed package must assemble the compiled entry and
|
|
3555
|
+
# no raw .ts. Without this the fire below could pass on a layout that silently chose
|
|
3556
|
+
# the dev-clone branch.
|
|
3557
|
+
if [ ! -f "$cop_unit/meta-bridge-hook-copilot.js" ] || [ -f "$cop_unit/meta-bridge-hook-copilot.ts" ]; then
|
|
3558
|
+
fail "[check-pack-install] installed install-copilot-bridge did not select the compiled branch (want meta-bridge-hook-copilot.js, no raw .ts) in $cop_unit"
|
|
3559
|
+
return 1
|
|
3560
|
+
fi
|
|
3561
|
+
local cop_out
|
|
3562
|
+
# Fired the way Copilot fires it: NO ARGV, envelope on stdin.
|
|
3563
|
+
if ! cop_out="$(printf '%s' '{"sessionId":"pack-copilot-probe","cwd":"/tmp","source":"new"}' | env PI_CODING_AGENT_DIR="$cop_store" "$cop_unit/scripts/copilot-hook-launch.sh" 2>&1)"; then
|
|
3564
|
+
fail "[check-pack-install] the installed Copilot launcher failed: $(printf '%s' "$cop_out" | tr '\n' ' ' | cut -c1-200)"
|
|
3565
|
+
return 1
|
|
3566
|
+
fi
|
|
3567
|
+
local cop_records
|
|
3568
|
+
cop_records="$(grep -l '"backend": "copilot"' "$cop_store"/meta-sessions/*.meta.json 2>/dev/null | wc -l | tr -d ' ')"
|
|
3569
|
+
if [ "$cop_records" != "1" ]; then
|
|
3570
|
+
fail "[check-pack-install] the installed Copilot unit did not mint exactly one copilot citizen (found ${cop_records:-0}); log: $(tail -1 "$cop_store/meta-bridge-hook.log" 2>/dev/null)"
|
|
3571
|
+
return 1
|
|
3572
|
+
fi
|
|
3573
|
+
rm -rf "$cop_store"
|
|
3574
|
+
echo "[check-pack-install] installed Copilot birth unit assembles its compiled branch and mints a citizen from a no-argv launch"
|
|
3397
3575
|
python3 - "$mb_cfg/settings.json" "$mb_home/.claude.json" "$stable_asm" <<'PY'
|
|
3398
3576
|
import json, sys
|
|
3399
3577
|
settings = json.load(open(sys.argv[1]))
|
|
@@ -3596,6 +3774,60 @@ JS
|
|
|
3596
3774
|
return 1
|
|
3597
3775
|
fi
|
|
3598
3776
|
|
|
3777
|
+
# #82 RAIL 7 — the managed launch, from the INSTALLED package. Hard Rule 11: a green
|
|
3778
|
+
# clone is not a green tarball. `entwurf copilot` is a bash leaf, so its risk here is
|
|
3779
|
+
# not the strip-types fence but PACKAGING — `scripts/copilot-launch.sh` has to be in
|
|
3780
|
+
# the tarball and reachable from the installed `run.sh`, and a file-list assertion
|
|
3781
|
+
# cannot tell a shipped script from a shipped script that resolves its siblings wrongly
|
|
3782
|
+
# once it lives under node_modules. So the cell RUNS it, against a fake vendor on a
|
|
3783
|
+
# sandbox PATH and a fake receiver install-state, and reads what the vendor was handed.
|
|
3784
|
+
local cop_launch_home="$npm_tmp/cop-launch-home" cop_launch_xdg="$npm_tmp/cop-launch-xdg" cop_launch_bin="$npm_tmp/cop-launch-bin"
|
|
3785
|
+
local cop_unit_dir="$cop_launch_home/.copilot/extensions/entwurf-receive"
|
|
3786
|
+
local cop_state_dir="$cop_launch_xdg/entwurf/copilot-receive"
|
|
3787
|
+
mkdir -p "$cop_unit_dir" "$cop_state_dir" "$cop_launch_bin"
|
|
3788
|
+
printf '// fixture\n' > "$cop_unit_dir/extension.mjs"
|
|
3789
|
+
printf '{"schemaVersion":1,"unit":"entwurf-receive","path":"%s"}\n' "$cop_unit_dir" > "$cop_state_dir/install-state.json"
|
|
3790
|
+
# The stand-in is installed under the REAL name on a sandbox PATH: the launcher resolves
|
|
3791
|
+
# `copilot` and nothing else, so there is no env switch here to prove the wrong contract with.
|
|
3792
|
+
{
|
|
3793
|
+
printf '#!/usr/bin/env bash\n'
|
|
3794
|
+
printf 'echo "FLAG=[${COPILOT_CLI_ENABLED_FEATURE_FLAGS-<unset>}]"\n'
|
|
3795
|
+
printf 'for a in "$@"; do printf "ARG<%%s>\\n" "$a"; done\n'
|
|
3796
|
+
} > "$cop_launch_bin/copilot"
|
|
3797
|
+
chmod +x "$cop_launch_bin/copilot"
|
|
3798
|
+
# `env -u` for BOTH carriers, not just a reassignment: an operator running this gate with
|
|
3799
|
+
# their own COPILOT_CLI_ENABLED_FEATURE_FLAGS exported would otherwise inherit those tokens
|
|
3800
|
+
# into the oracle below and read a FALSE RED, and an inherited launch sentinel would trip
|
|
3801
|
+
# the recursion fence before the vendor was ever reached. The cell must measure the
|
|
3802
|
+
# installed launcher, not the shell that happened to start it.
|
|
3803
|
+
if ! op_out=$(env -u COPILOT_CLI_ENABLED_FEATURE_FLAGS -u ENTWURF_COPILOT_LAUNCH_ACTIVE \
|
|
3804
|
+
HOME="$cop_launch_home" XDG_DATA_HOME="$cop_launch_xdg" PATH="$cop_launch_bin:$PATH" \
|
|
3805
|
+
"$installed_entwurf" copilot -p hi 2>&1); then
|
|
3806
|
+
fail "[check-pack-install] installed 'entwurf copilot' FAILED to reach the vendor:"
|
|
3807
|
+
echo "$op_out" | tail -8 | sed 's/^/ /' >&2
|
|
3808
|
+
return 1
|
|
3809
|
+
fi
|
|
3810
|
+
# Assert MEANING: the scan flag this whole surface exists to set, the managed defaults,
|
|
3811
|
+
# and the operator's own argument, all arriving at the vendor from the installed tree.
|
|
3812
|
+
if ! printf '%s' "$op_out" | grep -q 'FLAG=\[EXTENSIONS\]'; then
|
|
3813
|
+
fail "[check-pack-install] installed 'entwurf copilot' did not hand the vendor COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS:"
|
|
3814
|
+
echo "$op_out" | tail -8 | sed 's/^/ /' >&2
|
|
3815
|
+
return 1
|
|
3816
|
+
fi
|
|
3817
|
+
for want in 'ARG<-p>' 'ARG<hi>' 'ARG<--model>' 'ARG<auto>' 'ARG<--yolo>'; do
|
|
3818
|
+
if ! printf '%s' "$op_out" | grep -qF "$want"; then
|
|
3819
|
+
fail "[check-pack-install] installed 'entwurf copilot' did not forward the managed argv (missing $want):"
|
|
3820
|
+
echo "$op_out" | tail -8 | sed 's/^/ /' >&2
|
|
3821
|
+
return 1
|
|
3822
|
+
fi
|
|
3823
|
+
done
|
|
3824
|
+
if printf '%s' "$op_out" | grep -qF 'ARG<copilot>'; then
|
|
3825
|
+
fail "[check-pack-install] installed 'entwurf copilot' leaked the dispatcher verb into the vendor's argv:"
|
|
3826
|
+
echo "$op_out" | tail -8 | sed 's/^/ /' >&2
|
|
3827
|
+
return 1
|
|
3828
|
+
fi
|
|
3829
|
+
echo "[check-pack-install] installed 'entwurf copilot' reached the vendor with the scan flag and the managed argv"
|
|
3830
|
+
|
|
3599
3831
|
# The generation verb must reach its verdict from under node_modules. On the
|
|
3600
3832
|
# sandbox 0-record agent dir it archives nothing and opens a fresh generation.
|
|
3601
3833
|
# The exit code alone can't tell a verdict from a fence crash, so read the line.
|
|
@@ -4677,6 +4909,18 @@ case "$cmd" in
|
|
|
4677
4909
|
check-hook-launch-topology)
|
|
4678
4910
|
check_hook_launch_topology
|
|
4679
4911
|
;;
|
|
4912
|
+
check-copilot-birth-hook)
|
|
4913
|
+
check_copilot_birth_hook
|
|
4914
|
+
;;
|
|
4915
|
+
check-copilot-statusline)
|
|
4916
|
+
check_copilot_statusline
|
|
4917
|
+
;;
|
|
4918
|
+
check-copilot-launch)
|
|
4919
|
+
check_copilot_launch
|
|
4920
|
+
;;
|
|
4921
|
+
check-copilot-receive-arm)
|
|
4922
|
+
check_copilot_receive_arm
|
|
4923
|
+
;;
|
|
4680
4924
|
check-meta-capability-source)
|
|
4681
4925
|
check_meta_capability_source
|
|
4682
4926
|
;;
|
|
@@ -5061,6 +5305,77 @@ case "$cmd" in
|
|
|
5061
5305
|
# zero claude-code meta-records is a SILENT MISS -> non-zero exit.
|
|
5062
5306
|
(cd "$REPO_DIR" && bash scripts/meta-bridge-doctor.sh "$@")
|
|
5063
5307
|
;;
|
|
5308
|
+
install-copilot-bridge)
|
|
5309
|
+
# #82: the Copilot BIRTH install. Deliberately not a mode of install-meta-bridge —
|
|
5310
|
+
# it assembles its OWN marketplace root (the Claude assembler copies one plugin out
|
|
5311
|
+
# of one root, so a shared marketplace.json would publish a missing `source`), it
|
|
5312
|
+
# bakes node+entry into the launcher rather than into the manifest (Copilot's exec
|
|
5313
|
+
# form is a single string with no argv beside it), and it wires NO MCP: a drain tool
|
|
5314
|
+
# for a mailbox nothing rings would advertise delivery this backend does not have.
|
|
5315
|
+
shift || true
|
|
5316
|
+
(cd "$REPO_DIR" && bash scripts/copilot-bridge-install.sh "$@")
|
|
5317
|
+
;;
|
|
5318
|
+
doctor-copilot-bridge)
|
|
5319
|
+
# #82: the fail-loud surface for the Copilot unit. Its red conditions differ from
|
|
5320
|
+
# the Claude doctor's on purpose: a Copilot session mints on its FIRST PROMPT, not
|
|
5321
|
+
# at session open, so "installed with zero records" is reported as NOT-YET rather
|
|
5322
|
+
# than as a silent miss. Red is a hook that RAN and failed.
|
|
5323
|
+
shift || true
|
|
5324
|
+
(cd "$REPO_DIR" && bash scripts/copilot-bridge-doctor.sh "$@")
|
|
5325
|
+
;;
|
|
5326
|
+
install-copilot-statusline)
|
|
5327
|
+
(cd "$REPO_DIR" && bash scripts/copilot-statusline-bridge.sh install "$@")
|
|
5328
|
+
;;
|
|
5329
|
+
uninstall-copilot-statusline)
|
|
5330
|
+
(cd "$REPO_DIR" && bash scripts/copilot-statusline-bridge.sh uninstall "$@")
|
|
5331
|
+
;;
|
|
5332
|
+
doctor-copilot-statusline)
|
|
5333
|
+
(cd "$REPO_DIR" && bash scripts/copilot-statusline-bridge.sh doctor "$@")
|
|
5334
|
+
;;
|
|
5335
|
+
smoke-copilot-statusline-state)
|
|
5336
|
+
(cd "$REPO_DIR" && bash scripts/smoke-copilot-statusline-state.sh)
|
|
5337
|
+
;;
|
|
5338
|
+
install-copilot-mcp)
|
|
5339
|
+
(cd "$REPO_DIR" && bash scripts/copilot-mcp-bridge.sh install "$@")
|
|
5340
|
+
;;
|
|
5341
|
+
uninstall-copilot-mcp)
|
|
5342
|
+
(cd "$REPO_DIR" && bash scripts/copilot-mcp-bridge.sh uninstall "$@")
|
|
5343
|
+
;;
|
|
5344
|
+
doctor-copilot-mcp)
|
|
5345
|
+
(cd "$REPO_DIR" && bash scripts/copilot-mcp-bridge.sh doctor "$@")
|
|
5346
|
+
;;
|
|
5347
|
+
smoke-copilot-mcp-state)
|
|
5348
|
+
(cd "$REPO_DIR" && bash scripts/smoke-copilot-mcp-state.sh)
|
|
5349
|
+
;;
|
|
5350
|
+
copilot)
|
|
5351
|
+
# #82 RAIL 7: the managed launch. `exec` and NO subshell/cd on purpose — the vendor
|
|
5352
|
+
# must inherit this terminal exactly: the caller's cwd, this pid, this tty, and its own
|
|
5353
|
+
# exit status. The sibling install/doctor verbs wrap themselves in `(cd "$REPO_DIR" && …)`
|
|
5354
|
+
# because they operate on the repo; this one operates on the operator's session, and a
|
|
5355
|
+
# subshell would make run.sh a parent that outlives nothing and owns nothing.
|
|
5356
|
+
#
|
|
5357
|
+
# `shift` is load-bearing here, not cosmetic: this dispatcher keeps the verb in "$@"
|
|
5358
|
+
# and each branch drops it for itself. The neighbouring install/doctor verbs get away
|
|
5359
|
+
# without one because their bridge scripts take a leading subcommand and ignore the
|
|
5360
|
+
# trailing noise; this branch forwards straight into the VENDOR's argv, where a stray
|
|
5361
|
+
# "copilot" would arrive as a prompt argument.
|
|
5362
|
+
shift || true
|
|
5363
|
+
exec bash "$REPO_DIR/scripts/copilot-launch.sh" "$@"
|
|
5364
|
+
;;
|
|
5365
|
+
install-copilot-receive)
|
|
5366
|
+
# #82 RAIL 5: install the RECEIVER extension into the Copilot USER extensions dir.
|
|
5367
|
+
# Artifact ownership only — it sets no launch flag (`run.sh copilot` owns one
|
|
5368
|
+
# invocation's environment; this owns the unit on disk), and it arms
|
|
5369
|
+
# nothing by itself: a session arms after birth, on a CLI launched with
|
|
5370
|
+
# COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS.
|
|
5371
|
+
(cd "$REPO_DIR" && bash scripts/copilot-receive-bridge.sh install "$@")
|
|
5372
|
+
;;
|
|
5373
|
+
uninstall-copilot-receive)
|
|
5374
|
+
(cd "$REPO_DIR" && bash scripts/copilot-receive-bridge.sh uninstall "$@")
|
|
5375
|
+
;;
|
|
5376
|
+
doctor-copilot-receive)
|
|
5377
|
+
(cd "$REPO_DIR" && bash scripts/copilot-receive-bridge.sh doctor "$@")
|
|
5378
|
+
;;
|
|
5064
5379
|
install-agy-bridge)
|
|
5065
5380
|
# 봉인 7: the agy (Antigravity) MCP install ADAPTER (SEPARATE from the Claude
|
|
5066
5381
|
# marketplace install — only runner/reporting is shared). Registers ONE entwurf-bridge
|
|
@@ -5316,6 +5631,9 @@ case "$cmd" in
|
|
|
5316
5631
|
check-pack)
|
|
5317
5632
|
check_pack
|
|
5318
5633
|
;;
|
|
5634
|
+
check-pack-pin-matcher)
|
|
5635
|
+
check_pack_pin_matcher
|
|
5636
|
+
;;
|
|
5319
5637
|
check-pack-install)
|
|
5320
5638
|
check_pack_install
|
|
5321
5639
|
;;
|