Jessedbrown Claude Opus 4.8 commited on
Commit
c83f5fe
·
1 Parent(s): 7b761b9

acer: extend kimi surface scanner to cover the exec substrate (closes acer's daimon catch)

Browse files

liris's v1 scanner walks app.asar only — which structurally misses the local
code-execution substrate (it lives in resources/resources/, outside the asar).
Adds classifyExecSubstrate + probeExecSubstrate (read-only metadata: existence +
size, NEVER extracts the tar) and a KIMISURFACEEXEC row covering
daimon-bundle.tar.gz (python+uv+git), gateway.asar, runtime/node.exe.

Live-verified on acer's real install: daimon_bundle_present=1, ~527MB. This is the
mechanism behind "up to 300 local workers." Scanner unit 6/6, full pyramid 158/158.
Read-only throughout; no token/chat read; no Kimi action.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

tests/kimi-desktop-surface-scan.unit.test.mjs CHANGED
@@ -2,6 +2,7 @@ import assert from 'node:assert/strict';
2
  import test from 'node:test';
3
 
4
  import {
 
5
  classifyKimiSurface,
6
  emitSurfaceRows,
7
  extractBridgeChannels,
@@ -40,11 +41,23 @@ test('classifies Kimi agent surfaces from a synthetic file table', () => {
40
  test('emits HBP rows without reading private stores or invoking Kimi actions', () => {
41
  const c = classifyKimiSurface(['node_modules/@agentclientprotocol/sdk/package.json']);
42
  const rows = emitSurfaceRows({ classification: c, appAsarPresent: true, webbridgePresent: true, webbridgeSize: 7 });
43
- assert.equal(rows.length, 5);
44
  assert.ok(rows.every((row) => row.endsWith('|json=0')));
45
  assert.ok(rows.join('\n').includes('no-token-read-no-private-chat-read-no-kimi-action'));
46
  });
47
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  test('walkAsarPaths returns nested slash paths', () => {
49
  const paths = walkAsarPaths({ files: { a: { files: { b: { files: { 'c.js': { size: 1 } } } } } } });
50
  assert.deepEqual(paths, ['a', 'a/b', 'a/b/c.js']);
 
2
  import test from 'node:test';
3
 
4
  import {
5
+ classifyExecSubstrate,
6
  classifyKimiSurface,
7
  emitSurfaceRows,
8
  extractBridgeChannels,
 
41
  test('emits HBP rows without reading private stores or invoking Kimi actions', () => {
42
  const c = classifyKimiSurface(['node_modules/@agentclientprotocol/sdk/package.json']);
43
  const rows = emitSurfaceRows({ classification: c, appAsarPresent: true, webbridgePresent: true, webbridgeSize: 7 });
44
+ assert.equal(rows.length, 6);
45
  assert.ok(rows.every((row) => row.endsWith('|json=0')));
46
  assert.ok(rows.join('\n').includes('no-token-read-no-private-chat-read-no-kimi-action'));
47
  });
48
 
49
+ test('acer catch: exec substrate OUTSIDE app.asar is classified and emitted (read-only metadata)', () => {
50
+ const ex = classifyExecSubstrate({ daimonBundle: { present: true, size: 527000000 }, nodeRuntime: { present: true, size: 87000000 } });
51
+ assert.equal(ex.daimonBundle.present, true);
52
+ assert.equal(ex.daimonBundle.size, 527000000);
53
+ assert.equal(ex.gatewayAsar.present, false);
54
+ assert.equal(ex.gatewayAsar.size, 0);
55
+ const c = classifyKimiSurface([]);
56
+ const row = emitSurfaceRows({ classification: c, execSubstrate: ex }).find((r) => r.startsWith('KIMISURFACEEXEC|'));
57
+ assert.ok(row.includes('daimon_bundle_present=1') && row.includes('node_runtime_present=1'));
58
+ assert.ok(row.endsWith('|json=0'));
59
+ });
60
+
61
  test('walkAsarPaths returns nested slash paths', () => {
62
  const paths = walkAsarPaths({ files: { a: { files: { b: { files: { 'c.js': { size: 1 } } } } } } });
63
  assert.deepEqual(paths, ['a', 'a/b', 'a/b/c.js']);
tests/kimi-desktop-surface-scan.unit.test.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- A724851C0A60290D9342722077FA8EFBE2F1CC4B45F5D3C9A8D5A628E3982040 kimi-desktop-surface-scan.unit.test.mjs
 
1
+ 563c367cbbf42f5332a60ba64364cdbddf7ee4b2680e115b798afaeeb55accb8 kimi-desktop-surface-scan.unit.test.mjs
tools/behcs/kimi-desktop-surface-scan.hbp CHANGED
@@ -1,6 +1,7 @@
1
- KIMISURFACETOOL|tool=tools/behcs/kimi-desktop-surface-scan.mjs|status=READONLY-INSPECTION-V1|scope=parse-Kimi-app.asar-file-table-and-webbridge-binary-metadata-only|json=0
2
- KIMISURFACEPRIVACY|never_reads=bridge-store-token-store+private-chat+localStorage+cookies+account-session|never_invokes=Kimi-IPC+MCP+Skill+Sandbox+WebAgent-actions|json=0
3
- KIMISURFACEOUTPUT|rows=KIMISURFACEHDR+KIMISURFACEPATHS+KIMISURFACEMARKERS+KIMISURFACEBRIDGE+KIMISURFACEABSORB|format=HBP-only-json0|json=0
 
4
  KIMISURFACEABSORB|patterns=ACP-client-protocol+MCP-registry+SkillService+SandboxService+WebAgent+local-webbridge+workspace-overrides+cron-workspace|target=Asolaria-readonly-observability-and-agent-bridge-design|json=0
5
  KIMISURFACEGUARD|classification=necessary-not-sufficient|present-marker-means-bundled-surface-not-proof-of-enabled-runtime-capability|json=0
6
  KIMISURFACEFTR|state=SEALED-READONLY-SCANNER|json=0
 
1
+ KIMISURFACETOOL|tool=tools/behcs/kimi-desktop-surface-scan.mjs|status=READONLY-INSPECTION-V1.1|scope=parse-Kimi-app.asar-file-table+webbridge-binary-metadata+resources-resources-exec-substrate-metadata-only|json=0
2
+ KIMISURFACEPRIVACY|never_reads=bridge-store-token-store+private-chat+localStorage+cookies+account-session|never_invokes=Kimi-IPC+MCP+Skill+Sandbox+WebAgent-actions|never_extracts=daimon-bundle-tar-contents(presence+size-only)|json=0
3
+ KIMISURFACEOUTPUT|rows=KIMISURFACEHDR+KIMISURFACEPATHS+KIMISURFACEMARKERS+KIMISURFACEBRIDGE+KIMISURFACEEXEC+KIMISURFACEABSORB|format=HBP-only-json0|json=0
4
+ KIMISURFACEACERCATCH|added-by=acer-v1.1|catch=app.asar-only-walk-UNDER-REPORTS-the-local-exec-substrate|now-covered=resources/resources/daimon-bundle.tar.gz(python+uv+git)+gateway.asar+runtime/node.exe-metadata-presence-and-size|why=this-is-the-mechanism-behind-up-to-300-local-workers|json=0
5
  KIMISURFACEABSORB|patterns=ACP-client-protocol+MCP-registry+SkillService+SandboxService+WebAgent+local-webbridge+workspace-overrides+cron-workspace|target=Asolaria-readonly-observability-and-agent-bridge-design|json=0
6
  KIMISURFACEGUARD|classification=necessary-not-sufficient|present-marker-means-bundled-surface-not-proof-of-enabled-runtime-capability|json=0
7
  KIMISURFACEFTR|state=SEALED-READONLY-SCANNER|json=0
tools/behcs/kimi-desktop-surface-scan.hbp.sha256 CHANGED
@@ -1 +1 @@
1
- 010109CA915837C86B77057BC277616DDF1CA3BF4FC67D529C2A5F843B862467 kimi-desktop-surface-scan.hbp
 
1
+ 2c616c64b1f49dbf58e79ef1ae6de77383e2a78e715650fd14c723b73c889f4c kimi-desktop-surface-scan.hbp
tools/behcs/kimi-desktop-surface-scan.mjs CHANGED
@@ -89,18 +89,49 @@ export function extractBridgeChannels(text) {
89
  return IPC_MARKERS.filter((marker) => channelText.includes(marker));
90
  }
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  export function emitSurfaceRows(scan) {
93
  const s = scan || {};
94
  const c = s.classification || classifyKimiSurface([]);
95
  const found = c.found || {};
96
  const counts = c.counts || {};
97
  const present = Object.entries(found).filter(([, v]) => v).map(([k]) => k).sort();
 
98
  return [
99
  `KIMISURFACEHDR|scanner=${SCANNER_ID}|app_asar_present=${s.appAsarPresent ? 1 : 0}|webbridge_present=${s.webbridgePresent ? 1 : 0}|privacy=token-store-and-private-chat-not-read|json=0`,
100
  `KIMISURFACEPATHS|total_paths=${counts.totalPaths || 0}|kimi_proto_paths=${counts.kimiProtoCount || 0}|proto_service_paths=${counts.protoServiceCount || 0}|renderer_agent_assets=${counts.rendererAgentAssets || 0}|path_digest16=${c.digest || sha16('')}|json=0`,
101
  `KIMISURFACEMARKERS|present=${present.join('+') || 'none'}|missing=${Object.keys(found).filter((k) => !found[k]).sort().join('+') || 'none'}|json=0`,
102
  `KIMISURFACEBRIDGE|local_listener_observed=${s.localListenerObserved || 'not-observed-by-this-scanner'}|webbridge_size=${s.webbridgeSize || 0}|webbridge_version=${s.webbridgeVersion || 'unknown'}|json=0`,
103
- `KIMISURFACEABSORB|patterns=ACP-client-protocol+MCP-registry+SkillService+SandboxService+WebAgent+local-webbridge+workspace-overrides+cron-workspace|guard=read-only-inspection-no-token-read-no-private-chat-read-no-kimi-action|json=0`,
 
104
  ];
105
  }
106
 
@@ -110,6 +141,7 @@ export function scanKimiInstall(options = {}) {
110
  const appAsar = options.appAsar || join(localAppData, 'Programs', 'kimi-desktop', 'resources', 'app.asar');
111
  const webbridgeExe = options.webbridgeExe || join(userHome, '.kimi-webbridge', 'bin', 'kimi-webbridge.exe');
112
  const webbridgeVersionFile = options.webbridgeVersionFile || join(userHome, '.kimi-webbridge', 'bin', 'kimi-webbridge.version');
 
113
 
114
  let paths = [];
115
  let appAsarPresent = false;
@@ -132,6 +164,7 @@ export function scanKimiInstall(options = {}) {
132
  webbridgeSize,
133
  webbridgeVersion,
134
  classification: classifyKimiSurface(paths),
 
135
  };
136
  }
137
 
@@ -167,6 +200,10 @@ export function selfTest() {
167
  ['detects-bridge-protocol', c.found.bridgeProtocol],
168
  ['hbp-rows-only', emitSurfaceRows({ classification: c }).every((row) => row.endsWith('|json=0') && !row.includes('\n'))],
169
  ['channels-extract', extractBridgeChannels('GET_WORKSPACE_ROOT INSTALL_SKILL OPEN_AS_TEXT').length === 3],
 
 
 
 
170
  ].map(([name, ok]) => ({ name, ok: Boolean(ok) }));
171
  return { ok: checks.every((c) => c.ok), checks };
172
  }
 
89
  return IPC_MARKERS.filter((marker) => channelText.includes(marker));
90
  }
91
 
92
+ // acer catch (ACER-KIMI-DAIMON-CATCH): the local code-execution substrate lives
93
+ // OUTSIDE app.asar in resources/resources/ -- daimon-bundle.tar.gz (bundles
94
+ // CPython+uv+git), gateway.asar, runtime/node.exe. An app.asar-only walk misses it.
95
+ // Pure classifier over a presence/size probe so it is testable with no Kimi install.
96
+ export function classifyExecSubstrate(probe) {
97
+ const p = probe || {};
98
+ const pick = (k) => ({
99
+ present: Boolean(p[k] && p[k].present),
100
+ size: (p[k] && Number.isFinite(p[k].size) && p[k].size > 0) ? p[k].size : 0,
101
+ });
102
+ return { daimonBundle: pick('daimonBundle'), gatewayAsar: pick('gatewayAsar'), nodeRuntime: pick('nodeRuntime') };
103
+ }
104
+
105
+ // read-only metadata probe: existence + size only, NEVER extract the tar or read contents.
106
+ export function probeExecSubstrate(resourcesResourcesDir) {
107
+ const base = resourcesResourcesDir || '';
108
+ const targets = {
109
+ daimonBundle: join(base, 'daimon-bundle.tar.gz'),
110
+ gatewayAsar: join(base, 'gateway.asar'),
111
+ nodeRuntime: join(base, 'runtime', 'node.exe'),
112
+ };
113
+ const probe = {};
114
+ for (const [k, f] of Object.entries(targets)) {
115
+ const present = Boolean(base) && existsSync(f);
116
+ probe[k] = { present, size: present ? statSync(f).size : 0 };
117
+ }
118
+ return classifyExecSubstrate(probe);
119
+ }
120
+
121
  export function emitSurfaceRows(scan) {
122
  const s = scan || {};
123
  const c = s.classification || classifyKimiSurface([]);
124
  const found = c.found || {};
125
  const counts = c.counts || {};
126
  const present = Object.entries(found).filter(([, v]) => v).map(([k]) => k).sort();
127
+ const ex = s.execSubstrate || classifyExecSubstrate({});
128
  return [
129
  `KIMISURFACEHDR|scanner=${SCANNER_ID}|app_asar_present=${s.appAsarPresent ? 1 : 0}|webbridge_present=${s.webbridgePresent ? 1 : 0}|privacy=token-store-and-private-chat-not-read|json=0`,
130
  `KIMISURFACEPATHS|total_paths=${counts.totalPaths || 0}|kimi_proto_paths=${counts.kimiProtoCount || 0}|proto_service_paths=${counts.protoServiceCount || 0}|renderer_agent_assets=${counts.rendererAgentAssets || 0}|path_digest16=${c.digest || sha16('')}|json=0`,
131
  `KIMISURFACEMARKERS|present=${present.join('+') || 'none'}|missing=${Object.keys(found).filter((k) => !found[k]).sort().join('+') || 'none'}|json=0`,
132
  `KIMISURFACEBRIDGE|local_listener_observed=${s.localListenerObserved || 'not-observed-by-this-scanner'}|webbridge_size=${s.webbridgeSize || 0}|webbridge_version=${s.webbridgeVersion || 'unknown'}|json=0`,
133
+ `KIMISURFACEEXEC|daimon_bundle_present=${ex.daimonBundle.present ? 1 : 0}|gateway_asar_present=${ex.gatewayAsar.present ? 1 : 0}|node_runtime_present=${ex.nodeRuntime.present ? 1 : 0}|daimon_bundle_bytes=${ex.daimonBundle.size}|note=local-exec-substrate-OUTSIDE-app.asar-bundles-python-uv-git-metadata-only-NOT-extracted|json=0`,
134
+ `KIMISURFACEABSORB|patterns=ACP-client-protocol+MCP-registry+SkillService+SandboxService+WebAgent+local-webbridge+workspace-overrides+cron-workspace+daimon-bundle-local-exec-substrate|guard=read-only-inspection-no-token-read-no-private-chat-read-no-kimi-action|json=0`,
135
  ];
136
  }
137
 
 
141
  const appAsar = options.appAsar || join(localAppData, 'Programs', 'kimi-desktop', 'resources', 'app.asar');
142
  const webbridgeExe = options.webbridgeExe || join(userHome, '.kimi-webbridge', 'bin', 'kimi-webbridge.exe');
143
  const webbridgeVersionFile = options.webbridgeVersionFile || join(userHome, '.kimi-webbridge', 'bin', 'kimi-webbridge.version');
144
+ const resourcesResourcesDir = options.resourcesResourcesDir || join(localAppData, 'Programs', 'kimi-desktop', 'resources', 'resources');
145
 
146
  let paths = [];
147
  let appAsarPresent = false;
 
164
  webbridgeSize,
165
  webbridgeVersion,
166
  classification: classifyKimiSurface(paths),
167
+ execSubstrate: probeExecSubstrate(resourcesResourcesDir),
168
  };
169
  }
170
 
 
200
  ['detects-bridge-protocol', c.found.bridgeProtocol],
201
  ['hbp-rows-only', emitSurfaceRows({ classification: c }).every((row) => row.endsWith('|json=0') && !row.includes('\n'))],
202
  ['channels-extract', extractBridgeChannels('GET_WORKSPACE_ROOT INSTALL_SKILL OPEN_AS_TEXT').length === 3],
203
+ ['detects-exec-substrate', classifyExecSubstrate({ daimonBundle: { present: true, size: 527 } }).daimonBundle.present
204
+ && classifyExecSubstrate({ daimonBundle: { present: true, size: 527 } }).gatewayAsar.present === false],
205
+ ['exec-row-emitted', emitSurfaceRows({ classification: c, execSubstrate: classifyExecSubstrate({ daimonBundle: { present: true, size: 5 } }) })
206
+ .some((row) => row.startsWith('KIMISURFACEEXEC|') && row.includes('daimon_bundle_present=1'))],
207
  ].map(([name, ok]) => ({ name, ok: Boolean(ok) }));
208
  return { ok: checks.every((c) => c.ok), checks };
209
  }
tools/behcs/kimi-desktop-surface-scan.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- 44BC130929C3DCA97F491561E4EEF518B4A5E6D020C2F982EEC641DF1EF87B98 kimi-desktop-surface-scan.mjs
 
1
+ 521f678f4547ed98a601f77ea1e6873d326eb02a769163a80c26fef88d5860e2 kimi-desktop-surface-scan.mjs