deadbyte-mcp 0.15.3 → 0.15.4

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/MANIFEST.SHA256 CHANGED
@@ -1328,7 +1328,7 @@ db605a698f917c4006462596e6526fe6a9c6eff9b8409e8472fe545d4b70027c node_modules/z
1328
1328
  f67a25ded944912bd4621b68df17c7c70a52aae117278c076c0aabbc32a3abba node_modules/zod/v4/mini/schemas.d.ts
1329
1329
  51b3a7869df2d3a1bd98acb9d5b6a61bbccc7653d7a3d8fca7f0e0db7e84e284 node_modules/zod/v4/mini/schemas.js
1330
1330
  3e3125b5a537a24c3632c1c5c09640ce7bcb3935901b127ad8ae3c37a27f133f node_modules/zod/v4/package.json
1331
- c4b737f228612561169b4f9cccc8f5c33c57e2461506cc8df9e5b984800acba0 package.json
1331
+ 79175ae788fe8d549c51586c57605fd2558af0dfbcea4d916394be7620e3730b package.json
1332
1332
  8177e3a354721a73df889f386a97e7744a2e017d150aecf4bf309f5177d18690 proof/CONTAINMENT-BUILD.txt
1333
1333
  a8efa13e44ff50902aee64cfca542d19605a1ae23db95280ad2d44b324f3eae7 proof/MCP-SMOKE-STATUS.txt
1334
1334
  7c115069cc4a343ca21b0ebdee74bd8f544b02d4aa906ffa13308725825d891a proof/NODE-SYNTAX.txt
@@ -1388,7 +1388,7 @@ d433aaea5cccd1e184775ac4d915f34e0b39c6c99916dddd009731ad5fd6443f proof/V073-WIN
1388
1388
  bd0773a9e02e8ab11475c9cc5a7db29a8313233b7eab7f837922737e75ec5938 proof/VERIFY.txt
1389
1389
  2c821808d4596965c577f40191daee224d3aea81989778c4af97f53a83b487db proof/WINDOWS-CONTAINED-STATUS.txt
1390
1390
  f8bc839c7b4fcb0ea7b7e7ad9448847c3beae6f95f2eb4d407d1b284aaa4ff68 proof/WINDOWS-CONTAINMENT-STATUS.txt
1391
- 1976040c88ef2cf0911a6578ef31291758d99598fe28c84a169822df548fada1 PROVENANCE.json
1391
+ e0788cf183f40755bf892a93d1067a79aa6a68641d60e31568fc604bb66d3e94 PROVENANCE.json
1392
1392
  27ca0f3c9ee3a1b6374a9c8dd98008decdd0c7659c7a569c70ad7b9734c74655 R34-BASELINE.json
1393
1393
  0b7ec5ee347ddfa6cca59740fc7a8fe3fc5d51406265bb12189e82fa106319d2 R41-PARENT.json
1394
1394
  bd2a789b0aab5663f0d208af2ca8e4ec98179bc8c7b57e70a962d4e06a3dcfc4 R42-PARENT.json
@@ -1397,7 +1397,7 @@ f932ef78b7a72b1bb0d7aedb5fe42fbb9951c2492eb528b72442f46ddff81a6c R44-DONORS.jso
1397
1397
  731b4c559fc0d25dea701e4474f02400b27e8e3f4cac9f230d5214497d4490a9 R44-PARENT.json
1398
1398
  d33ec5d167dd44800ba4e68372b08db43deb8d01df2ef71dd435ff004ac66c8b R45-PARENT.json
1399
1399
  9928e50a62721b5b953c8b2851bc81625a8b4b5ea10470b8080983d746f764d9 README.txt
1400
- ea437b51dc76a18bc6bfdbdd17874144184cfbd7eec49ea0e2703fb3a61d973d RELEASE.json
1400
+ 6c233588e01f646535bdf2d1ab5130202dfcfb49b540be961777ef27396631d1 RELEASE.json
1401
1401
  507a42441c8fbb0b1bef63a13fad9e1680262cd6d34cc176b7ed0c5423ddbcc7 SBOM.cdx.json
1402
1402
  bd138fe5a64088e8e1a7a5bf6104c5b17317bdc8cf3ad8191ea00ed82ace7d9b scripts/agent-eval-r42.mjs
1403
1403
  1d4e9dee6f0669bd825334a6a72e13ee85ee29ab430dcef21d893ffd744774b5 scripts/autonomous-benchmark.mjs
@@ -1562,12 +1562,12 @@ da5181cec30034ddf089baa5358becb5651da238a2e7cf0888007a4c60b4ea6b src/capability
1562
1562
  2b62295591f142ca4b3bc5b03e6434f7fc3c51d9502f9a40ef8a03d1f72a8899 src/capability-benchmark.mjs
1563
1563
  160199b25f45bd0490f6b21a9fa8194313e9673c4b2699afce68249d3d249a7b src/capability-ledger.mjs
1564
1564
  94e5aeff2453cdc0239aee4d547dbbefee183c71933cb84e5e8a418fa99bc1e8 src/codex-app-server-r44.mjs
1565
- 56b5b37716ce1590bd3531841a5d6509fdf32bd2bb2330b842174726b8decd08 src/coding-mcp-tools.mjs
1566
- 379d94e7d4bb18f659eb08ed20fe5cd42f5d418335d5ae4aedc740ddfa7f3c54 src/coding-output-contracts.mjs
1565
+ 6d0a80daaa2711e67e2597bff3db5bd2802682f559107a492f3cd89b9c6785ed src/coding-mcp-tools.mjs
1566
+ d6fc395575f49abbbf60bf6f6ef5ee9ad51034a7e770a381e6ec34f869788306 src/coding-output-contracts.mjs
1567
1567
  0857a458e9c5101eee94c0596b7699adc34c50687455688fe38d03d241d27935 src/coding-plane.mjs
1568
- 57dfef5a42f3863e2514e3f3b91497bfd412a3371e2d1d09cc7cd16cba992ba6 src/coding-search.mjs
1568
+ 38a1b4e9f5aa14cd5fd9058345c3480ae72c4a6a6eeccdc46e71297c68b5b5a6 src/coding-search.mjs
1569
1569
  f87284dc71c167f6a17575b93730c258ed6c433831013c776bf2d14e2b77767f src/coding-task-runtime.mjs
1570
- 881b138dac41b33a4f57a137d23398261b1147307217b54dceb59bce800388d2 src/compact-gateway-mcp-tools.mjs
1570
+ bfe4b641b61e4e7da8848c6c39d256a39191639315fb9f3c17a0b11f999ec792 src/compact-gateway-mcp-tools.mjs
1571
1571
  4218d1d1478d9e9a044d9b61c5ae205cd2ca0651a314900fad03992d0b12d286 src/compact-gateway-output-contracts.mjs
1572
1572
  40ac70ece531de7709d3c51686b36b48e0ae60283d1fb18d0adc037bfe6f9063 src/contained-cli.mjs
1573
1573
  d2bacef2443705e372071d0de3c72d45d57febb1dcbb11e369fce8a78bf0bf3e src/contained-executor.mjs
@@ -1596,17 +1596,20 @@ f57fe200ad916a03480c804ca57ab12b603822cbfb8d45ba7bce4376ec3d712a src/document-a
1596
1596
  ea03db2bb706033f32045ed1dad67925d0d2e89cc97bc1aff805736dcab3b153 src/evidence-publisher-r42.mjs
1597
1597
  f5fafd46052b09f71a528594eb230edc5766ee0d006432d744590ec97c9c580d src/executor.mjs
1598
1598
  bd5b4496676d5399cfd73a684af4aff06b44af9ab51f0d5901ead00c4c540e74 src/external-job-provider-r44.mjs
1599
+ 99d741c72028e1cea94e971f1863a299eb6fb3445ea0d0b6af5b40ae5ee06d0c src/fuzzy-search-core.mjs
1600
+ f6c316f52e9096a92879dbc5debf63a486953bf87b65620601c0a5a0a96eae1f src/fuzzy-search-worker.mjs
1601
+ f89acac9935ec9e757ee611893d1ffbe04ae3c2a03c43feb87af0427da39e830 src/fuzzy-search.mjs
1599
1602
  264d21a4385a0a04613fe78203e7f5e231a5c06397086cfacc88076e60b89b71 src/hash.mjs
