@junghanacs/entwurf 0.14.1 → 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 +113 -0
- package/DELIVERY.md +73 -3
- package/README.md +55 -4
- package/VERIFY.md +6 -6
- package/demo/README.md +3 -1
- package/demo/demo-baseline.sh +12 -1
- package/demo/demo.sh +9 -1
- package/docs/acp-backend-rail.md +103 -4
- 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/dist/scripts/doctor-pi-provider.js +139 -47
- package/mcp/entwurf-bridge/dist/scripts/probe-bridge-command.js +294 -0
- package/mcp/entwurf-bridge/src/index.ts +10 -6
- package/mcp/entwurf-bridge/tsconfig.build.json +17 -6
- package/package.json +23 -12
- 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/acp/backend.ts +229 -9
- 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 +389 -26
- package/scripts/agy-bridge-config.py +47 -13
- package/scripts/agy-bridge.sh +73 -23
- package/scripts/check-acp-prompt-lifecycle.ts +221 -9
- 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-bridge-boot.ts +28 -0
- package/scripts/check-entwurf-capabilities.ts +25 -6
- package/scripts/check-fresh-cut-gate.sh +92 -23
- package/scripts/check-gate-qualification.ts +10 -3
- 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/check-probe-bridge-command.ts +201 -0
- package/scripts/check-release-gate-outcomes.ts +54 -1
- 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/doctor-pi-provider.ts +155 -51
- package/scripts/meta-bridge-hook-log.sh +17 -5
- package/scripts/mutants/acp-prompt-lifecycle.json +25 -3
- package/scripts/mutants/bridge-command-boot.json +107 -0
- 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/mutants/release-gate.json +13 -0
- package/scripts/probe-bridge-command.ts +330 -0
- package/scripts/raw-async-delivery/README.md +203 -1
- 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/raw-async-delivery/copilot-ui-server-probe.mjs +337 -0
- package/scripts/smoke-acp-raw-turn-live.ts +1 -1
- package/scripts/smoke-agy-install-state.sh +76 -2
- package/scripts/smoke-copilot-mcp-state.sh +153 -0
- package/scripts/smoke-copilot-statusline-state.sh +131 -0
- package/scripts/smoke-entwurf-chain-live.ts +1 -1
- package/scripts/smoke-entwurf-v2-matrix-live.ts +2 -2
- package/scripts/smoke-mux-fresh-call-live.ts +3 -1
- package/scripts/smoke-mux-lifecycle-live.ts +4 -2
- package/scripts/smoke-pi-provider-state.sh +135 -6
- package/scripts/smoke-resident-garden-guard.sh +2 -2
- package/scripts/tsconfig.json +1 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"lane": "bridge-command-boot",
|
|
4
|
+
"mutants": [
|
|
5
|
+
{
|
|
6
|
+
"claim": "PI-DOCTOR-BOOT-NEGATIVE",
|
|
7
|
+
"title": "the pi doctor goes back to blessing a command that merely RESOLVES — the exact #81 false success, where a host ran ACP turns with no mcp__entwurf-bridge__* tool while the doctor printed ok",
|
|
8
|
+
"subject": "scripts/doctor-pi-provider.ts",
|
|
9
|
+
"find": ["\t\tif (probe.ok) {"],
|
|
10
|
+
"replace": ["\t\tif (probe.ok || true) {"],
|
|
11
|
+
"gate": ["bash", "scripts/smoke-pi-provider-state.sh"],
|
|
12
|
+
"timeoutSeconds": 120,
|
|
13
|
+
"signature": "[QK:PI-DOCTOR-BOOT-NEGATIVE]",
|
|
14
|
+
"signatureSource": "scripts/smoke-pi-provider-state.sh"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"claim": "AGY-DOCTOR-BOOT-NEGATIVE",
|
|
18
|
+
"title": "the agy doctor stops asking whether the configured command boots and reports the old '(resolvable)' green — a registered bridge agy could never actually call",
|
|
19
|
+
"subject": "scripts/agy-bridge.sh",
|
|
20
|
+
"find": [" if command_boots \"$invocation\"; then"],
|
|
21
|
+
"replace": [" if true; then"],
|
|
22
|
+
"gate": ["bash", "scripts/smoke-agy-install-state.sh"],
|
|
23
|
+
"timeoutSeconds": 300,
|
|
24
|
+
"signature": "[QK:AGY-DOCTOR-BOOT-NEGATIVE]",
|
|
25
|
+
"signatureSource": "scripts/smoke-agy-install-state.sh"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"claim": "PI-DOCTOR-PROBES-OVERRIDE",
|
|
29
|
+
"title": "the pi doctor skips runtime probing for a non-bare override, so a dead command that shadows the stable bridge returns green as an operator choice",
|
|
30
|
+
"subject": "scripts/doctor-pi-provider.ts",
|
|
31
|
+
"find": ["\tif (!resolvable(cmd)) {"],
|
|
32
|
+
"replace": [
|
|
33
|
+
"\tif (!isBare) {\n\t\tlog(` note: skipped runtime for override '${cmd}'`);\n\t} else if (!resolvable(cmd)) {"
|
|
34
|
+
],
|
|
35
|
+
"gate": ["bash", "scripts/smoke-pi-provider-state.sh"],
|
|
36
|
+
"timeoutSeconds": 120,
|
|
37
|
+
"signature": "[QK:PI-DOCTOR-PROBES-OVERRIDE]",
|
|
38
|
+
"signatureSource": "scripts/smoke-pi-provider-state.sh"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"claim": "AGY-DOCTOR-PROBES-ARGS",
|
|
42
|
+
"title": "the agy invocation parser drops configured args, so the doctor boots command defaults while agy executes a failing argv",
|
|
43
|
+
"subject": "scripts/agy-bridge-config.py",
|
|
44
|
+
"find": [" args = server.get(\"args\", [])"],
|
|
45
|
+
"replace": [" args = []"],
|
|
46
|
+
"gate": ["bash", "scripts/smoke-agy-install-state.sh"],
|
|
47
|
+
"timeoutSeconds": 300,
|
|
48
|
+
"signature": "[QK:AGY-DOCTOR-PROBES-ARGS]",
|
|
49
|
+
"signatureSource": "scripts/smoke-agy-install-state.sh"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"claim": "AGY-DOCTOR-PROBES-ENV",
|
|
53
|
+
"title": "the agy invocation parser drops configured environment, so the doctor boots command defaults while agy executes a failing environment",
|
|
54
|
+
"subject": "scripts/agy-bridge-config.py",
|
|
55
|
+
"find": [" env = server.get(\"env\", {})"],
|
|
56
|
+
"replace": [" env = {}"],
|
|
57
|
+
"gate": ["bash", "scripts/smoke-agy-install-state.sh"],
|
|
58
|
+
"timeoutSeconds": 300,
|
|
59
|
+
"signature": "[QK:AGY-DOCTOR-PROBES-ENV]",
|
|
60
|
+
"signatureSource": "scripts/smoke-agy-install-state.sh"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"claim": "PROBE-REASON-MISSING-VERB",
|
|
64
|
+
"title": "bridge identity shrinks back to a single tool, so a build missing entwurf_self — the measured #81 session shape — reads as a healthy bridge again",
|
|
65
|
+
"subject": "scripts/probe-bridge-command.ts",
|
|
66
|
+
"find": ["\t\t\t\tconst missing = EXPECTED_TOOLS.filter((t) => !served.has(t));"],
|
|
67
|
+
"replace": ["\t\t\t\tconst missing = [\"entwurf_v2\"].filter((t) => !served.has(t));"],
|
|
68
|
+
"gate": ["bash", "run.sh", "check-probe-bridge-command"],
|
|
69
|
+
"timeoutSeconds": 60,
|
|
70
|
+
"signature": "[QK:PROBE-REASON-MISSING-VERB]",
|
|
71
|
+
"signatureSource": "scripts/check-probe-bridge-command.ts"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"claim": "PROBE-REQUIRES-INITIALIZE",
|
|
75
|
+
"title": "the probe accepts tools/list before the MCP initialize handshake completes — a launcher the harness cannot initialize reads healthy",
|
|
76
|
+
"subject": "scripts/probe-bridge-command.ts",
|
|
77
|
+
"find": ["\t\t\t\tif (!initialized) {"],
|
|
78
|
+
"replace": ["\t\t\t\tif (false) {"],
|
|
79
|
+
"gate": ["bash", "run.sh", "check-probe-bridge-command"],
|
|
80
|
+
"timeoutSeconds": 60,
|
|
81
|
+
"signature": "[QK:PROBE-REQUIRES-INITIALIZE]",
|
|
82
|
+
"signatureSource": "scripts/check-probe-bridge-command.ts"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"claim": "PROBE-CLEANUP-ESCALATES",
|
|
86
|
+
"title": "the probe stops escalating past SIGTERM, so a launcher that traps TERM outlives the doctor that spawned it — the probe leaks the broken process it exists to detect",
|
|
87
|
+
"subject": "scripts/probe-bridge-command.ts",
|
|
88
|
+
"find": ["\t\t\t\t\t\tchild.kill(\"SIGKILL\");"],
|
|
89
|
+
"replace": ["\t\t\t\t\t\tvoid 0;"],
|
|
90
|
+
"gate": ["bash", "run.sh", "check-probe-bridge-command"],
|
|
91
|
+
"timeoutSeconds": 60,
|
|
92
|
+
"signature": "[QK:PROBE-CLEANUP-ESCALATES]",
|
|
93
|
+
"signatureSource": "scripts/check-probe-bridge-command.ts"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"claim": "PROBE-STDIN-EPIPE-GUARD",
|
|
97
|
+
"title": "the async EPIPE from a launcher that died on exec goes unlistened again, so the probe dies on an uncaught stream error and the doctor prints a Node stack trace where the LAUNCHER's own stderr belongs — the #81 diagnosis erased in the one cell that needs it",
|
|
98
|
+
"subject": "scripts/probe-bridge-command.ts",
|
|
99
|
+
"find": ["\t\tchild.stdin.on(\"error\", () => {});"],
|
|
100
|
+
"replace": ["\t\tvoid 0;"],
|
|
101
|
+
"gate": ["bash", "run.sh", "check-probe-bridge-command"],
|
|
102
|
+
"timeoutSeconds": 60,
|
|
103
|
+
"signature": "[QK:PROBE-STDIN-EPIPE-GUARD]",
|
|
104
|
+
"signatureSource": "scripts/check-probe-bridge-command.ts"
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"lane": "capability-cache",
|
|
4
|
+
"mutants": [
|
|
5
|
+
{
|
|
6
|
+
"claim": "CAPABILITY-REGISTRY-REREAD-SEES-REPLACEMENT",
|
|
7
|
+
"title": "memoizing the capability registry into a process-lifetime singleton makes every already-running dispatcher answer out of the registry it booted with — an install that moves a grade or wakeMode is invisible until the operator restarts, and nothing says so",
|
|
8
|
+
"subject": "pi-extensions/lib/meta-session.ts",
|
|
9
|
+
"find": [
|
|
10
|
+
"export function loadMetaCapabilityRegistry(): MetaCapabilityRegistry {",
|
|
11
|
+
"\treturn parseMetaCapabilityRegistry(fs.readFileSync(metaCapabilitiesFilePath(), \"utf8\"));",
|
|
12
|
+
"}"
|
|
13
|
+
],
|
|
14
|
+
"replace": [
|
|
15
|
+
"let cachedMetaCapabilities: MetaCapabilityRegistry | null = null;",
|
|
16
|
+
"export function loadMetaCapabilityRegistry(): MetaCapabilityRegistry {",
|
|
17
|
+
"\tif (cachedMetaCapabilities === null) {",
|
|
18
|
+
"\t\tcachedMetaCapabilities = parseMetaCapabilityRegistry(fs.readFileSync(metaCapabilitiesFilePath(), \"utf8\"));",
|
|
19
|
+
"\t}",
|
|
20
|
+
"\treturn cachedMetaCapabilities;",
|
|
21
|
+
"}"
|
|
22
|
+
],
|
|
23
|
+
"gate": ["bash", "run.sh", "check-meta-capability-source"],
|
|
24
|
+
"timeoutSeconds": 300,
|
|
25
|
+
"signature": "[QK:CAPABILITY-REGISTRY-REREAD-SEES-REPLACEMENT]",
|
|
26
|
+
"signatureSource": "scripts/check-meta-capability-source.ts"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"claim": "CAPABILITY-REGISTRY-MISSING-STILL-THROWS",
|
|
30
|
+
"title": "answering a missing registry with a built-in default turns a broken install into a citizen that silently claims capabilities nobody shipped",
|
|
31
|
+
"subject": "pi-extensions/lib/meta-session.ts",
|
|
32
|
+
"find": ["\treturn parseMetaCapabilityRegistry(fs.readFileSync(metaCapabilitiesFilePath(), \"utf8\"));"],
|
|
33
|
+
"replace": [
|
|
34
|
+
"\tconst registryPath = metaCapabilitiesFilePath();",
|
|
35
|
+
"\tif (!fs.existsSync(registryPath)) {",
|
|
36
|
+
"\t\treturn { schemaVersion: CAPABILITY_SCHEMA_VERSION, backends: {} } as unknown as MetaCapabilityRegistry;",
|
|
37
|
+
"\t}",
|
|
38
|
+
"\treturn parseMetaCapabilityRegistry(fs.readFileSync(registryPath, \"utf8\"));"
|
|
39
|
+
],
|
|
40
|
+
"gate": ["bash", "run.sh", "check-meta-capability-source"],
|
|
41
|
+
"timeoutSeconds": 300,
|
|
42
|
+
"signature": "[QK:CAPABILITY-REGISTRY-MISSING-STILL-THROWS]",
|
|
43
|
+
"signatureSource": "scripts/check-meta-capability-source.ts"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"claim": "CAPABILITY-REGISTRY-CORRUPT-STILL-THROWS",
|
|
47
|
+
"title": "swallowing a parse failure and returning a fallback lets a half-written or hand-edited registry read as a valid one, so the strict parser stops being load-bearing",
|
|
48
|
+
"subject": "pi-extensions/lib/meta-session.ts",
|
|
49
|
+
"find": ["\treturn parseMetaCapabilityRegistry(fs.readFileSync(metaCapabilitiesFilePath(), \"utf8\"));"],
|
|
50
|
+
"replace": [
|
|
51
|
+
"\tconst rawRegistry = fs.readFileSync(metaCapabilitiesFilePath(), \"utf8\");",
|
|
52
|
+
"\ttry {",
|
|
53
|
+
"\t\treturn parseMetaCapabilityRegistry(rawRegistry);",
|
|
54
|
+
"\t} catch {",
|
|
55
|
+
"\t\treturn { schemaVersion: CAPABILITY_SCHEMA_VERSION, backends: {} } as unknown as MetaCapabilityRegistry;",
|
|
56
|
+
"\t}"
|
|
57
|
+
],
|
|
58
|
+
"gate": ["bash", "run.sh", "check-meta-capability-source"],
|
|
59
|
+
"timeoutSeconds": 300,
|
|
60
|
+
"signature": "[QK:CAPABILITY-REGISTRY-CORRUPT-STILL-THROWS]",
|
|
61
|
+
"signatureSource": "scripts/check-meta-capability-source.ts"
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"lane": "copilot-birth",
|
|
4
|
+
"mutants": [
|
|
5
|
+
{
|
|
6
|
+
"claim": "COPILOT-BIRTH-NO-ARGV-LAUNCH",
|
|
7
|
+
"title": "reusing the Claude no-argv refusal in the Copilot launcher kills every Copilot birth (this is the exact defect that held copilot at 0 of 409 records)",
|
|
8
|
+
"subject": "pi/meta-bridge-copilot/entwurf-meta-receive-copilot/scripts/copilot-hook-launch.sh",
|
|
9
|
+
"find": ["exec \"$NODE_BIN\" \"$HOOK_ENTRY\""],
|
|
10
|
+
"replace": [
|
|
11
|
+
"if [ \"$#\" -eq 0 ]; then",
|
|
12
|
+
"\techo 'entwurf meta-bridge: this hook was launched with NO arguments.' >&2",
|
|
13
|
+
"\texit 1",
|
|
14
|
+
"fi",
|
|
15
|
+
"exec \"$NODE_BIN\" \"$HOOK_ENTRY\""
|
|
16
|
+
],
|
|
17
|
+
"gate": ["bash", "run.sh", "check-copilot-birth-hook"],
|
|
18
|
+
"timeoutSeconds": 300,
|
|
19
|
+
"signature": "[QK:COPILOT-BIRTH-NO-ARGV-LAUNCH]",
|
|
20
|
+
"signatureSource": "scripts/check-copilot-birth-hook.ts"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"claim": "COPILOT-BIRTH-MINTS-COPILOT",
|
|
24
|
+
"title": "minting a Copilot session under the claude-code backend gives it a citizenship it cannot own and hides the Copilot lane's own count",
|
|
25
|
+
"subject": "pi-extensions/meta-bridge-hook-copilot.ts",
|
|
26
|
+
"find": ["\t\t\tinput: { backend: \"copilot\", nativeSessionId: envelope.sessionId, cwd: envelope.cwd },"],
|
|
27
|
+
"replace": ["\t\t\tinput: { backend: \"claude-code\", nativeSessionId: envelope.sessionId, cwd: envelope.cwd },"],
|
|
28
|
+
"gate": ["bash", "run.sh", "check-copilot-birth-hook"],
|
|
29
|
+
"timeoutSeconds": 300,
|
|
30
|
+
"signature": "[QK:COPILOT-BIRTH-MINTS-COPILOT]",
|
|
31
|
+
"signatureSource": "scripts/check-copilot-birth-hook.ts"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"claim": "COPILOT-BIRTH-ID-DISAGREEMENT",
|
|
35
|
+
"title": "preferring one id when the two envelope keys disagree mints a citizen no live session can be joined back to",
|
|
36
|
+
"subject": "pi-extensions/meta-bridge-hook-copilot.ts",
|
|
37
|
+
"find": [
|
|
38
|
+
"\tif (native && compat && native !== compat) {",
|
|
39
|
+
"\t\treturn { refusal: `sessionId and session_id disagree (${native} vs ${compat})` };",
|
|
40
|
+
"\t}"
|
|
41
|
+
],
|
|
42
|
+
"replace": ["\t// disagreement tolerated: the native key simply wins"],
|
|
43
|
+
"gate": ["bash", "run.sh", "check-copilot-birth-hook"],
|
|
44
|
+
"timeoutSeconds": 300,
|
|
45
|
+
"signature": "[QK:COPILOT-BIRTH-ID-DISAGREEMENT]",
|
|
46
|
+
"signatureSource": "scripts/check-copilot-birth-hook.ts"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"claim": "COPILOT-BIRTH-EXEC-IS-STRING",
|
|
50
|
+
"title": "declaring the Copilot hook in Claude's array form is rejected at plugin load, before any prompt — the plugin never runs at all",
|
|
51
|
+
"subject": "pi/meta-bridge-copilot/entwurf-meta-receive-copilot/hooks/hooks.json",
|
|
52
|
+
"find": ["\t\t\"sessionStart\": [{ \"exec\": \"__COPILOT_LAUNCHER__\" }],"],
|
|
53
|
+
"replace": ["\t\t\"sessionStart\": [{ \"exec\": [\"__COPILOT_LAUNCHER__\"] }],"],
|
|
54
|
+
"gate": ["bash", "run.sh", "check-copilot-birth-hook"],
|
|
55
|
+
"timeoutSeconds": 300,
|
|
56
|
+
"signature": "[QK:COPILOT-BIRTH-EXEC-IS-STRING]",
|
|
57
|
+
"signatureSource": "scripts/check-copilot-birth-hook.ts"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"claim": "CAPABILITY-DRIFT-SCOPE-FROM-CONST",
|
|
61
|
+
"title": "a literal lane list in the capability drift guard lets any new backend's descriptor ship without ever being compared — the hole #82 found and closed",
|
|
62
|
+
"subject": "scripts/check-entwurf-capabilities.ts",
|
|
63
|
+
"find": ["const driftScope: readonly MetaBackend[] = META_BACKENDS;"],
|
|
64
|
+
"replace": ["const driftScope: readonly MetaBackend[] = [\"claude-code\", \"antigravity\", \"codex\"];"],
|
|
65
|
+
"gate": ["bash", "run.sh", "check-entwurf-capabilities"],
|
|
66
|
+
"timeoutSeconds": 300,
|
|
67
|
+
"signature": "[QK:CAPABILITY-DRIFT-SCOPE-FROM-CONST]",
|
|
68
|
+
"signatureSource": "scripts/check-entwurf-capabilities.ts"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"claim": "COPILOT-INSTALL-QUALIFIED-STALE",
|
|
72
|
+
"title": "a BARE stale-unit name reaches a same-named plugin from somebody else's marketplace and uninstalls it",
|
|
73
|
+
"subject": "scripts/copilot-bridge-install.sh",
|
|
74
|
+
"find": ["STALE_CLAUDE_UNIT=\"entwurf-meta-receive@meta-bridge-local\""],
|
|
75
|
+
"replace": ["STALE_CLAUDE_UNIT=\"entwurf-meta-receive\""],
|
|
76
|
+
"gate": ["bash", "run.sh", "check-copilot-birth-hook"],
|
|
77
|
+
"timeoutSeconds": 300,
|
|
78
|
+
"signature": "[QK:COPILOT-INSTALL-QUALIFIED-STALE]",
|
|
79
|
+
"signatureSource": "scripts/check-copilot-birth-hook.ts"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"claim": "COPILOT-INSTALL-UNINSTALL-FAILURE-IS-FATAL",
|
|
83
|
+
"title": "swallowing a failed stale-unit uninstall installs on top of a unit that is still firing and reports success",
|
|
84
|
+
"subject": "scripts/copilot-bridge-install.sh",
|
|
85
|
+
"find": [
|
|
86
|
+
" copilot plugin uninstall \"$STALE_CLAUDE_UNIT\" >/dev/null \\",
|
|
87
|
+
" || die \"the stale Claude unit '$STALE_CLAUDE_UNIT' is installed in Copilot but could not be removed. It fires on every prompt and exits 1 before node starts, so installing on top of it would leave that noise in place. Fix the Copilot CLI error above, or re-run with --keep-stale-claude-unit to proceed deliberately.\""
|
|
88
|
+
],
|
|
89
|
+
"replace": [" copilot plugin uninstall \"$STALE_CLAUDE_UNIT\" >/dev/null 2>&1 || true"],
|
|
90
|
+
"gate": ["bash", "run.sh", "check-copilot-birth-hook"],
|
|
91
|
+
"timeoutSeconds": 300,
|
|
92
|
+
"signature": "[QK:COPILOT-INSTALL-UNINSTALL-FAILURE-IS-FATAL]",
|
|
93
|
+
"signatureSource": "scripts/check-copilot-birth-hook.ts"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"claim": "HOOK-LOG-RAIL-SCOPED",
|
|
97
|
+
"title": "an untagged ERROR grep lets a Copilot fail-closed refusal redden the CLAUDE doctor forever — copilot's recovery token cannot exist on that rail",
|
|
98
|
+
"subject": "scripts/meta-bridge-hook-log.sh",
|
|
99
|
+
"find": [" own=\"$(grep -v ' \\[copilot\\] ' \"$log\" 2>/dev/null || true)\""],
|
|
100
|
+
"replace": [" own=\"$(cat \"$log\" 2>/dev/null || true)\""],
|
|
101
|
+
"gate": ["bash", "run.sh", "check-meta-doctor-oracle"],
|
|
102
|
+
"timeoutSeconds": 600,
|
|
103
|
+
"signature": "[QK:HOOK-LOG-RAIL-SCOPED]",
|
|
104
|
+
"signatureSource": "scripts/check-meta-doctor-oracle.sh"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"claim": "COPILOT-BIRTH-DOES-NOT-ARM-RECEIVER",
|
|
108
|
+
"title": "arming a mailbox from the BIRTH hook claims a watch this process does not hold. Copilot now has a doorbell (#82 RAIL 5), which is exactly why the writer matters: the extension owns the watch, so a marker minted here would name the host pid as a watcher and keep a wired-to-nothing citizen deliverable for as long as the TUI stayed open",
|
|
109
|
+
"subject": "pi-extensions/meta-bridge-hook-copilot.ts",
|
|
110
|
+
"find": ["\t\tlogLine(\n\t\t\t\"INFO\","],
|
|
111
|
+
"replace": [
|
|
112
|
+
"\t\tfs.mkdirSync(path.join(path.dirname(defaultMetaSessionsDir()), \"meta-mailbox\", result.record.gardenId), { recursive: true });\n\t\tlogLine(\n\t\t\t\"INFO\","
|
|
113
|
+
],
|
|
114
|
+
"gate": ["bash", "run.sh", "check-copilot-birth-hook"],
|
|
115
|
+
"timeoutSeconds": 300,
|
|
116
|
+
"signature": "[QK:COPILOT-BIRTH-DOES-NOT-ARM-RECEIVER]",
|
|
117
|
+
"signatureSource": "scripts/check-copilot-birth-hook.ts"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"claim": "COPILOT-BIRTH-WRITES-SENDER-MARKER",
|
|
121
|
+
"title": "dropping the sender-marker write leaves the reader open and the writer closed — the citizen calls entwurf_v2, the bridge holds its owner pid, finds no marker, and the send is refused as anonymous with nothing in any log naming the cause (the #46 defect, re-planted on the copilot rail)",
|
|
122
|
+
"subject": "pi-extensions/meta-bridge-hook-copilot.ts",
|
|
123
|
+
"find": ["\t\twriteCopilotSenderMarker(result.record.gardenId, envelope);"],
|
|
124
|
+
"replace": ["\t\t// sender marker skipped"],
|
|
125
|
+
"gate": ["bash", "run.sh", "check-copilot-birth-hook"],
|
|
126
|
+
"timeoutSeconds": 300,
|
|
127
|
+
"signature": "[QK:COPILOT-BIRTH-WRITES-SENDER-MARKER]",
|
|
128
|
+
"signatureSource": "scripts/check-copilot-birth-hook.ts"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"claim": "COPILOT-SENDER-READER-OPEN",
|
|
132
|
+
"title": "closing the reader half leaves the writer talking to nobody — the hook writes a copilot marker, the bridge never looks in that directory, and the citizen's sends are refused as anonymous (the #46 shape, which is why writer and reader open in one change)",
|
|
133
|
+
"subject": "pi-extensions/lib/meta-sender-identity.ts",
|
|
134
|
+
"find": [
|
|
135
|
+
"export const META_SENDER_BACKENDS: readonly MetaBackend[] = [\"claude-code\", \"antigravity\", \"copilot\"];"
|
|
136
|
+
],
|
|
137
|
+
"replace": ["export const META_SENDER_BACKENDS: readonly MetaBackend[] = [\"claude-code\", \"antigravity\"];"],
|
|
138
|
+
"gate": ["bash", "run.sh", "check-copilot-birth-hook"],
|
|
139
|
+
"timeoutSeconds": 300,
|
|
140
|
+
"signature": "[QK:COPILOT-SENDER-READER-OPEN]",
|
|
141
|
+
"signatureSource": "scripts/check-copilot-birth-hook.ts"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"claim": "COPILOT-INSTALL-LIST-FAILURE-IS-FATAL",
|
|
145
|
+
"title": "reading a failed `copilot plugin list` as an empty host installs on top of a stale unit that is still firing",
|
|
146
|
+
"subject": "scripts/copilot-bridge-install.sh",
|
|
147
|
+
"find": [" if ! INSTALLED_LIST=\"$(copilot plugin list 2>/dev/null)\"; then"],
|
|
148
|
+
"replace": [" INSTALLED_LIST=\"$(copilot plugin list 2>/dev/null || true)\"", " if false; then"],
|
|
149
|
+
"gate": ["bash", "run.sh", "check-copilot-birth-hook"],
|
|
150
|
+
"timeoutSeconds": 300,
|
|
151
|
+
"signature": "[QK:COPILOT-INSTALL-LIST-FAILURE-IS-FATAL]",
|
|
152
|
+
"signatureSource": "scripts/check-copilot-birth-hook.ts"
|
|
153
|
+
}
|
|
154
|
+
]
|
|
155
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"lane": "copilot-launch",
|
|
4
|
+
"mutants": [
|
|
5
|
+
{
|
|
6
|
+
"claim": "COPILOT-LAUNCH-REQUIRES-RECEIVER",
|
|
7
|
+
"title": "launching with the scan flag while no receiver unit is installed promises a doorbell nothing can ring — the session looks managed and is permanently undeliverable, with no error anywhere",
|
|
8
|
+
"subject": "scripts/copilot-launch.sh",
|
|
9
|
+
"find": [
|
|
10
|
+
"[ -f \"$STATE_FILE\" ] \\",
|
|
11
|
+
"\t|| fail \"no receiver install-state at $STATE_FILE.",
|
|
12
|
+
" '$VENDOR_CMD' launched with $FLAG_ENV=$FLAG_VALUE would scan for an extension that is",
|
|
13
|
+
" not there, and the session would never become deliverable. Run: $REPAIR\""
|
|
14
|
+
],
|
|
15
|
+
"replace": [
|
|
16
|
+
"if [ ! -f \"$STATE_FILE\" ]; then",
|
|
17
|
+
"\tmkdir -p \"$STATE_DIR\"",
|
|
18
|
+
"\tprintf '{\"schemaVersion\":1,\"unit\":\"%s\",\"path\":\"%s\"}\\n' \"$UNIT\" \"$DEST\" > \"$STATE_FILE\"",
|
|
19
|
+
"fi"
|
|
20
|
+
],
|
|
21
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
22
|
+
"timeoutSeconds": 300,
|
|
23
|
+
"signature": "[QK:COPILOT-LAUNCH-REQUIRES-RECEIVER]",
|
|
24
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"claim": "COPILOT-LAUNCH-REFUSES-PATH-MISMATCH",
|
|
28
|
+
"title": "accepting an install-state that names a different extensions root lets the CLI scan a directory nobody installed into, while every artifact check stays green",
|
|
29
|
+
"subject": "scripts/copilot-launch.sh",
|
|
30
|
+
"find": [
|
|
31
|
+
"[ \"$claimed_path\" = \"$DEST\" ] \\",
|
|
32
|
+
"\t|| fail \"receiver install-state points at '$claimed_path' but this environment scans '$DEST'.",
|
|
33
|
+
" The CLI would read a different extensions root than the one that was installed",
|
|
34
|
+
" (COPILOT_EXTENSIONS_DIR / HOME differ from install time). Run: $REPAIR\""
|
|
35
|
+
],
|
|
36
|
+
"replace": ["# whichever root the state names is close enough"],
|
|
37
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
38
|
+
"timeoutSeconds": 300,
|
|
39
|
+
"signature": "[QK:COPILOT-LAUNCH-REFUSES-PATH-MISMATCH]",
|
|
40
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"claim": "COPILOT-LAUNCH-SETS-EXTENSIONS-TOKEN",
|
|
44
|
+
"title": "not guaranteeing the EXTENSIONS token makes the managed launch identical to a plain one — Copilot skips the extension scan silently and the whole surface is decoration",
|
|
45
|
+
"subject": "scripts/copilot-launch.sh",
|
|
46
|
+
"find": ["[ \"$seen_extensions\" -eq 1 ] || flags_out=\"${flags_out:+$flags_out,}$FLAG_VALUE\""],
|
|
47
|
+
"replace": ["# assume the operator already set it"],
|
|
48
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
49
|
+
"timeoutSeconds": 300,
|
|
50
|
+
"signature": "[QK:COPILOT-LAUNCH-SETS-EXTENSIONS-TOKEN]",
|
|
51
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"claim": "COPILOT-LAUNCH-PRESERVES-OPERATOR-TOKENS",
|
|
55
|
+
"title": "overwriting the feature-flag variable instead of extending it silently disables every other vendor feature flag the operator had enabled",
|
|
56
|
+
"subject": "scripts/copilot-launch.sh",
|
|
57
|
+
"find": ["export \"$FLAG_ENV=$flags_out\""],
|
|
58
|
+
"replace": ["export \"$FLAG_ENV=$FLAG_VALUE\""],
|
|
59
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
60
|
+
"timeoutSeconds": 300,
|
|
61
|
+
"signature": "[QK:COPILOT-LAUNCH-PRESERVES-OPERATOR-TOKENS]",
|
|
62
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"claim": "COPILOT-LAUNCH-DEFAULTS-BEFORE-TERMINATOR",
|
|
66
|
+
"title": "appending the injected defaults after the argv terminator turns them from options into positional data the vendor reads as prompt text, so the managed profile silently stops applying",
|
|
67
|
+
"subject": "scripts/copilot-launch.sh",
|
|
68
|
+
"find": [
|
|
69
|
+
"final_args=()",
|
|
70
|
+
"for (( i = 0; i < scan_end; i++ )); do final_args+=(\"${args[$i]}\"); done",
|
|
71
|
+
"if [ \"${#injected[@]}\" -gt 0 ]; then final_args+=(\"${injected[@]}\"); fi",
|
|
72
|
+
"for (( i = scan_end; i < ${#args[@]}; i++ )); do final_args+=(\"${args[$i]}\"); done"
|
|
73
|
+
],
|
|
74
|
+
"replace": [
|
|
75
|
+
"final_args=(\"${args[@]}\")",
|
|
76
|
+
"if [ \"${#injected[@]}\" -gt 0 ]; then final_args+=(\"${injected[@]}\"); fi"
|
|
77
|
+
],
|
|
78
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
79
|
+
"timeoutSeconds": 300,
|
|
80
|
+
"signature": "[QK:COPILOT-LAUNCH-DEFAULTS-BEFORE-TERMINATOR]",
|
|
81
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"claim": "COPILOT-LAUNCH-NO-DEFAULT-OVER-EXPLICIT-POLICY",
|
|
85
|
+
"title": "treating only the broadening flags as explicit policy means an operator who NARROWS permissions (--allow-url, --deny-tool, --excluded-tools) still gets --yolo appended — the managed default silently widens exactly what they were restricting",
|
|
86
|
+
"subject": "scripts/copilot-launch.sh",
|
|
87
|
+
"find": ["\t--allow-url", "\t--deny-url", "\t--available-tools", "\t--excluded-tools"],
|
|
88
|
+
"replace": ["\t# narrowing flags are not policy"],
|
|
89
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
90
|
+
"timeoutSeconds": 300,
|
|
91
|
+
"signature": "[QK:COPILOT-LAUNCH-NO-DEFAULT-OVER-EXPLICIT-POLICY]",
|
|
92
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"claim": "COPILOT-LAUNCH-PREFIX-IS-NOT-POLICY",
|
|
96
|
+
"title": "matching policy flags by prefix instead of exactly makes --allow-all-mcp-server-instructions read as --allow-all, so a prompt-content flag suppresses the managed permission default",
|
|
97
|
+
"subject": "scripts/copilot-launch.sh",
|
|
98
|
+
"find": ["\t\tif [ \"$head\" = \"$ov\" ]; then"],
|
|
99
|
+
"replace": ["\t\tif case \"$head\" in \"$ov\"*) true ;; *) false ;; esac; then"],
|
|
100
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
101
|
+
"timeoutSeconds": 300,
|
|
102
|
+
"signature": "[QK:COPILOT-LAUNCH-PREFIX-IS-NOT-POLICY]",
|
|
103
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"claim": "COPILOT-LAUNCH-KEEPS-OPERATOR-MODEL",
|
|
107
|
+
"title": "injecting the default model regardless of what the operator asked for silently overrides an explicit --model",
|
|
108
|
+
"subject": "scripts/copilot-launch.sh",
|
|
109
|
+
"find": ["\t\thas_model=1"],
|
|
110
|
+
"replace": ["\t\thas_model=0"],
|
|
111
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
112
|
+
"timeoutSeconds": 300,
|
|
113
|
+
"signature": "[QK:COPILOT-LAUNCH-KEEPS-OPERATOR-MODEL]",
|
|
114
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"claim": "COPILOT-LAUNCH-EXECS-NOT-FORKS",
|
|
118
|
+
"title": "running the vendor as a child instead of exec'ing it leaves an entwurf shell sitting between the operator's terminal and the CLI, owning a pid and a signal path that belong to the vendor",
|
|
119
|
+
"subject": "scripts/copilot-launch.sh",
|
|
120
|
+
"find": ["exec \"$copilot_bin\" \"${final_args[@]}\""],
|
|
121
|
+
"replace": ["\"$copilot_bin\" \"${final_args[@]}\""],
|
|
122
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
123
|
+
"timeoutSeconds": 300,
|
|
124
|
+
"signature": "[QK:COPILOT-LAUNCH-EXECS-NOT-FORKS]",
|
|
125
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"claim": "COPILOT-LAUNCH-REFUSES-RECURSION",
|
|
129
|
+
"title": "dropping the sentinel lets a PATH entry that calls back into the managed launch spin forever; the operator sees a hung terminal, not an error",
|
|
130
|
+
"subject": "scripts/copilot-launch.sh",
|
|
131
|
+
"find": ["if [ -n \"${ENTWURF_COPILOT_LAUNCH_ACTIVE:-}\" ]; then"],
|
|
132
|
+
"replace": ["if false; then"],
|
|
133
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
134
|
+
"timeoutSeconds": 300,
|
|
135
|
+
"signature": "[QK:COPILOT-LAUNCH-REFUSES-RECURSION]",
|
|
136
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"claim": "COPILOT-LAUNCH-REFUSES-ABSENT-VENDOR",
|
|
140
|
+
"title": "not checking that the vendor resolved turns a missing CLI into an opaque exec failure instead of the one sentence that says what is missing",
|
|
141
|
+
"subject": "scripts/copilot-launch.sh",
|
|
142
|
+
"find": [
|
|
143
|
+
"[ -n \"$copilot_bin\" ] \\",
|
|
144
|
+
"\t|| fail \"no '$VENDOR_CMD' executable found on PATH.",
|
|
145
|
+
" The managed launch runs the GitHub Copilot CLI; install it, or put it on PATH.\""
|
|
146
|
+
],
|
|
147
|
+
"replace": ["# an empty resolution will surface itself at exec time"],
|
|
148
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
149
|
+
"timeoutSeconds": 300,
|
|
150
|
+
"signature": "[QK:COPILOT-LAUNCH-REFUSES-ABSENT-VENDOR]",
|
|
151
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"claim": "COPILOT-LAUNCH-KEEPS-CALLER-CWD",
|
|
155
|
+
"title": "dispatching the managed launch through the repo-scoped subshell every neighbouring verb uses would start the vendor in the entwurf checkout instead of the operator's own directory",
|
|
156
|
+
"subject": "run.sh",
|
|
157
|
+
"find": [" shift || true", " exec bash \"$REPO_DIR/scripts/copilot-launch.sh\" \"$@\""],
|
|
158
|
+
"replace": [" shift || true", " (cd \"$REPO_DIR\" && bash scripts/copilot-launch.sh \"$@\")"],
|
|
159
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
160
|
+
"timeoutSeconds": 300,
|
|
161
|
+
"signature": "[QK:COPILOT-LAUNCH-KEEPS-CALLER-CWD]",
|
|
162
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"claim": "COPILOT-LAUNCH-STRIPS-PI-IDENTITY",
|
|
166
|
+
"title": "the managed launch forwards inherited PI_SESSION_ID/PI_AGENT_ID — the Copilot session and every child it spawns then speak under the PARENT pi citizen's garden id, with a perfectly correct native marker sitting unused beside it",
|
|
167
|
+
"subject": "scripts/copilot-launch.sh",
|
|
168
|
+
"find": ["unset PI_SESSION_ID PI_AGENT_ID\n"],
|
|
169
|
+
"replace": [""],
|
|
170
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
171
|
+
"timeoutSeconds": 300,
|
|
172
|
+
"signature": "[QK:COPILOT-LAUNCH-STRIPS-PI-IDENTITY]",
|
|
173
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"claim": "COPILOT-LAUNCH-STRIPS-BOTH-CARRIERS",
|
|
177
|
+
"title": "only one half of the identity pair is cleared — the failure merely changes wording while a carrier stays behind for the next partial reader to believe",
|
|
178
|
+
"subject": "scripts/copilot-launch.sh",
|
|
179
|
+
"find": ["unset PI_SESSION_ID PI_AGENT_ID"],
|
|
180
|
+
"replace": ["unset PI_SESSION_ID"],
|
|
181
|
+
"gate": ["bash", "run.sh", "check-copilot-launch"],
|
|
182
|
+
"timeoutSeconds": 300,
|
|
183
|
+
"signature": "[QK:COPILOT-LAUNCH-STRIPS-BOTH-CARRIERS]",
|
|
184
|
+
"signatureSource": "scripts/check-copilot-launch.ts"
|
|
185
|
+
}
|
|
186
|
+
]
|
|
187
|
+
}
|