deadbyte-mcp 0.15.10 → 0.15.11

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
- fc923c05c542ed4d3eeace06c1f782fe431d877ee0227c24096aeea45af5d03e package.json
1331
+ 34e5345b9f07fad9e3f7f54c496f3cf0cc4ff07c34c938c35244a9e1f209eeeb 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
- 2a17d078ccbf03b254509985b3cdf51496e8d02958b4f3bc878e5aac7bb15b10 PROVENANCE.json
1391
+ c7a11729f77023dd1d741d61b35ea0b75cca061a28f3a4cbe0062ca6a536f4ab 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
  4d8bc9d61d7558a484269cc13263b42bb39417700bb3858069d64a2d1ae190e8 README.txt
1400
- de2c63a505343a61cfbfe4a905d9021ccdc4cce39ccb3e681c2526518bf494c5 RELEASE.json
1400
+ be4640a1d9e47f904e758e0b88b6e2ef7ee8b1921c90a95e404d28d1eb01a69b RELEASE.json
1401
1401
  507a42441c8fbb0b1bef63a13fad9e1680262cd6d34cc176b7ed0c5423ddbcc7 SBOM.cdx.json
1402
1402
  bd138fe5a64088e8e1a7a5bf6104c5b17317bdc8cf3ad8191ea00ed82ace7d9b scripts/agent-eval-r42.mjs
1403
1403
  8d90256a6863f3bbbff02e95cb12389fc6f9e8dbcb77bf1c20c902de371425e8 scripts/archive-source-zips.mjs
@@ -1522,6 +1522,7 @@ cabfa63d5edb83f32b3e6e5ce22e76223644d81a3361d52a28de2dbc07e59a54 scripts/run-r4
1522
1522
  abf8ac3074e8964c9648b5b60069730c255faa5f4169f3aefc7a9eff350a1efc scripts/run-skill-creator-scaffold.mjs
1523
1523
  caac2867971dfdf56456528b816ff56282a11cbba81510c13e1723accffac678 scripts/runtime-self-update.mjs
1524
1524
  b0cc75c38e0163dbcf7fb1b0d21f2dc34c71f2d0e2a156a53e570ff84afc64e6 scripts/semantic-preflight.ps1
1525
+ bf54d2dfa2a77c2c13cc0b8a9ac2eb926132ecd331ad56ebbf88cc5cc4280a96 scripts/sign-adaptive-skill.mjs
1525
1526
  0a115aa9829576c86cc247f754cae69ae09ba146b637d3a1c9fbc16420d20a5d scripts/tool-surface-snapshot.mjs
1526
1527
  f8d9c6718cbe20e02e517297e8f35f51c7dcd51b62b8b4a483630a9cd3b1f788 scripts/verify-memory-r41.mjs
1527
1528
  e552634ca1f8673f5daaaf5e45302d2a7fc4b1a1eac256f60bed2c9136bafa05 scripts/verify-package.ps1
@@ -1577,13 +1578,14 @@ e5f944a310ed957e3b8f7b1cab54c082acf1b35f8fdd7d9b672ebe1a80dc37ac src/canonical-
1577
1578
  da5181cec30034ddf089baa5358becb5651da238a2e7cf0888007a4c60b4ea6b src/capability-benchmark-runner.mjs
1578
1579
  2b62295591f142ca4b3bc5b03e6434f7fc3c51d9502f9a40ef8a03d1f72a8899 src/capability-benchmark.mjs
1579
1580
  160199b25f45bd0490f6b21a9fa8194313e9673c4b2699afce68249d3d249a7b src/capability-ledger.mjs
1581
+ 1b0ba08c5d5a75d95953a84a00b551af8ba1ee21cf1995255daa198368017760 src/capability-resolver.mjs
1580
1582
  94e5aeff2453cdc0239aee4d547dbbefee183c71933cb84e5e8a418fa99bc1e8 src/codex-app-server-r44.mjs
1581
1583
  6d0a80daaa2711e67e2597bff3db5bd2802682f559107a492f3cd89b9c6785ed src/coding-mcp-tools.mjs
1582
1584
  d6fc395575f49abbbf60bf6f6ef5ee9ad51034a7e770a381e6ec34f869788306 src/coding-output-contracts.mjs
1583
1585
  0857a458e9c5101eee94c0596b7699adc34c50687455688fe38d03d241d27935 src/coding-plane.mjs
1584
1586
  38a1b4e9f5aa14cd5fd9058345c3480ae72c4a6a6eeccdc46e71297c68b5b5a6 src/coding-search.mjs
1585
1587
  f87284dc71c167f6a17575b93730c258ed6c433831013c776bf2d14e2b77767f src/coding-task-runtime.mjs
1586
- bfe4b641b61e4e7da8848c6c39d256a39191639315fb9f3c17a0b11f999ec792 src/compact-gateway-mcp-tools.mjs
1588
+ 8478ef1f7b3dc89480c4310a20268048f581041bddcc0b7de9298fa2bfc654ca src/compact-gateway-mcp-tools.mjs
1587
1589
  4218d1d1478d9e9a044d9b61c5ae205cd2ca0651a314900fad03992d0b12d286 src/compact-gateway-output-contracts.mjs
1588
1590
  40ac70ece531de7709d3c51686b36b48e0ae60283d1fb18d0adc037bfe6f9063 src/contained-cli.mjs
1589
1591
  d2bacef2443705e372071d0de3c72d45d57febb1dcbb11e369fce8a78bf0bf3e src/contained-executor.mjs
@@ -1632,7 +1634,7 @@ ad4ca3635cb228b57b5b98e9518f379380ee1a03ad07ab4d12f8b7f324be2517 src/machine-mc
1632
1634
  e81b3ac2955e5dfafe308c82da24356a14da396230cb9fc47b231ab672d5be48 src/machine-output-contracts.mjs
1633
1635
  ed85d41c494a334117661ddec8191d34974fe28cb2a3378f3c04ee0e4c5d3ccc src/mcp-contained-smoke-client.mjs
1634
1636
  b705345aa432b6a6ebbf62aabce1f78ba7e392bdfe998e79217eba8289ed0a7e src/mcp-host-smoke-client.mjs