1600
1603
  880e942358ba4fae2139027f924b79045a7cc90c775b09761d35cd5e411b005f src/host-plane.mjs
1601
1604
  cd00584f346160c8ad16b4dcf64b3fb6499668f3bc299c199b67f53caa995746 src/ingress-mode.mjs
1602
1605
  e1afae872e4252a4002032f1610033d41f5224896b0b06be077f54b267ed4f4f src/invocation.mjs
1603
1606
  9efb25c69ecb0cf5778483d24a3944d2f08f52ebcbd271a212e89189add50167 src/job-supervisor-host-r44.mjs
1604
1607
  532fbd7d5402bb9d65b81a1efdfa9ea1d7292d96e1d9c2d1e8d40ccc52af2670 src/lsp-stdio-client.mjs
1605
- e130a08d7c33755537133108778caa4972b0a7cefb1ac348200a13bcc12452e3 src/machine-fs-mcp-tools.mjs
1606
- 8fbbccf4f94d14d0ff514757d51da995012dd709bd6f3e31141abc4ab16b0b5d src/machine-fs-output-contracts.mjs
1608
+ 6856b81e8aab42d144b88d0c4be5b2b4c9ad7e51b5bb36d2d4e8fd134935ae56 src/machine-fs-mcp-tools.mjs
1609
+ ff54c503b8503b2837d8eb3c4a2e0d06e67c609e43b964c7a1a1305c135c2bbf src/machine-fs-output-contracts.mjs
1607
1610
  7f68488f9e48ada11b1f1ea64032efa82a68dc6b632fffcf37fbe9bd95237e26 src/machine-fs-read-worker.mjs
1608
1611
  4b46fca90489cc314c5dd884d4d0968f7702c512f87a3166d2bc12023767caf8 src/machine-fs-smoke-client.mjs
1609
- 894eaaa069d562856d90f87c75386ef2b60d220b5328e2525d6395eda1427c04 src/machine-fs.mjs
1612
+ 74391e536f403e27de471fa6a452a79f236addaba4b4dee97f8f94060f599866 src/machine-fs.mjs
1610
1613
  14c072f1eefac6e9a7b91e50a0eb4669b972212c1e4bab03c8141fef86933cc8 src/machine-identity.mjs
1611
1614
  ad4ca3635cb228b57b5b98e9518f379380ee1a03ad07ab4d12f8b7f324be2517 src/machine-mcp-tools.mjs
1612
1615
  e81b3ac2955e5dfafe308c82da24356a14da396230cb9fc47b231ab672d5be48 src/machine-output-contracts.mjs
@@ -1835,6 +1838,7 @@ f95c920ee2b24d5ec940a9bae277771562ce275556bd89f0071f183b13c154b8 test/fixtures/
1835
1838
  3eddb2d1ac91187c59d9989b015886953a93e5ce84f0fd1710f4801be6b19efc test/full-max-catalog-r44.test.mjs
1836
1839
  3d257a6d8313548e9b4327cf8b8a49cabd5af035d9bff2e1edc58a15eae80309 test/full-max-catalog-r45.test.mjs
1837
1840
  54f5096003ea13a6232a1e4756c7496a3d6425c145d9bef4f96696cdc22df024 test/full-max-catalog-r46.test.mjs
1841
+ 3cecf2bb61027d210f6bdf65a140ce1d5bedf2d4135e02f94edfeb2ef89ae6ae test/fuzzy-search-r46.test.mjs
1838
1842
  506e5437ed41da3955d006294d81230c25825ff898b266fa2758ffd885ee3d07 test/hardware-observation-r45.test.mjs
1839
1843
  2efdac248a608fe84588de8e9223f39ee32d4a483f71594ab05f20f1110be0c9 test/helpers/autonomous-r34-fixture.mjs
1840
1844
  78f9efaafe3286a3003209e8fb4c0117822d3f8996508159e19e217b1246faba test/helpers/coding-crash-child.mjs
@@ -1842,8 +1846,8 @@ f95c920ee2b24d5ec940a9bae277771562ce275556bd89f0071f183b13c154b8 test/fixtures/
1842
1846
  e80f4172b400f126d0280eba53ffcc748597442ef57c4a62b3fd6f76c27e5fdc test/host-plane.test.mjs
1843
1847
  1205e33a1924dcc33a18372f0c973076fff39e99203a671b39d14269d51b2999 test/human-clarification-r42.test.mjs
1844
1848
  b12322450d23f44513b02d2c54f216520f392bf76e221af22fdcb5a11261ec3d test/lsp-stdio-client.test.mjs
1845
- 3772b033ff6ae9065458b7539eef4b158140952e5e32376c596055bf1ae4e493 test/machine-fs-mcp-tools.test.mjs
1846
- 0016edf22e48480a66e6cc6c1d4b85c2a90f6333e09545f7a1e08eb5e44a7732 test/machine-fs-runtime.test.mjs
1849
+ af1716b6b831eabe8f43e1276b85519c3cedee9ecb98d261033ac3f5e6f84166 test/machine-fs-mcp-tools.test.mjs
1850
+ 6eae806805d59a844e27ff410313874bc263c84a84d83dc166b442448092c3be test/machine-fs-runtime.test.mjs
1847
1851
  ce6b64a55a3288d9c94d3ee700c508544cd2339636fc65ad4915b7f607836182 test/machine-identity.test.mjs
1848
1852
  4429edf1a34a94e58e1bde7554af160fdf122d508ec78b01f375169a544ea422 test/machine-mcp-integration.test.mjs
1849
1853
  fc9662d3c92d0615e9ef54ec1853862358c71659917567ae6e614912ed0b1cfc test/machine-mcp-tools.test.mjs
package/PROVENANCE.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "schema": "deadbyte.provenance.v1",
3
- "version": "0.15.2",
3
+ "version": "0.15.4",
4
4
  "builder": "deadbyte-r46-fileless-powershell",
5
5
  "source_model": "development-root -> MANIFEST.SHA256 -> immutable release slot -> generation bundle -> signed final closure",
6
6
  "signing": "ed25519",
7
- "parent_release_id": "v0.15.1-d55f00b5144dc31a",
8
- "parent_manifest_sha256": "d55f00b5144dc31a7fe39e4dc60d640a94780da6aaeca0918e87636b816d7854",
7
+ "parent_release_id": "v0.15.2-0fb46542f6a4345f",
8
+ "parent_manifest_sha256": "0fb46542f6a4345f1c527565d06bf6e9b8e283260e47bf684fb70a60308fcf34",
9
9
  "reproducibility": "manifest-bound package bytes; native payloads hash-bound; Windows process executables target-repinned",
10
10
  "parent_generation_manifest_sha256": "00cde7bf540cc2804d679a39040d5b07193c5f8a0d49cac3b882402f8f4e6ad8"
11
11
  }
package/RELEASE.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schema": "deadbyte.release.v1",
3
3
  "name": "deadbyte-mcp",
4
- "version": "0.15.2",
4
+ "version": "0.15.4",
5
5
  "train": "R46",
6
6
  "label": "FILELESS POWERSHELL PRODUCT BASELINE",
7
7
  "protocol_revision": "2026-07-28",
8
8
  "parent": {
9
- "release_id": "v0.15.1-d55f00b5144dc31a",
10
- "manifest_sha256": "d55f00b5144dc31a7fe39e4dc60d640a94780da6aaeca0918e87636b816d7854",
9
+ "release_id": "v0.15.2-0fb46542f6a4345f",
10
+ "manifest_sha256": "0fb46542f6a4345f1c527565d06bf6e9b8e283260e47bf684fb70a60308fcf34",
11
11
  "generation_manifest_sha256": "00cde7bf540cc2804d679a39040d5b07193c5f8a0d49cac3b882402f8f4e6ad8"
12
12
  },
