Kevin Crutt commited on
Commit
b625129
·
1 Parent(s): 6dbe8c8

liris: add odysseus mtp control surface

Browse files
docs/LIRIS-ODYSSEUS-MTP-CONTROL-SURFACE-2026-06-14.hbp ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ ODYSSEUSMTPCANONHDR|doc=LIRIS-ODYSSEUS-MTP-CONTROL-SURFACE-2026-06-14|date=2026-06-14|owner=liris|scope=odysseus-pattern-absorption-MTP-plus-v8-map3d-control-surface|tag=DESCRIPTOR-ONLY|json=0
2
+ ODYSSEUSMTPCANONSOURCE|source=docs/LIRIS-ODYSSEUS-CHATOS-FRONTEND-ABSORPTION-2026-06-12.hbp|mode=pattern-absorption-not-code-copy|invariant=every-visible-cell-has-route-file-sha-or-explicit-CANNOT-SEE|json=0
3
+ ODYSSEUSMTPCANONBANDS|bands=M-model-selector+T-tool-skill+P-project-guide+MAP3D-v8-real-graph|M=tools/behcs/model-selector-matrix.mjs|T=tools/behcs/tool-skill-registry-matrix.mjs|P=tools/behcs/project-guide-matrix.mjs|MAP3D=tools/behcs/eight-byte-host-process-upgrade.mjs|json=0
4
+ ODYSSEUSMTPCANONSTATUS|mtp_descriptor_backed=3|map3d_real_math_descriptor_backed=1|phone_render_proven_here=0|cutover_ready=0|live_execution_ready=0|json=0
5
+ ODYSSEUSMTPCANONGATES|live_model_invocation=0|live_tool_execution=0|workflow_execution=0|process_launch=0|provider_terms_apply=1|operator_cosign_required_for_live_actions=1|json=0
6
+ ODYSSEUSMTPCANONTOOL|tool=tools/behcs/odysseus-mtp-control-surface.mjs|test=tests/odysseus-mtp-control-surface.unit.test.mjs|catalog=tools/behcs/fabric-agent-preload-catalog.mjs|json=0
7
+ ODYSSEUSMTPCANONFTR|state=SEALED-ODYSSEUS-MTP-CONTROL-SURFACE|next=use-before-claiming-odysseus-upgraded-ui-or-MTP-green-cutover|json=0
docs/LIRIS-ODYSSEUS-MTP-CONTROL-SURFACE-2026-06-14.hbp.sha256 ADDED
@@ -0,0 +1 @@
 
 
1
+ E60AFA9D6D67DD188997A401A50DEE57DCA10435150B21D4E1120F77352D69C0 LIRIS-ODYSSEUS-MTP-CONTROL-SURFACE-2026-06-14.hbp
tests/fabric-agent-preload-catalog.unit.test.mjs CHANGED
@@ -37,6 +37,7 @@ test('preload catalog includes the laws, tools, roles, and cadence agents need',
37
  assert.ok(TOOLS.some((t) => t.id === 'cellphone-host-bridge-boundary' && t.gate.includes('radio_bypass-0')));
38
  assert.ok(TOOLS.some((t) => t.id === 'frozen-slice-city-signal-lifecycle' && t.gate.includes('measured_200ns-0')));
39
  assert.ok(TOOLS.some((t) => t.id === 'eight-byte-host-process-upgrade' && t.gate.includes('provider_compute_replaced-0')));
 
40
  assert.ok(ROLES.some((r) => r.id === 'flywheel' && r.must_do.includes('compare-to-acer-local-truth')));
41
  assert.ok(WORKFLOW.join('-').includes('memory-index-plan'));
42
  assert.equal(toolById('token-cube-catalog-binder').gate, 'mint-write-live-DEFER_TO_OPERATOR');
 
37
  assert.ok(TOOLS.some((t) => t.id === 'cellphone-host-bridge-boundary' && t.gate.includes('radio_bypass-0')));
38
  assert.ok(TOOLS.some((t) => t.id === 'frozen-slice-city-signal-lifecycle' && t.gate.includes('measured_200ns-0')));
39
  assert.ok(TOOLS.some((t) => t.id === 'eight-byte-host-process-upgrade' && t.gate.includes('provider_compute_replaced-0')));
40
+ assert.ok(TOOLS.some((t) => t.id === 'odysseus-mtp-control-surface' && t.gate.includes('phone_render_proven_here-0')));
41
  assert.ok(ROLES.some((r) => r.id === 'flywheel' && r.must_do.includes('compare-to-acer-local-truth')));
42
  assert.ok(WORKFLOW.join('-').includes('memory-index-plan'));
43
  assert.equal(toolById('token-cube-catalog-binder').gate, 'mint-write-live-DEFER_TO_OPERATOR');
tests/fabric-agent-preload-catalog.unit.test.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- AEECC42FFBF57603B927CA292D4672E0B166CE3F73E44B5207F01B77A441FF89 fabric-agent-preload-catalog.unit.test.mjs
 
1
+ 8FA46CF24BF6AE488875682041E7409DA31F37607C193B1E4F04B8EC23A3EC9A fabric-agent-preload-catalog.unit.test.mjs
tests/odysseus-mtp-control-surface.unit.test.mjs ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import assert from 'node:assert/strict';
2
+ import { readFileSync } from 'node:fs';
3
+ import test from 'node:test';
4
+
5
+ import {
6
+ BANDS, ODYSSEUS_SOURCE, SURFACE_ID,
7
+ buildSurface, emitRows, selfTest,
8
+ } from '../tools/behcs/odysseus-mtp-control-surface.mjs';
9
+
10
+ test('odysseus MTP control surface self-test passes', () => {
11
+ assert.equal(selfTest().ok, true);
12
+ });
13
+
14
+ test('surface binds Odysseus source, M/T/P cells, and v8 map band', () => {
15
+ const surface = buildSurface();
16
+ assert.equal(surface.tool, SURFACE_ID);
17
+ assert.equal(surface.source, ODYSSEUS_SOURCE);
18
+ assert.deepEqual(BANDS, ['M-model-selector', 'T-tool-skill', 'P-project-guide', 'MAP3D-v8-real-graph']);
19
+ assert.equal(surface.summary.bands, 4);
20
+ assert.equal(surface.summary.mtp_descriptor_backed, 3);
21
+ assert.ok(surface.bands.some((b) => b.id === 'MAP3D' && b.source === 'tools/behcs/eight-byte-host-process-upgrade.mjs'));
22
+ });
23
+
24
+ test('M/T/P are descriptor-backed but not cutover-green', () => {
25
+ const surface = buildSurface();
26
+ for (const id of ['M', 'T', 'P']) {
27
+ const band = surface.bands.find((b) => b.id === id);
28
+ assert.equal(band.status, 'PARTIAL_DESCRIPTOR_BACKED');
29
+ assert.equal(band.cutover, 0);
30
+ }
31
+ assert.equal(surface.summary.cutover_ready, false);
32
+ assert.equal(surface.summary.live_execution_ready, false);
33
+ });
34
+
35
+ test('routes use existing selector registry and guide artifacts', () => {
36
+ const surface = buildSurface({
37
+ model_need: 'pixel frame world model',
38
+ tool_need: 'live engine daemon launch',
39
+ project_topic: 'cosign submit schema',
40
+ });
41
+ assert.equal(surface.routes.model.selected, 'frozen-gemma-proof-gated');
42
+ assert.equal(surface.routes.tool.selected, 'live-engine-daemon-contract');
43
+ assert.equal(surface.routes.project.selected, 'cosign-submit');
44
+ });
45
+
46
+ test('phone rendering is not claimed by the repo descriptor', () => {
47
+ const surface = buildSurface();
48
+ assert.equal(surface.summary.phone_render_proven_here, false);
49
+ assert.ok(surface.bands.find((b) => b.id === 'MAP3D').next.includes('phone-render-proof'));
50
+ });
51
+
52
+ test('emitted rows are HBP-only and hold all live actions', () => {
53
+ const rows = emitRows({ model_need: 'fischer score', tool_need: 'cosign submit schema', project_topic: 'frontier catch queue' });
54
+ assert.ok(rows.every((row) => row.endsWith('|json=0') && !/[{\r\n]/.test(row)));
55
+ assert.ok(rows.some((row) => row.startsWith('ODYSSEUSMTPHDR|') && row.includes('process_launch=0') && row.includes('cutover=0')));
56
+ assert.ok(rows.some((row) => row.startsWith('ODYSSEUSMTPROUTE|cell=M') && row.includes('selected=fischer-draft-standin')));
57
+ assert.ok(rows.some((row) => row.startsWith('ODYSSEUSMTPGATE|') && row.includes('operator_cosign_required_for_live_actions=1')));
58
+ });
59
+
60
+ test('tool remains descriptor-only and has no live call surface', () => {
61
+ const source = readFileSync(new URL('../tools/behcs/odysseus-mtp-control-surface.mjs', import.meta.url), 'utf8');
62
+ assert.doesNotMatch(source, /from ['"]node:fs['"]|child_process|\bexecFile\b|\bexecSync\b|\bspawn\(|\bfetch\(|Invoke-WebRequest|Start-Process|node:http|node:net|createWriteStream/);
63
+ });
tests/odysseus-mtp-control-surface.unit.test.mjs.sha256 ADDED
@@ -0,0 +1 @@
 
 
1
+ 6A88BA38FBF6A0DA2DB95916DE31EFF5C74D632D1FA5D92BA2EA2CEBC9AD07AA odysseus-mtp-control-surface.unit.test.mjs
tests/supervisor-collision-router.system.test.mjs CHANGED
@@ -96,6 +96,7 @@ const sealedFiles = [
96
  'docs/LIRIS-CELLPHONE-HOST-BRIDGE-BOUNDARY-2026-06-14.hbp',
97
  'docs/LIRIS-FROZEN-SLICE-CITY-SIGNAL-LIFECYCLE-2026-06-14.hbp',
98
  'docs/LIRIS-EIGHT-BYTE-HOST-PROCESS-UPGRADE-2026-06-14.hbp',
 
99
  'docs/ACER-SLICE-ENGINE-LIVE-CRANK-RECEIPT-2026-06-13.hbp',
100
  'docs/LIRIS-ROUTE-HEALTH-BASELINE-2026-06-13.hbp',
101
  'docs/ACER-ROUTE-HEALTH-CROSS-VANTAGE-2026-06-13.hbp',
@@ -243,6 +244,7 @@ const sealedFiles = [
243
  'tools/behcs/cellphone-host-bridge-boundary.mjs',
244
  'tools/behcs/frozen-slice-city-signal-lifecycle.mjs',
245
  'tools/behcs/eight-byte-host-process-upgrade.mjs',
 
246
  'tools/behcs/logical-extreme-stress.mjs',
247
  'tools/behcs/logical-stress-cube-feed.mjs',
248
  'tools/behcs/brown-hilbert-expansion-stress.mjs',
@@ -284,6 +286,7 @@ const sealedFiles = [
284
  'tests/cellphone-host-bridge-boundary.unit.test.mjs',
285
  'tests/frozen-slice-city-signal-lifecycle.unit.test.mjs',
286
  'tests/eight-byte-host-process-upgrade.unit.test.mjs',
 
287
  'tests/logical-extreme-stress.unit.test.mjs',
288
  'tests/logical-stress-cube-feed.unit.test.mjs',
289
  'tests/brown-hilbert-expansion-stress.unit.test.mjs',
 
96
  'docs/LIRIS-CELLPHONE-HOST-BRIDGE-BOUNDARY-2026-06-14.hbp',
97
  'docs/LIRIS-FROZEN-SLICE-CITY-SIGNAL-LIFECYCLE-2026-06-14.hbp',
98
  'docs/LIRIS-EIGHT-BYTE-HOST-PROCESS-UPGRADE-2026-06-14.hbp',
99
+ 'docs/LIRIS-ODYSSEUS-MTP-CONTROL-SURFACE-2026-06-14.hbp',
100
  'docs/ACER-SLICE-ENGINE-LIVE-CRANK-RECEIPT-2026-06-13.hbp',
101
  'docs/LIRIS-ROUTE-HEALTH-BASELINE-2026-06-13.hbp',
102
  'docs/ACER-ROUTE-HEALTH-CROSS-VANTAGE-2026-06-13.hbp',
 
244
  'tools/behcs/cellphone-host-bridge-boundary.mjs',
245
  'tools/behcs/frozen-slice-city-signal-lifecycle.mjs',
246
  'tools/behcs/eight-byte-host-process-upgrade.mjs',
247
+ 'tools/behcs/odysseus-mtp-control-surface.mjs',
248
  'tools/behcs/logical-extreme-stress.mjs',
249
  'tools/behcs/logical-stress-cube-feed.mjs',
250
  'tools/behcs/brown-hilbert-expansion-stress.mjs',
 
286
  'tests/cellphone-host-bridge-boundary.unit.test.mjs',
287
  'tests/frozen-slice-city-signal-lifecycle.unit.test.mjs',
288
  'tests/eight-byte-host-process-upgrade.unit.test.mjs',
289
+ 'tests/odysseus-mtp-control-surface.unit.test.mjs',
290
  'tests/logical-extreme-stress.unit.test.mjs',
291
  'tests/logical-stress-cube-feed.unit.test.mjs',
292
  'tests/brown-hilbert-expansion-stress.unit.test.mjs',
tests/supervisor-collision-router.system.test.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- DD76DA203B8D65AA30696D93603D37DA34C1251048290E90E3C908646DD8CE4E supervisor-collision-router.system.test.mjs
 
1
+ 853F2019B6FFCBACC56227AA0045E3094DD00EE411FE7E8EF3A8CF03790F33DF supervisor-collision-router.system.test.mjs
tools/behcs/fabric-agent-preload-catalog.mjs CHANGED
@@ -171,6 +171,12 @@ export const TOOLS = Object.freeze([
171
  provides: 'v8-real-bh-index-cylinder-prime-tier-host-process-upgrade-boundary',
172
  gate: 'descriptor-only-node_per_agent-0-provider_compute_replaced-0-process_launch-0-p5_materialized-0',
173
  }),
 
 
 
 
 
 
174
  Object.freeze({
175
  id: 'token-cube-catalog-binder',
176
  path: 'tools/behcs/token-cube-catalog-binder.mjs',
@@ -344,7 +350,8 @@ export function selfTest() {
344
  && !!toolById('tool-skill-registry-matrix') && !!toolById('program-cube-ingestion-map')
345
  && !!toolById('agent-cost-layer-boundary') && !!toolById('triad-host-router-gulp-pipeline')
346
  && !!toolById('pid-emitter-cost-envelope') && !!toolById('cellphone-host-bridge-boundary')
347
- && !!toolById('frozen-slice-city-signal-lifecycle') && !!toolById('eight-byte-host-process-upgrade'));
 
348
  add('slice-engine-law-preloaded', LAWS.some((law) => law.startsWith('slice-engine-law-'))
349
  && emitPreloadRows().some((row) => row.startsWith('FABPRELOADSLICEENGINE|')));
350
  add('emitters-pipe-hookwall-gnn', EMITTERS.some((e) => e.id === 'hookwall') && EMITTERS.some((e) => e.id === 'gnn-edge'));
 
171
  provides: 'v8-real-bh-index-cylinder-prime-tier-host-process-upgrade-boundary',
172
  gate: 'descriptor-only-node_per_agent-0-provider_compute_replaced-0-process_launch-0-p5_materialized-0',
173
  }),
174
+ Object.freeze({
175
+ id: 'odysseus-mtp-control-surface',
176
+ path: 'tools/behcs/odysseus-mtp-control-surface.mjs',
177
+ provides: 'odysseus-pattern-MTP-descriptor-backed-control-surface-plus-v8-map3d-band',
178
+ gate: 'descriptor-only-live_execution-0-cutover-0-phone_render_proven_here-0',
179
+ }),
180
  Object.freeze({
181
  id: 'token-cube-catalog-binder',
182
  path: 'tools/behcs/token-cube-catalog-binder.mjs',
 
350
  && !!toolById('tool-skill-registry-matrix') && !!toolById('program-cube-ingestion-map')
351
  && !!toolById('agent-cost-layer-boundary') && !!toolById('triad-host-router-gulp-pipeline')
352
  && !!toolById('pid-emitter-cost-envelope') && !!toolById('cellphone-host-bridge-boundary')
353
+ && !!toolById('frozen-slice-city-signal-lifecycle') && !!toolById('eight-byte-host-process-upgrade')
354
+ && !!toolById('odysseus-mtp-control-surface'));
355
  add('slice-engine-law-preloaded', LAWS.some((law) => law.startsWith('slice-engine-law-'))
356
  && emitPreloadRows().some((row) => row.startsWith('FABPRELOADSLICEENGINE|')));
357
  add('emitters-pipe-hookwall-gnn', EMITTERS.some((e) => e.id === 'hookwall') && EMITTERS.some((e) => e.id === 'gnn-edge'));
tools/behcs/fabric-agent-preload-catalog.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- 2D8C985558C801FE76A0D55F0102EC6D2F57BBEA898B2BE93480F263F62476C7 fabric-agent-preload-catalog.mjs
 
1
+ 92DC04C5133E3768C175FB3241C34CBC354E733CE246B4D460E3BE256A42AF2A fabric-agent-preload-catalog.mjs
tools/behcs/odysseus-mtp-control-surface.mjs ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env node
2
+ // odysseus-mtp-control-surface.mjs - binds Odysseus M/T/P cells to v8 map3d.
3
+ //
4
+ // Descriptor-only. This absorbs the Odysseus/ChatOS pattern as an agent work
5
+ // surface: model selector, tool/skill registry, project guide, and real graph
6
+ // band. It does not render a phone UI, launch a model/tool/workflow, fetch a
7
+ // dashboard, or perform a front-end cutover.
8
+
9
+ import { createHash } from 'node:crypto';
10
+ import { resolve } from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+
13
+ import { buildUpgrade } from './eight-byte-host-process-upgrade.mjs';
14
+ import { M_CELL_STATUS, buildSelector, selectRole } from './model-selector-matrix.mjs';
15
+ import { P_CELL_STATUS, buildGuide, guideSection } from './project-guide-matrix.mjs';
16
+ import { T_CELL_STATUS, buildRegistry, registryItem } from './tool-skill-registry-matrix.mjs';
17
+
18
+ export const SURFACE_ID = 'odysseus-mtp-control-surface.v1';
19
+ export const ODYSSEUS_SOURCE = 'docs/LIRIS-ODYSSEUS-CHATOS-FRONTEND-ABSORPTION-2026-06-12.hbp';
20
+ export const BANDS = Object.freeze(['M-model-selector', 'T-tool-skill', 'P-project-guide', 'MAP3D-v8-real-graph']);
21
+
22
+ const sha16 = (text) => createHash('sha256').update(String(text), 'utf8').digest('hex').slice(0, 16);
23
+ const isObj = (x) => x !== null && typeof x === 'object';
24
+ const safe = (x) => String(x ?? '').replace(/[|\r\n]/g, '_').replace(/[^A-Za-z0-9._:/+@=()-]+/g, '-').replace(/^-|-$/g, '') || 'empty';
25
+ const prop = (obj, key, fallback = '') => {
26
+ try { return isObj(obj) ? obj[key] : fallback; } catch { return fallback; }
27
+ };
28
+
29
+ function bandRow({ id, source, status, evidence, next }) {
30
+ return Object.freeze({
31
+ id,
32
+ source: safe(source),
33
+ status: safe(status),
34
+ evidence: safe(evidence),
35
+ next: safe(next),
36
+ row_sha16: sha16([id, source, status, evidence, next].join('|')),
37
+ process_launch: 0,
38
+ live_model_invocation: 0,
39
+ live_tool_execution: 0,
40
+ workflow_execution: 0,
41
+ cutover: 0,
42
+ });
43
+ }
44
+
45
+ export function buildSurface(input = {}) {
46
+ const selector = buildSelector();
47
+ const registry = buildRegistry();
48
+ const guide = buildGuide();
49
+ const graph = buildUpgrade();
50
+ const modelNeed = safe(prop(input, 'model_need') || 'fischer score');
51
+ const toolNeed = safe(prop(input, 'tool_need') || 'cosign submit schema');
52
+ const projectTopic = safe(prop(input, 'project_topic') || 'frontier catch queue');
53
+ const bands = Object.freeze([
54
+ bandRow({
55
+ id: 'M',
56
+ source: 'tools/behcs/model-selector-matrix.mjs',
57
+ status: selector.summary.red === 0 ? 'PARTIAL_DESCRIPTOR_BACKED' : 'RED',
58
+ evidence: `${M_CELL_STATUS}:roles-${selector.summary.total}:green-${selector.summary.green}:partial-${selector.summary.partial}:gated-${selector.summary.gated}`,
59
+ next: 'live-model-contract-and-runtime-proof-before-green',
60
+ }),
61
+ bandRow({
62
+ id: 'T',
63
+ source: 'tools/behcs/tool-skill-registry-matrix.mjs',
64
+ status: registry.summary.red === 0 ? 'PARTIAL_DESCRIPTOR_BACKED' : 'RED',
65
+ evidence: `${T_CELL_STATUS}:items-${registry.summary.total}:green-${registry.summary.green}:partial-${registry.summary.partial}:gated-${registry.summary.gated}`,
66
+ next: 'submit-schema-and-live-tool-execution-proof-before-green',
67
+ }),
68
+ bandRow({
69
+ id: 'P',
70
+ source: 'tools/behcs/project-guide-matrix.mjs',
71
+ status: guide.summary.red === 0 ? 'PARTIAL_DESCRIPTOR_BACKED' : 'RED',
72
+ evidence: `${P_CELL_STATUS}:sections-${guide.summary.total}:green-${guide.summary.green}:partial-${guide.summary.partial}:gated-${guide.summary.gated}`,
73
+ next: 'workflow-binding-and-cosign-submit-schema-proof-before-green',
74
+ }),
75
+ bandRow({
76
+ id: 'MAP3D',
77
+ source: 'tools/behcs/eight-byte-host-process-upgrade.mjs',
78
+ status: graph.summary.p5_materialized === false && graph.summary.provider_compute_replaced === false ? 'REAL_MATH_DESCRIPTOR_BACKED' : 'RED',
79
+ evidence: `hosts-${graph.summary.hosts}:systems-${graph.summary.systems}:node_per_agent-${graph.summary.node_per_agent}:p5_materialized-${graph.summary.p5_materialized ? 1 : 0}`,
80
+ next: 'phone-render-proof-or-browser-screenshot-is-external-to-this-repo',
81
+ }),
82
+ ]);
83
+ const mRoute = selectRole({ need: modelNeed });
84
+ const tRoute = registryItem({ topic: toolNeed });
85
+ const pRoute = guideSection({ topic: projectTopic });
86
+ return Object.freeze({
87
+ tool: SURFACE_ID,
88
+ source: ODYSSEUS_SOURCE,
89
+ bands,
90
+ routes: Object.freeze({
91
+ model: Object.freeze({ need: modelNeed, selected: mRoute.selected, status: safe(prop(mRoute.role, 'status', 'RED')) }),
92
+ tool: Object.freeze({ topic: toolNeed, selected: tRoute.selected, status: safe(prop(tRoute.item, 'status', 'RED')) }),
93
+ project: Object.freeze({ topic: projectTopic, selected: pRoute.selected, status: safe(prop(pRoute.section, 'status', 'RED')) }),
94
+ }),
95
+ summary: Object.freeze({
96
+ bands: bands.length,
97
+ descriptor_backed_bands: bands.filter((b) => b.status !== 'RED').length,
98
+ mtp_descriptor_backed: bands.filter((b) => ['M', 'T', 'P'].includes(b.id) && b.status === 'PARTIAL_DESCRIPTOR_BACKED').length,
99
+ phone_render_proven_here: false,
100
+ cutover_ready: false,
101
+ live_execution_ready: false,
102
+ }),
103
+ });
104
+ }
105
+
106
+ export function emitRows(input = {}) {
107
+ try {
108
+ const surface = buildSurface(input);
109
+ const s = surface.summary;
110
+ const rows = [
111
+ `ODYSSEUSMTPHDR|tool=${SURFACE_ID}|source=${ODYSSEUS_SOURCE}|purpose=bind-MTP-descriptor-cells-to-v8-map3d-agent-control-surface|bands=${s.bands}|descriptor_backed=${s.descriptor_backed_bands}|mtp_descriptor_backed=${s.mtp_descriptor_backed}|process_launch=0|live_execution=0|cutover=0|json=0`,
112
+ `ODYSSEUSMTPSUM|phone_render_proven_here=0|cutover_ready=0|live_execution_ready=0|pattern_absorption=1|code_copy=0|json=0`,
113
+ ];
114
+ for (const band of surface.bands) {
115
+ rows.push(`ODYSSEUSMTPBAND|id=${band.id}|status=${band.status}|source=${band.source}|evidence=${band.evidence}|next=${band.next}|row_sha16=${band.row_sha16}|process_launch=0|live_model_invocation=0|live_tool_execution=0|workflow_execution=0|cutover=0|json=0`);
116
+ }
117
+ rows.push(`ODYSSEUSMTPROUTE|cell=M|need=${safe(surface.routes.model.need)}|selected=${safe(surface.routes.model.selected)}|selected_status=${safe(surface.routes.model.status)}|live_model_invocation=0|json=0`);
118
+ rows.push(`ODYSSEUSMTPROUTE|cell=T|topic=${safe(surface.routes.tool.topic)}|selected=${safe(surface.routes.tool.selected)}|selected_status=${safe(surface.routes.tool.status)}|live_tool_execution=0|json=0`);
119
+ rows.push(`ODYSSEUSMTPROUTE|cell=P|topic=${safe(surface.routes.project.topic)}|selected=${safe(surface.routes.project.selected)}|selected_status=${safe(surface.routes.project.status)}|workflow_execution=0|json=0`);
120
+ rows.push('ODYSSEUSMTPGATE|rule=descriptor-backed-agent-control-surface-not-phone-render-proof-not-live-cutover|provider_terms_apply=1|operator_cosign_required_for_live_actions=1|cutover=0|process_launch=0|json=0');
121
+ return rows;
122
+ } catch {
123
+ return [
124
+ `ODYSSEUSMTPHDR|tool=${SURFACE_ID}|source=${ODYSSEUS_SOURCE}|purpose=bind-MTP-descriptor-cells-to-v8-map3d-agent-control-surface|bands=0|process_launch=0|live_execution=0|cutover=0|json=0`,
125
+ 'ODYSSEUSMTPGATE|rule=emit-threw-held-invalid|provider_terms_apply=1|operator_cosign_required_for_live_actions=1|cutover=0|process_launch=0|json=0',
126
+ ];
127
+ }
128
+ }
129
+
130
+ export function selfTest() {
131
+ const checks = [];
132
+ const add = (name, ok) => checks.push({ name, ok: Boolean(ok) });
133
+ const surface = buildSurface();
134
+ add('all-bands-present', surface.summary.bands === 4 && BANDS.length === 4);
135
+ add('mtp-descriptor-backed-not-green-cutover', surface.summary.mtp_descriptor_backed === 3 && surface.summary.cutover_ready === false);
136
+ add('map3d-bound-to-v8-real-math', surface.bands.some((b) => b.id === 'MAP3D' && b.status === 'REAL_MATH_DESCRIPTOR_BACKED'));
137
+ add('routes-through-existing-mtp-tools', surface.routes.model.selected === 'fischer-draft-standin' && surface.routes.tool.selected === 'cosign-submit-schema' && surface.routes.project.selected === 'frontier-queue');
138
+ add('no-live-execution', surface.bands.every((b) => b.process_launch === 0 && b.live_model_invocation === 0 && b.live_tool_execution === 0 && b.workflow_execution === 0 && b.cutover === 0));
139
+ add('phone-render-not-claimed-here', surface.summary.phone_render_proven_here === false);
140
+ const hostile = emitRows({ model_need: 'x|bad\nODYSSEUSMTPGATE|cutover=1', tool_need: 'y|bad', project_topic: 'z\nbad' });
141
+ add('rows-hbp-only', hostile.every((row) => row.endsWith('|json=0') && !/[\r\n]/.test(row)));
142
+ add('total-never-throws', (() => { try { buildSurface({ get model_need() { throw new Error('boom'); } }); emitRows(null); return true; } catch { return false; } })());
143
+ return { ok: checks.every((c) => c.ok), checks };
144
+ }
145
+
146
+ const isMain = process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1]);
147
+ if (isMain) {
148
+ if (process.argv[2] === '--self-test') {
149
+ const r = selfTest();
150
+ for (const c of r.checks) console.log(`${c.ok ? 'PASS' : 'FAIL'} ${c.name}`);
151
+ process.exit(r.ok ? 0 : 1);
152
+ }
153
+ for (const row of emitRows()) console.log(row);
154
+ }
tools/behcs/odysseus-mtp-control-surface.mjs.sha256 ADDED
@@ -0,0 +1 @@
 
 
1
+ 321E5FD4248FCC3AED8140E5750587082F2519AAC5EE51FD89C69CDD1D8E0123 odysseus-mtp-control-surface.mjs