1635
- 02f6f0d456491dbd7687c4c81c7a2c3d9dd9db411d97617fcb9927b766f75a67 src/mcp-server.mjs
1637
+ 3300d50f8a015bb090d5820dafe42edcc3d16a741e3ff12232ec03aadf115158 src/mcp-server.mjs
1636
1638
  b490c4152b16adae658b3af20a4827847866cec352e1b0c9eb6b36094116b83b src/mcp-smoke-client.mjs
1637
1639
  cde7c813f5a2e9a69f09849455d1504e766963845a1f4b201ecc84090fa260d5 src/memory-r41.mjs
1638
1640
  9525aee66944023603f6d1ebb0768b8e8ab8bb93582a10dd7f9cd4459ee07454 src/native-diff-v2.mjs
@@ -1649,7 +1651,7 @@ b8e4e38fc38bd8d2efb01b58028944bc8133dcc42de12b1035784c5e01beca35 src/output-con
1649
1651
  974b5e9a5f60c4b2ac8bed629fb39a4e3c06b591995bec3f5f4756da8f3fd2e1 src/process-mcp-tools.mjs
1650
1652
  4c90265628194d989ac78f2b06eadbfffceb9c006d5b6c2e982f5667f7a385ed src/process-output-contracts.mjs
1651
1653
  f5322664c669bc193214a803f9723e3728053f60bc008530db39a9af7f7bab75 src/process-policy.mjs
1652
- 23fb2a9394c6039d4238577eea377679fdd4be7a753e35452799ef9705aad894 src/process-runtime.mjs
1654
+ 622b984e577932ed0c342a6d7e0e8a17d08e888caa2ca67c5ecc1bbcca16042a src/process-runtime.mjs
1653
1655
  65d81b6cbdf4f4ce34ccef11793e79cfed6883288288915d077c11674f0873bb src/process-smoke-client.mjs
1654
1656
  bb4d1532684b8f81a42377c4b0a9d4c61207856edfff496e878ffbb885b52442 src/proof-cli.mjs
1655
1657
  be4a4f7f16e473ac842559a5a18eccb59e3693bded59a1abc71e75ff448cc755 src/proof-worker.mjs
@@ -1686,7 +1688,7 @@ c8fd6fd3e49e866f2c3be326ab07222b36a44528ee0fc3f7b371c34a60e3c45b src/remote-ses
1686
1688
  827b156eac01cc9ec6f5ca9a49219612f0da511fde770a9eb1235aa913b5e514 src/request-identity.mjs
1687
1689
  39251ab165bb0a0b8ea9b4c533aa0cd674934c0fa2c7f63145eac680d1d67be9 src/resource-identity.mjs
1688
1690
  ce2223bf6075e96cc02505c1439acce18bb1f204c5e86cf9152bb7194daf3cd2 src/runtime-identity.mjs
1689
- 9ea6bbebe732a2925b14807228cf5d74848def69b10216495498ae20f3a919ad src/runtime-update.mjs
1691
+ 88fe013cc2474e7e015235df39e54c3c6cd8afb8ac50a97b15a9dee590fed541 src/runtime-update.mjs
1690
1692
  c61335adb38bfc415fe1cdabfe2c0a87e61579dfd1e52cce91c44d6993479457 src/search-cursor.mjs
1691
1693
  fc5407ef8338ebeeede16225b3249166dc4d45e903d873eb46c15c3df07dc9ad src/semantic-backend-registry.mjs
1692
1694
  686e9b55b9f4352b941579f186a9b9d348d86af53d052cbd5da953e7d15470ff src/semantic-code.mjs
@@ -1704,7 +1706,7 @@ bac271c6f5218752ac5ff4decf5249e3893ddb35c63c092ce17238c27fc4d35b src/trust-init
1704
1706
  16df134040e3ff1e73df722b568d3e8ac0a6923b097696cead7580da75aa8d2a src/tunnel-stdio-compat.mjs
1705
1707
  642cb67d1854850e336ee73fbd71b329056bdcbdab35cea19c1a995a155ff5d9 src/verifier-cli.mjs
1706
1708
  8f818a4852ce3be3a380cd4736c3073a7a3e0e45cd7c7ca90588a6b843d3d022 src/verifier.mjs
1707
- afb1d220f824f94a3c1b654213f50e25af380d22e89cba6efb0d58324026e62a src/version.mjs
1709
+ 87f3f4370c3e0e8db4ce0816a205836bb7736000b95d6fd24348944bb739bf6a src/version.mjs
1708
1710
  7e09c57a97289360aabfaf3d531208e54872efbfb3182f3c18203d2cb88c46b5 src/worker-registry.mjs
1709
1711
  76361d5ae9a710273cf64a7525082197b692236bf23689875e5fd1ef4aa96d2b src/worker-scheduler.mjs
1710
1712
  4da1b32f5198bb089bc68b7eb6de21ea296678b5020018a73742bf0df57d62fa src/workload-substrate.mjs
@@ -1745,6 +1747,7 @@ bad448d7bfd0c66b8d0dc0fa601fc22d69ccc3f447140ed0f77b68957984daea test/capabilit
1745
1747
  c343906ca0878e13c576cd9f615802b1139c693bf6769a780dfb052637cf0d83 test/capability-benchmark.test.mjs
1746
1748
  b9a8faa4b86683ac5aea891fe6bc95f8e425fb31635176aa4603f9d582b52a79 test/capability-claims-r36.test.mjs
1747
1749
  a466a490759d438a8ac68919f79ddcb52253bdbecb5e4448a4fbf62af118184e test/capability-ledger-r36.test.mjs
1750
+ 5cdf20eace97fa87563c6b139390e6bd8ccbe80215f53aacd041579bfbad20d6 test/capability-resolver.test.mjs
1748
1751
  84eefe1a43474927fdc6fb7ef269309c662cefb229d6af2c91d9e2f0b9ba5c23 test/cli-entrypoint.test.mjs
1749
1752
  bec565ffa8550d56a5bb21927177c37d9d05f8353e3bc2541fc156886fe23688 test/codex-app-server-r44.test.mjs