13
13
  "platform": {
package/package.json CHANGED
@@ -1,88 +1,88 @@
1
- {
2
- "name": "deadbyte-mcp",
3
- "version": "0.15.3",
4
- "private": false,
5
- "type": "module",
6
- "description": "Authenticated MCP agentic runtime with signed skills, persistent model backends, identity-bound remote devices, durable job supervision, immutable release slots, and separately revocable machine authority.",
7
- "engines": {
8
- "node": "\u003e=22"
9
- },
10
- "scripts": {
11
- "test": "node --test test/*.test.mjs",
12
- "manifest:write": "node scripts/release-manifest.mjs write",
13
- "manifest:verify": "node scripts/release-manifest.mjs verify",
14
- "r41:parent:verify": "node scripts/verify-r41-parent.mjs",
15
- "r41:memory:verify": "node scripts/verify-memory-r41.mjs",
16
- "r42:parent:verify": "node scripts/verify-r42-parent.mjs",
17
- "r42:eval": "node scripts/agent-eval-r42.mjs",
18
- "self-update:runtime": "node scripts/runtime-self-update.mjs",
19
- "self-update:deferred": "node scripts/deferred-slot-operation-r46.mjs",
20
- "release:parity": "node scripts/release-parity-r46.mjs",
21
- "release:final:write": "node scripts/final-closure-r46.mjs",
22
- "release:final:verify": "node scripts/final-closure-verify-r46.mjs",
23
- "proof": "node src/proof-cli.mjs workspaces/demo input.txt",
24
- "verify": "node src/verifier-cli.mjs workspaces/demo evidence/latest.json",
25
- "trust:init": "node src/trust-init.mjs",
26
- "mcp": "node src/mcp-server.mjs",
27
- "mcp:smoke": "node src/mcp-smoke-client.mjs",
28
- "mcp:agent:smoke": "node --test test/agent-runtime.test.mjs test/agent-runtime-adversarial.test.mjs test/agent-runtime-crash.test.mjs test/agent-task-receipt.test.mjs",
29
- "mcp:coding:smoke": "node --test test/coding-plane.test.mjs test/coding-plane-adversarial.test.mjs test/coding-runtime.test.mjs test/coding-crash.test.mjs",
30
- "mcp:machine-fs:smoke": "node src/machine-fs-smoke-client.mjs",
31
- "mcp:observation:smoke": "node src/observation-smoke-client.mjs",
32
- "mcp:process:smoke": "node src/process-smoke-client.mjs",
33
- "process:policy:refresh": "node scripts/refresh-process-policy.mjs",
34
- "mcp:autonomous:smoke": "node --test test/autonomous-runtime.test.mjs test/autonomous-loop.test.mjs test/autonomous-adversarial.test.mjs test/autonomous-supervisor-integration.test.mjs test/native-diff.test.mjs",
35
- "containment:build": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-containment.ps1",
36
- "containment:smoke": "node src/containment-smoke.mjs appcontainer",
37
- "containment:bootstrap": "node src/containment-bootstrap.mjs",
38
- "containment:smoke:lpac": "node src/containment-smoke.mjs lpac",
39
- "containment:smoke:appcontainer": "node src/containment-smoke.mjs appcontainer",
40
- "containment:construction": "node src/containment-construction.mjs",
41
- "containment:child-control": "node src/containment-child-control.mjs",
42
- "contained:run": "node src/contained-cli.mjs workspaces/demo input.txt",
43
- "contained:smoke": "node src/contained-smoke.mjs",
44
- "mcp:contained:smoke": "node src/mcp-contained-smoke-client.mjs",
45
- "gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r46.ps1",
46
- "authority:smoke": "node src/authority-smoke.mjs",
47
- "mcp:remote:smoke": "node src/remote-mcp-smoke-client.mjs",
48
- "mcp:host:smoke": "node src/mcp-host-smoke-client.mjs",
49
- "host:policy:init": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/init-host-policy.ps1",
50
- "mcp:remote:host:smoke": "node src/remote-mcp-host-smoke-client.mjs",
51
- "mcp:remote:autonomous:smoke": "node src/remote-mcp-autonomous-smoke-client.mjs",
52
- "mcp:tunnel-compat:smoke": "node src/tunnel-stdio-compat-smoke.mjs",
53
- "audit:verify": "node src/deadbyte-cli.mjs audit verify",
54
- "audit:status": "node src/deadbyte-cli.mjs audit status",
55
- "desktop:build": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-desktop-r40.ps1",
56
- "desktop:policy:refresh": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/init-desktop-policy-r40.ps1",
57
- "r43:parent:verify": "node scripts/verify-r43-parent.mjs",
58
- "r43:full:test": "node scripts/full-regression-r43.mjs",
59
- "r44:parent:verify": "node scripts/verify-r44-parent.mjs",
60
- "r44:full:test": "node scripts/full-regression-r44.mjs",
61
- "finalize:r44": "node scripts/finalize-r44.mjs",
62
- "hardware:build": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-hardware-r45.ps1",
63
- "doctor": "node src/deadbyte-cli.mjs doctor",
64
- "r45:parent:verify": "node scripts/verify-r45-parent.mjs",
65
- "r45:full:test": "node scripts/full-regression-r45.mjs",
66
- "finalize:r45": "node scripts/finalize-r45.mjs",
67
- "r46:fileless:test": "node --test --test-concurrency=1 test/process-policy.test.mjs test/process-policy-refresh.test.mjs test/release-generation.test.mjs test/process-runtime.test.mjs test/process-mcp-tools.test.mjs test/compact-gateway-r36.test.mjs test/capability-ledger-r36.test.mjs test/remote-device-r44.test.mjs test/observation-runtime.test.mjs test/observation-mcp-tools.test.mjs",
68
- "r46:full:test": "node scripts/full-regression-r46.mjs"
69
- },
70
- "bundleDependencies": [
71
- "@modelcontextprotocol/server",
72
- "@modelcontextprotocol/client",
73
- "typescript",
74
- "zod"
75
- ],
76
- "dependencies": {
77
- "@modelcontextprotocol/client": "2.0.0",
78
- "@modelcontextprotocol/server": "2.0.0",
79
- "typescript": "5.9.3",
80
- "zod": "4.4.3"
81
- },
82
- "bin": {
83
- "deadbyte-mcp": "src/deadbyte-cli.mjs"
84
- },
85
- "publishConfig": {
86
- "access": "public"
87
- }
88
- }
1
+ {
2
+ "name": "deadbyte-mcp",
3
+ "version": "0.15.4",
4
+ "private": false,
5
+ "type": "module",
6
+ "description": "Authenticated MCP agentic runtime with signed skills, persistent model backends, identity-bound remote devices, durable job supervision, immutable release slots, and separately revocable machine authority.",
7
+ "engines": {
8
+ "node": ">=22"
9
+ },
10
+ "scripts": {
11
+ "test": "node --test test/*.test.mjs",
12
+ "manifest:write": "node scripts/release-manifest.mjs write",
13
+ "manifest:verify": "node scripts/release-manifest.mjs verify",
14
+ "r41:parent:verify": "node scripts/verify-r41-parent.mjs",
15
+ "r41:memory:verify": "node scripts/verify-memory-r41.mjs",
16
+ "r42:parent:verify": "node scripts/verify-r42-parent.mjs",
17
+ "r42:eval": "node scripts/agent-eval-r42.mjs",
18
+ "self-update:runtime": "node scripts/runtime-self-update.mjs",
19
+ "self-update:deferred": "node scripts/deferred-slot-operation-r46.mjs",
20
+ "release:parity": "node scripts/release-parity-r46.mjs",
21
+ "release:final:write": "node scripts/final-closure-r46.mjs",
22
+ "release:final:verify": "node scripts/final-closure-verify-r46.mjs",
23
+ "proof": "node src/proof-cli.mjs workspaces/demo input.txt",
24
+ "verify": "node src/verifier-cli.mjs workspaces/demo evidence/latest.json",
25
+ "trust:init": "node src/trust-init.mjs",
26
+ "mcp": "node src/mcp-server.mjs",
27
+ "mcp:smoke": "node src/mcp-smoke-client.mjs",
28
+ "mcp:agent:smoke": "node --test test/agent-runtime.test.mjs test/agent-runtime-adversarial.test.mjs test/agent-runtime-crash.test.mjs test/agent-task-receipt.test.mjs",
29
+ "mcp:coding:smoke": "node --test test/coding-plane.test.mjs test/coding-plane-adversarial.test.mjs test/coding-runtime.test.mjs test/coding-crash.test.mjs",
30
+ "mcp:machine-fs:smoke": "node src/machine-fs-smoke-client.mjs",
31
+ "mcp:observation:smoke": "node src/observation-smoke-client.mjs",
32
+ "mcp:process:smoke": "node src/process-smoke-client.mjs",
33
+ "process:policy:refresh": "node scripts/refresh-process-policy.mjs",
34
+ "mcp:autonomous:smoke": "node --test test/autonomous-runtime.test.mjs test/autonomous-loop.test.mjs test/autonomous-adversarial.test.mjs test/autonomous-supervisor-integration.test.mjs test/native-diff.test.mjs",
35
+ "containment:build": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-containment.ps1",
36
+ "containment:smoke": "node src/containment-smoke.mjs appcontainer",
37
+ "containment:bootstrap": "node src/containment-bootstrap.mjs",
38
+ "containment:smoke:lpac": "node src/containment-smoke.mjs lpac",
39
+ "containment:smoke:appcontainer": "node src/containment-smoke.mjs appcontainer",
40
+ "containment:construction": "node src/containment-construction.mjs",
41
+ "containment:child-control": "node src/containment-child-control.mjs",
42
+ "contained:run": "node src/contained-cli.mjs workspaces/demo input.txt",
43
+ "contained:smoke": "node src/contained-smoke.mjs",
44
+ "mcp:contained:smoke": "node src/mcp-contained-smoke-client.mjs",
45
+ "gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r46.ps1",
46
+ "authority:smoke": "node src/authority-smoke.mjs",
47
+ "mcp:remote:smoke": "node src/remote-mcp-smoke-client.mjs",
48
+ "mcp:host:smoke": "node src/mcp-host-smoke-client.mjs",
49
+ "host:policy:init": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/init-host-policy.ps1",
50
+ "mcp:remote:host:smoke": "node src/remote-mcp-host-smoke-client.mjs",
51
+ "mcp:remote:autonomous:smoke": "node src/remote-mcp-autonomous-smoke-client.mjs",
52
+ "mcp:tunnel-compat:smoke": "node src/tunnel-stdio-compat-smoke.mjs",
53
+ "audit:verify": "node src/deadbyte-cli.mjs audit verify",
54
+ "audit:status": "node src/deadbyte-cli.mjs audit status",
55
+ "desktop:build": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-desktop-r40.ps1",
56
+ "desktop:policy:refresh": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/init-desktop-policy-r40.ps1",
57
+ "r43:parent:verify": "node scripts/verify-r43-parent.mjs",
58
+ "r43:full:test": "node scripts/full-regression-r43.mjs",
59
+ "r44:parent:verify": "node scripts/verify-r44-parent.mjs",
60
+ "r44:full:test": "node scripts/full-regression-r44.mjs",
61
+ "finalize:r44": "node scripts/finalize-r44.mjs",
62
+ "hardware:build": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-hardware-r45.ps1",
63
+ "doctor": "node src/deadbyte-cli.mjs doctor",
64
+ "r45:parent:verify": "node scripts/verify-r45-parent.mjs",
65
+ "r45:full:test": "node scripts/full-regression-r45.mjs",
66
+ "finalize:r45": "node scripts/finalize-r45.mjs",
67
+ "r46:fileless:test": "node --test --test-concurrency=1 test/process-policy.test.mjs test/process-policy-refresh.test.mjs test/release-generation.test.mjs test/process-runtime.test.mjs test/process-mcp-tools.test.mjs test/compact-gateway-r36.test.mjs test/capability-ledger-r36.test.mjs test/remote-device-r44.test.mjs test/observation-runtime.test.mjs test/observation-mcp-tools.test.mjs",
68
+ "r46:full:test": "node scripts/full-regression-r46.mjs"
69
+ },
70
+ "bundleDependencies": [
71
+ "@modelcontextprotocol/server",
72
+ "@modelcontextprotocol/client",
73
+ "typescript",
74
+ "zod"
75
+ ],
76
+ "dependencies": {
77
+ "@modelcontextprotocol/client": "2.0.0",
78
+ "@modelcontextprotocol/server": "2.0.0",
79
+ "typescript": "5.9.3",
80
+ "zod": "4.4.3"
81
+ },
82
+ "bin": {
83
+ "deadbyte-mcp": "src/deadbyte-cli.mjs"
84
+ },
85
+ "publishConfig": {
86
+ "access": "public"
87
+ }
88
+ }
@@ -70,14 +70,14 @@ export function registerCodingTools(server, { codingRuntime, taskRuntime, semant
70
70
  server.registerTool('coding_search', {
71
71
  description: 'Deterministic bounded content/path search with literal or regex mode, signed cursor paging, and observed file identities.',
72
72
  inputSchema: z.strictObject({ root_id: rootId, path: relPath.default('.'), pattern: z.string().min(1).max(256),
73
- target: z.enum(['content','path']).default('content'), mode: z.enum(['literal','regex']).default('literal'), case_sensitive: z.boolean().default(false),
73
+ target: z.enum(['content','path']).default('content'), mode: z.enum(['literal','regex','fuzzy']).default('literal'), case_sensitive: z.boolean().default(false),
74
74
  max_results: z.number().int().min(1).max(1000).default(200), max_file_bytes: z.number().int().min(1).max(4194304).default(262144),
75
75
  max_scan_bytes: z.number().int().min(1).max(67108864).default(4194304), page_size: z.number().int().min(1).max(500).default(100),
76
- cursor: z.string().max(8192).nullable().default(null) }),
76
+ cursor: z.string().max(8192).nullable().default(null), fuzzy_timeout_ms: z.number().int().min(100).max(30000).default(30000) }),
77
77
  outputSchema: codingSearchOutputSchema
78
- }, async ({ root_id, path, pattern, target, mode, case_sensitive, max_results, max_file_bytes, max_scan_bytes, page_size, cursor }) => {
78
+ }, async ({ root_id, path, pattern, target, mode, case_sensitive, max_results, max_file_bytes, max_scan_bytes, page_size, cursor, fuzzy_timeout_ms }) => {
79
79
  try { return result(codingSearchOutputSchema, await codingRuntime.search({ rootId: root_id, path, pattern, target, mode, caseSensitive: case_sensitive,
80
- maxResults: max_results, maxFileBytes: max_file_bytes, maxScanBytes: max_scan_bytes, pageSize: page_size, cursor })); }
80
+ maxResults: max_results, maxFileBytes: max_file_bytes, maxScanBytes: max_scan_bytes, pageSize: page_size, cursor, fuzzyTimeoutMs: fuzzy_timeout_ms })); }
81
81
  catch (error) { return fail(codingSearchOutputSchema, error); }
