@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
|
@@ -147,7 +147,7 @@
|
|
|
147
147
|
"title": "native pi drops the required model field from fresh-call while the composition still expects one",
|
|
148
148
|
"subject": "pi-extensions/entwurf-control.ts",
|
|
149
149
|
"find": [
|
|
150
|
-
"\t\t\tmodel: Type.String({\n\t\t\t\tminLength: 1,\n\t\t\t\tmaxLength: 200,\n\t\t\t\tpattern: \"^[A-Za-z0-9][A-Za-z0-9._/:\\\\[\\\\]-]*$\",\n\t\t\t\tdescription
|
|
150
|
+
"\t\t\tmodel: Type.String({\n\t\t\t\tminLength: 1,\n\t\t\t\tmaxLength: 200,\n\t\t\t\tpattern: \"^[A-Za-z0-9][A-Za-z0-9._/:\\\\[\\\\]-]*$\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Required runtime model: canonical provider/model for pi, a Claude Code model id/alias, or a Copilot model name (or auto).\",\n\t\t\t}),\n"
|
|
151
151
|
],
|
|
152
152
|
"replace": [""],
|
|
153
153
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
"title": "MCP drops the required model field from fresh-call while the composition still expects one",
|
|
174
174
|
"subject": "mcp/entwurf-bridge/src/index.ts",
|
|
175
175
|
"find": [
|
|
176
|
-
"\t\tmodel: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.max(200)\n\t\t\t// The `\\[` below is USELESS TO JS AND LOAD-BEARING TO THE HOST. zod emits this source\n\t\t\t// text verbatim as the JSON Schema `pattern`, and the host's tool-schema validator is a\n\t\t\t// Rust regex engine that rejects an unescaped `[` inside a character class as \"unclosed\n\t\t\t// character class\" — a 400 on tools/list that stops EVERY Claude session from opening\n\t\t\t// (7-M-fix). Biome's safe fix removes it; do not accept that fix. The suppression must\n\t\t\t// stay on the line DIRECTLY above the expression, or it attaches to nothing and reads\n\t\t\t// as an unused suppression while the escape goes back to being fixable.\n\t\t\t// biome-ignore lint/complexity/noUselessEscapeInRegex: emitted to a Rust regex validator, see above\n\t\t\t.regex(/^[A-Za-z0-9][A-Za-z0-9._/:\\[\\]-]*$/)\n\t\t\t.describe(\"Required runtime model: canonical provider/model for pi,
|
|
176
|
+
"\t\tmodel: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.max(200)\n\t\t\t// The `\\[` below is USELESS TO JS AND LOAD-BEARING TO THE HOST. zod emits this source\n\t\t\t// text verbatim as the JSON Schema `pattern`, and the host's tool-schema validator is a\n\t\t\t// Rust regex engine that rejects an unescaped `[` inside a character class as \"unclosed\n\t\t\t// character class\" — a 400 on tools/list that stops EVERY Claude session from opening\n\t\t\t// (7-M-fix). Biome's safe fix removes it; do not accept that fix. The suppression must\n\t\t\t// stay on the line DIRECTLY above the expression, or it attaches to nothing and reads\n\t\t\t// as an unused suppression while the escape goes back to being fixable.\n\t\t\t// biome-ignore lint/complexity/noUselessEscapeInRegex: emitted to a Rust regex validator, see above\n\t\t\t.regex(/^[A-Za-z0-9][A-Za-z0-9._/:\\[\\]-]*$/)\n\t\t\t.describe(\n\t\t\t\t\"Required runtime model: canonical provider/model for pi, a Claude Code model id/alias, or a Copilot model name (or auto).\",\n\t\t\t),\n"
|
|
177
177
|
],
|
|
178
178
|
"replace": [""],
|
|
179
179
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
@@ -224,6 +224,220 @@
|
|
|
224
224
|
"timeoutSeconds": 60,
|
|
225
225
|
"signature": "[QK:VITEST-FAILED-TITLE-ATTRIBUTION]",
|
|
226
226
|
"signatureSource": "scripts/check-gate-qualification.ts"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"claim": "FRESHCALL-COPILOT-MANAGED-RUNTIME",
|
|
230
|
+
"title": "fresh call opens the BARE vendor instead of entwurf's managed invocation — the window opens, the EXTENSIONS scan is skipped silently, and the sibling can never be delivered to",
|
|
231
|
+
"subject": "pi-extensions/lib/mux-fresh-call.ts",
|
|
232
|
+
"find": ["\tcopilot: \"entwurf\","],
|
|
233
|
+
"replace": ["\tcopilot: \"copilot\","],
|
|
234
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
235
|
+
"timeoutSeconds": 180,
|
|
236
|
+
"signature": "[QK:FRESHCALL-COPILOT-MANAGED-RUNTIME]",
|
|
237
|
+
"signatureSource": "test/mux-fresh-call.test.ts"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"claim": "FRESHCALL-COPILOT-ARGV-INTERACTIVE",
|
|
241
|
+
"title": "the Copilot prompt rides -p instead of --interactive — the turn runs and the CLI EXITS, closing the window on a sibling that was supposed to stay open",
|
|
242
|
+
"subject": "pi-extensions/lib/mux-fresh-call.ts",
|
|
243
|
+
"find": ["\t\t\treturn [\"copilot\", \"--interactive\", prompt, \"--model\", model, \"--yolo\"];"],
|
|
244
|
+
"replace": ["\t\t\treturn [\"copilot\", \"-p\", prompt, \"--model\", model, \"--yolo\"];"],
|
|
245
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
246
|
+
"timeoutSeconds": 180,
|
|
247
|
+
"signature": "[QK:FRESHCALL-COPILOT-ARGV-INTERACTIVE]",
|
|
248
|
+
"signatureSource": "test/mux-fresh-call.test.ts"
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"claim": "FRESHCALL-COPILOT-MODEL-ARGV",
|
|
252
|
+
"title": "the Copilot argv drops the explicit model — the managed launcher then injects `--model auto` and the caller's model choice is silently discarded",
|
|
253
|
+
"subject": "pi-extensions/lib/mux-fresh-call.ts",
|
|
254
|
+
"find": ["\t\t\treturn [\"copilot\", \"--interactive\", prompt, \"--model\", model, \"--yolo\"];"],
|
|
255
|
+
"replace": ["\t\t\treturn [\"copilot\", \"--interactive\", prompt, \"--yolo\"];"],
|
|
256
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
257
|
+
"timeoutSeconds": 180,
|
|
258
|
+
"signature": "[QK:FRESHCALL-COPILOT-MODEL-ARGV]",
|
|
259
|
+
"signatureSource": "test/mux-fresh-call.test.ts"
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"claim": "FRESHCALL-COPILOT-YOLO-POLICY",
|
|
263
|
+
"title": "the policy token narrows back to the callback-only --allow-tool grant — the exact regression GLG measured on 2026-08-25: no YOLO in the footer, a confirmation prompt at every task tool, an impractical sibling",
|
|
264
|
+
"subject": "pi-extensions/lib/mux-fresh-call.ts",
|
|
265
|
+
"find": ["\t\t\treturn [\"copilot\", \"--interactive\", prompt, \"--model\", model, \"--yolo\"];"],
|
|
266
|
+
"replace": [
|
|
267
|
+
"\t\t\treturn [\"copilot\", \"--interactive\", prompt, \"--model\", model, \"--allow-tool=entwurf-bridge(entwurf_v2)\"];"
|
|
268
|
+
],
|
|
269
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
270
|
+
"timeoutSeconds": 180,
|
|
271
|
+
"signature": "[QK:FRESHCALL-COPILOT-YOLO-POLICY]",
|
|
272
|
+
"signatureSource": "test/mux-fresh-call.test.ts"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"claim": "FRESHCALL-COPILOT-CALLBACK-TOOL",
|
|
276
|
+
"title": "the Copilot callback names Claude Code's `mcp__server__tool` spelling — a dialect copied instead of measured, and the whole first turn is spent looking for a tool that is not there",
|
|
277
|
+
"subject": "pi-extensions/lib/mux-fresh-call.ts",
|
|
278
|
+
"find": ["\tcopilot: \"entwurf-bridge-entwurf_v2\","],
|
|
279
|
+
"replace": ["\tcopilot: \"mcp__entwurf-bridge__entwurf_v2\","],
|
|
280
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
281
|
+
"timeoutSeconds": 180,
|
|
282
|
+
"signature": "[QK:FRESHCALL-COPILOT-CALLBACK-TOOL]",
|
|
283
|
+
"signatureSource": "test/mux-fresh-call.test.ts"
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"claim": "FRESHCALL-COPILOT-PREFLIGHT-PREMUTATION",
|
|
287
|
+
"title": "the capability preflight is removed — a host missing the birth, MCP, receiver or footer unit gets a real window and a launch receipt for a sibling that can never call home",
|
|
288
|
+
"subject": "pi-extensions/lib/mux-fresh-call.ts",
|
|
289
|
+
"find": [
|
|
290
|
+
"\tif (params.backend === \"copilot\") {\n\t\tconst missing = copilotFreshPreflight(env);\n\t\tif (missing) return { ok: false, reason: missing };\n\t}\n"
|
|
291
|
+
],
|
|
292
|
+
"replace": [""],
|
|
293
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
294
|
+
"timeoutSeconds": 180,
|
|
295
|
+
"signature": "[QK:FRESHCALL-COPILOT-PREFLIGHT-PREMUTATION]",
|
|
296
|
+
"signatureSource": "test/mux-fresh-call.test.ts"
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
"claim": "FRESHCALL-COPILOT-PREFLIGHT-AFTER-RUNTIME",
|
|
300
|
+
"title": "the preflight runs before the runtime is proven — an operator with no entwurf at all is told to install a Copilot unit, which is the wrong repair",
|
|
301
|
+
"subject": "pi-extensions/lib/mux-fresh-call.ts",
|
|
302
|
+
"find": ["\tlet runtimePath: string;"],
|
|
303
|
+
"replace": [
|
|
304
|
+
"\tif (params.backend === \"copilot\") {\n\t\tconst early = copilotFreshPreflight(env);\n\t\tif (early) return { ok: false, reason: early };\n\t}\n\tlet runtimePath: string;"
|
|
305
|
+
],
|
|
306
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
307
|
+
"timeoutSeconds": 180,
|
|
308
|
+
"signature": "[QK:FRESHCALL-COPILOT-PREFLIGHT-AFTER-RUNTIME]",
|
|
309
|
+
"signatureSource": "test/mux-fresh-call.test.ts"
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"claim": "FRESHCALL-BACKEND-SET-SURFACE-PARITY",
|
|
313
|
+
"title": "a backend the composition can open is missing from the MCP surface enum — the capability exists and no external host can reach it",
|
|
314
|
+
"subject": "mcp/entwurf-bridge/src/index.ts",
|
|
315
|
+
"find": ["\t\t\t.enum([\"pi\", \"claude-code\", \"copilot\"])"],
|
|
316
|
+
"replace": ["\t\t\t.enum([\"pi\", \"claude-code\"])"],
|
|
317
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
318
|
+
"timeoutSeconds": 180,
|
|
319
|
+
"signature": "[QK:FRESHCALL-BACKEND-SET-SURFACE-PARITY]",
|
|
320
|
+
"signatureSource": "test/fresh-call-surfaces.contract.test.ts"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"claim": "COPILOT-PREFLIGHT-VISIBLE-IDENTITY-EFFECTIVE",
|
|
324
|
+
"title": "the visible-identity axis gates on entwurf's ownership RECEIPT instead of the settings Copilot actually reads — a host with a correct, resolvable footer and no install-state is refused for a working identity surface (measured: that is the acceptance host)",
|
|
325
|
+
"subject": "pi-extensions/lib/copilot-fresh-preflight.ts",
|
|
326
|
+
"find": ["\tif (state === null) return false; // absent state is not drift — see the doc comment above"],
|
|
327
|
+
"replace": ["\tif (state === null) return true;"],
|
|
328
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
329
|
+
"timeoutSeconds": 180,
|
|
330
|
+
"signature": "[QK:COPILOT-PREFLIGHT-VISIBLE-IDENTITY-EFFECTIVE]",
|
|
331
|
+
"signatureSource": "test/copilot-fresh-preflight.test.ts"
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
"claim": "COPILOT-PREFLIGHT-VISIBLE-IDENTITY-REQUIRED",
|
|
335
|
+
"title": "the visible-identity axis is dropped entirely — a Copilot citizen is admitted whose garden id can only be found by scraping records, which step 4 refuses to call lifecycle parity",
|
|
336
|
+
"subject": "pi-extensions/lib/copilot-fresh-preflight.ts",
|
|
337
|
+
"find": ["\tif (visibleIdentityMissing(env, data)) return \"copilot-visible-identity-missing\";"],
|
|
338
|
+
"replace": [""],
|
|
339
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
340
|
+
"timeoutSeconds": 180,
|
|
341
|
+
"signature": "[QK:COPILOT-PREFLIGHT-VISIBLE-IDENTITY-REQUIRED]",
|
|
342
|
+
"signatureSource": "test/copilot-fresh-preflight.test.ts"
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"claim": "COPILOT-PREFLIGHT-MCP-CONFIG-DRIFT",
|
|
346
|
+
"title": "the MCP axis trusts the install-state alone — a config that lost the server key still reads as installed, and the first turn calls a tool that is not registered",
|
|
347
|
+
"subject": "pi-extensions/lib/copilot-fresh-preflight.ts",
|
|
348
|
+
"find": [
|
|
349
|
+
"\tif (!Object.hasOwn(servers as Record<string, unknown>, MCP_SERVER_KEY)) return \"copilot-mcp-hand-missing\";"
|
|
350
|
+
],
|
|
351
|
+
"replace": [""],
|
|
352
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
353
|
+
"timeoutSeconds": 180,
|
|
354
|
+
"signature": "[QK:COPILOT-PREFLIGHT-MCP-CONFIG-DRIFT]",
|
|
355
|
+
"signatureSource": "test/copilot-fresh-preflight.test.ts"
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"claim": "COPILOT-PREFLIGHT-BIRTH-AXIS",
|
|
359
|
+
"title": "the birth axis is satisfied by the directory alone — an assembly root with no hooks.json passes as a hook unit, so a host that cannot mint a record reads as ready",
|
|
360
|
+
"subject": "pi-extensions/lib/copilot-fresh-preflight.ts",
|
|
361
|
+
"find": ["\tif (!isDir(birthUnit) || !existsSync(path.join(birthUnit, \"hooks\", \"hooks.json\"))) {"],
|
|
362
|
+
"replace": ["\tif (!isDir(birthUnit)) {"],
|
|
363
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
364
|
+
"timeoutSeconds": 180,
|
|
365
|
+
"signature": "[QK:COPILOT-PREFLIGHT-BIRTH-AXIS]",
|
|
366
|
+
"signatureSource": "test/copilot-fresh-preflight.test.ts"
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
"claim": "COPILOT-PREFLIGHT-RECEIVE-PATH-MISMATCH",
|
|
370
|
+
"title": "the receive axis ignores the launcher's DEST equality — a unit in a different extensions root than this env will scan still preflights green, then entwurf copilot refuses inside the new window",
|
|
371
|
+
"subject": "pi-extensions/lib/copilot-fresh-preflight.ts",
|
|
372
|
+
"find": [
|
|
373
|
+
"\tconst dest = receiveDest(env);\n\tif (dest === null || recvPath !== dest) return \"copilot-receive-unit-missing\";\n"
|
|
374
|
+
],
|
|
375
|
+
"replace": [""],
|
|
376
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
377
|
+
"timeoutSeconds": 180,
|
|
378
|
+
"signature": "[QK:COPILOT-PREFLIGHT-RECEIVE-PATH-MISMATCH]",
|
|
379
|
+
"signatureSource": "test/copilot-fresh-preflight.test.ts"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"claim": "COPILOT-PREFLIGHT-RECEIVE-AXIS",
|
|
383
|
+
"title": "the receive axis is satisfied by the directory alone — a leftover folder with no extension.mjs passes as our unit, so a host that cannot arm still reads as ready",
|
|
384
|
+
"subject": "pi-extensions/lib/copilot-fresh-preflight.ts",
|
|
385
|
+
"find": [
|
|
386
|
+
"\tif (!isDir(recvPath) || !existsSync(path.join(recvPath, \"extension.mjs\"))) return \"copilot-receive-unit-missing\";"
|
|
387
|
+
],
|
|
388
|
+
"replace": ["\tif (!isDir(recvPath)) return \"copilot-receive-unit-missing\";"],
|
|
389
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
390
|
+
"timeoutSeconds": 180,
|
|
391
|
+
"signature": "[QK:COPILOT-PREFLIGHT-RECEIVE-AXIS]",
|
|
392
|
+
"signatureSource": "test/copilot-fresh-preflight.test.ts"
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
"claim": "COPILOT-PREFLIGHT-COMPLETE-HOST-PASSES",
|
|
396
|
+
"title": "a correctly wired host is still refused — the preflight becomes a permanent closed door wearing a check's clothes",
|
|
397
|
+
"subject": "pi-extensions/lib/copilot-fresh-preflight.ts",
|
|
398
|
+
"find": [
|
|
399
|
+
"\tif (visibleIdentityMissing(env, data)) return \"copilot-visible-identity-missing\";\n\n\treturn null;"
|
|
400
|
+
],
|
|
401
|
+
"replace": [
|
|
402
|
+
"\tif (visibleIdentityMissing(env, data)) return \"copilot-visible-identity-missing\";\n\n\treturn \"copilot-birth-unit-missing\";"
|
|
403
|
+
],
|
|
404
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
405
|
+
"timeoutSeconds": 180,
|
|
406
|
+
"signature": "[QK:COPILOT-PREFLIGHT-COMPLETE-HOST-PASSES]",
|
|
407
|
+
"signatureSource": "test/copilot-fresh-preflight.test.ts"
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
"claim": "COPILOT-PREFLIGHT-STATUSLINE-STATE-DRIFT",
|
|
411
|
+
"title": "an install-state that manages a different settings file is accepted — two files then disagree about who owns the footer and the preflight pretends they do not",
|
|
412
|
+
"subject": "pi-extensions/lib/copilot-fresh-preflight.ts",
|
|
413
|
+
"find": ["\treturn path.resolve(managed) !== path.resolve(settingsPath);"],
|
|
414
|
+
"replace": ["\treturn false;"],
|
|
415
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
416
|
+
"timeoutSeconds": 180,
|
|
417
|
+
"signature": "[QK:COPILOT-PREFLIGHT-STATUSLINE-STATE-DRIFT]",
|
|
418
|
+
"signatureSource": "test/copilot-fresh-preflight.test.ts"
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
"claim": "FRESHCALL-COPILOT-EXPLICIT-POLICY",
|
|
422
|
+
"title": "the composition stops stating its policy and silently leans on the launcher to inject --yolo — the effective profile survives but the fresh contract loses its explicit permission statement",
|
|
423
|
+
"subject": "pi-extensions/lib/mux-fresh-call.ts",
|
|
424
|
+
"find": ["\t\t\treturn [\"copilot\", \"--interactive\", prompt, \"--model\", model, \"--yolo\"];"],
|
|
425
|
+
"replace": ["\t\t\treturn [\"copilot\", \"--interactive\", prompt, \"--model\", model];"],
|
|
426
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
427
|
+
"timeoutSeconds": 180,
|
|
428
|
+
"signature": "[QK:FRESHCALL-COPILOT-EXPLICIT-POLICY]",
|
|
429
|
+
"signatureSource": "test/mux-fresh-call.test.ts"
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
"claim": "FRESHCALL-BACKEND-SET-SURFACE-PARITY-PI",
|
|
433
|
+
"title": "a backend the composition can open is missing from the native pi surface enum — an in-process pi session cannot name a capability the module already opens",
|
|
434
|
+
"subject": "pi-extensions/entwurf-control.ts",
|
|
435
|
+
"find": ["\t\t\tbackend: StringEnum([\"pi\", \"claude-code\", \"copilot\"], {"],
|
|
436
|
+
"replace": ["\t\t\tbackend: StringEnum([\"pi\", \"claude-code\"], {"],
|
|
437
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
438
|
+
"timeoutSeconds": 180,
|
|
439
|
+
"signature": "[QK:FRESHCALL-BACKEND-SET-SURFACE-PARITY-PI]",
|
|
440
|
+
"signatureSource": "test/fresh-call-surfaces.contract.test.ts"
|
|
227
441
|
}
|
|
228
442
|
]
|
|
229
443
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"lane": "pack-install",
|
|
4
|
+
"mutants": [
|
|
5
|
+
{
|
|
6
|
+
"claim": "PACK-INSTALL-PIN-MATCHER-BOUNDED",
|
|
7
|
+
"title": "the pin-leak matcher loses its version boundary and blesses substring lookalikes — @0.84.30 reads as the pinned 0.84.3 and the gate announces a verified tree it never verified (independent review, 2026-08-25)",
|
|
8
|
+
"subject": "run.sh",
|
|
9
|
+
"find": [" grep '^@earendil-works+pi-' | grep -Ev '@0\\.84\\.3(_|$)' || true"],
|
|
10
|
+
"replace": [" grep '^@earendil-works+pi-' | grep -v '@0\\.84\\.3' || true"],
|
|
11
|
+
"gate": ["bash", "run.sh", "check-pack-pin-matcher"],
|
|
12
|
+
"timeoutSeconds": 120,
|
|
13
|
+
"signature": "[QK:PACK-INSTALL-PIN-MATCHER-BOUNDED]",
|
|
14
|
+
"signatureSource": "run.sh"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -12,12 +12,26 @@ Codex is split by launch surface:
|
|
|
12
12
|
auto-attached to a default-path app-server): raw `turn/start` over
|
|
13
13
|
WebSocket-over-UDS wakes the live thread — **demonstrated, no managed
|
|
14
14
|
standalone, no cloud**.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
|
|
16
|
+
Copilot is no longer blocked on transport, and the probe below is no longer the
|
|
17
|
+
product — it is the receipt the product was built on:
|
|
18
|
+
|
|
19
|
+
- **Copilot CLI 1.0.80 extension**: the CLI forks a first-party extension and
|
|
20
|
+
speaks JSON-RPC over that child's **stdio**, so `fs.watch` -> `session.send()`
|
|
21
|
+
wakes the idle TUI with **no network listener or token-authentication axis**. Idle wake
|
|
22
|
+
and exact-marker attribution were demonstrated; addressed isolation was observed but its
|
|
23
|
+
decisive control log was not preserved (2026-08-23, one Linux workstation). It needs the experimental
|
|
24
|
+
`COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS` flag at launch. The older
|
|
25
|
+
hidden `--ui-server` loopback probe is retired — it found the capability
|
|
26
|
+
through a door that could not pass admission. Undocumented
|
|
20
27
|
`~/.copilot/run/ws.*` is still not a rail.
|
|
28
|
+
- **The MANAGED receiver now lives at `pi/copilot-receive/entwurf-receive/`** and is
|
|
29
|
+
installed with `run.sh install-copilot-receive` (#82 RAIL 5). Read it before reusing
|
|
30
|
+
anything here, because it deliberately differs on three points: it binds to the V3
|
|
31
|
+
record instead of publishing its own `ready.json`; its receiver marker is owned by the
|
|
32
|
+
extension pid, so a crash retires it; and it **announces** the inbox rather than
|
|
33
|
+
sending the body, leaving the drain (and the read-receipt) to `entwurf_inbox_read`.
|
|
34
|
+
The files below stay as the measurement — do not develop the product in them.
|
|
21
35
|
|
|
22
36
|
## TL;DR — three reception paths, ranked
|
|
23
37
|
|
|
@@ -88,7 +102,9 @@ do not ship that. Proven: deliver to A's sessionId → A wakes (FileChanged), B'
|
|
|
88
102
|
- `raw-agy-send.sh <conv_id> …` — agy parity: PUSH into a live Antigravity session (LS gRPC)
|
|
89
103
|
- `raw-codex-ws-turn-start.py <sock> <thread_id> …` — Codex parity (no managed standalone, no cloud): PUSH `turn/start` over WebSocket-over-UDS into a bare `app-server --listen` socket
|
|
90
104
|
- `codex-local-appserver.sh [sock]` — start a bare local app-server so plain `codex` auto-attaches and becomes addressable
|
|
91
|
-
- `copilot-
|
|
105
|
+
- `copilot-enqueue-addressed.sh <session_id> …` — Copilot raw sender: write `.msg` + poke one session's signal; refuses a missing marker, but deliberately does not claim production stale-receiver safety
|
|
106
|
+
- `copilot-extension-receive/extension.mjs` — Copilot reception unit: a first-party CLI extension that arms the per-session mailbox and calls `session.send()` (stdio JSON-RPC; no port, no token)
|
|
107
|
+
- `copilot-ui-server-probe.mjs` — RETIRED rail, kept as history; the hidden `--ui-server` loopback path whose authentication could not be established
|
|
92
108
|
|
|
93
109
|
### Reproduction drivers
|
|
94
110
|
- `repro-plugin-idle-wake.sh` — single-session smoke.
|
|
@@ -251,7 +267,7 @@ send-message-v2` spins a fresh thread, not the live one.
|
|
|
251
267
|
4. **Unix-socket transport is WebSocket** (tokio-tungstenite), not newline JSON-RPC,
|
|
252
268
|
and requires **no auth token** on the UDS. A plain WS client suffices.
|
|
253
269
|
|
|
254
|
-
## Copilot CLI
|
|
270
|
+
## Copilot CLI delivery status (1.0.80) — idle wake DEMONSTRATED on the extension rail
|
|
255
271
|
|
|
256
272
|
Copilot is a GitHub **harness** (issues, PR, CI, model `auto`, mode `autopilot`,
|
|
257
273
|
remote/delegate), not a second GPT provider next to pi. This makes a native lane
|
|
@@ -264,136 +280,156 @@ premium-interaction entitlement; model `auto` chooses a path within that budget.
|
|
|
264
280
|
The reason to use it is GitHub specialization and auto routing, not an unlimited
|
|
265
281
|
subscription claim. Model `auto` and mode `autopilot` are separate axes.
|
|
266
282
|
|
|
267
|
-
###
|
|
268
|
-
|
|
269
|
-
The first-party `@github/copilot-sdk` exposes TUI+server coordination:
|
|
270
|
-
`getForegroundSessionId()`, `getSessionMetadata()`, `resumeSession(id)`, and
|
|
271
|
-
session-scoped `send({mode:"enqueue"|"immediate"})`. The native TUI launch mode is:
|
|
283
|
+
### The rail: a first-party CLI extension, stdio only
|
|
272
284
|
|
|
273
|
-
|
|
274
|
-
copilot --ui-server --port 43817 --model auto
|
|
275
|
-
```
|
|
285
|
+
`copilot-extension-receive/extension.mjs` + `copilot-enqueue-addressed.sh`.
|
|
276
286
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
Measured once on 2026-08-19 with SDK 1.0.11, **using the earlier chronological-slice
|
|
282
|
-
probe** (it scored the events following the marker's position in the history). The probe
|
|
283
|
-
in the tree today scores a named turn instead — see "Current probe contract" below — and
|
|
284
|
-
that contract has NOT been run LIVE, so nothing in this list is retroactively evidence
|
|
285
|
-
for it. Evidence level for the list: **L4 direct-native, ONE Linux workstation, one run**;
|
|
286
|
-
the receipt is host-local probe stdout and was NOT archived as a durable artifact, so what
|
|
287
|
-
follows is reproducible by instruction, not citable to a stored file:
|
|
288
|
-
|
|
289
|
-
- protocol v3 ping succeeded;
|
|
290
|
-
- foreground session id joined to metadata containing cwd/git root/branch;
|
|
291
|
-
- `resumeSession(id)` + idle `enqueue` woke the visible TUI with zero typing;
|
|
292
|
-
- the unique body appeared as `user.message` with `delivery:"idle"`;
|
|
293
|
-
- model `auto` selected `gpt-5.6-luna` and returned the exact marker;
|
|
294
|
-
- `assistant.message`, `assistant.turn_end`, and (in the one-session run)
|
|
295
|
-
ephemeral `session.idle` gave completion/reply evidence;
|
|
296
|
-
- a two-session control then targeted A while B received no `user.message`, turn,
|
|
297
|
-
or assistant event, so D3 passed too.
|
|
298
|
-
|
|
299
|
-
D0–D7 passed; D8 is unproven. One robustness defect surfaced in the two-session
|
|
300
|
-
shape: the target visibly replied and persisted `assistant.message` + `turn_end`,
|
|
301
|
-
but that joining SDK client did not receive ephemeral `session.idle`, so SDK
|
|
302
|
-
`sendAndWait()` timed out after 60 seconds. The probe therefore uses `send()` plus
|
|
303
|
-
bounded polling of the official session event-history API (`session.getEvents()` /
|
|
304
|
-
`getMessages()`) and reports completion at `turn_end`. Name that surface at its real
|
|
305
|
-
size: it is the SDK's own full event history — no narrower, no more privileged — and it
|
|
306
|
-
is **not** TUI, file, or database transcript scraping; the probe never reads Copilot's
|
|
307
|
-
storage. This is evidence, not a product retry/polling design.
|
|
308
|
-
|
|
309
|
-
### Current probe contract — designed, not yet run LIVE
|
|
310
|
-
|
|
311
|
-
Attribution is the load-bearing part, and it runs off the probe's own marker body:
|
|
287
|
+
The CLI forks an extension as its own child and speaks JSON-RPC over that
|
|
288
|
+
child's stdio. `joinSession()` attaches it to the foreground session; from
|
|
289
|
+
there `session.send({mode:"enqueue"})` injects a user message. So the whole
|
|
290
|
+
delivery path is:
|
|
312
291
|
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
→ its interactionId
|
|
316
|
-
→ exactly one assistant.turn_start on that interaction
|
|
317
|
-
→ that turn_start's required turnId
|
|
318
|
-
→ only assistant.message / assistant.turn_end on that turnId
|
|
292
|
+
```
|
|
293
|
+
external file write -> fs.watch in the extension -> session.send() -> the idle session takes a turn
|
|
319
294
|
```
|
|
320
295
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
296
|
+
`fs.watch` -> `session.send()` is not a mechanism found by inspection: the
|
|
297
|
+
bundled SDK documents it (`copilot-sdk/docs/examples.md`, "Detecting when the
|
|
298
|
+
plan file is created or edited"). The SDK also ships *inside* the CLI package
|
|
299
|
+
(`<platform-pkg>/copilot-sdk/`) and is injected into extension children by
|
|
300
|
+
`preloads/extension_bootstrap.mjs`, so nothing has to be installed and the SDK
|
|
301
|
+
version cannot drift from the CLI.
|
|
325
302
|
|
|
326
|
-
|
|
327
|
-
`
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
303
|
+
**This is why the rail clears the network-boundary bar the old one could not.**
|
|
304
|
+
The `--ui-server` probe was refused because its loopback RPC authentication was
|
|
305
|
+
not established. An extension has no port, token, or listener, so that network
|
|
306
|
+
authentication axis does not exist. Product admission must instead certify the
|
|
307
|
+
installed extension's provenance and the CLI-owned parent/child lifecycle; the
|
|
308
|
+
fork is the transport boundary, not proof that every permission, liveness, and
|
|
309
|
+
integrity obligation is already closed.
|
|
331
310
|
|
|
332
|
-
|
|
333
|
-
non-target session received no `user.message` and no `assistant.*` event of any kind.
|
|
311
|
+
### Launch contract
|
|
334
312
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
ownership is re-confirmed immediately before teardown, the TUI keeps A as its foreground
|
|
339
|
-
session, so the net effect on A is detach-equivalent, not removal. The probe deletes only
|
|
340
|
-
the control session it created itself, and reads `client.stop()`'s returned error list so a
|
|
341
|
-
failed teardown cannot exit 0 behind a printed verdict. Reaching past the SDK for a raw
|
|
342
|
-
detach wrapper is out of bounds — it would be a second lifecycle authority.
|
|
313
|
+
Extensions sit behind an experimental feature flag. Without it the CLI never
|
|
314
|
+
scans for extensions and the receiver is inert **with no error at all** —
|
|
315
|
+
budget for that when a receiver appears not to arm:
|
|
343
316
|
|
|
344
|
-
|
|
345
|
-
|
|
317
|
+
```bash
|
|
318
|
+
COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS copilot --model auto
|
|
319
|
+
```
|
|
346
320
|
|
|
347
|
-
|
|
321
|
+
`--experimental` is NOT required (measured: a session launched with the env var
|
|
322
|
+
alone armed its receiver). Discovery scopes are `user`
|
|
323
|
+
(`~/.copilot/extensions/`), `plugin`, `session`, and — interactive mode only —
|
|
324
|
+
`project` (`.github/extensions/`). Prompt mode (`-p`) drops `project` unless
|
|
325
|
+
`GITHUB_COPILOT_PROMPT_MODE_EXTENSIONS=true`. The `plugin` scope matters most
|
|
326
|
+
here: the existing entwurf Copilot plugin is the candidate install scope for
|
|
327
|
+
this receiver, so product design need not start from a per-repository
|
|
328
|
+
`.github/extensions/` directory.
|
|
348
329
|
|
|
349
|
-
|
|
350
|
-
a raw probe. Install it in scratch and point the probe at its ESM entry:
|
|
330
|
+
### Reproduce
|
|
351
331
|
|
|
352
332
|
```bash
|
|
353
|
-
mkdir -p /tmp/
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
333
|
+
mkdir -p /tmp/cop-lab/.github/extensions/entwurf-mailbox
|
|
334
|
+
cp copilot-extension-receive/extension.mjs /tmp/cop-lab/.github/extensions/entwurf-mailbox/
|
|
335
|
+
|
|
336
|
+
# terminal A: a visible session that arms its own receiver
|
|
337
|
+
cd /tmp/cop-lab
|
|
338
|
+
export COPILOT_MAILBOX_ROOT=/tmp/cop-lab/mbx COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS
|
|
339
|
+
copilot --model auto --allow-all-tools # accept folder trust
|
|
340
|
+
|
|
341
|
+
# terminal B: find the armed receiver, then wake it with zero typing
|
|
342
|
+
ls /tmp/cop-lab/mbx/*/ready.json
|
|
343
|
+
COPILOT_MAILBOX_ROOT=/tmp/cop-lab/mbx \
|
|
344
|
+
./copilot-enqueue-addressed.sh <session_id> "Reply with exactly PING and nothing else."
|
|
345
|
+
```
|
|
359
346
|
|
|
360
|
-
|
|
361
|
-
COPILOT_SDK_MODULE=/tmp/copilot-sdk-probe/node_modules/@github/copilot-sdk/dist/index.js \
|
|
362
|
-
./copilot-ui-server-probe.mjs
|
|
347
|
+
### Measured — 2026-08-23, CLI 1.0.80, model `auto`, one Linux workstation (oracle, arm64)
|
|
363
348
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
349
|
+
Evidence level **L4 direct-native, one host**. The receiver log lines that still
|
|
350
|
+
travel are pasted here. Scratch was cleaned before the second-session control and
|
|
351
|
+
second-turn lines were copied, so those two observations are explicitly downgraded
|
|
352
|
+
below rather than being laundered into durable receipts:
|
|
367
353
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
354
|
+
```text
|
|
355
|
+
02:19:33.996 ARMED sessionId=4fc16d8d-473d-4258-a1fd-f99d3cb375e9
|
|
356
|
+
02:20:03.388 DELIVER (signal) 1787451603.msg bytes=96
|
|
357
|
+
02:20:03.422 SENT 1787451603.msg
|
|
358
|
+
02:20:06.141 EVENT user.message {"content":"...Reply with exactly ENTWURF-WAKE-1787451603..."}
|
|
359
|
+
02:20:06.492 EVENT assistant.turn_start {"turnId":"0"}
|
|
360
|
+
02:20:09.935 EVENT assistant.message {"turnId":"0","content":"ENTWURF-WAKE-1787451603"}
|
|
361
|
+
02:20:10.024 EVENT session.idle {}
|
|
372
362
|
```
|
|
373
363
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
364
|
+
- **Idle wake: PASS.** The session had never been typed into — an empty timeline,
|
|
365
|
+
already past any turn boundary. An external file write started a turn. ~2.7 s
|
|
366
|
+
poke -> `user.message`, ~6.5 s poke -> reply. The visible TUI showed the prompt
|
|
367
|
+
and the answer.
|
|
368
|
+
- **Attribution: PASS.** A unique per-run marker went in and came back exactly,
|
|
369
|
+
on one `assistant.turn_start`/`assistant.message` pair.
|
|
370
|
+
- **Addressed routing: reported, receipt not preserved.** The measuring Opus
|
|
371
|
+
reported that a second armed process B stayed at one `ARMED` line across two
|
|
372
|
+
deliveries to A, with no `user.message` or `assistant.*` event. The decisive B
|
|
373
|
+
line and A's second delivery were not copied before scratch cleanup, so this is
|
|
374
|
+
a lead for the admission rerun, not durable D3 acceptance.
|
|
375
|
+
- **Continuity: one turn demonstrated.** The pasted chain shows one joined
|
|
376
|
+
session taking the marker turn and replying; no `-p` process was spawned. A
|
|
377
|
+
second same-session turn was reported but its lines were not preserved, so no
|
|
378
|
+
stronger repeatability claim crosses from this checkpoint.
|
|
379
|
+
|
|
380
|
+
### Not proven — do not describe these as working
|
|
381
|
+
|
|
382
|
+
- **Active-turn delivery.** Every measured send landed on an idle session.
|
|
383
|
+
`mode:"enqueue"` vs `"immediate"` against a busy turn is untested.
|
|
384
|
+
- **Multi-session inside ONE CLI process.** A and B were separate `copilot`
|
|
385
|
+
processes. Whether a *background* session inside one process (sidebar tabs)
|
|
386
|
+
can be woken while another holds the foreground is untested, and
|
|
387
|
+
`joinSession()` attaching to "the foreground session" is the reason to doubt it.
|
|
388
|
+
- **`/clear` and foreground replacement.** The docs say extensions reload there;
|
|
389
|
+
re-arming was not measured. `[문서]`, not `[측정]`.
|
|
390
|
+
- **Flag durability.** `EXTENSIONS` is an experimental flag with
|
|
391
|
+
`experimental`/`staff-or-experimental` availability. It can move or be
|
|
392
|
+
withdrawn between CLI releases; re-verify on upgrade. A flagged surface is an
|
|
393
|
+
admission question for a managed lane even when the transport is sound.
|
|
394
|
+
- **Permission ownership, crash and ordering behavior, delivery under load.**
|
|
395
|
+
|
|
396
|
+
That fence has since been walked, not deleted: `backend:"copilot"` receive capability
|
|
397
|
+
IS now real (`wakeMode: self-fetch` plus a record-bound receiver marker, #82 RAIL 5),
|
|
398
|
+
and it arrived through the managed unit with its own installer, doctor, gate and
|
|
399
|
+
mutants — not by widening anything in this directory. `FRESH_CALL_BACKENDS` now
|
|
400
|
+
includes `copilot` (#82 RAIL 9); that launch path lives in `mux-fresh-call`, not here.
|
|
401
|
+
This probe still does not open a sibling. Waking an already-running Copilot and
|
|
402
|
+
opening a new one remain different capabilities.
|
|
403
|
+
The registry's receive grade moved off D0 later, and NOT because of this probe: a managed
|
|
404
|
+
LIVE wake was observed on 2026-08-23 (garden `20260823T181316-d9f6ba`, CLI 1.0.80,
|
|
405
|
+
doorbell→`lastReadAt` 09:23:41.235Z→09:23:56.480Z) and that is what makes the shipped lane
|
|
406
|
+
D6, with D7 partial and D3 pending. This probe's receipt remains what it always was —
|
|
407
|
+
evidence about the MECHANISM, not about the shipped lane. Keep the two apart when citing
|
|
408
|
+
either.
|
|
409
|
+
|
|
410
|
+
### Retired: the hidden `--ui-server` probe (kept for the lesson)
|
|
411
|
+
|
|
412
|
+
The 2026-08-19 probe reached the TUI through `copilot --ui-server --port 43817`
|
|
413
|
+
and the separately-installed SDK, and it did demonstrate an idle enqueue. It was
|
|
414
|
+
refused admission because the launch flag is hidden from `copilot --help` and its
|
|
415
|
+
loopback RPC authentication could not be established: an unauthenticated client
|
|
416
|
+
connected, while setting `COPILOT_CONNECTION_TOKEN` on the server made a
|
|
417
|
+
token-bearing client fail with `AUTHENTICATION_NOT_CONFIGURED`.
|
|
418
|
+
|
|
419
|
+
The lesson is not "that probe was wrong". It found a real capability through the
|
|
420
|
+
wrong door, and then the door — not the capability — was what failed admission.
|
|
421
|
+
The bundled extension door was in the same package the whole time: the SDK that
|
|
422
|
+
this probe installed from npm also ships inside the CLI, with an `extension.mjs` contract and
|
|
423
|
+
docs beside it. `copilot-ui-server-probe.mjs` remains in this tree as that history.
|
|
424
|
+
Do not revive `--ui-server` as a rail; use the extension.
|
|
425
|
+
|
|
426
|
+
Also still true, and still out of bounds: hooks have no `FileChanged` /
|
|
427
|
+
`watchPaths` / `asyncRewake`, so the Claude mailbox hook mechanism cannot be
|
|
428
|
+
copied; the shell command-hook `sessionStart` input carries no `sessionId`
|
|
429
|
+
(the receiver publishes its own `ready.json` instead of scraping for one);
|
|
430
|
+
`--acp` is a pi-host child path and `--remote` is GitHub web/mobile steering,
|
|
431
|
+
neither of which is a local `entwurf_v2` API; and undocumented
|
|
432
|
+
`~/.copilot/run/ws.*` is not a rail.
|
|
397
433
|
|
|
398
434
|
## Live SSOT for "is the target session alive?"
|
|
399
435
|
|
|
@@ -407,9 +443,18 @@ boundary.
|
|
|
407
443
|
`$HOME/.codex/app-server-control/app-server-control.sock` (or any owned 0700
|
|
408
444
|
socket via `codex app-server --listen unix://PATH`) is the delivery surface.
|
|
409
445
|
threadId comes from the newest rollout's `session_meta.id`.
|
|
410
|
-
- Copilot
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
446
|
+
- Copilot raw probe: `<COPILOT_MAILBOX_ROOT>/<session_id>/ready.json`, written by
|
|
447
|
+
the receiver extension about itself (sessionId, pid, cwd, armedAt). `[번들]`
|
|
448
|
+
`preloads/extension_bootstrap.mjs` monitors the CLI parent, but this is a
|
|
449
|
+
discovery marker for the experiment, **not a production liveness SSOT**: the
|
|
450
|
+
probe sender checks only that the file exists, so a crashed extension can
|
|
451
|
+
leave stale state and produce a false enqueue receipt.
|
|
452
|
+
- Copilot PRODUCT: `<pi-agent-dir>/meta-receivers/<gardenId>.json`, written by the
|
|
453
|
+
managed extension and keyed by the garden id a sender actually targets. Liveness is
|
|
454
|
+
pid + start-key on the EXTENSION child, so a crashed receiver reads as inactive at the
|
|
455
|
+
next read — that is what `ready.json` could not do. Parent monitoring never cleaned the
|
|
456
|
+
probe's marker by itself; the product does not depend on cleanup at all. Nothing
|
|
457
|
+
scrapes `~/.copilot/session-store.db` or the session-state dirs, and the shell
|
|
458
|
+
command-hook `sessionStart` input is NOT
|
|
459
|
+
a source — it carries no `sessionId`. The retired `--ui-server` TCP port was
|
|
460
|
+
never an identity axis.
|