1750
1753
  c43105a78ee4c93417d720ee660cfebc75b17f142a6484568e3cbaa583457f8c test/codex-autonomous-r44.test.mjs
package/PROVENANCE.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema": "deadbyte.provenance.v1",
3
- "version": "0.15.10",
3
+ "version": "0.15.11",
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",
package/README.txt CHANGED
@@ -7,12 +7,12 @@ NPX PRIMARY OPERATOR UX
7
7
  ------------------------
8
8
  Use the npm CLI entry point instead of the legacy CMD convenience wrapper:
9
9
 
10
- npx -y deadbyte-mcp@0.15.9 mcp
11
- npx -y deadbyte-mcp@0.15.9 remote
12
- npx -y deadbyte-mcp@0.15.9 remote status
13
- npx -y deadbyte-mcp@0.15.9 remote restart
14
- npx -y deadbyte-mcp@0.15.9 audit status
15
- npx -y deadbyte-mcp@0.15.9 audit verify
10
+ npx -y deadbyte-mcp@0.15.11 mcp
11
+ npx -y deadbyte-mcp@0.15.11 remote
12
+ npx -y deadbyte-mcp@0.15.11 remote status
13
+ npx -y deadbyte-mcp@0.15.11 remote restart
14
+ npx -y deadbyte-mcp@0.15.11 audit status
15
+ npx -y deadbyte-mcp@0.15.11 audit verify
16
16
 
17
17
  The `mcp` command is the quiet stdio server entry for local MCP clients; stdout is reserved for MCP.
18
18
  The remote CLI invokes the stable active-release PowerShell launcher directly with shell=false.
package/RELEASE.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema": "deadbyte.release.v1",
3
3
  "name": "deadbyte-mcp",
4
- "version": "0.15.10",
4
+ "version": "0.15.11",
5
5
  "train": "R46",
6
6
  "label": "FILELESS POWERSHELL PRODUCT BASELINE",
7
7
  "protocol_revision": "2026-07-28",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deadbyte-mcp",
3
- "version": "0.15.10",
3
+ "version": "0.15.11",
4
4
  "private": false,
5
5
  "type": "module",