82
82
  });
83
83
 
@@ -92,7 +92,8 @@ export const codingSearchOutputSchema = statusContract({
92
92
  pattern: z.string().min(1).max(256).optional(), target: z.enum(['content','path']).optional(),
93
93
  mode: z.enum(['literal','regex']).optional(), case_sensitive: z.boolean().optional(),
94
94
  matches: z.array(z.strictObject({ path: z.string().min(1).max(512), line: z.number().int().min(1).nullable(),
95
- column: z.number().int().min(1).nullable(), preview: z.string().max(512), file_sha256: hex64.nullable() })).max(500).optional(),
95
+ column: z.number().int().min(1).nullable(), preview: z.string().max(512), file_sha256: hex64.nullable(),
96
+ distance: z.number().int().nonnegative().optional(), similarity: z.number().min(0).max(1).optional(), match_length: z.number().int().positive().optional() })).max(500).optional(),
96
97
  files_scanned: z.number().int().min(0).optional(), bytes_scanned: z.number().int().min(0).optional(),
97
98
  binary_files_skipped: z.number().int().min(0).optional(), truncated: z.boolean().optional(),
98
99
  truncation_reason: z.enum(['tree_limit','scan_byte_limit','max_results']).nullable().optional(),
@@ -2,6 +2,8 @@ import { createHash } from 'node:crypto';
2
2
  import { canonicalJson } from './canonical-json.mjs';
