@junghanacs/entwurf 0.41.1 → 0.41.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/BASELINE.md +7 -5
- package/CHANGELOG.md +185 -0
- package/DELIVERY.md +37 -20
- package/README.md +70 -65
- package/VERIFY.md +9 -9
- package/docs/external-mcp-host.md +1 -1
- package/docs/setup-clean-host.md +59 -33
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +14 -11
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +10 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +23 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-decider.js +7 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +3 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-composition.js +21 -10
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +4 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +5 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +6 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/register.js +13 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/omp-fresh-preflight.js +2 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-fresh-preflight.js +1 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/remote-pair-receive.js +25 -17
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/remote-pair-send.js +94 -28
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-omp.js +57 -7
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +2 -2
- package/mcp/entwurf-bridge/dist/scripts/remote-pair-receive.js +12 -12
- package/mcp/entwurf-bridge/src/index.ts +14 -11
- package/native/win32-x64/entwurf_win.node +0 -0
- package/native/win32-x64/manifest.json +2 -2
- package/package.json +4 -4
- package/pi-extensions/lib/entwurf-self-address.ts +13 -0
- package/pi-extensions/lib/entwurf-v2-contract.ts +25 -2
- package/pi-extensions/lib/entwurf-v2-decider.ts +7 -0
- package/pi-extensions/lib/entwurf-v2-surface.ts +3 -0
- package/pi-extensions/lib/fresh-call-composition.ts +21 -10
- package/pi-extensions/lib/herdr-fresh-call.ts +4 -2
- package/pi-extensions/lib/meta-sender-identity.ts +4 -0
- package/pi-extensions/lib/mux-fresh-call.ts +6 -4
- package/pi-extensions/lib/native-push/register.ts +17 -2
- package/pi-extensions/lib/omp-fresh-preflight.ts +2 -2
- package/pi-extensions/lib/pi-durable-fresh-preflight.ts +1 -1
- package/pi-extensions/lib/remote-pair-receive.ts +27 -19
- package/pi-extensions/lib/remote-pair-send.ts +117 -30
- package/pi-extensions/meta-bridge-omp.ts +69 -7
- package/pi-extensions/meta-bridge-pi-durable.ts +2 -2
- package/run.sh +173 -22
- package/scripts/check-agy-sender-identity.ts +6 -4
- package/scripts/check-entwurf-self-address.ts +34 -3
- package/scripts/check-entwurf-v2-contract.ts +24 -2
- package/scripts/check-entwurf-v2-production.ts +45 -31
- package/scripts/check-gate-qualification.ts +10 -8
- package/scripts/check-native-push-adapter.ts +4 -0
- package/scripts/check-native-push-register.ts +32 -82
- package/scripts/check-remote-pair-installed.ts +2 -2
- package/scripts/dev-bin.sh +112 -1
- package/scripts/lib/chain-terminus-publication.ts +58 -0
- package/scripts/lib/codex-fresh-live-protocol.ts +30 -0
- package/scripts/lib/codex-fresh-source-receipts.ts +112 -3
- package/scripts/lib/pi-durable-fresh-live-receipts.ts +29 -1
- package/scripts/mutants/chain-terminus-publication.json +17 -0
- package/scripts/mutants/codex-native.json +98 -0
- package/scripts/mutants/control-send-receipt.json +2 -2
- package/scripts/mutants/mux-fresh-call.json +16 -1
- package/scripts/mutants/native-push-paused.json +17 -0
- package/scripts/mutants/omp-fresh.json +13 -2
- package/scripts/mutants/pack-install.json +46 -0
- package/scripts/mutants/remote-pair-display.json +3 -3
- package/scripts/mutants/remote-pair-receive.json +41 -11
- package/scripts/mutants/remote-pair-roundtrip.json +67 -7
- package/scripts/mutants/remote-pair-send.json +156 -17
- package/scripts/mutants/remote-pair-transport.json +4 -4
- package/scripts/mutants/source-install.json +66 -0
- package/scripts/remote-pair-receive.ts +12 -12
- package/scripts/smoke-agy-install-state.sh +121 -0
- package/scripts/smoke-agy-native-push-live.ts +13 -0
- package/scripts/smoke-codex-fresh-live.ts +50 -27
- package/scripts/smoke-entwurf-chain-live.ts +7 -9
- package/scripts/smoke-herdr-fresh-call-live.ts +4 -4
- package/scripts/smoke-herdr-plugin-build-live.ts +179 -50
- package/scripts/smoke-mux-lifecycle-live.ts +140 -8
- package/scripts/smoke-omp-fresh-live.ts +5 -4
- package/scripts/smoke-pi-durable-fresh-live.ts +29 -7
- package/scripts/smoke-setup-verdict.sh +27 -2
|
@@ -9,6 +9,11 @@ export interface SourceToolReceipt {
|
|
|
9
9
|
text: string;
|
|
10
10
|
status: SourceToolStatus;
|
|
11
11
|
isError: boolean;
|
|
12
|
+
/** Pi only: the transcript row index of this call's assistant message. Rows are appended in
|
|
13
|
+
* order, so this is a source fact about WHEN the call was recorded. Codex leaves it unset. */
|
|
14
|
+
callOrdinal?: number;
|
|
15
|
+
/** Pi only: the transcript row index of this call's toolResult. Unset while pending and on Codex. */
|
|
16
|
+
resultOrdinal?: number;
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
export interface ExpectedSourceToolCall {
|
|
@@ -104,6 +109,107 @@ export function assertExactSourceToolCalls(
|
|
|
104
109
|
if (remaining.length > 0) throw new Error(`${label}: missing source calls ${JSON.stringify(remaining)}`);
|
|
105
110
|
}
|
|
106
111
|
|
|
112
|
+
/** The callback a fresh sibling makes before its task, and the one read-only check it may make first. */
|
|
113
|
+
export interface BootstrapOrderExpectation {
|
|
114
|
+
/** Exact arguments of the read-only `entwurf_peers` check the framing offers before the callback. */
|
|
115
|
+
peersArguments: Record<string, unknown>;
|
|
116
|
+
/** The callback role: zero-argument `entwurf_callback`, or Codex's `entwurf_v2` to the caller. */
|
|
117
|
+
callback: ExpectedSourceToolCall;
|
|
118
|
+
/** A GUIDED launch that asked for the check requires at least this many peers checks. Absent = 0:
|
|
119
|
+
* the check is optional everywhere else, and a fixture's guided task is not a product rule. */
|
|
120
|
+
minPeersPrefix?: number;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Bootstrap arguments: `entwurf_v2` keeps its schema default (absent `wants_reply` IS false — see
|
|
125
|
+
* `normalizeSourceArguments`), because Codex's callback IS that verb and a model that omits the key
|
|
126
|
+
* has obeyed it. Every other verb compared here is byte-exact: `entwurf_callback` is ZERO-argument,
|
|
127
|
+
* so `{ wants_reply: false }` is a model supplying a parameter the verb does not have, and the peers
|
|
128
|
+
* check is held to the exact call the framing offers.
|
|
129
|
+
*/
|
|
130
|
+
function bootstrapArgumentsMatch(toolName: string, expected: Record<string, unknown>, actual: Record<string, unknown>) {
|
|
131
|
+
return toolName === "entwurf_v2" ? sourceArgumentsMatch(expected, actual) : isDeepStrictEqual(expected, actual);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The bootstrap order of one fresh sibling, judged on its source receipts IN CALL ORDER:
|
|
136
|
+
* zero or more successful exact `entwurf_peers` checks, then exactly one successful exact callback,
|
|
137
|
+
* then the rest — which is returned for the existing exact-once role audit. `[GLG 직접, 2026-10-24]`
|
|
138
|
+
* checking the caller and then calling back is the right order; nothing else may come first.
|
|
139
|
+
*
|
|
140
|
+
* Refused: any other call before the callback (a `bash true`, a task role), a peers check with other
|
|
141
|
+
* arguments or that did not succeed, a missing / pending / failed callback, a callback with drifted
|
|
142
|
+
* arguments, a peers check or a second exact callback AFTER the callback, and — where the source
|
|
143
|
+
* records it — a callback CALLED before a peers check's RESULT was recorded, or a later call recorded
|
|
144
|
+
* before the callback's RESULT.
|
|
145
|
+
*
|
|
146
|
+
* WHAT THE ORDER PROVES DEPENDS ON THE SOURCE. Pi rows carry `callOrdinal`/`resultOrdinal`, so on Pi
|
|
147
|
+
* this proves every peers result was recorded before the callback was called, and the callback's
|
|
148
|
+
* result before every later call. Codex `thread/read` gives item order and a status read at audit
|
|
149
|
+
* time, nothing more, so on Codex this proves CALL ORDER and completion-at-audit only; that a peers
|
|
150
|
+
* result preceded the callback call, and that the callback result preceded the next call, are both
|
|
151
|
+
* UNVERIFIED there.
|
|
152
|
+
* The peers check is never filtered out by position: it is admitted only as a prefix.
|
|
153
|
+
*
|
|
154
|
+
* SCOPE. This is the audit's condition for the short fixture tasks that call it ("use no other tool
|
|
155
|
+
* before the callback"), not a universal list of what a fresh sibling may do; a sibling whose own
|
|
156
|
+
* check does not hold up may also hold the callback, which these fixtures then see as no callback.
|
|
157
|
+
*/
|
|
158
|
+
export function assertBootstrapOrder(
|
|
159
|
+
receipts: readonly SourceToolReceipt[],
|
|
160
|
+
expected: BootstrapOrderExpectation,
|
|
161
|
+
label: string,
|
|
162
|
+
): SourceToolReceipt[] {
|
|
163
|
+
let at = 0;
|
|
164
|
+
for (; at < receipts.length && receipts[at]?.toolName === "entwurf_peers"; at++) {
|
|
165
|
+
const check = receipts[at] as SourceToolReceipt;
|
|
166
|
+
if (!isDeepStrictEqual(check.arguments, expected.peersArguments))
|
|
167
|
+
throw new Error(
|
|
168
|
+
`${label}: pre-callback entwurf_peers arguments differ\nexpected=${JSON.stringify(expected.peersArguments)}\nactual=${JSON.stringify(check.arguments)}`,
|
|
169
|
+
);
|
|
170
|
+
if (check.status !== "completed" || check.isError)
|
|
171
|
+
throw new Error(`${label}: pre-callback entwurf_peers ${check.isError ? "failed" : check.status}`);
|
|
172
|
+
}
|
|
173
|
+
const callback = receipts[at];
|
|
174
|
+
if (callback === undefined) throw new Error(`${label}: no callback after ${at} pre-callback check(s)`);
|
|
175
|
+
const minPeers = expected.minPeersPrefix ?? 0;
|
|
176
|
+
if (at < minPeers)
|
|
177
|
+
throw new Error(`${label}: the guided caller check was not made (peers prefix=${at}, required ≥ ${minPeers})`);
|
|
178
|
+
const role = expected.callback;
|
|
179
|
+
if (
|
|
180
|
+
callback.toolName !== role.toolName ||
|
|
181
|
+
!bootstrapArgumentsMatch(role.toolName, role.arguments, callback.arguments)
|
|
182
|
+
)
|
|
183
|
+
throw new Error(
|
|
184
|
+
`${label}: unexpected pre-callback call ${callback.toolName} ${JSON.stringify(callback.arguments)} — only the read-only entwurf_peers check may precede ${role.toolName} ${JSON.stringify(role.arguments)}`,
|
|
185
|
+
);
|
|
186
|
+
if (callback.status !== "completed" || callback.isError)
|
|
187
|
+
throw new Error(`${label}: the callback ${callback.isError ? "failed" : `remained ${callback.status}`}`);
|
|
188
|
+
// A check is a check only if its answer was in hand before the callback was made.
|
|
189
|
+
for (const check of receipts.slice(0, at)) {
|
|
190
|
+
if (
|
|
191
|
+
check.resultOrdinal !== undefined &&
|
|
192
|
+
callback.callOrdinal !== undefined &&
|
|
193
|
+
!(check.resultOrdinal < callback.callOrdinal)
|
|
194
|
+
)
|
|
195
|
+
throw new Error(`${label}: ${callback.toolName} was called before the entwurf_peers result was recorded`);
|
|
196
|
+
}
|
|
197
|
+
const rest = receipts.slice(at + 1);
|
|
198
|
+
for (const later of rest) {
|
|
199
|
+
if (later.toolName === "entwurf_peers")
|
|
200
|
+
throw new Error(`${label}: entwurf_peers after the callback — the check is offered only before it`);
|
|
201
|
+
if (later.toolName === role.toolName && bootstrapArgumentsMatch(role.toolName, role.arguments, later.arguments))
|
|
202
|
+
throw new Error(`${label}: duplicate callback ${later.toolName}`);
|
|
203
|
+
if (
|
|
204
|
+
callback.resultOrdinal !== undefined &&
|
|
205
|
+
later.callOrdinal !== undefined &&
|
|
206
|
+
later.callOrdinal < callback.resultOrdinal
|
|
207
|
+
)
|
|
208
|
+
throw new Error(`${label}: ${later.toolName} was called before the callback result was recorded`);
|
|
209
|
+
}
|
|
210
|
+
return rest;
|
|
211
|
+
}
|
|
212
|
+
|
|
107
213
|
/** The only production leaf that turns joined source receipts into cleanup window authority. */
|
|
108
214
|
export function sourceCleanupWindows(receipts: readonly SourceToolReceipt[]): string[] {
|
|
109
215
|
const windows: string[] = [];
|
|
@@ -199,9 +305,9 @@ function piSourceVerb(nativeName: string): string {
|
|
|
199
305
|
/** Join Pi's own toolCall and toolResult rows by native id, retaining pending calls.
|
|
200
306
|
* Native-name equality is checked before translating the exact current Pi dialect. */
|
|
201
307
|
export function piSourceToolReceipts(entries: readonly unknown[]): SourceToolReceipt[] {
|
|
202
|
-
const calls = new Map<string, { toolName: string; arguments: Record<string, unknown
|
|
203
|
-
const results = new Map<string, { toolName: string; text: string; isError: boolean }>();
|
|
204
|
-
for (const raw of entries) {
|
|
308
|
+
const calls = new Map<string, { toolName: string; arguments: Record<string, unknown>; callOrdinal: number }>();
|
|
309
|
+
const results = new Map<string, { toolName: string; text: string; isError: boolean; resultOrdinal: number }>();
|
|
310
|
+
for (const [ordinal, raw] of entries.entries()) {
|
|
205
311
|
if (typeof raw !== "object" || raw === null) continue;
|
|
206
312
|
const entry = raw as { type?: unknown; message?: unknown };
|
|
207
313
|
if (entry.type !== "message" || typeof entry.message !== "object" || entry.message === null) continue;
|
|
@@ -229,6 +335,7 @@ export function piSourceToolReceipts(entries: readonly unknown[]): SourceToolRec
|
|
|
229
335
|
calls.set(block.id, {
|
|
230
336
|
toolName: block.name,
|
|
231
337
|
arguments: block.arguments as Record<string, unknown>,
|
|
338
|
+
callOrdinal: ordinal,
|
|
232
339
|
});
|
|
233
340
|
}
|
|
234
341
|
}
|
|
@@ -242,6 +349,7 @@ export function piSourceToolReceipts(entries: readonly unknown[]): SourceToolRec
|
|
|
242
349
|
toolName: message.toolName,
|
|
243
350
|
text: textContent(message.content),
|
|
244
351
|
isError: message.isError,
|
|
352
|
+
resultOrdinal: ordinal,
|
|
245
353
|
});
|
|
246
354
|
}
|
|
247
355
|
}
|
|
@@ -263,6 +371,7 @@ export function piSourceToolReceipts(entries: readonly unknown[]): SourceToolRec
|
|
|
263
371
|
text: result.text,
|
|
264
372
|
status: result.isError ? "failed" : "completed",
|
|
265
373
|
isError: result.isError,
|
|
374
|
+
resultOrdinal: result.resultOrdinal,
|
|
266
375
|
});
|
|
267
376
|
}
|
|
268
377
|
return joined;
|
|
@@ -11,8 +11,12 @@
|
|
|
11
11
|
* its entry kinds — `pi.system` (tool offering, applied as toolsAdded/toolsRemoved in order),
|
|
12
12
|
* `pi.assistant` (the model that answered, and the tool calls in order) and `pi.tool-result` (each
|
|
13
13
|
* call's settled result, joined by toolCallId).
|
|
14
|
+
*
|
|
15
|
+
* Each call also carries the native ENTRY ids of its call and of its result (`callOrdinal` /
|
|
16
|
+
* `resultOrdinal`). Entries are read in id order, so the ids order what the store recorded — the same
|
|
17
|
+
* fact Pi's transcript row index gives the bootstrap-order leaf (`assertBootstrapOrder`).
|
|
14
18
|
*/
|
|
15
|
-
import { piCallbackSenders } from "./codex-fresh-source-receipts.ts";
|
|
19
|
+
import { piCallbackSenders, type SourceToolReceipt } from "./codex-fresh-source-receipts.ts";
|
|
16
20
|
|
|
17
21
|
/** The one Pi transcript row whose exact payload arrived from `expectedSender`, or null. */
|
|
18
22
|
export function piExactDeliveryRow(
|
|
@@ -43,6 +47,10 @@ export interface PdToolCall {
|
|
|
43
47
|
name: string;
|
|
44
48
|
arguments: Record<string, unknown>;
|
|
45
49
|
result: { text: string; isError: boolean } | null;
|
|
50
|
+
/** Native entry id of the assistant row that made this call. */
|
|
51
|
+
callOrdinal: number;
|
|
52
|
+
/** Native entry id of the tool-result row joined to it, or null while none is recorded. */
|
|
53
|
+
resultOrdinal: number | null;
|
|
46
54
|
}
|
|
47
55
|
export interface PdRootView {
|
|
48
56
|
offering: string[];
|
|
@@ -98,6 +106,8 @@ export function pdRootView(entries: readonly PdNativeRow[], rootConversationId:
|
|
|
98
106
|
name: b.name,
|
|
99
107
|
arguments: (b.arguments ?? {}) as Record<string, unknown>,
|
|
100
108
|
result: null,
|
|
109
|
+
callOrdinal: row.id,
|
|
110
|
+
resultOrdinal: null,
|
|
101
111
|
};
|
|
102
112
|
calls.push(call);
|
|
103
113
|
byId.set(b.id, call);
|
|
@@ -115,12 +125,30 @@ export function pdRootView(entries: readonly PdNativeRow[], rootConversationId:
|
|
|
115
125
|
)
|
|
116
126
|
.join("");
|
|
117
127
|
call.result = { text, isError: message.isError === true };
|
|
128
|
+
call.resultOrdinal = row.id;
|
|
118
129
|
}
|
|
119
130
|
}
|
|
120
131
|
}
|
|
121
132
|
return { offering, models: [...models], calls };
|
|
122
133
|
}
|
|
123
134
|
|
|
135
|
+
/**
|
|
136
|
+
* The root calls as source receipts, in call order, for the bootstrap-order leaf: a call with no joined
|
|
137
|
+
* result is PENDING, an errored result is FAILED. pd's verbs are its own bare tool names, so no
|
|
138
|
+
* dialect translation happens here.
|
|
139
|
+
*/
|
|
140
|
+
export function pdSourceToolReceipts(calls: readonly PdToolCall[]): SourceToolReceipt[] {
|
|
141
|
+
return calls.map((call) => ({
|
|
142
|
+
toolName: call.name,
|
|
143
|
+
arguments: call.arguments,
|
|
144
|
+
text: call.result?.text ?? "",
|
|
145
|
+
status: call.result === null ? "pending" : call.result.isError ? "failed" : "completed",
|
|
146
|
+
isError: call.result?.isError ?? false,
|
|
147
|
+
callOrdinal: call.callOrdinal,
|
|
148
|
+
...(call.resultOrdinal === null ? {} : { resultOrdinal: call.resultOrdinal }),
|
|
149
|
+
}));
|
|
150
|
+
}
|
|
151
|
+
|
|
124
152
|
/** The doorbell submission for exactly this mailbox message, on the root conversation. */
|
|
125
153
|
export function pdDoorbellSubmission(
|
|
126
154
|
submissions: readonly PdNativeSubmissionRow[],
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"lane": "chain-terminus-publication",
|
|
4
|
+
"mutants": [
|
|
5
|
+
{
|
|
6
|
+
"claim": "CHAIN-TERMINUS-WAITS-FOR-SIGNAL",
|
|
7
|
+
"title": "the terminus wait stops at the first body again, so smoke-entwurf-chain-live checks the doorbell while enqueueMetaMessage is still between its .msg write and its inbox.signal write and reports a false RED",
|
|
8
|
+
"subject": "scripts/lib/chain-terminus-publication.ts",
|
|
9
|
+
"find": ["\t\tif (msgs.length > 0 && signalled) break;"],
|
|
10
|
+
"replace": ["\t\tif (msgs.length > 0) break;"],
|
|
11
|
+
"gate": ["bash", "run.sh", "check-chain-terminus-publication"],
|
|
12
|
+
"timeoutSeconds": 120,
|
|
13
|
+
"signature": "[QK:CHAIN-TERMINUS-WAITS-FOR-SIGNAL]",
|
|
14
|
+
"signatureSource": "test/chain-terminus-publication.test.ts"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -1066,6 +1066,104 @@
|
|
|
1066
1066
|
"timeoutSeconds": 180,
|
|
1067
1067
|
"signature": "[QK:CODEX-SOCKET-LISTEN-ROW-ONLY]",
|
|
1068
1068
|
"signatureSource": "test/codex-socket-listener.test.ts"
|
|
1069
|
+
},
|
|
1070
|
+
{
|
|
1071
|
+
"claim": "BOOTSTRAP-PEERS-PREFIX-THEN-EXACT-CALLBACK",
|
|
1072
|
+
"title": "the bootstrap ORDER removed: everything before the first callback is skipped instead of only an exact peers check, so `bash true → callback → task` — the r3 RED — passes again, and a task call made before the callback is no longer refused",
|
|
1073
|
+
"subject": "scripts/lib/codex-fresh-source-receipts.ts",
|
|
1074
|
+
"find": ["\tfor (; at < receipts.length && receipts[at]?.toolName === \"entwurf_peers\"; at++) {"],
|
|
1075
|
+
"replace": [
|
|
1076
|
+
"\tfor (; at < receipts.length && receipts[at]?.toolName !== expected.callback.toolName; at++) {\n\t\tif (receipts[at]?.toolName !== \"entwurf_peers\") continue;"
|
|
1077
|
+
],
|
|
1078
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
1079
|
+
"timeoutSeconds": 180,
|
|
1080
|
+
"signature": "[QK:BOOTSTRAP-PEERS-PREFIX-THEN-EXACT-CALLBACK]",
|
|
1081
|
+
"signatureSource": "test/codex-fresh-live-protocol.test.ts"
|
|
1082
|
+
},
|
|
1083
|
+
{
|
|
1084
|
+
"claim": "BOOTSTRAP-PEERS-ONLY-AS-PREFIX",
|
|
1085
|
+
"title": "the peers check filtered out wherever it appears instead of admitted only as a prefix — a check after the callback disappears from the audit, which is the position-independent filter the contract forbids",
|
|
1086
|
+
"subject": "scripts/lib/codex-fresh-source-receipts.ts",
|
|
1087
|
+
"find": ["\tconst rest = receipts.slice(at + 1);"],
|
|
1088
|
+
"replace": ["\tconst rest = receipts.slice(at + 1).filter((r) => r.toolName !== \"entwurf_peers\");"],
|
|
1089
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
1090
|
+
"timeoutSeconds": 180,
|
|
1091
|
+
"signature": "[QK:BOOTSTRAP-PEERS-ONLY-AS-PREFIX]",
|
|
1092
|
+
"signatureSource": "test/codex-fresh-live-protocol.test.ts"
|
|
1093
|
+
},
|
|
1094
|
+
{
|
|
1095
|
+
"claim": "BOOTSTRAP-ZERO-ARG-CALLBACK-STRICT",
|
|
1096
|
+
"title": "the v2 wants_reply default stretched over the zero-argument callback: `entwurf_callback {wants_reply:false}` reads as `{}`, so a model supplying a parameter the verb does not have passes as the exact callback",
|
|
1097
|
+
"subject": "scripts/lib/codex-fresh-source-receipts.ts",
|
|
1098
|
+
"find": [
|
|
1099
|
+
"\treturn toolName === \"entwurf_v2\" ? sourceArgumentsMatch(expected, actual) : isDeepStrictEqual(expected, actual);"
|
|
1100
|
+
],
|
|
1101
|
+
"replace": ["\treturn sourceArgumentsMatch(expected, actual);"],
|
|
1102
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
1103
|
+
"timeoutSeconds": 180,
|
|
1104
|
+
"signature": "[QK:BOOTSTRAP-ZERO-ARG-CALLBACK-STRICT]",
|
|
1105
|
+
"signatureSource": "test/codex-fresh-live-protocol.test.ts"
|
|
1106
|
+
},
|
|
1107
|
+
{
|
|
1108
|
+
"claim": "BOOTSTRAP-CODEX-V2-CALLBACK-DEFAULT",
|
|
1109
|
+
"title": "deep-strict comparison forced onto Codex's entwurf_v2 callback too — a Codex callback that omits wants_reply (schema default false) is refused, resurrecting the 2026-09-16 default-false RED",
|
|
1110
|
+
"subject": "scripts/lib/codex-fresh-source-receipts.ts",
|
|
1111
|
+
"find": [
|
|
1112
|
+
"\treturn toolName === \"entwurf_v2\" ? sourceArgumentsMatch(expected, actual) : isDeepStrictEqual(expected, actual);"
|
|
1113
|
+
],
|
|
1114
|
+
"replace": ["\treturn isDeepStrictEqual(expected, actual);"],
|
|
1115
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
1116
|
+
"timeoutSeconds": 180,
|
|
1117
|
+
"signature": "[QK:BOOTSTRAP-CODEX-V2-CALLBACK-DEFAULT]",
|
|
1118
|
+
"signatureSource": "test/codex-fresh-live-protocol.test.ts"
|
|
1119
|
+
},
|
|
1120
|
+
{
|
|
1121
|
+
"claim": "BOOTSTRAP-PI-RESULT-BEFORE-TASK-CALL",
|
|
1122
|
+
"title": "the Pi result-ordinal check dropped: a task call made in the same assistant row as the callback — before the callback result existed — passes on call order alone",
|
|
1123
|
+
"subject": "scripts/lib/codex-fresh-source-receipts.ts",
|
|
1124
|
+
"find": ["\t\t\tcallback.resultOrdinal !== undefined &&"],
|
|
1125
|
+
"replace": ["\t\t\tfalse &&"],
|
|
1126
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
1127
|
+
"timeoutSeconds": 180,
|
|
1128
|
+
"signature": "[QK:BOOTSTRAP-PI-RESULT-BEFORE-TASK-CALL]",
|
|
1129
|
+
"signatureSource": "test/codex-fresh-live-protocol.test.ts"
|
|
1130
|
+
},
|
|
1131
|
+
{
|
|
1132
|
+
"claim": "CODEX-LIVE-INITIAL-PI-BOOTSTRAP-TASK",
|
|
1133
|
+
"title": "the initial Pi's task restored to the retired forced-first wording — `Your FIRST tool call must be … callback … and nothing before it` with a blanket identity-recheck ban — so the LIVE task forbids the read-only caller check the shared framing offers and the order audit admits",
|
|
1134
|
+
"subject": "scripts/lib/codex-fresh-live-protocol.ts",
|
|
1135
|
+
"find": [
|
|
1136
|
+
"\t\t\"This launch is a guided caller check: first call mcp__entwurf_bridge__entwurf_peers once (read-only, no \" +\n\t\t\"arguments) to corroborate your caller, and only after its result call mcp__entwurf_bridge__entwurf_callback \" +\n\t\t\"with no arguments. Use no other tool before the callback. \" +"
|
|
1137
|
+
],
|
|
1138
|
+
"replace": [
|
|
1139
|
+
"\t\t\"Do not recheck identity with other tools. Your FIRST tool call must be mcp__entwurf_bridge__entwurf_callback with no arguments, and nothing before it. \" +"
|
|
1140
|
+
],
|
|
1141
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
1142
|
+
"timeoutSeconds": 180,
|
|
1143
|
+
"signature": "[QK:CODEX-LIVE-INITIAL-PI-BOOTSTRAP-TASK]",
|
|
1144
|
+
"signatureSource": "test/codex-fresh-live-protocol.test.ts"
|
|
1145
|
+
},
|
|
1146
|
+
{
|
|
1147
|
+
"claim": "BOOTSTRAP-PI-PEERS-RESULT-BEFORE-CALLBACK",
|
|
1148
|
+
"title": "the peers-result-before-callback ordinal check dropped: a callback made in the same assistant row as the peers check — before its answer existed — passes as if the caller had been checked",
|
|
1149
|
+
"subject": "scripts/lib/codex-fresh-source-receipts.ts",
|
|
1150
|
+
"find": ["\t\t\tcheck.resultOrdinal !== undefined &&"],
|
|
1151
|
+
"replace": ["\t\t\tfalse &&"],
|
|
1152
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
1153
|
+
"timeoutSeconds": 180,
|
|
1154
|
+
"signature": "[QK:BOOTSTRAP-PI-PEERS-RESULT-BEFORE-CALLBACK]",
|
|
1155
|
+
"signatureSource": "test/codex-fresh-live-protocol.test.ts"
|
|
1156
|
+
},
|
|
1157
|
+
{
|
|
1158
|
+
"claim": "BOOTSTRAP-GUIDED-PEERS-REQUIRED",
|
|
1159
|
+
"title": "the guided launch's required check ignored: a guided initial Pi that called back without the peers check it was asked for passes, so a zero-check PASS is counted as the positive path",
|
|
1160
|
+
"subject": "scripts/lib/codex-fresh-source-receipts.ts",
|
|
1161
|
+
"find": ["\tif (at < minPeers)"],
|
|
1162
|
+
"replace": ["\tif (false && at < minPeers)"],
|
|
1163
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
1164
|
+
"timeoutSeconds": 180,
|
|
1165
|
+
"signature": "[QK:BOOTSTRAP-GUIDED-PEERS-REQUIRED]",
|
|
1166
|
+
"signatureSource": "test/codex-fresh-live-protocol.test.ts"
|
|
1069
1167
|
}
|
|
1070
1168
|
]
|
|
1071
1169
|
}
|
|
@@ -166,10 +166,10 @@
|
|
|
166
166
|
"title": "the pi queue oracle's public coordinate is dropped from `check:vitest`, so the file that proves every claim the receipt makes about a receiver's queues is green only when somebody runs `pnpm test` by hand — the discovery door deliberately does not select `test/**`, so nothing else would notice",
|
|
167
167
|
"subject": "package.json",
|
|
168
168
|
"find": [
|
|
169
|
-
"\"check:vitest\": \"./run.sh check-mux-fresh-call && ./run.sh check-acp-sdk-surface && ./run.sh check-pi-queue-oracle && ./run.sh check-tests-beside-behavior && ./run.sh check-remote-pair-installed-audit\""
|
|
169
|
+
"\"check:vitest\": \"./run.sh check-mux-fresh-call && ./run.sh check-acp-sdk-surface && ./run.sh check-pi-queue-oracle && ./run.sh check-tests-beside-behavior && ./run.sh check-remote-pair-installed-audit && ./run.sh check-chain-terminus-publication\""
|
|
170
170
|
],
|
|
171
171
|
"replace": [
|
|
172
|
-
"\"check:vitest\": \"./run.sh check-mux-fresh-call && ./run.sh check-acp-sdk-surface && ./run.sh check-tests-beside-behavior && ./run.sh check-remote-pair-installed-audit\""
|
|
172
|
+
"\"check:vitest\": \"./run.sh check-mux-fresh-call && ./run.sh check-acp-sdk-surface && ./run.sh check-tests-beside-behavior && ./run.sh check-remote-pair-installed-audit && ./run.sh check-chain-terminus-publication\""
|
|
173
173
|
],
|
|
174
174
|
"gate": ["bash", "run.sh", "check-tests-beside-behavior"],
|
|
175
175
|
"timeoutSeconds": 600,
|
|
@@ -69,7 +69,9 @@
|
|
|
69
69
|
"claim": "FRESHCALL-CALLBACK-PRECEDES-TASK",
|
|
70
70
|
"title": "the task is framed before the callback instruction, so a sibling that stalls in the task never names itself",
|
|
71
71
|
"subject": "pi-extensions/lib/fresh-call-composition.ts",
|
|
72
|
-
"find": [
|
|
72
|
+
"find": [
|
|
73
|
+
"\t\t\t\t\t`BEFORE THE TASK, and before reading files or running commands: call ${birthTool} with no arguments.`"
|
|
74
|
+
],
|
|
73
75
|
"replace": ["\t\t\t\t\t`FINAL ACTION, after completing the task: call ${birthTool} with no arguments.`"],
|
|
74
76
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
75
77
|
"timeoutSeconds": 120,
|
|
@@ -766,6 +768,19 @@
|
|
|
766
768
|
"timeoutSeconds": 60,
|
|
767
769
|
"signature": "[QK:PIIMPORT-CARRIER-FENCE]",
|
|
768
770
|
"signatureSource": "run.sh"
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
"claim": "PD-FRESH-LIVE-BOOTSTRAP-ORDER",
|
|
774
|
+
"title": "a pd call with no joined result read as COMPLETED instead of pending, so a callback whose result the native store never recorded passes pd's bootstrap order",
|
|
775
|
+
"subject": "scripts/lib/pi-durable-fresh-live-receipts.ts",
|
|
776
|
+
"find": ["\t\tstatus: call.result === null ? \"pending\" : call.result.isError ? \"failed\" : \"completed\","],
|
|
777
|
+
"replace": [
|
|
778
|
+
"\t\tstatus: call.result === null ? \"completed\" : call.result.isError ? \"failed\" : \"completed\","
|
|
779
|
+
],
|
|
780
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
781
|
+
"timeoutSeconds": 120,
|
|
782
|
+
"signature": "[QK:PD-FRESH-LIVE-BOOTSTRAP-ORDER]",
|
|
783
|
+
"signatureSource": "test/pi-durable-fresh-live-receipts.test.ts"
|
|
769
784
|
}
|
|
770
785
|
]
|
|
771
786
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"lane": "native-push-paused",
|
|
4
|
+
"mutants": [
|
|
5
|
+
{
|
|
6
|
+
"claim": "AGY-NATIVE-PUSH-PAUSED",
|
|
7
|
+
"title": "the paused native-push backend set is emptied, so agy dispatch, sender replyability and register_native reach the agy language server again, whose measured external callers were refused for a missing CSRF token (#128, #152)",
|
|
8
|
+
"subject": "pi-extensions/lib/entwurf-v2-contract.ts",
|
|
9
|
+
"find": ["export const NATIVE_PUSH_PAUSED_BACKENDS: readonly NativePushBackend[] = [\"antigravity\"];"],
|
|
10
|
+
"replace": ["export const NATIVE_PUSH_PAUSED_BACKENDS: readonly NativePushBackend[] = [];"],
|
|
11
|
+
"gate": ["bash", "run.sh", "check-native-push-paused"],
|
|
12
|
+
"timeoutSeconds": 120,
|
|
13
|
+
"signature": "[QK:AGY-NATIVE-PUSH-PAUSED]",
|
|
14
|
+
"signatureSource": "pi-extensions/lib/native-push/paused.test.ts"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -169,8 +169,8 @@
|
|
|
169
169
|
"claim": "OMP-BOOTSTRAP-CALLBACK-ONLY",
|
|
170
170
|
"title": "the task folded back into the stage-one prompt, so the sibling is asked to call back AND to work in one message. This is the prompt the failed LIVE actually ran, minus the missing tool: a competing goal beside the callback is what the two-stage split exists to remove, and nothing about argv or readiness would notice it coming back",
|
|
171
171
|
"subject": "pi-extensions/meta-bridge-omp.ts",
|
|
172
|
-
"find": ["\t\t\tsend(buildOmpCallbackOnlyPrompt());"],
|
|
173
|
-
"replace": ["\t\t\tsend(`${buildOmpCallbackOnlyPrompt()}\\n\\n${payload.task}`);"],
|
|
172
|
+
"find": ["\t\t\tsend(buildOmpCallbackOnlyPrompt(opts.callerGardenId));"],
|
|
173
|
+
"replace": ["\t\t\tsend(`${buildOmpCallbackOnlyPrompt(opts.callerGardenId)}\\n\\n${payload.task}`);"],
|
|
174
174
|
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
175
175
|
"timeoutSeconds": 300,
|
|
176
176
|
"signature": "[QK:OMP-BOOTSTRAP-CALLBACK-ONLY]",
|
|
@@ -295,6 +295,17 @@
|
|
|
295
295
|
"timeoutSeconds": 300,
|
|
296
296
|
"signature": "[QK:OMP-BOOTSTRAP-EPOCH-ENDS-BEFORE-ENVELOPE]",
|
|
297
297
|
"signatureSource": "test/omp-fresh-bootstrap.contract.test.ts"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"claim": "OMP-BOOTSTRAP-CALLER-TARGET-REQUIRED",
|
|
301
|
+
"title": "a requested omp bootstrap with no well-formed caller target proceeds anyway — the stage silently drops the caller check (or names `undefined` as the caller) and the task is still released, instead of a named refusal",
|
|
302
|
+
"subject": "pi-extensions/meta-bridge-omp.ts",
|
|
303
|
+
"find": ["\tif (!caller.ok) {"],
|
|
304
|
+
"replace": ["\tif (false && !caller.ok) {"],
|
|
305
|
+
"gate": ["bash", "run.sh", "check-mux-fresh-call"],
|
|
306
|
+
"timeoutSeconds": 300,
|
|
307
|
+
"signature": "[QK:OMP-BOOTSTRAP-CALLER-TARGET-REQUIRED]",
|
|
308
|
+
"signatureSource": "test/omp-fresh-bootstrap.contract.test.ts"
|
|
298
309
|
}
|
|
299
310
|
]
|
|
300
311
|
}
|
|
@@ -60,6 +60,52 @@
|
|
|
60
60
|
"timeoutSeconds": 120,
|
|
61
61
|
"signature": "[QK:WIN32-PACK-DIGEST]",
|
|
62
62
|
"signatureSource": "run.sh"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"claim": "PACK-INSTALL-ARGV-LEAK-CAUGHT",
|
|
66
|
+
"title": "the dispatcher-verb refusal goes back to the retired verdict, `printf | grep -qF` under pipefail refusing only when that pipeline exits 0, so a leak ahead of more output SIGPIPEs the producer and the cell passes \u2014 killed deterministically only because the self-test front-loads the leak ahead of ~260 KB, past the default 64 KiB pipe buffer (its teeth control measures that); on the real small stand-in output the same restoration would survive",
|
|
67
|
+
"subject": "run.sh",
|
|
68
|
+
"find": [" grep -qF -- \"$token\" <<<\"$out\" || argv_search_rc=$?"],
|
|
69
|
+
"replace": [" printf '%s' \"$out\" | grep -qF -- \"$token\" || argv_search_rc=1"],
|
|
70
|
+
"gate": ["bash", "run.sh", "check-pack-argv-matcher"],
|
|
71
|
+
"timeoutSeconds": 120,
|
|
72
|
+
"signature": "[QK:PACK-INSTALL-ARGV-LEAK-CAUGHT]",
|
|
73
|
+
"signatureSource": "run.sh"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"claim": "PACK-INSTALL-ARGV-CLEAN-PASSES",
|
|
77
|
+
"title": "the dispatcher-verb refusal stops accepting a clean search (grep rc=1), so every installed copilot / codex-app-server launch is refused, silently",
|
|
78
|
+
"subject": "run.sh",
|
|
79
|
+
"find": [" 1) return 0 ;;"],
|
|
80
|
+
"replace": [" 1) ;;"],
|
|
81
|
+
"gate": ["bash", "run.sh", "check-pack-argv-matcher"],
|
|
82
|
+
"timeoutSeconds": 120,
|
|
83
|
+
"signature": "[QK:PACK-INSTALL-ARGV-CLEAN-PASSES]",
|
|
84
|
+
"signatureSource": "run.sh"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"claim": "PACK-INSTALL-ARGV-SEARCH-ERROR-REFUSED",
|
|
88
|
+
"title": "a failed dispatcher-verb search (grep rc=2) is accepted as clean, so a search that never ran lets the leak refusal pass",
|
|
89
|
+
"subject": "run.sh",
|
|
90
|
+
"find": [
|
|
91
|
+
" *) fail \"[check-pack-install] installed 'entwurf $label': the dispatcher-verb search itself failed (rc=$argv_search_rc) \u2014 refused, never read as no leak\" ;;"
|
|
92
|
+
],
|
|
93
|
+
"replace": [" *) return 0 ;;"],
|
|
94
|
+
"gate": ["bash", "run.sh", "check-pack-argv-matcher"],
|
|
95
|
+
"timeoutSeconds": 120,
|
|
96
|
+
"signature": "[QK:PACK-INSTALL-ARGV-SEARCH-ERROR-REFUSED]",
|
|
97
|
+
"signatureSource": "run.sh"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"claim": "PACK-INSTALL-ARGV-CELLS-BOUND",
|
|
101
|
+
"title": "the copilot leak refusal of check-pack-install goes back to its own `printf | grep -qF` instead of returning through the proved verdict, so the self-test stays green while the heavy cell regains the SIGPIPE window (the codex-app-server call is held by the same text check, with no mutant of its own)",
|
|
102
|
+
"subject": "run.sh",
|
|
103
|
+
"find": [" pack_install_refuse_argv_leak copilot \"$op_out\" 'ARG<copilot>' || return 1"],
|
|
104
|
+
"replace": [" if printf '%s' \"$op_out\" | grep -qF 'ARG<copilot>'; then return 1; fi"],
|
|
105
|
+
"gate": ["bash", "run.sh", "check-pack-argv-matcher"],
|
|
106
|
+
"timeoutSeconds": 120,
|
|
107
|
+
"signature": "[QK:PACK-INSTALL-ARGV-CELLS-BOUND]",
|
|
108
|
+
"signatureSource": "run.sh"
|
|
63
109
|
}
|
|
64
110
|
]
|
|
65
111
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"replace": [
|
|
11
11
|
"\tconst remote = !replyable ? (sender.remote ?? { via: \"?\", replyRoute: \"none\" as const }) : undefined;"
|
|
12
12
|
],
|
|
13
|
-
"gate": ["bash", "run.sh", "check-
|
|
13
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
14
14
|
"timeoutSeconds": 600,
|
|
15
15
|
"signature": "[QK:REMOTE-DISPLAY-LOCAL-UNCHANGED]",
|
|
16
16
|
"signatureSource": "pi-extensions/lib/meta-mailbox-body.test.ts",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"subject": "pi-extensions/lib/meta-mailbox-body.ts",
|
|
26
26
|
"find": ["\"reply route declared, not probed\""],
|
|
27
27
|
"replace": ["\"reply via entwurf_v2 to this sessionId\""],
|
|
28
|
-
"gate": ["bash", "run.sh", "check-
|
|
28
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
29
29
|
"timeoutSeconds": 600,
|
|
30
30
|
"signature": "[QK:REMOTE-DISPLAY-SESSIONLINE]",
|
|
31
31
|
"signatureSource": "pi-extensions/lib/meta-mailbox-body.test.ts",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"subject": "pi-extensions/lib/meta-mailbox-body.ts",
|
|
41
41
|
"find": ["\tconst where = remote ? `${sender.cwd} (sender-host path)` : abbreviateHome(sender.cwd);"],
|
|
42
42
|
"replace": ["\tconst where = abbreviateHome(sender.cwd);"],
|
|
43
|
-
"gate": ["bash", "run.sh", "check-
|
|
43
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
44
44
|
"timeoutSeconds": 600,
|
|
45
45
|
"signature": "[QK:REMOTE-DISPLAY-SENDER-HOST-CWD]",
|
|
46
46
|
"signatureSource": "pi-extensions/lib/meta-mailbox-body.test.ts",
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
"claim": "REMOTE-PAIR-FROM-OUTSIDE-NO-MUTATION",
|
|
7
7
|
"title": "the receiving entry stops checking the claimed sender against the declared pair, so any gid the SSH account writes is dispatched into the declared target's mailbox",
|
|
8
8
|
"subject": "pi-extensions/lib/remote-pair-receive.ts",
|
|
9
|
-
"find": ["\tif (
|
|
9
|
+
"find": ["\tif (fromRoutes.length === 0) {"],
|
|
10
10
|
"replace": ["\tif (false) {"],
|
|
11
|
-
"gate": ["bash", "run.sh", "check-
|
|
11
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
12
12
|
"timeoutSeconds": 600,
|
|
13
13
|
"signature": "[QK:REMOTE-PAIR-FROM-OUTSIDE-NO-MUTATION]",
|
|
14
14
|
"signatureSource": "pi-extensions/lib/remote-pair-receive.test.ts",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"claim": "REMOTE-PAIR-TARGET-OUTSIDE-NO-MUTATION",
|
|
22
22
|
"title": "the receiving entry stops checking the claimed target against the declared pair, so a declared remote can reach every deliverable citizen on this host",
|
|
23
23
|
"subject": "pi-extensions/lib/remote-pair-receive.ts",
|
|
24
|
-
"find": ["\
|
|
25
|
-
"replace": ["\
|
|
26
|
-
"gate": ["bash", "run.sh", "check-
|
|
24
|
+
"find": ["\tconst decl = fromRoutes.find((d) => d.localGardenId === claim.target);"],
|
|
25
|
+
"replace": ["\tconst decl = fromRoutes.find((d) => d.localGardenId === claim.target) ?? fromRoutes[0];"],
|
|
26
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
27
27
|
"timeoutSeconds": 600,
|
|
28
28
|
"signature": "[QK:REMOTE-PAIR-TARGET-OUTSIDE-NO-MUTATION]",
|
|
29
29
|
"signatureSource": "pi-extensions/lib/remote-pair-receive.test.ts",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"subject": "pi-extensions/lib/remote-pair-receive.ts",
|
|
39
39
|
"find": ["\t\tsessionId: claim.from,"],
|
|
40
40
|
"replace": ["\t\tsessionId: process.env.PI_SESSION_ID ?? claim.from,"],
|
|
41
|
-
"gate": ["bash", "run.sh", "check-
|
|
41
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
42
42
|
"timeoutSeconds": 600,
|
|
43
43
|
"signature": "[QK:REMOTE-PAIR-IGNORES-AMBIENT-SENDER]",
|
|
44
44
|
"signatureSource": "pi-extensions/lib/remote-pair-receive.test.ts",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"subject": "pi-extensions/lib/remote-pair-receive.ts",
|
|
54
54
|
"find": ["\t\treplyable: false,"],
|
|
55
55
|
"replace": ["\t\treplyable: true,"],
|
|
56
|
-
"gate": ["bash", "run.sh", "check-
|
|
56
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
57
57
|
"timeoutSeconds": 600,
|
|
58
58
|
"signature": "[QK:REMOTE-PAIR-MATCH-DISPATCHES-ONCE]",
|
|
59
59
|
"signatureSource": "pi-extensions/lib/remote-pair-receive.test.ts",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"subject": "pi-extensions/lib/remote-pair-receive.ts",
|
|
69
69
|
"find": ["\tif (got.length !== want.length || got.some((k, i) => k !== want[i])) {"],
|
|
70
70
|
"replace": ["\tif (false) {"],
|
|
71
|
-
"gate": ["bash", "run.sh", "check-
|
|
71
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
72
72
|
"timeoutSeconds": 600,
|
|
73
73
|
"signature": "[QK:REMOTE-PAIR-CLAIM-EXACT-SHAPE]",
|
|
74
74
|
"signatureSource": "pi-extensions/lib/remote-pair-receive.test.ts",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"subject": "scripts/remote-pair-receive.ts",
|
|
84
84
|
"find": ["emit(receipt, receipt.kind === \"rejected\" ? 3 : receipt.isError ? 4 : 0);"],
|
|
85
85
|
"replace": ["emit(receipt, receipt.kind === \"rejected\" ? 0 : receipt.isError ? 4 : 0);"],
|
|
86
|
-
"gate": ["bash", "run.sh", "check-
|
|
86
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
87
87
|
"timeoutSeconds": 600,
|
|
88
88
|
"signature": "[QK:REMOTE-PAIR-ENTRY-REFUSES-OUTSIDE]",
|
|
89
89
|
"signatureSource": "pi-extensions/lib/remote-pair-receive.test.ts",
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"subject": "scripts/remote-pair-receive.ts",
|
|
99
99
|
"find": ["\tif (!path.isAbsolute(pairFile) || path.normalize(pairFile) !== own) {"],
|
|
100
100
|
"replace": ["\tif (false) {"],
|
|
101
|
-
"gate": ["bash", "run.sh", "check-
|
|
101
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
102
102
|
"timeoutSeconds": 600,
|
|
103
103
|
"signature": "[QK:REMOTE-PAIR-ENTRY-USAGE]",
|
|
104
104
|
"signatureSource": "pi-extensions/lib/remote-pair-receive.test.ts",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
"subject": "scripts/remote-pair-receive.ts",
|
|
114
114
|
"find": ["\treplyRoute: \"declared\","],
|
|
115
115
|
"replace": ["\treplyRoute: \"none\","],
|
|
116
|
-
"gate": ["bash", "run.sh", "check-
|
|
116
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
117
117
|
"timeoutSeconds": 600,
|
|
118
118
|
"signature": "[QK:REMOTE-PAIR-ENTRY-REPLY-ROUTE-DECLARED]",
|
|
119
119
|
"signatureSource": "pi-extensions/lib/remote-pair-receive.test.ts",
|
|
@@ -121,6 +121,36 @@
|
|
|
121
121
|
"argv": ["bash", "scripts/build-bridge.sh"],
|
|
122
122
|
"output": "mcp/entwurf-bridge/dist"
|
|
123
123
|
}
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"claim": "REMOTE-PAIR-CROSS-PAIR-REFUSED",
|
|
127
|
+
"title": "the two ends are checked as independent memberships, so a sender declared in one route reaches the local citizen of another route",
|
|
128
|
+
"subject": "pi-extensions/lib/remote-pair-receive.ts",
|
|
129
|
+
"find": ["\tconst decl = fromRoutes.find((d) => d.localGardenId === claim.target);"],
|
|
130
|
+
"replace": ["\tconst decl = decls.some((d) => d.localGardenId === claim.target) ? fromRoutes[0] : undefined;"],
|
|
131
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
132
|
+
"timeoutSeconds": 600,
|
|
133
|
+
"signature": "[QK:REMOTE-PAIR-CROSS-PAIR-REFUSED]",
|
|
134
|
+
"signatureSource": "pi-extensions/lib/remote-pair-receive.test.ts",
|
|
135
|
+
"build": {
|
|
136
|
+
"argv": ["bash", "scripts/build-bridge.sh"],
|
|
137
|
+
"output": "mcp/entwurf-bridge/dist"
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"claim": "REMOTE-PAIR-SELECTED-ROUTE-LABEL",
|
|
142
|
+
"title": "the body is labelled with the first declared route, so a message that came over one host is shown as arriving over another",
|
|
143
|
+
"subject": "pi-extensions/lib/remote-pair-receive.ts",
|
|
144
|
+
"find": ["\tconst sender = buildRemoteSenderEnvelope(claim, picked.decl,"],
|
|
145
|
+
"replace": ["\tconst sender = buildRemoteSenderEnvelope(claim, decls[0],"],
|
|
146
|
+
"gate": ["bash", "run.sh", "check-remote-pair-beside"],
|
|
147
|
+
"timeoutSeconds": 600,
|
|
148
|
+
"signature": "[QK:REMOTE-PAIR-SELECTED-ROUTE-LABEL]",
|
|
149
|
+
"signatureSource": "pi-extensions/lib/remote-pair-receive.test.ts",
|
|
150
|
+
"build": {
|
|
151
|
+
"argv": ["bash", "scripts/build-bridge.sh"],
|
|
152
|
+
"output": "mcp/entwurf-bridge/dist"
|
|
153
|
+
}
|
|
124
154
|
}
|
|
125
155
|
]
|
|
126
156
|
}
|