6
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.",
@@ -0,0 +1,86 @@
1
+ import { readFile, writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ import { createHash, createPrivateKey, createPublicKey, sign } from 'node:crypto';
5
+ import { createSkillPlane } from '../src/skill-plane-r44.mjs';
6
+
7
+ const home = os.homedir();
8
+ const stateDir = path.join(home, '.deadbyte-mcp');
9
+ const skillDir = path.join(stateDir, 'skills', 'deadbyte-adaptive-reverse-engineering');
10
+ const sha = b => createHash('sha256').update(b).digest('hex');
11
+ function canonical(v) {
12
+ return Array.isArray(v) ? v.map(canonical) : v && typeof v === 'object'
13
+ ? Object.fromEntries(Object.keys(v).sort((a, b) => a.localeCompare(b, 'en')).map(k => [k, canonical(v[k])])) : v;
14
+ }
15
+
16
+ const skillBytes = await readFile(path.join(skillDir, 'SKILL.md'));
17
+ const skillText = new TextDecoder('utf-8').decode(skillBytes);
18
+ const skillSha = sha(skillBytes);
19
+
20
+ const refFiles = ['references/adaptive-routing.md', 'references/evidence-correlation.md'].sort((a, b) => a.localeCompare(b, 'en'));
21
+ const resources = [];
22
+ for (const rel of refFiles) {
23
+ const bytes = await readFile(path.join(skillDir, ...rel.split('/')));
24
+ resources.push({
25
+ path: rel,
26
+ sha256: sha(bytes),
27
+ kind: 'reference'
28
+ });
29
+ }
30
+
31
+ const body = {
32
+ schema: 'deadbyte.skill-manifest.v1',
33
+ name: 'deadbyte-adaptive-reverse-engineering',
34
+ version: '1.1.0',
35
+ description: 'Adaptive evidence-driven low-level reverse-engineering workflow that selects the smallest discriminating analysis path, allocates evidence budget by information gain, tracks contradictions, correlates bytes with semantics, and closes every claim with fresh verification.',
36
+ audience: 'agent',
37
+ skill_md_sha256: skillSha,
38
+ resources,
39
+ required_capabilities: [],
40
+ authority_planes: ['coding'],
41
+ provenance: {
42
+ source: 'skill-creator',
43
+ origin_url: null,
44
+ source_revision: 'local-draft-2026-09-24-v1.1'
45
+ }
46
+ };
47
+
48
+ const bodyBytes = Buffer.from(JSON.stringify(canonical(body)), 'utf8');
49
+ const bodySha256 = sha(bodyBytes);
50
+
51
+ const privPem = await readFile(path.join(stateDir, 'trust', 'ed25519-private.pem'));
52
+ const priv = createPrivateKey(privPem);
53
+ const pub = createPublicKey(priv);
54
+ const keyId = sha(pub.export({ type: 'spki', format: 'der' }));
55
+
56
+ const DOMAIN = Buffer.from('DEADBYTE-SKILL-MANIFEST-V1\0', 'utf8');
57
+ const signature = sign(null, Buffer.concat([DOMAIN, bodyBytes]), priv);
58
+ const attestation = {
59
+ algorithm: 'ed25519',
60
+ domain: 'DEADBYTE-SKILL-MANIFEST-V1',
61
+ key_id: keyId,
62
+ signature_base64: signature.toString('base64')
63
+ };
64
+
65
+ const unsigned = { body, body_sha256: bodySha256, attestation };
66
+ const envelope = {
67
+ ...unsigned,
68
+ manifest_sha256: sha(Buffer.from(JSON.stringify(canonical(unsigned)), 'utf8'))
69
+ };
70
+
71
+ await writeFile(path.join(skillDir, 'skill.json'), JSON.stringify(envelope, null, 2), 'utf8');
72
+ console.log('Skill envelope written successfully:', envelope.manifest_sha256);
73
+
74
+ // Verify with createSkillPlane
75
+ const plane = await createSkillPlane({
76
+ root: path.join(stateDir, 'skills'),
77
+ verifyKeyPath: path.join(stateDir, 'trust', 'ed25519-public.pem')
78
+ });
79
+ const list = await plane.list();
80
+ console.log('Skill plane list result: skills=' + list.skills.length + ' invalid=' + list.invalid_skills.length);
81
+ if (list.invalid_skills.length > 0) {
82
+ console.error('Invalid skills remain:', list.invalid_skills);
83
+ process.exit(1);
84
+ }
85
+ const loaded = await plane.load({ name: 'deadbyte-adaptive-reverse-engineering' });
86
+ console.log('Skill loaded OK: name=' + loaded.name + ' verified=' + loaded.verified);
@@ -0,0 +1,303 @@
1
+ export const CAPABILITY_STATES = Object.freeze({
2
+ AVAILABLE: 'AVAILABLE',
3
+ DEGRADED: 'DEGRADED',
4
+ DISABLED: 'DISABLED',
5
+ DENIED: 'DENIED',
6
+ UNAVAILABLE: 'UNAVAILABLE'
7
+ });
8
+
9
+ const CAPABILITY_OPERATIONS = Object.freeze({
10
+ 'skill.catalog': ['list', 'load', 'resource'],
11
+ 'machine.list': ['machine_list'],
12
+ 'machine.status': ['machine_status'],
13
+ 'machine.ping': ['machine_ping'],
14
+ 'machine.revoke': ['machine_revoke'],
15
+ 'process.start': ['start'],
16
+ 'process.read': ['read'],
17
+ 'process.write': ['write'],
18
+ 'process.status': ['status'],
19
+ 'process.list': ['list'],
20
+ 'process.action': ['action'],
21
+ 'process.terminate': ['terminate'],
22
+ 'coding.session_status': ['coding_session_status'],
23
+ 'coding.tree': ['coding_tree'],
24
+ 'coding.stat': ['stat'],
25
+ 'coding.search': ['search'],
26
+ 'coding.files_read': ['files_read'],
27
+ 'coding.file_read': ['coding_file_read'],
28
+ 'coding.file_write': ['coding_file_write'],
29
+ 'coding.text_replace': ['coding_text_replace'],
30
+ 'coding.command_run': ['coding_command_run'],
31
+ 'coding.benchmark_run': ['coding_benchmark_run'],
32
+ 'coding.receipt_verify': ['coding_receipt_verify'],
33
+ 'coding.task_submit': ['coding_task_submit'],
34
+ 'coding.task_run': ['coding_task_run'],
35
+ 'coding.task_status': ['coding_task_status'],
36
+ 'coding.task_events': ['coding_task_events'],
37
+ 'coding.task_cancel': ['coding_task_cancel'],
38
+ 'coding.task_approve': ['coding_task_approve'],
39
+ 'coding.task_verify': ['coding_task_verify'],
40
+ 'semantic.outline': ['symbol_outline'],
41
+ 'semantic.definition': ['symbol_definition'],
42
+ 'semantic.references': ['symbol_references'],
43
+ 'semantic.diagnostics': ['symbol_diagnostics'],
44
+ 'semantic.implementations': ['symbol_implementations'],
45
+ 'semantic.rename_preview': ['symbol_rename_preview'],
46
+ 'semantic.replace': ['coding_symbol_replace'],
47
+ 'machine_fs.stat': ['stat'],
48
+ 'machine_fs.list': ['list'],
49
+ 'machine_fs.read': ['read'],
50
+ 'machine_fs.write': ['write'],
51
+ 'machine_fs.edit_exact': ['edit_exact'],
52
+ 'machine_fs.mkdir': ['mkdir'],
53
+ 'machine_fs.move': ['move'],
54
+ 'machine_fs.delete': ['delete'],
55
+ 'observation.search_start': ['search_start'],
56
+ 'observation.search_page': ['search_page'],
57
+ 'observation.search_status': ['search_status'],
58
+ 'observation.search_cancel': ['search_cancel'],
59
+ 'observation.process_list': ['process_list'],
60
+ 'observation.system_status': ['system_status'],
61
+ 'observation.hardware_query': ['hardware_query'],
62
+ 'desktop.status': ['status'],
63
+ 'desktop.observe': ['observe'],
64
+ 'desktop.target': ['target'],
65
+ 'desktop.action': ['action'],
66
+ 'autonomous.session_status': ['autonomous_session_status'],
67
+ 'native_diff.preview': ['native_diff_preview'],
68
+ 'native_diff.apply': ['native_diff_apply'],
69
+ 'native_diff.verify': ['native_diff_verify'],
70
+ 'autonomous.goal_submit': ['autonomous_goal_submit'],
71
+ 'autonomous.goal_run': ['autonomous_goal_run'],
72
+ 'autonomous.goal_status': ['autonomous_goal_status'],
73
+ 'autonomous.goal_events': ['autonomous_goal_events'],
74
+ 'autonomous.goal_cancel': ['autonomous_goal_cancel'],
75
+ 'autonomous.goal_approve': ['autonomous_goal_approve'],
76
+ 'autonomous.goal_verify': ['autonomous_goal_verify'],
77
+ 'autonomous.release_gate': ['autonomous_release_gate'],
78
+ 'host.file_read': ['host_file_read'],
79
+ 'host.file_write': ['host_file_write'],
80
+ 'host.exec': ['host_exec'],
81
+ 'evidence.verify': ['evidence_verify']
82
+ });
83
+
84
+ export function deriveCapabilityRequirements(capability) {
85
+ const reqs = [];
86
+ if (capability.runtime_flag) reqs.push(capability.runtime_flag);
87
+ if (capability.id === 'skill.catalog') {
88
+ reqs.push('skill_plane.valid');
89
+ return reqs;
90
+ }
91
+ if (capability.authority === 'coding') {
92
+ if (capability.mutating) {
93
+ reqs.push('coding_session.armed', 'policy.write');
94
+ } else {
95
+ reqs.push('coding_runtime.ready');
96
+ }
97
+ } else if (capability.authority === 'process') {
98
+ if (capability.mutating) {
99
+ reqs.push('process_session.armed');
100
+ } else {
101
+ reqs.push('process_runtime.ready');
102
+ }
103
+ } else if (capability.authority === 'autonomous') {
104
+ if (capability.mutating) {
105
+ reqs.push('autonomous_session.armed');
106
+ } else {
107
+ reqs.push('autonomous_runtime.ready');
108
+ }
109
+ } else if (capability.authority === 'desktop') {
110
+ if (capability.mutating) {
111
+ reqs.push('desktop_control.armed', 'policy.desktop');
112
+ } else {
113
+ reqs.push('desktop_runtime.ready');
114
+ }
115
+ } else if (capability.authority === 'host' || capability.host_only) {
116
+ if (capability.mutating) {
117
+ reqs.push('host_policy.armed');
118
+ } else {
119
+ reqs.push('host_policy.configured');
120
+ }
121
+ }
122
+ return reqs;
123
+ }
124
+
125
+ export async function resolveCapabilityStates({
126
+ ledger,
127
+ toolCatalog = [],
128
+ profile = 'full',
129
+ env = process.env,
130
+ codingRuntime = null,
131
+ processRuntime = null,
132
+ processPolicy = null,
133
+ machineFsRuntime = null,
134
+ observationRuntime = null,
135
+ desktopRuntime = null,
136
+ desktopPolicy = null,
137
+ autonomousRuntime = null,
138
+ skillRuntime = null,
139
+ hostPolicy = null
140
+ } = {}) {
141
+ const capabilities = ledger?.entries ?? [];
142
+ const resolved = [];
143
+ const catalogSet = new Set(toolCatalog);
144
+
145
+ // Probe session authorities asynchronously
146
+ let codingStatus = null;
147
+ if (codingRuntime?.sessionStatus) {
148
+ try { codingStatus = await codingRuntime.sessionStatus(); } catch {}
149
+ }
150
+
151
+ let autonomousStatus = null;
152
+ if (autonomousRuntime?.sessionStatus) {
153
+ try { autonomousStatus = await autonomousRuntime.sessionStatus(); } catch {}
154
+ }
155
+
156
+ let skillListResult = null;
157
+ if (skillRuntime?.list) {
158
+ try { skillListResult = await skillRuntime.list(); } catch (err) {
159
+ skillListResult = { invalid_skills: [{ name: '*', error: String(err) }] };
160
+ }
161
+ }
162
+
163
+ for (const cap of capabilities) {
164
+ const activeTool = profile === 'compact' ? (cap.compact_tool || cap.full_tool) : cap.full_tool;
165
+ const activeOp = profile === 'compact' ? (cap.compact_op || 'direct') : 'direct';
166
+ const ops = CAPABILITY_OPERATIONS[cap.id] ?? [activeOp];
167
+ const requires = deriveCapabilityRequirements(cap);
168
+
169
+ let state = CAPABILITY_STATES.AVAILABLE;
170
+ let ready = true;
171
+ let diagnostic = null;
172
+
173
+ // 1. Runtime Flag Disabled check
174
+ if (cap.runtime_flag && env[cap.runtime_flag] === '0') {
175
+ state = CAPABILITY_STATES.DISABLED;
176
+ ready = false;
177
+ diagnostic = {
178
+ code: 'RUNTIME_FLAG_DISABLED',
179
+ reason: `Runtime flag ${cap.runtime_flag}=0 is disarmed`,
180
+ recoverable: false
181
+ };
182
+ }
183
+ // 2. Tool presence check
184
+ else if (!catalogSet.has(activeTool)) {
185
+ state = CAPABILITY_STATES.UNAVAILABLE;
186
+ ready = false;
187
+ diagnostic = {
188
+ code: 'TOOL_NOT_REGISTERED',
189
+ reason: `Tool '${activeTool}' is not registered in the active tool catalog`,
190
+ recoverable: false
191
+ };
192
+ }
193
+ // 3. Subsystem runtime instantiation check
194
+ else if (cap.id.startsWith('machine_fs.') && !machineFsRuntime) {
195
+ state = CAPABILITY_STATES.UNAVAILABLE;
196
+ ready = false;
197
+ diagnostic = {
198
+ code: 'MACHINE_FS_NOT_INSTANTIATED',
199
+ reason: 'Machine filesystem runtime is uninitialized',
200
+ recoverable: false
201
+ };
202
+ } else if (cap.id.startsWith('observation.') && !observationRuntime) {
203
+ state = CAPABILITY_STATES.UNAVAILABLE;
204
+ ready = false;
205
+ diagnostic = {
206
+ code: 'OBSERVATION_NOT_INSTANTIATED',
207
+ reason: 'Observation runtime is uninitialized',
208
+ recoverable: false
209
+ };
210
+ } else if (cap.id.startsWith('desktop.') && !desktopRuntime) {
211
+ state = CAPABILITY_STATES.UNAVAILABLE;
212
+ ready = false;
213
+ diagnostic = {
214
+ code: 'DESKTOP_NOT_INSTANTIATED',
215
+ reason: 'Desktop runtime is uninitialized',
216
+ recoverable: false
217
+ };
218
+ } else if ((cap.authority === 'host' || cap.host_only) && !hostPolicy) {
219
+ state = CAPABILITY_STATES.DENIED;
220
+ ready = false;
221
+ diagnostic = {
222
+ code: 'HOST_POLICY_DISARMED',
223
+ reason: 'Privileged host policy is not configured or disarmed',
224
+ recoverable: true
225
+ };
226
+ }
227
+ // 4. Session Authority Checks
228
+ else if (cap.authority === 'coding' && cap.mutating && codingStatus && !codingStatus.armed) {
229
+ state = CAPABILITY_STATES.DENIED;
230
+ ready = false;
231
+ diagnostic = {
232
+ code: 'CODING_SESSION_DISARMED',
233
+ reason: codingStatus.reason || 'Coding session is not armed for mutation',
234
+ recoverable: true
235
+ };
236
+ } else if (cap.authority === 'autonomous' && cap.mutating && autonomousStatus && !autonomousStatus.armed) {
237
+ state = CAPABILITY_STATES.DENIED;
238
+ ready = false;
239
+ diagnostic = {
240
+ code: 'AUTONOMOUS_SESSION_DISARMED',
241
+ reason: autonomousStatus.reason || 'Autonomous session is not armed for mutation',
242
+ recoverable: true
243
+ };
244
+ }
245
+ // 5. Subsystem Health Probes (e.g. Skill Plane envelope verification)
246
+ else if (cap.id === 'skill.catalog') {
247
+ if (skillListResult?.invalid_skills && skillListResult.invalid_skills.length > 0) {
248
+ state = CAPABILITY_STATES.DEGRADED;
249
+ ready = false;
250
+ diagnostic = {
251
+ code: 'SKILL_ENVELOPE_MISMATCH',
252
+ reason: `Skill registry rejected envelope for: ${skillListResult.invalid_skills.map(s => s.name).join(', ')}`,
253
+ recoverable: true
254
+ };
255
+ }
256
+ }
257
+
258
+ resolved.push(Object.freeze({
259
+ id: cap.id,
260
+ tool: activeTool,
261
+ compact_tool: cap.compact_tool,
262
+ compact_op: cap.compact_op,
263
+ operations: ops,
264
+ authority: cap.authority,
265
+ mutating: cap.mutating,
266
+ production: cap.production,
267
+ runtime_flag: cap.runtime_flag,
268
+ requires,
269
+ state,
270
+ ready,
271
+ diagnostic
272
+ }));
273
+ }
274
+
275
+ const effectiveCapabilities = resolved
276
+ .filter(c => c.state === CAPABILITY_STATES.AVAILABLE)
277
+ .map(c => c.id);
278
+
279
+ const unavailableCapabilities = resolved
280
+ .filter(c => c.state === CAPABILITY_STATES.UNAVAILABLE || c.state === CAPABILITY_STATES.DISABLED || c.state === CAPABILITY_STATES.DENIED)
281
+ .map(c => ({
282
+ id: c.id,
283
+ state: c.state,
284
+ reason_code: c.diagnostic?.code ?? 'UNAVAILABLE',
285
+ reason: c.diagnostic?.reason ?? 'Capability not available'
286
+ }));
287
+
288
+ const degradedCapabilities = resolved
289
+ .filter(c => c.state === CAPABILITY_STATES.DEGRADED)
290
+ .map(c => ({
291
+ id: c.id,
292
+ state: c.state,
293
+ reason_code: c.diagnostic?.code ?? 'DEGRADED',
294
+ reason: c.diagnostic?.reason ?? 'Capability operating in degraded mode'
295
+ }));
296
+
297
+ return Object.freeze({
298
+ capabilities: resolved,
299
+ effective_capabilities: effectiveCapabilities,
300
+ unavailable_capabilities: unavailableCapabilities,
301
+ degraded_capabilities: degradedCapabilities
302
+ });
303
+ }
@@ -2,6 +2,7 @@ import { createHash } from 'node:crypto';
2
2
  import * as z from 'zod/v4';
3
3
  import { compactGatewayOutputSchema, compactGatewayResult } from './compact-gateway-output-contracts.mjs';
4
4
  import { desktopControlInputSchema,invokeDesktopOperation } from './desktop-mcp-tools-r40.mjs';
5
+ import { resolveCapabilityStates } from './capability-resolver.mjs';
5
6
 
6
7
  const id=z.string().regex(/^[A-Za-z0-9._-]{1,64}$/);
7
8
  const rel=z.string().min(1).max(2048);
@@ -123,17 +124,26 @@ async function machineObserve(args,machineRuntime,observationRuntime){
123
124
  return invoke(args.op,observationRuntime,'observation',map[args.op]);
124
125
  }
125
126
 
126
- export function registerCompactGatewayTools(server,{profile,ledger,codingRuntime,semanticRuntime,machineFsRuntime,processRuntime,observationRuntime,machineRuntime,desktopRuntime,catalogProvider}){
127
+ export function registerCompactGatewayTools(server,{profile,ledger,codingRuntime,semanticRuntime,machineFsRuntime,processRuntime,observationRuntime,machineRuntime,desktopRuntime,skillRuntime,autonomousRuntime,hostPolicy,env=process.env,catalogProvider}){
127
128
  if(!server) throw new Error('compact gateway registration requires server');
128
129
  if(profile!=='compact') return;
129
130
  if(typeof catalogProvider!=='function') throw new Error('compact gateway requires catalogProvider');
130
- server.registerTool('capability_manifest',{description:'Read the canonical capability ledger and exact active compact tool catalog.',inputSchema:capabilityManifestInputSchema,outputSchema:compactGatewayOutputSchema},async()=>{
131
+ server.registerTool('capability_manifest',{description:'Read the canonical capability ledger and exact active compact tool catalog with runtime-aware resolution.',inputSchema:capabilityManifestInputSchema,outputSchema:compactGatewayOutputSchema},async()=>{
131
132
  const toolCatalog=[...catalogProvider()].map(String).sort();
132
133
  if(toolCatalog.length<1||new Set(toolCatalog).size!==toolCatalog.length) throw new Error('compact catalog provider returned invalid catalog');
133
134
  const catalogSha256=createHash('sha256').update(JSON.stringify(toolCatalog),'utf8').digest('hex');
135
+ const dynamicResolution = await resolveCapabilityStates({
136
+ ledger, toolCatalog, profile, env,
137
+ codingRuntime, processRuntime, machineFsRuntime, observationRuntime, desktopRuntime,
138
+ autonomousRuntime, skillRuntime, hostPolicy
139
+ });
134
140
  return compactGatewayResult({status:'ok',op:'manifest',result:{
135
141
  schema:'deadbyte.capability-manifest.v2',profile,ledger_sha256:ledger?.ledger_sha256??null,
136
- tool_catalog:toolCatalog,tool_count:toolCatalog.length,catalog_sha256:catalogSha256,capabilities:ledger?.entries??[]
142
+ tool_catalog:toolCatalog,tool_count:toolCatalog.length,catalog_sha256:catalogSha256,
143
+ capabilities:dynamicResolution.capabilities,
144
+ effective_capabilities:dynamicResolution.effective_capabilities,
145
+ unavailable_capabilities:dynamicResolution.unavailable_capabilities,
146
+ degraded_capabilities:dynamicResolution.degraded_capabilities
137
147
  }},false);
138
148
  });
139
149
  server.registerTool('coding_inspect',{description:'Typed compact coding inspection and semantic navigation gateway. No arbitrary tool dispatch.',inputSchema:codingInspectInputSchema,outputSchema:compactGatewayOutputSchema},args=>codingInspect(args,codingRuntime,semanticRuntime));
@@ -459,7 +459,8 @@ serveStdio(() => {
459
459
 
460
460
  registerCompactGatewayTools(toolServer,{
461
461
  profile:surfaceProfile,ledger:R36_CAPABILITY_LEDGER,codingRuntime,semanticRuntime,machineFsRuntime,
462
- processRuntime,observationRuntime,machineRuntime,desktopRuntime,catalogProvider:()=>[...registeredToolNames]
462
+ processRuntime,observationRuntime,machineRuntime,desktopRuntime,skillRuntime,autonomousRuntime,hostPolicy,
463
+ catalogProvider:()=>[...registeredToolNames]
463
464
  });
464
465
 
465
466
  if (hostPolicy) {
@@ -20,12 +20,27 @@ const TERMINAL_RECOVERY_SCHEMA = 'deadbyte.process-terminal.v1';
20
20
  const sha256Bytes = bytes => createHash('sha256').update(bytes).digest('hex');
21
21
  const nowUtc = () => new Date().toISOString();
22
22
 
23
+ const STANDARD_PATHEXT = '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC';
24
+
25
+ export function getRepairedPathExt() {
26
+ const current = process.env.PATHEXT;
27
+ if (!current) return STANDARD_PATHEXT;
28
+ const exts = current.split(';').map(e => e.trim().toUpperCase()).filter(Boolean);
29
+ if (!exts.includes('.EXE')) {
30
+ return [...new Set([...STANDARD_PATHEXT.split(';'), ...exts])].join(';');
31
+ }
32
+ return current;
33
+ }
34
+
23
35
  function processEnvironment(profile) {
24
36
  const allow = new Set(profile.env_allow.map(name => name.toLowerCase()));
25
37
  const env = {};
26
38
  for (const [key, value] of Object.entries(process.env)) {
27
39
  if (allow.has(key.toLowerCase()) && typeof value === 'string') env[key] = value;
28
40
  }
41
+ if (process.platform === 'win32') {
42
+ env.PATHEXT = getRepairedPathExt();
43
+ }
29
44
  return env;
30
45
  }
31
46
  async function resolveCwd(policy, grant, profile, rootId, cwd) {
@@ -1157,15 +1157,15 @@ async function resumeSlotUpdate({handoffPath}){
1157
1157
  const stableMcpUrl=body.stable_mcp_url?{...body.stable_mcp_url}:releaseState.stable_mcp_url?{...releaseState.stable_mcp_url}:null;
1158
1158
  const mcpUrlSnapshot=body.mcp_url_snapshot?decodeSnapshot(body.mcp_url_snapshot,'MCP URL'):{exists:false,bytes:null,sha256:null};
1159
1159
  const cleanup=await acquireSupervisorLease(absoluteHandoff);
1160
+ const journal=releaseState;
1161
+ let pointerCommitted=phaseRank(phase)>=phaseRank('pointer_committed')||samePublicPointer(currentPointer,candidatePointer);
1162
+ let stopped=phaseRank(phase)>=phaseRank('old_runtime_stopped');
1160
1163
  try{
1161
- const journal=releaseState;
1162
1164
  if(phaseRank(phase)<phaseRank('supervisor_spawned')){
1163
1165
  await writeState(statePath,journal,'supervisor_spawned',{supervisor_pid:process.pid,supervisor_script:body.supervisor_script,supervisor_script_sha256:body.supervisor_script_sha256});
1164
1166
  phase='supervisor_spawned';
1165
1167
  }
1166
1168
  let revoked=phaseRank(phase)>=phaseRank('authority_revoked')||journal.revoked_before_switch===true;
1167
- let stopped=phaseRank(phase)>=phaseRank('old_runtime_stopped');
1168
- let pointerCommitted=phaseRank(phase)>=phaseRank('pointer_committed')||samePublicPointer(currentPointer,candidatePointer);
1169
1169
  let newRuntime=null,stabilization=null;
1170
1170
 
1171
1171
  if(phaseRank(phase)<phaseRank('authority_revoked')){
package/src/version.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export const DEADBYTE_VERSION = '0.15.10';
1
+ export const DEADBYTE_VERSION = '0.15.11';
2
2
  export const MCP_PROTOCOL_VERSION = '2026-07-28';
3
3
  export const RECEIPT_SCHEMA_V1 = 'deadbyte.receipt.v1';
4
4
  export const RECEIPT_SCHEMA_V2 = 'deadbyte.receipt.v2';
@@ -0,0 +1,133 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {
4
+ CAPABILITY_STATES,
5
+ deriveCapabilityRequirements,
6
+ resolveCapabilityStates
7
+ } from '../src/capability-resolver.mjs';
8
+ import { R36_CAPABILITY_LEDGER } from '../src/capability-ledger.mjs';
9
+
10
+ test('capability resolver enforces 5 canonical states', () => {
11
+ assert.equal(CAPABILITY_STATES.AVAILABLE, 'AVAILABLE');
12
+ assert.equal(CAPABILITY_STATES.DEGRADED, 'DEGRADED');
13
+ assert.equal(CAPABILITY_STATES.DISABLED, 'DISABLED');
14
+ assert.equal(CAPABILITY_STATES.DENIED, 'DENIED');
15
+ assert.equal(CAPABILITY_STATES.UNAVAILABLE, 'UNAVAILABLE');
16
+ });
17
+
18
+ test('deriveCapabilityRequirements maps dependencies accurately', () => {
19
+ const reqCodingRead = deriveCapabilityRequirements({
20
+ id: 'coding.search',
21
+ authority: 'coding',
22
+ mutating: false,
23
+ runtime_flag: 'DEADBYTE_CODING_RUNTIME'
24
+ });
25
+ assert.deepEqual(reqCodingRead, ['DEADBYTE_CODING_RUNTIME', 'coding_runtime.ready']);
26
+
27
+ const reqCodingWrite = deriveCapabilityRequirements({
28
+ id: 'coding.file_write',
29
+ authority: 'coding',
30
+ mutating: true,
31
+ runtime_flag: 'DEADBYTE_CODING_RUNTIME'
32
+ });
33
+ assert.deepEqual(reqCodingWrite, ['DEADBYTE_CODING_RUNTIME', 'coding_session.armed', 'policy.write']);
34
+
35
+ const reqSkill = deriveCapabilityRequirements({
36
+ id: 'skill.catalog',
37
+ authority: 'operator',
38
+ mutating: false
39
+ });
40
+ assert.deepEqual(reqSkill, ['skill_plane.valid']);
41
+ });
42
+
43
+ test('resolveCapabilityStates resolves all 5 states correctly', async () => {
44
+ const allCompactTools = [
45
+ 'capability_manifest',
46
+ 'coding_inspect',
47
+ 'machine_fs',
48
+ 'process_session',
49
+ 'machine_observe',
50
+ 'desktop_control',
51
+ 'skill_catalog'
52
+ ];
53
+
54
+ // 1. Fully available & armed state
55
+ const armedRes = await resolveCapabilityStates({
56
+ ledger: R36_CAPABILITY_LEDGER,
57
+ toolCatalog: allCompactTools,
58
+ profile: 'compact',
59
+ env: {},
60
+ codingRuntime: { sessionStatus: async () => ({ armed: true }) },
61
+ processRuntime: {},
62
+ machineFsRuntime: {},
63
+ observationRuntime: {},
64
+ desktopRuntime: {},
65
+ autonomousRuntime: { sessionStatus: async () => ({ armed: true }) },
66
+ skillRuntime: { list: async () => ({ invalid_skills: [] }) },
67
+ hostPolicy: {}
68
+ });
69
+
70
+ assert.ok(armedRes.capabilities.length > 0);
71
+ assert.ok(armedRes.effective_capabilities.includes('coding.search'));
72
+ assert.ok(armedRes.effective_capabilities.includes('skill.catalog'));
73
+
74
+ // 2. Disabled by runtime flag
75
+ const disabledRes = await resolveCapabilityStates({
76
+ ledger: R36_CAPABILITY_LEDGER,
77
+ toolCatalog: allCompactTools,
78
+ profile: 'compact',
79
+ env: { DEADBYTE_CODING_RUNTIME: '0' },
80
+ codingRuntime: { sessionStatus: async () => ({ armed: true }) },
81
+ processRuntime: {},
82
+ machineFsRuntime: {},
83
+ observationRuntime: {},
84
+ desktopRuntime: {},
85
+ skillRuntime: { list: async () => ({ invalid_skills: [] }) }
86
+ });
87
+
88
+ const codingSearch = disabledRes.capabilities.find(c => c.id === 'coding.search');
89
+ assert.equal(codingSearch.state, CAPABILITY_STATES.DISABLED);
90
+ assert.equal(codingSearch.diagnostic.code, 'RUNTIME_FLAG_DISABLED');
91
+ assert.ok(disabledRes.unavailable_capabilities.some(u => u.id === 'coding.search' && u.state === CAPABILITY_STATES.DISABLED));
92
+
93
+ // 3. Unavailable due to uninstantiated subsystem
94
+ const uninstantiatedRes = await resolveCapabilityStates({
95
+ ledger: R36_CAPABILITY_LEDGER,
96
+ toolCatalog: allCompactTools,
97
+ profile: 'compact',
98
+ env: {},
99
+ machineFsRuntime: null
100
+ });
101
+ const fsStat = uninstantiatedRes.capabilities.find(c => c.id === 'machine_fs.stat');
102
+ assert.equal(fsStat.state, CAPABILITY_STATES.UNAVAILABLE);
103
+ assert.equal(fsStat.diagnostic.code, 'MACHINE_FS_NOT_INSTANTIATED');
104
+
105
+ // 4. Denied when coding session is disarmed for mutating operations in full profile
106
+ const disarmedRes = await resolveCapabilityStates({
107
+ ledger: R36_CAPABILITY_LEDGER,
108
+ toolCatalog: ['coding_file_write', 'coding_search'],
109
+ profile: 'full',
110
+ env: {},
111
+ codingRuntime: { sessionStatus: async () => ({ armed: false, reason: 'policy grant not confirmed' }) },
112
+ machineFsRuntime: {},
113
+ skillRuntime: { list: async () => ({ invalid_skills: [] }) }
114
+ });
115
+ const fileWrite = disarmedRes.capabilities.find(c => c.id === 'coding.file_write');
116
+ assert.equal(fileWrite.state, CAPABILITY_STATES.DENIED);
117
+ assert.equal(fileWrite.diagnostic.code, 'CODING_SESSION_DISARMED');
118
+
119
+ // 5. Degraded when skill plane reports envelope mismatch
120
+ const degradedRes = await resolveCapabilityStates({
121
+ ledger: R36_CAPABILITY_LEDGER,
122
+ toolCatalog: allCompactTools,
123
+ profile: 'compact',
124
+ env: {},
125
+ codingRuntime: { sessionStatus: async () => ({ armed: true }) },
126
+ machineFsRuntime: {},
127
+ skillRuntime: { list: async () => ({ invalid_skills: [{ name: 'test-broken', error: 'envelope mismatch' }] }) }
128
+ });
129
+ const skillCap = degradedRes.capabilities.find(c => c.id === 'skill.catalog');
130
+ assert.equal(skillCap.state, CAPABILITY_STATES.DEGRADED);
131
+ assert.equal(skillCap.diagnostic.code, 'SKILL_ENVELOPE_MISMATCH');
132
+ assert.ok(degradedRes.degraded_capabilities.some(d => d.id === 'skill.catalog'));
133
+ });