3
3
  import { decodeUtf8Strict } from './text-policy.mjs';
4
4
  import { createSequenceStream } from './workload-substrate.mjs';
5
+ import { fuzzyIndexOf } from './fuzzy-search-core.mjs';
6
+ import { runFuzzySearchInWorker, FUZZY_SEARCH_TIMEOUT_MS } from './fuzzy-search.mjs';
5
7
 
6
8
  const sha256Object=value=>createHash('sha256').update(canonicalJson(value),'utf8').digest('hex');
7
9
  const sha256Bytes=bytes=>createHash('sha256').update(bytes).digest('hex');
@@ -53,11 +55,11 @@ function preview(text,index,length){
53
55
  const start=Math.max(0,index-48); const end=Math.min(text.length,index+Math.max(length,1)+112);
54
56
  return text.slice(start,end);
55
57
  }
56
- function normalizeQuery({rootId,path,target,mode,pattern,caseSensitive,maxResults,maxFileBytes,maxScanBytes,pageSize}){
58
+ function normalizeQuery({rootId,path,target,mode,pattern,caseSensitive,maxResults,maxFileBytes,maxScanBytes,pageSize,fuzzyTimeoutMs}){
57
59
  return {
58
- schema:'deadbyte.coding-search-query.v2',root_id:rootId,path,target,mode,pattern,
60
+ schema:'deadbyte.coding-search-query.v3',root_id:rootId,path,target,mode,pattern,
59
61
  case_sensitive:caseSensitive,max_results:maxResults,max_file_bytes:maxFileBytes,
60
- max_scan_bytes:maxScanBytes,page_size:pageSize
62
+ max_scan_bytes:maxScanBytes,page_size:pageSize,fuzzy_timeout_ms:fuzzyTimeoutMs
61
63
  };
62
64
  }
63
65
 
@@ -67,15 +69,18 @@ export function createCodingSearch({tree,fileRead,cursorCodec}){
67
69
  }
68
70
  return async function search({
69
71
  rootId,path='.',pattern,target='content',mode='literal',caseSensitive=false,
70
- maxResults=200,maxFileBytes=262144,maxScanBytes=4*1024*1024,pageSize=100,cursor=null
72
+ maxResults=200,maxFileBytes=262144,maxScanBytes=4*1024*1024,pageSize=100,cursor=null,
73
+ fuzzyTimeoutMs=FUZZY_SEARCH_TIMEOUT_MS
71
74
  }){
72
75
  if(!['content','path'].includes(target)) throw new Error('coding search target must be content or path');
76
+ if(!['literal','regex','fuzzy'].includes(mode)) throw new Error('coding search mode must be literal, regex, or fuzzy');
73
77
  validateInt(maxResults,'max_results',1,1000);
74
78
  validateInt(maxFileBytes,'max_file_bytes',1,4*1024*1024);
75
79
  validateInt(maxScanBytes,'max_scan_bytes',1,64*1024*1024);
76
80
  validateInt(pageSize,'page_size',1,500);
77
- const matcher=compileMatcher({pattern,mode,caseSensitive});
78
- const query=normalizeQuery({rootId,path,target,mode,pattern,caseSensitive,maxResults,maxFileBytes,maxScanBytes,pageSize});
81
+ if(!Number.isInteger(fuzzyTimeoutMs)||fuzzyTimeoutMs<100||fuzzyTimeoutMs>FUZZY_SEARCH_TIMEOUT_MS) throw new Error('fuzzy_timeout_ms must be in [100, 30000]');
82
+ const matcher=mode==='fuzzy'?null:compileMatcher({pattern,mode,caseSensitive});
83
+ const query=normalizeQuery({rootId,path,target,mode,pattern,caseSensitive,maxResults,maxFileBytes,maxScanBytes,pageSize,fuzzyTimeoutMs});
79
84
  const querySha=sha256Object(query);
80
85
  let decodedCursor=null;
81
86
  if(cursor!==null){
@@ -93,10 +98,18 @@ export function createCodingSearch({tree,fileRead,cursorCodec}){
93
98
  if(target==='path'){
94
99
  for(const entry of entries){
95
100
  snapshotEntries.push({path:entry.path,bytes:entry.bytes,type:'file'});
96
- if(matcher.path(entry.path)){
97
- matches.push({path:entry.path,line:null,column:null,preview:entry.path,file_sha256:null});
101
+ const found=mode==='fuzzy'
102
+ ? [fuzzyIndexOf(caseSensitive?entry.path:entry.path.toLowerCase(),caseSensitive?pattern:pattern.toLowerCase())]
103
+ : (matcher.path(entry.path)?[{start:0,end:entry.path.length,value:entry.path}]:[]);
104
+ for(const hit of found){
105
+ if(mode==='fuzzy' && hit.distance>Math.max(1,Math.floor(pattern.length*0.75))) continue;
106
+ matches.push({
107
+ path:entry.path,line:null,column:null,preview:entry.path,file_sha256:null,
108
+ ...(mode==='fuzzy'?{distance:hit.distance,similarity:hit.similarity,match_length:Math.max(1,hit.value.length)}:{})
109
+ });
98
110
  if(matches.length>=maxResults){truncated=true;truncationReason='max_results';break;}
99
111
  }
112
+ if(matches.length>=maxResults) break;
100
113
  }
101
114
  } else {
102
115
  for(const entry of entries){
@@ -110,11 +123,26 @@ export function createCodingSearch({tree,fileRead,cursorCodec}){
110
123
  snapshotEntries.push({path:entry.path,bytes:item.bytes,sha256:fileSha});
111
124
  let text;
112
125
  try{text=decodeUtf8Strict(raw);}catch{binaryFilesSkipped+=1;continue;}
113
- const found=matcher.all(text);
114
- for(const hit of found){
115
- const lc=lineColumn(text,hit.index);
116
- matches.push({path:entry.path,line:lc.line,column:lc.column,preview:preview(text,hit.index,hit.length),file_sha256:fileSha});
117
- if(matches.length>=maxResults){truncated=true;truncationReason='max_results';break;}
126
+ if(mode==='fuzzy'){
127
+ const haystack=caseSensitive?text:text.toLowerCase();
128
+ const queryText=caseSensitive?pattern:pattern.toLowerCase();
129
+ const hit=await runFuzzySearchInWorker(haystack,queryText,fuzzyTimeoutMs);
130
+ const threshold=Math.max(1,Math.floor(queryText.length*0.75));
131
+ if(hit.distance<=threshold){
132
+ const lc=lineColumn(haystack,hit.start);
133
+ matches.push({
134
+ path:entry.path,line:lc.line,column:lc.column,
135
+ preview:preview(text,hit.start,hit.end-hit.start),file_sha256:fileSha,
136
+ distance:hit.distance,similarity:hit.similarity,match_length:Math.max(1,hit.value.length)
137
+ });
138
+ }
139
+ } else {
140
+ const found=matcher.all(text);
141
+ for(const hit of found){
142
+ const lc=lineColumn(text,hit.index);
143
+ matches.push({path:entry.path,line:lc.line,column:lc.column,preview:preview(text,hit.index,hit.length),file_sha256:fileSha});
144
+ if(matches.length>=maxResults){truncated=true;truncationReason='max_results';break;}
145
+ }
118
146
  }
119
147
  if(matches.length>=maxResults) break;
120
148
  }
@@ -13,7 +13,7 @@ const symbolName=z.string().regex(/^[A-Za-z_$][A-Za-z0-9_$]{0,127}$/);
13
13
 
14
14
  export const codingInspectInputSchema=z.discriminatedUnion('op',[
15
15
  z.strictObject({op:z.literal('stat'),root_id:id,path:rel512.default('.'),hash:z.boolean().default(false)}),
16
- z.strictObject({op:z.literal('search'),root_id:id,path:rel512.default('.'),pattern:z.string().min(1).max(256),target:z.enum(['content','path']).default('content'),mode:z.enum(['literal','regex']).default('literal'),case_sensitive:z.boolean().default(false),max_results:z.number().int().min(1).max(1000).default(200),max_file_bytes:z.number().int().min(1).max(4*1024*1024).default(262144),max_scan_bytes:z.number().int().min(1).max(64*1024*1024).default(4*1024*1024),page_size:z.number().int().min(1).max(500).default(100),cursor}),
16
+ z.strictObject({op:z.literal('search'),root_id:id,path:rel512.default('.'),pattern:z.string().min(1).max(256),target:z.enum(['content','path']).default('content'),mode:z.enum(['literal','regex','fuzzy']).default('literal'),case_sensitive:z.boolean().default(false),max_results:z.number().int().min(1).max(1000).default(200),max_file_bytes:z.number().int().min(1).max(4*1024*1024).default(262144),max_scan_bytes:z.number().int().min(1).max(64*1024*1024).default(4*1024*1024),page_size:z.number().int().min(1).max(500).default(100),cursor,fuzzy_timeout_ms:z.number().int().min(100).max(30000).default(30000)}),
17
17
  z.strictObject({op:z.literal('files_read'),root_id:id,files:z.array(z.strictObject({path:rel512,encoding:z.enum(['utf8','base64']).default('utf8')})).min(1).max(32),max_total_bytes:z.number().int().min(1).max(2097152).default(1048576)}),
18
18
  z.strictObject({op:z.literal('symbol_outline'),root_id:id,path:rel512,max_symbols:z.number().int().min(1).max(500).default(200)}),
19
19
  z.strictObject({op:z.literal('symbol_definition'),root_id:id,path:rel512,line:nonneg,column:nonneg,max_results:z.number().int().min(1).max(200).default(50)}),
@@ -26,7 +26,7 @@ export const codingInspectInputSchema=z.discriminatedUnion('op',[
26
26
  export const machineFsGatewayInputSchema=z.discriminatedUnion('op',[
27
27
  z.strictObject({op:z.literal('stat'),root_id:id,path:rel.default('.'),hash:z.boolean().default(false)}),
28
28
  z.strictObject({op:z.literal('list'),root_id:id,path:rel.default('.'),cursor,limit:z.number().int().min(1).max(1000).default(100),hash_files:z.boolean().default(false)}),
29
- z.strictObject({op:z.literal('read'),root_id:id,path:rel,offset:nonneg.default(0),max_bytes:z.number().int().min(1).max(4*1024*1024).default(65536),hash_file:z.boolean().default(false),timeout_ms:z.number().int().min(100).max(180000).default(30000)}),
29
+ z.strictObject({op:z.literal('read'),root_id:id,path:rel,offset:z.number().int().min(-4*1024*1024).max(4*1024*1024).default(0),max_bytes:z.number().int().min(1).max(4*1024*1024).default(65536),hash_file:z.boolean().default(false),timeout_ms:z.number().int().min(100).max(180000).default(30000)}),
30
30
  z.strictObject({op:z.literal('write'),root_id:id,path:rel,content:z.string().max(12*1024*1024),encoding:z.enum(['utf8','base64']).default('utf8'),expected_sha256:z.string().regex(/^(?:absent|[0-9a-f]{64})$/)}),
31
31
  z.strictObject({op:z.literal('edit_exact'),root_id:id,path:rel,expected_sha256:hex64,old_string:z.string().min(1).max(262144),new_string:z.string().max(524288),expected_replacements:z.number().int().min(1).max(64).default(1)}),
32
32
  z.strictObject({op:z.literal('mkdir'),root_id:id,path:rel}),
@@ -69,7 +69,7 @@ async function invoke(op,runtime,name,call){
69
69
  async function codingInspect(args,codingRuntime,semanticRuntime){
70
70
  switch(args.op){
71
71
  case 'stat': return invoke(args.op,codingRuntime,'coding',r=>r.stat({rootId:args.root_id,relativePath:args.path,hash:args.hash}));
72
- case 'search': return invoke(args.op,codingRuntime,'coding',r=>r.search({rootId:args.root_id,path:args.path,pattern:args.pattern,target:args.target,mode:args.mode,caseSensitive:args.case_sensitive,maxResults:args.max_results,maxFileBytes:args.max_file_bytes,maxScanBytes:args.max_scan_bytes,pageSize:args.page_size,cursor:args.cursor}));
72
+ case 'search': return invoke(args.op,codingRuntime,'coding',r=>r.search({rootId:args.root_id,path:args.path,pattern:args.pattern,target:args.target,mode:args.mode,caseSensitive:args.case_sensitive,maxResults:args.max_results,maxFileBytes:args.max_file_bytes,maxScanBytes:args.max_scan_bytes,pageSize:args.page_size,cursor:args.cursor,fuzzyTimeoutMs:args.fuzzy_timeout_ms}));
73
73
  case 'files_read': return invoke(args.op,codingRuntime,'coding',r=>r.filesRead({rootId:args.root_id,files:args.files,maxTotalBytes:args.max_total_bytes}));
74
74
  case 'symbol_outline': return invoke(args.op,semanticRuntime,'semantic',r=>r.outline({rootId:args.root_id,relativePath:args.path,maxSymbols:args.max_symbols}));
75
75
  case 'symbol_definition': return invoke(args.op,semanticRuntime,'semantic',r=>r.definition({rootId:args.root_id,relativePath:args.path,line:args.line,column:args.column,maxResults:args.max_results}));
@@ -0,0 +1,117 @@
1
+ const clamp=(value,min,max)=>Math.min(max,Math.max(min,value));
2
+
3
+ function boundedLevenshtein(a,b,cutoff=Number.POSITIVE_INFINITY){
4
+ if(a===b)return 0;
5
+ if(a.length===0)return b.length;
6
+ if(b.length===0)return a.length;
7
+ if(a.length>b.length){const t=a;a=b;b=t;}
8
+ const previous=new Uint16Array(a.length+1);
9
+ const current=new Uint16Array(a.length+1);
10
+ for(let i=0;i<=a.length;i+=1)previous[i]=i;
11
+ const limit=Number.isFinite(cutoff)?Math.floor(cutoff):Number.MAX_SAFE_INTEGER;
12
+ for(let row=1;row<=b.length;row+=1){
13
+ current[0]=row;
14
+ let rowMin=current[0];
15
+ const ch=b.charCodeAt(row-1);
16
+ for(let col=1;col<=a.length;col+=1){
17
+ const cost=a.charCodeAt(col-1)===ch?0:1;
18
+ const value=Math.min(current[col-1]+1,previous[col]+1,previous[col-1]+cost);
19
+ current[col]=value;
20
+ if(value<rowMin)rowMin=value;
21
+ }
22
+ if(rowMin>limit)return limit+1;
23
+ previous.set(current);
24
+ }
25
+ return previous[a.length];
26
+ }
27
+
28
+ function cheapPositionalScore(text,query,start,length){
29
+ const overlap=Math.min(length,query.length);
30
+ if(overlap<=0)return -1;
31
+ let same=0;
32
+ for(let i=0;i<overlap;i+=1)if(text.charCodeAt(start+i)===query.charCodeAt(i))same+=1;
33
+ const lengthPenalty=Math.abs(length-query.length)/Math.max(1,query.length);
34
+ return (same/overlap)-lengthPenalty*0.20;
35
+ }
36
+
37
+ function candidateLengths(queryLength,textLength){
38
+ if(textLength<=queryLength)return [textLength];
39
+ const delta=clamp(Math.floor(queryLength*0.25),2,32);
40
+ return [...new Set([
41
+ Math.max(1,queryLength-delta),
42
+ queryLength,
43
+ Math.min(textLength,queryLength+delta)
44
+ ])];
45
+ }
46
+
47
+ export function fuzzyIndexOf(text,query){
48
+ if(typeof text!=='string'||typeof query!=='string')throw new Error('fuzzy search requires text and query strings');
49
+ if(query.length===0)return {start:0,end:0,value:'',distance:0,similarity:1};
50
+ if(text.length===0)return {start:0,end:0,value:'',distance:query.length,similarity:0};
51
+
52
+ const lengths=candidateLengths(query.length,text.length);
53
+ const stride=query.length<=32?1:Math.max(1,Math.floor(query.length/4));
54
+ const ranked=[];
55
+ const seen=new Set();
56
+ for(let start=0;start<text.length;start+=stride){
57
+ for(const length of lengths){
58
+ if(start+length>text.length)continue;
59
+ const key=`${start}:${length}`;
60
+ if(seen.has(key))continue;
61
+ seen.add(key);
62
+ ranked.push({start,length,score:cheapPositionalScore(text,query,start,length)});
63
+ }
64
+ }
65
+ const tailStart=Math.max(0,text.length-query.length);
66
+ for(const start of [0,tailStart]){
67
+ for(const length of lengths){
68
+ if(start<0||start+length>text.length)continue;
69
+ const key=`${start}:${length}`;
70
+ if(seen.has(key))continue;
71
+ seen.add(key);
72
+ ranked.push({start,length,score:cheapPositionalScore(text,query,start,length)});
73
+ }
74
+ }
75
+
76
+ ranked.sort((a,b)=>b.score-a.score||a.start-b.start||a.length-b.length);
77
+ const shortlist=ranked.slice(0,64);
78
+ const refined=new Set();
79
+ for(const item of shortlist){
80
+ const radius=Math.max(1,Math.floor(stride/2));
81
+ for(let delta=-radius;delta<=radius;delta+=1){
82
+ const start=item.start+delta;
83
+ if(start<0||start>=text.length)continue;
84
+ for(const length of lengths){
85
+ if(start+length>text.length)continue;
86
+ refined.add(`${start}:${length}`);
87
+ }
88
+ }
89
+ }
90
+ if(refined.size===0)refined.add(`0:${Math.min(text.length,query.length)}`);
91
+
92
+ let best=null;
93
+ for(const key of refined){
94
+ const [startText,lengthText]=key.split(':');
95
+ const start=Number(startText);
96
+ const length=Number(lengthText);
97
+ const value=text.slice(start,start+length);
98
+ const cutoff=best?.distance??Number.POSITIVE_INFINITY;
99
+ const distance=boundedLevenshtein(value,query,cutoff);
100
+ if(best&&distance>best.distance)continue;
101
+ const similarity=1-(distance/Math.max(query.length,value.length));
102
+ const candidate={start,end:start+value.length,value,distance,similarity};
103
+ if(!best||
104
+ candidate.distance<best.distance||
105
+ (candidate.distance===best.distance&&candidate.similarity>best.similarity)||
106
+ (candidate.distance===best.distance&&candidate.similarity===best.similarity&&candidate.start<best.start)){
107
+ best=candidate;
108
+ }
109
+ }
110
+ return best??{start:0,end:Math.min(text.length,query.length),value:text.slice(0,query.length),
111
+ distance:boundedLevenshtein(text.slice(0,query.length),query),similarity:0};
112
+ }
113
+
114
+ export function getSimilarityRatio(a,b){
115
+ if(a.length===0&&b.length===0)return 1;
116
+ return 1-(boundedLevenshtein(a,b)/Math.max(a.length,b.length));
117
+ }
@@ -0,0 +1,8 @@
1
+ import { parentPort, workerData } from 'node:worker_threads';
2
+ import { fuzzyIndexOf } from './fuzzy-search-core.mjs';
3
+
4
+ try {
5
+ parentPort.postMessage({ ok:true, result:fuzzyIndexOf(workerData.text,workerData.query) });
6
+ } catch (error) {
7
+ parentPort.postMessage({ ok:false, error:String(error?.stack??error) });
8
+ }
@@ -0,0 +1,34 @@
1
+ import { Worker } from 'node:worker_threads';
2
+
3
+ export const FUZZY_SEARCH_TIMEOUT_MS=30000;
4
+ const WORKER_URL=new URL('./fuzzy-search-worker.mjs',import.meta.url);
5
+
6
+ export function runFuzzySearchInWorker(text,query,timeoutMs=FUZZY_SEARCH_TIMEOUT_MS){
7
+ if(!Number.isInteger(timeoutMs)||timeoutMs<100||timeoutMs>FUZZY_SEARCH_TIMEOUT_MS)throw new Error('fuzzy timeout_ms must be in [100, 30000]');
8
+ return new Promise((resolve,reject)=>{
9
+ const worker=new Worker(WORKER_URL,{type:'module',workerData:{text,query},execArgv:[]});
10
+ worker.unref?.();
11
+ let settled=false;
12
+ let timer;
13
+ const finish=(fn,value)=>{
14
+ if(settled)return;
15
+ settled=true;
16
+ clearTimeout(timer);
17
+ fn(value);
18
+ };
19
+ timer=setTimeout(()=>{
20
+ worker.terminate().catch(()=>{});
21
+ finish(reject,new Error(`fuzzy search timed out after ${timeoutMs}ms`));
22
+ },timeoutMs);
23
+ timer.unref?.();
24
+ worker.once('message',message=>{
25
+ if(message?.ok)finish(resolve,message.result);
26
+ else finish(reject,new Error(`fuzzy search worker failed: ${String(message?.error??'unknown error')}`));
27
+ worker.terminate().catch(()=>{});
28
+ });
29
+ worker.once('error',error=>finish(reject,error));
30
+ worker.once('exit',code=>{
31
+ if(code!==0)finish(reject,new Error(`fuzzy search worker exited with code ${code}`));
32
+ });
33
+ });
34
+ }
@@ -32,7 +32,7 @@ export function registerMachineFsTools(server, { runtime }) {
32
32
  });
33
33
  server.registerTool('machine_fs_read', {
34
34
  description:'Read one bounded byte range from a root-relative regular file.',
35
- inputSchema:z.strictObject({ root_id:id, path:rel, offset:z.number().int().nonnegative().default(0), max_bytes:z.number().int().min(1).max(4*1024*1024).default(65536), hash_file:z.boolean().default(false), timeout_ms:z.number().int().min(100).max(180000).default(30000) }),
35
+ inputSchema:z.strictObject({ root_id:id, path:rel, offset:z.number().int().min(-4*1024*1024).max(4*1024*1024).default(0), max_bytes:z.number().int().min(1).max(4*1024*1024).default(65536), hash_file:z.boolean().default(false), timeout_ms:z.number().int().min(100).max(180000).default(30000) }),
36
36
  outputSchema:machineFsReadOutputSchema
37
37
  }, async ({root_id,path,offset,max_bytes,hash_file,timeout_ms}) => {
38
38
  try { return ok(machineFsReadOutputSchema, await runtime.read({rootId:root_id,relativePath:path,offset,maxBytes:max_bytes,hashFile:hash_file,timeoutMs:timeout_ms})); }
@@ -30,7 +30,7 @@ export const machineFsListOutputSchema = z.strictObject({
30
30
  export const machineFsReadOutputSchema = z.strictObject({
31
31
  status: statusOk, error,
32
32
  root_id: z.string().min(1).max(64).optional(), path: pathText.optional(),
33
- offset: z.number().int().nonnegative().optional(), next_offset: z.number().int().nonnegative().optional(),
33
+ offset: z.number().int().nonnegative().optional(), requested_offset: z.number().int().optional(), next_offset: z.number().int().nonnegative().optional(),
34
34
  file_size: z.number().int().nonnegative().optional(), eof: z.boolean().optional(),
35
35
  data_base64: z.string().max(12 * 1024 * 1024).optional(), data_sha256: hex64.optional(),
36
36
  file_sha256: hex64.nullable().optional(), timeout_ms: z.number().int().min(100).max(180000).optional()
@@ -324,24 +324,25 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath,
324
324
  return { status: 'ok', root_id: rootId, path: found.relative, entries, next_cursor: nextCursor };
325
325
  }
326
326
  async function readRange({ rootId, relativePath, offset = 0, maxBytes = 65536, hashFile = false, timeoutMs = 30000 }) {
327
- if (!Number.isInteger(offset) || offset < 0) throw new Error('machine fs read offset must be nonnegative integer');
327
+ if (!Number.isInteger(offset) || offset < -policy.max_read_bytes || offset > policy.max_read_bytes) throw new Error(`machine fs read offset must be in [-${policy.max_read_bytes}, ${policy.max_read_bytes}]`);
328
328
  if (!Number.isInteger(maxBytes) || maxBytes < 1 || maxBytes > policy.max_read_bytes) throw new Error(`machine fs max_bytes must be in [1, ${policy.max_read_bytes}]`);
329
329
  if (!Number.isInteger(timeoutMs) || timeoutMs < 100 || timeoutMs > 180000) throw new Error('machine fs read timeout_ms must be in [100, 180000]');
330
330
  const grant = await assertCodingArmed(policy, rootId);
331
331
  const found = await resolveExisting(policy, grant, rootId, relativePath, 'read', false);
332
332
  const info = await lstat(found.resolved);
333
333
  if (!info.isFile()) throw new Error('machine fs read target must be a regular file');
334
- if (offset > info.size) throw new Error('machine fs read offset exceeds file size');
335
- const length = Math.min(maxBytes, info.size - offset);
334
+ const effectiveOffset = offset < 0 ? Math.max(0, info.size + offset) : offset;
335
+ if (effectiveOffset > info.size) throw new Error('machine fs read offset exceeds file size');
336
+ const length = Math.min(maxBytes, info.size - effectiveOffset);
336
337
  await recheckCodingAuthority(policy, grant, rootId);
337
- const worker = await boundedReadWorker({ file: found.resolved, offset, length, hashFile, timeoutMs, workerPath: readWorkerPath });
338
+ const worker = await boundedReadWorker({ file: found.resolved, offset: effectiveOffset, length, hashFile, timeoutMs, workerPath: readWorkerPath });
338
339
  const buffer = Buffer.from(worker.data_base64, 'base64');
339
340
  if (buffer.length !== worker.bytes_read || buffer.length > length) throw new Error('machine fs read worker byte count mismatch');
340
341
  await recheckCodingAuthority(policy, grant, rootId);
341
342
  return {
342
343
  status: 'ok', root_id: rootId, path: found.relative,
343
- offset, next_offset: offset + buffer.length, file_size: info.size,
344
- eof: offset + buffer.length >= info.size, data_base64: buffer.toString('base64'),
344
+ offset: effectiveOffset, requested_offset: offset, next_offset: effectiveOffset + buffer.length, file_size: info.size,
345
+ eof: effectiveOffset + buffer.length >= info.size, data_base64: buffer.toString('base64'),
345
346
  data_sha256: sha256Bytes(buffer), file_sha256: worker.file_sha256,
346
347
  timeout_ms: timeoutMs
347
348
  };
@@ -0,0 +1,54 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { createHash } from 'node:crypto';
4
+ import { fuzzyIndexOf } from '../src/fuzzy-search-core.mjs';
5
+ import { runFuzzySearchInWorker } from '../src/fuzzy-search.mjs';
6
+ import { createCodingSearch } from '../src/coding-search.mjs';
7
+
8
+ const sha = text => createHash('sha256').update(text,'utf8').digest('hex');
9
+ const files = new Map([
10
+ ['src/a.mjs','const deadbyte_machine_identity = true;'],
11
+ ['src/b.mjs','const unrelated = false;']
12
+ ]);
13
+
14
+ function cursorCodec(){
15
+ return {
16
+ async encode(value){ return Buffer.from(JSON.stringify(value)).toString('base64url'); },
17
+ async decode(value){ return JSON.parse(Buffer.from(value,'base64url').toString('utf8')); }
18
+ };
19
+ }
20
+
21
+ test('R46 fuzzy core and worker agree under a hard timeout boundary', async () => {
22
+ const text='AAAA deadbyte_machine_identity SHA256 CATALOG';
23
+ const direct=fuzzyIndexOf(text,'deadbyte_machine_identiti');
24
+ const worker=await runFuzzySearchInWorker(text,'deadbyte_machine_identiti',3000);
25
+ assert.equal(worker.start,direct.start);
26
+ assert.equal(worker.end,direct.end);
27
+ assert.equal(worker.distance,direct.distance);
28
+ assert.ok(worker.similarity >= 0.90);
29
+ });
30
+
31
+ test('R46 coding search fuzzy mode preserves bounded paging and file identity', async () => {
32
+ const search=createCodingSearch({
33
+ tree: async ({rootId,path,maxEntries}) => ({
34
+ status:'ok',root_id:rootId,path,
35
+ entries:[...files].map(([item])=>({path:item,type:'file',bytes:files.get(item).length})).slice(0,maxEntries),
36
+ truncated:false
37
+ }),
38
+ fileRead: async ({relativePath}) => {
39
+ const text=files.get(relativePath);
40
+ return {content:Buffer.from(text,'utf8').toString('base64'),bytes:Buffer.byteLength(text),sha256:sha(text)};
41
+ },
42
+ cursorCodec:cursorCodec()
43
+ });
44
+ const value=await search({
45
+ rootId:'core',path:'.',pattern:'deadbyte_machine_identiti',
46
+ target:'content',mode:'fuzzy',maxResults:10,maxFileBytes:4096,maxScanBytes:4096,pageSize:10
47
+ });
48
+ assert.equal(value.status,'ok');
49
+ assert.equal(value.matches.length,1);
50
+ assert.equal(value.matches[0].path,'src/a.mjs');
51
+ assert.equal(value.matches[0].distance,1);
52
+ assert.ok(value.matches[0].similarity >= 0.90);
53
+ assert.match(value.matches[0].file_sha256,/^[0-9a-f]{64}$/);
54
+ });
@@ -37,6 +37,8 @@ test('R31 machine filesystem schemas expose root-relative IDs/preconditions only
37
37
  registerMachineFsTools(server, { runtime: runtime() });
38
38
  const read = server.tools.get('machine_fs_read').spec.inputSchema;
39
39
  assert.equal(read.safeParse({ root_id:'core', path:'a.txt', offset:0, max_bytes:65536, hash_file:false, timeout_ms:30000 }).success, true);
40
+ assert.equal(read.safeParse({ root_id:'core', path:'a.txt', offset:-4096, max_bytes:4096, hash_file:false, timeout_ms:30000 }).success, true);
41
+ assert.equal(read.safeParse({ root_id:'core', path:'a.txt', offset:-4194305, max_bytes:4096, hash_file:false, timeout_ms:30000 }).success, false);
40
42
  assert.equal(read.safeParse({ root_id:'core', path:'a.txt', timeout_ms:99 }).success, false);
41
43
  const write = server.tools.get('machine_fs_write').spec.inputSchema;
42
44
  const move = server.tools.get('machine_fs_move').spec.inputSchema;
@@ -53,6 +53,12 @@ test('R31 machine fs supports exact mkdir/write/stat/list/range-read/edit/move/d
53
53
  assert.equal(Buffer.from(read.data_base64, 'base64').toString('utf8'), 'beta');
54
54
  assert.equal(read.next_offset, 10);
55
55
  assert.equal(read.timeout_ms, 30000);
56
+ const tail = await f.runtime.read({ rootId: 'project', relativePath: 'dir/a.txt', offset: -5, maxBytes: 8 });
57
+ assert.equal(Buffer.from(tail.data_base64, 'base64').toString('utf8'), 'gamma');
58
+ assert.equal(tail.offset, 11);
59
+ assert.equal(tail.requested_offset, -5);
60
+ assert.equal(tail.next_offset, 16);
61
+ assert.equal(tail.eof, true);
56
62
  const edited = await f.runtime.editExact({
57
63
  rootId: 'project', relativePath: 'dir/a.txt', expectedSha256: written.sha256,
58
64
  oldString: 'beta', newString: 'BETA', expectedReplacements: 1