@junghanacs/entwurf 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +299 -0
- package/DELIVERY.md +4 -3
- package/README.md +99 -67
- package/VERIFY.md +13 -7
- package/docs/acp-backend-rail.md +1 -1
- package/docs/external-mcp-host.md +147 -9
- package/docs/setup-clean-host.md +221 -16
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +65 -20
- package/mcp/entwurf-bridge/dist/pi-extensions/entwurf-capabilities.json +1 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +17 -6
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +1 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +172 -5
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +152 -17
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/omp-fresh-preflight.js +271 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-omp.js +988 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-receive-omp.js +574 -0
- package/mcp/entwurf-bridge/dist/scripts/omp-receive-facts.js +84 -0
- package/mcp/entwurf-bridge/src/index.ts +65 -19
- package/mcp/entwurf-bridge/tsconfig.build.json +19 -3
- package/mcp/tsconfig.json +10 -0
- package/package.json +14 -4
- package/pi/entwurf-capabilities.json +1 -0
- package/pi/meta-bridge-omp/entwurf-meta-omp/package.json +7 -0
- package/pi/omp-receive/entwurf-receive-omp/package.json +7 -0
- package/pi-extensions/entwurf-control.ts +12 -9
- package/pi-extensions/lib/entwurf-self-address.ts +18 -7
- package/pi-extensions/lib/meta-sender-identity.ts +1 -1
- package/pi-extensions/lib/meta-session.ts +219 -5
- package/pi-extensions/lib/mux-fresh-call.ts +171 -17
- package/pi-extensions/lib/omp-fresh-preflight.ts +275 -0
- package/pi-extensions/meta-bridge-omp.ts +1244 -0
- package/pi-extensions/meta-bridge-receive-omp.ts +666 -0
- package/run.sh +1041 -174
- package/scripts/agy-bridge.sh +4 -2
- package/scripts/check-copilot-birth-hook.ts +700 -23
- package/scripts/check-entwurf-self-address.ts +31 -0
- package/scripts/check-fresh-cut-gate.sh +12 -4
- package/scripts/check-gate-qualification.ts +8 -2
- package/scripts/check-harness-admission-parity.ts +143 -0
- package/scripts/check-meta-doctor-oracle.sh +20 -0
- package/scripts/check-omp-birth-hook.ts +1049 -0
- package/scripts/check-omp-fresh-preflight.ts +181 -0
- package/scripts/check-omp-receive-arm.ts +516 -0
- package/scripts/check-setup-qualification.sh +126 -0
- package/scripts/copilot-bridge-doctor.sh +104 -71
- package/scripts/copilot-bridge-install.sh +180 -20
- package/scripts/copilot-bridge-oracle.sh +223 -0
- package/scripts/copilot-bridge-uninstall.sh +137 -0
- package/scripts/dev-bin.sh +50 -9
- package/scripts/fake-copilot-vendor.sh +67 -0
- package/scripts/inventory-verification-surface.ts +1 -1
- package/scripts/meta-bridge-hook-log.sh +9 -1
- package/scripts/mutants/copilot-birth.json +96 -5
- package/scripts/mutants/mux-fresh-call.json +22 -22
- package/scripts/mutants/omp-birth.json +173 -0
- package/scripts/mutants/omp-fresh.json +300 -0
- package/scripts/mutants/omp-receive.json +135 -0
- package/scripts/mutants/pi-package-ownership.json +92 -0
- package/scripts/mutants/self-address.json +34 -0
- package/scripts/mutants/setup-verdict.json +148 -0
- package/scripts/mutants/source-install.json +32 -0
- package/scripts/omp-bridge-doctor.sh +315 -0
- package/scripts/omp-bridge-install.sh +221 -0
- package/scripts/omp-bridge-oracle.sh +154 -0
- package/scripts/omp-bridge-uninstall.sh +57 -0
- package/scripts/omp-mcp-bridge.sh +320 -0
- package/scripts/omp-mcp-config.py +392 -0
- package/scripts/omp-receive-doctor.sh +246 -0
- package/scripts/omp-receive-facts.ts +106 -0
- package/scripts/omp-receive-install.sh +228 -0
- package/scripts/omp-receive-uninstall.sh +60 -0
- package/scripts/omp-tool-surface.py +349 -0
- package/scripts/pi_settings_io.py +22 -0
- package/scripts/raw-omp-measure/README.md +420 -0
- package/scripts/raw-omp-measure/probe-extension.ts +76 -0
- package/scripts/raw-omp-measure/probe-receive-surface.ts +250 -0
- package/scripts/raw-omp-measure/source-audit.md +414 -0
- package/scripts/register-pi-package.py +525 -7
- package/scripts/register-pi-provider.py +162 -12
- package/scripts/smoke-agy-install-state.sh +86 -30
- package/scripts/smoke-agy-statusline-state.sh +9 -6
- package/scripts/smoke-omp-bridge-state.sh +221 -0
- package/scripts/smoke-omp-fresh-live.ts +497 -0
- package/scripts/smoke-omp-mcp-state.sh +327 -0
- package/scripts/smoke-omp-receive-live.ts +340 -0
- package/scripts/smoke-omp-receive-state.sh +196 -0
- package/scripts/smoke-setup-verdict.sh +291 -0
- package/scripts/smoke-user-scope-citizen.sh +388 -1
- package/scripts/tsconfig.json +2 -0
|
@@ -155,6 +155,26 @@ function row(facts: SelfAddressabilityFacts): { replyable: boolean; socketState:
|
|
|
155
155
|
);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
// meta-session / NONE rail: no inbound transport at all. Mailbox facts and a live probe
|
|
159
|
+
// cannot buy replyability — there is nothing to land on. Distinct from the unsupplied
|
|
160
|
+
// (undefined) domain row below, which stays fail-closed for a caller that forgot the axis.
|
|
161
|
+
{
|
|
162
|
+
const noneFacts: SelfAddressabilityFacts = {
|
|
163
|
+
origin: "meta-session",
|
|
164
|
+
metaDeliveryDomain: "none",
|
|
165
|
+
recordBacked: true,
|
|
166
|
+
ownerAlive: true,
|
|
167
|
+
watchArmed: true,
|
|
168
|
+
probeAlive: true,
|
|
169
|
+
};
|
|
170
|
+
const noneRail = computeSelfAddressability(noneFacts);
|
|
171
|
+
ok("meta/none + all facts true → NOT replyable", noneRail.replyable === false);
|
|
172
|
+
ok(
|
|
173
|
+
"meta/none names the missing inbound rail (mailbox/probe facts cannot rescue it)",
|
|
174
|
+
noneRail.reason.includes("no inbound rail"),
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
158
178
|
// meta-session with NO rail declared: we cannot say how a reply would travel, so we do not
|
|
159
179
|
// claim it would arrive. The domain is derived from nativePushSupported(backend) — a caller
|
|
160
180
|
// that forgets it gets a refusal, not an optimistic guess.
|
|
@@ -246,6 +266,17 @@ ok(
|
|
|
246
266
|
/existsSync\s*\(/.test(piBody) && /controlSocketPathIn\s*\(\s*ENTWURF_DIR\s*,/.test(piBody),
|
|
247
267
|
);
|
|
248
268
|
|
|
269
|
+
const metaBuilder = functionBody("buildTrustedMetaSenderEnvelope");
|
|
270
|
+
// FIRST of the two derivation claims so a binary-fallback mutant dies here, not at the seam pin.
|
|
271
|
+
ok(
|
|
272
|
+
"buildTrustedMetaSenderEnvelope does not fall back every non-native-push backend to self-fetch [QK:SELFADDR-NO-FALLBACK-SELF-FETCH]",
|
|
273
|
+
!/\?\s*"native-push"\s*:\s*"self-fetch"/.test(metaBuilder),
|
|
274
|
+
);
|
|
275
|
+
ok(
|
|
276
|
+
"buildTrustedMetaSenderEnvelope derives self-fetch through resolveMailboxWakeModeCapability(identity), not a backend-name list [QK:SELFADDR-MAILBOX-WAKE-SEAM]",
|
|
277
|
+
/resolveMailboxWakeModeCapability\s*\(\s*identity\s*\)/.test(metaBuilder),
|
|
278
|
+
);
|
|
279
|
+
|
|
249
280
|
const selfRegion = toolRegion("entwurf_self");
|
|
250
281
|
ok(
|
|
251
282
|
"entwurf_self existsSync-probes the pi socket (alive vs expected, no synthesized path lie)",
|
|
@@ -394,11 +394,19 @@ esac
|
|
|
394
394
|
# Static order: the gate precedes the first writer in each entrypoint, and the
|
|
395
395
|
# preflight never runs the cut on the operator's behalf.
|
|
396
396
|
gate_ln=$(grep -n 'preflight_v3_store setup' "$REPO/run.sh" | head -1 | cut -d: -f1) || true
|
|
397
|
-
|
|
398
|
-
if [ -n "$gate_ln" ] && [ -n "$
|
|
399
|
-
ok "D4 setup_all calls the gate before
|
|
397
|
+
boot_ln=$(awk '/^setup_all\(\)/,/^}/{ if ($0 ~ /pnpm install --frozen-lockfile/) { print NR; exit } }' "$REPO/run.sh")
|
|
398
|
+
if [ -n "$gate_ln" ] && [ -n "$boot_ln" ] && [ "$gate_ln" -lt "$boot_ln" ]; then
|
|
399
|
+
ok "D4 setup_all calls the gate before the source bootstrap (line $gate_ln < $boot_ln)"
|
|
400
400
|
else
|
|
401
|
-
bad "D4 setup_all's gate is missing or sits after
|
|
401
|
+
bad "D4 setup_all's gate is missing or sits after the source bootstrap (gate=$gate_ln bootstrap=$boot_ln)"
|
|
402
|
+
fi
|
|
403
|
+
# #86 A5 credential tripwire: the retired sync_auth mutation (OAuth alias copy +
|
|
404
|
+
# auth.json.bak) must never resurrect as an invocable surface in run.sh. Comments
|
|
405
|
+
# documenting the removal are allowed; a function definition or call is not.
|
|
406
|
+
if awk '!/^[[:space:]]*#/' "$REPO/run.sh" | grep -q 'sync_auth'; then
|
|
407
|
+
bad "D4b the retired sync_auth credential mutation reappeared as code in run.sh"
|
|
408
|
+
else
|
|
409
|
+
ok "D4b no sync_auth credential surface remains in run.sh (comments only)"
|
|
402
410
|
fi
|
|
403
411
|
|
|
404
412
|
ilp_gate=$(awk '/^install_local_package\(\)/,/^}/{ if ($0 ~ /preflight_v3_store install/) { print NR; exit } }' "$REPO/run.sh")
|
|
@@ -807,7 +807,7 @@ console.log(`\n[gate-qualification] self-test: ${passed} checks passed`);
|
|
|
807
807
|
"bridge-boot-resume": 3,
|
|
808
808
|
"bridge-command-boot": 9,
|
|
809
809
|
"capability-cache": 3,
|
|
810
|
-
"copilot-birth":
|
|
810
|
+
"copilot-birth": 19,
|
|
811
811
|
"copilot-launch": 14,
|
|
812
812
|
"copilot-receive": 18,
|
|
813
813
|
"fresh-cut": 1,
|
|
@@ -819,12 +819,18 @@ console.log(`\n[gate-qualification] self-test: ${passed} checks passed`);
|
|
|
819
819
|
"mux-launcher-fence": 7,
|
|
820
820
|
"mux-parent-artifact": 3,
|
|
821
821
|
"pack-install": 1,
|
|
822
|
+
"pi-package-ownership": 6,
|
|
822
823
|
"mux-resume-call": 12,
|
|
824
|
+
"omp-birth": 11,
|
|
825
|
+
"omp-fresh": 24,
|
|
826
|
+
"omp-receive": 11,
|
|
823
827
|
"probe-ordering": 1,
|
|
824
828
|
"release-gate": 12,
|
|
825
829
|
"resume-args": 6,
|
|
826
830
|
"resume-launch-identity": 6,
|
|
827
|
-
"self-address":
|
|
831
|
+
"self-address": 5,
|
|
832
|
+
"setup-verdict": 10,
|
|
833
|
+
"source-install": 2,
|
|
828
834
|
"v2-surface": 7,
|
|
829
835
|
"v2-visible-resume": 17,
|
|
830
836
|
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* check-harness-admission-parity — the edge between two parity loops that were each closed and
|
|
3
|
+
* had nothing between them (#87 Bundle C).
|
|
4
|
+
*
|
|
5
|
+
* ── The defect this owns ──
|
|
6
|
+
*
|
|
7
|
+
* Two gates already held their own halves tight:
|
|
8
|
+
*
|
|
9
|
+
* `check-entwurf-capabilities` registry == META_CITIZEN_BACKENDS
|
|
10
|
+
* `fresh-call-surfaces.contract.test.ts` surfaces == FRESH_CALL_BACKENDS
|
|
11
|
+
*
|
|
12
|
+
* and NO file imported both constants. So a harness could be admitted as a full D6 citizen —
|
|
13
|
+
* birth, MCP hand, receive, a garden id on its own status line — while `entwurf_fresh_call`
|
|
14
|
+
* could not open it, and every gate in the repo stayed green. `docs/adding-a-harness.md` step 9
|
|
15
|
+
* says a backend is **supported** only when it can be opened as one visible fresh sibling, but
|
|
16
|
+
* that sentence had no consumer: the honest prose in `DELIVERY.md` ("Visible fresh is NOT
|
|
17
|
+
* implemented, so OMP is not a supported harness under step 9") sat there being true while a
|
|
18
|
+
* release package containing that backend passed the whole floor.
|
|
19
|
+
*
|
|
20
|
+
* `[측정]` 2026-08-30, on the Bundle A+B candidate: registry carried six backends, all D6;
|
|
21
|
+
* `FRESH_CALL_BACKENDS` carried three. The omp row read `unsupported` in the docs and shipped
|
|
22
|
+
* anyway. GLG's finding: **an `unsupported` label is not a partial-release permit.**
|
|
23
|
+
*
|
|
24
|
+
* ── The rule ──
|
|
25
|
+
*
|
|
26
|
+
* Every backend a meta-record may name is either
|
|
27
|
+
* (a) openable by `entwurf_fresh_call` — it walked step 9; or
|
|
28
|
+
* (b) a PRE-#82 admission, named here AND described as such in the delivery matrix.
|
|
29
|
+
*
|
|
30
|
+
* There is no third state. A post-#82 harness that is a citizen but not fresh-openable makes
|
|
31
|
+
* this gate red, which is what stops the release package rather than only the docs.
|
|
32
|
+
*
|
|
33
|
+
* ── Why the exception is a literal here plus a sentence there ──
|
|
34
|
+
*
|
|
35
|
+
* Same shape `check-release-gate-outcomes` cell 7 already uses for aggregate omissions, and for
|
|
36
|
+
* the same reason it states: *an exclusion that only this gate believes in is how the omission
|
|
37
|
+
* would come back.* The pair is deliberately redundant — the literal makes the exception a
|
|
38
|
+
* decision someone had to type, and the doc sentence makes it a thing an operator can read
|
|
39
|
+
* without opening this file. Neither half alone is the contract.
|
|
40
|
+
*
|
|
41
|
+
* This introduces NO new authority: the capability registry keeps its schema (there is no
|
|
42
|
+
* `supported` field and there must not be one — a self-declared grade is exactly what step 9
|
|
43
|
+
* refuses), and the fresh set stays the composition's own constant.
|
|
44
|
+
*
|
|
45
|
+
* Pure parse over shipped source + docs. No backend, no network, no subprocess.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
import assert from "node:assert/strict";
|
|
49
|
+
import fs from "node:fs";
|
|
50
|
+
import path from "node:path";
|
|
51
|
+
import { fileURLToPath } from "node:url";
|
|
52
|
+
import { META_CITIZEN_BACKENDS, type MetaCitizenBackend } from "../pi-extensions/lib/meta-session.ts";
|
|
53
|
+
import { FRESH_CALL_BACKENDS } from "../pi-extensions/lib/mux-fresh-call.ts";
|
|
54
|
+
|
|
55
|
+
const REPO_DIR = fileURLToPath(new URL("..", import.meta.url));
|
|
56
|
+
|
|
57
|
+
let passed = 0;
|
|
58
|
+
function ok(label: string, cond: boolean): void {
|
|
59
|
+
assert.ok(cond, label);
|
|
60
|
+
console.log(` ok ${label}`);
|
|
61
|
+
passed++;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Backends admitted BEFORE the #82 step 9 contract, which `docs/adding-a-harness.md` step 9
|
|
66
|
+
* preserves explicitly: "a pre-contract backend that has not walked this step remains
|
|
67
|
+
* legacy/probe evidence and must not be described as supported until it is re-evaluated here."
|
|
68
|
+
* Copilot is the first admission made UNDER that contract (step 9's worked example), so nothing
|
|
69
|
+
* admitted after it qualifies for this list.
|
|
70
|
+
*
|
|
71
|
+
* `claude-code` and `pi` are also pre-contract and are deliberately absent: they are fresh-
|
|
72
|
+
* openable, so they need no exception. An exception is for a backend that CANNOT be opened —
|
|
73
|
+
* never a convenience for one that simply has not been wired yet.
|
|
74
|
+
*
|
|
75
|
+
* Each value is the file and the sentence in it that carries the exception for a reader. The
|
|
76
|
+
* sentence must be the one that says WHY the backend is not step-9 supported; a row that merely
|
|
77
|
+
* mentions the backend is not an exception.
|
|
78
|
+
*/
|
|
79
|
+
const PRE_82_LEGACY: Partial<Record<MetaCitizenBackend, [file: string, sentence: string]>> = {
|
|
80
|
+
antigravity: [
|
|
81
|
+
"DELIVERY.md",
|
|
82
|
+
"Admitted before the #82 step 9 contract and not re-evaluated under it, so it is legacy citizen evidence, not a step-9 supported harness",
|
|
83
|
+
],
|
|
84
|
+
codex: ["DELIVERY.md", "No owned native-citizen install/invocation lane."],
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const fresh = new Set<string>(FRESH_CALL_BACKENDS);
|
|
88
|
+
const legacy = Object.keys(PRE_82_LEGACY);
|
|
89
|
+
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// 1. The join itself. This assertion is the entire point of the file: it is the
|
|
92
|
+
// first line in the repo that reads both constants at once.
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
const unaccounted = META_CITIZEN_BACKENDS.filter((b) => !fresh.has(b) && !(b in PRE_82_LEGACY));
|
|
95
|
+
ok(
|
|
96
|
+
"[QK:ADMISSION-FRESH-PARITY] every citizen backend is either openable by entwurf_fresh_call or a declared pre-#82 legacy admission — a post-contract harness that mints records but cannot be opened is not admissible, and an `unsupported` note is not a partial-release permit (docs/adding-a-harness.md step 9). Unaccounted: " +
|
|
97
|
+
(unaccounted.length === 0 ? "none" : unaccounted.join(", ")),
|
|
98
|
+
unaccounted.length === 0,
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// 2. The exception must be readable OUTSIDE this file. A literal nobody else
|
|
103
|
+
// carries is how the omission comes back (check-release-gate-outcomes cell 7).
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
for (const backend of legacy) {
|
|
106
|
+
const [file, sentence] = PRE_82_LEGACY[backend as MetaCitizenBackend] as [string, string];
|
|
107
|
+
const body = fs.readFileSync(path.join(REPO_DIR, file), "utf8");
|
|
108
|
+
ok(
|
|
109
|
+
`[QK:ADMISSION-LEGACY-DOCUMENTED] ${backend}'s pre-#82 exception is carried by a sentence an operator can read in ${file}, not only by this gate's literal`,
|
|
110
|
+
body.includes(sentence),
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// 3. The two states are exclusive, and the exception list has no dead entries.
|
|
116
|
+
// A backend that got wired for fresh while keeping its legacy excuse would
|
|
117
|
+
// leave a stale "cannot be opened" sentence in the matrix pointing at a
|
|
118
|
+
// capability that now exists.
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
for (const backend of legacy) {
|
|
121
|
+
ok(
|
|
122
|
+
`[QK:ADMISSION-LEGACY-EXCLUSIVE] ${backend} is excused OR fresh-openable, never both — a backend that walked step 9 must lose its exception and its matrix sentence together`,
|
|
123
|
+
!fresh.has(backend),
|
|
124
|
+
);
|
|
125
|
+
ok(
|
|
126
|
+
`[QK:ADMISSION-LEGACY-SCOPE] ${backend} is still a citizen backend — an exception for a backend no record may name is dead weight that hides the next real one`,
|
|
127
|
+
(META_CITIZEN_BACKENDS as readonly string[]).includes(backend),
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// 4. The reverse direction. The fresh set naming something that can never mint a
|
|
133
|
+
// record would be a launchable window with no address to call home from —
|
|
134
|
+
// `freshCall` would open it and the callback could carry no garden id.
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
const openableNonCitizens = [...fresh].filter((b) => !(META_CITIZEN_BACKENDS as readonly string[]).includes(b));
|
|
137
|
+
ok(
|
|
138
|
+
"[QK:ADMISSION-FRESH-IS-CITIZEN] every fresh-openable backend is also a citizen backend — opening a harness that cannot mint a record would produce a window with no address to call back from. Offenders: " +
|
|
139
|
+
(openableNonCitizens.length === 0 ? "none" : openableNonCitizens.join(", ")),
|
|
140
|
+
openableNonCitizens.length === 0,
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
console.log(`[check-harness-admission-parity] ${passed} assertions ok`);
|
|
@@ -526,6 +526,26 @@ else
|
|
|
526
526
|
fi
|
|
527
527
|
cp "$TMP/hook-log-precopilot.bak" "$AGENT/meta-bridge-hook.log"
|
|
528
528
|
|
|
529
|
+
# M9c — an OMP line in the shared hook log must not move this doctor either (#87). The
|
|
530
|
+
# omp birth unit is an in-process EXTENSION, and its scope fence writes a line for every
|
|
531
|
+
# task subagent it refuses, so this file now carries a second rail's routine traffic. Its
|
|
532
|
+
# ERROR lines are mint/marker faults on that rail and its recovery token is
|
|
533
|
+
# `create`/`attach`, never `armed watch` — so counting them here would redden the CLAUDE
|
|
534
|
+
# doctor for a fault it does not own and cannot prescribe a fix for. Same expect-GREEN
|
|
535
|
+
# shape as M9b: the defect this guards makes a HEALTHY host go red.
|
|
536
|
+
cp "$AGENT/meta-bridge-hook.log" "$TMP/hook-log-preomp.bak"
|
|
537
|
+
{
|
|
538
|
+
echo "2026-08-27T00:00:02.000Z ERROR [omp] upsert failed (edge=session_start, native=01a042da-537a-7770-a275-7b8162eecca4): store refused"
|
|
539
|
+
echo "2026-08-27T00:00:03.000Z INFO [omp] scope-refused edge=session_start mode=print: not the visible tui host, no record minted"
|
|
540
|
+
} >> "$AGENT/meta-bridge-hook.log"
|
|
541
|
+
run_doctor
|
|
542
|
+
if [ "$DOC_RC" -eq 0 ]; then
|
|
543
|
+
ok "an omp ERROR in the shared hook log leaves the CLAUDE doctor green (rails stay separate)"
|
|
544
|
+
else
|
|
545
|
+
bad "[QK:HOOK-LOG-OMP-RAIL-SCOPED] an omp ERROR in the shared hook log turned the CLAUDE doctor red — the hook-log judgement does not scope out the omp rail:"$'\n'"$(printf '%s\n' "$DOC_OUT" | grep -E '^ (FAIL|WARN)' | sed 's/^/ /')"
|
|
546
|
+
fi
|
|
547
|
+
cp "$TMP/hook-log-preomp.bak" "$AGENT/meta-bridge-hook.log"
|
|
548
|
+
|
|
529
549
|
# M10 — deployed writer bundle missing: staleness becomes unknowable.
|
|
530
550
|
mv "$PLANTED/lib/meta-session.ts" "$TMP/meta-session.bak"
|
|
531
551
|
expect_red "installed writer bundle missing" "deployed writer version is UNKNOWN"
|