Skip to content

Commit e07a8fa

Browse files
committed
feat(boj): align CapabilityDomain with 17-cartridge matrix and add V-lang CI check
1 parent c4980c1 commit e07a8fa

7 files changed

Lines changed: 124 additions & 53 deletions

File tree

.github/workflows/zig-test.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,23 @@ jobs:
5858

5959
- name: Run benchmarks
6060
run: cd ffi/zig && zig build bench
61+
62+
v-lang-check:
63+
name: V-lang Adapter Checks
64+
runs-on: ubuntu-latest
65+
steps:
66+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
67+
68+
- name: Install V-lang
69+
run: |
70+
sudo apt-get update && sudo apt-get install -y libgc-dev
71+
git clone --depth=1 https://github.com/vlang/v
72+
cd v && make && sudo ./v symlink
73+
cd ..
74+
75+
- name: Check LSP/DAP/BSP Adapters
76+
run: |
77+
for cart in lsp-mcp dap-mcp bsp-mcp; do
78+
echo "Checking $cart adapter..."
79+
v check cartridges/$cart/adapter/*.v
80+
done

docs/TOPOLOGY.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,16 @@
5858
│ │ │
5959
▼ ▼ ▼
6060
┌───────────────────────────────────────────────────────────────┐
61-
18 CARTRIDGES (2D Matrix) │
61+
17 CARTRIDGES (2D Matrix) │
6262
│ │
6363
│ database-mcp fleet-mcp nesy-mcp agent-mcp │
6464
│ cloud-mcp container-mcp k8s-mcp git-mcp │
6565
│ secrets-mcp queues-mcp iac-mcp observe-mcp │
6666
│ ssg-mcp proof-mcp lsp-mcp dap-mcp │
67-
│ bsp-mcp feedback-mcp
67+
│ bsp-mcp
6868
│ │
6969
│ Each: abi/ (Idris2) + ffi/ (Zig) + adapter/ (V-lang) │
70-
18/18 mounted + serving | 307 tests total │
70+
17/17 mounted + serving | 307 tests total │
7171
└───────────────────────────────────────────────────────────────┘
7272
7373
@@ -79,6 +79,7 @@
7979
│ vordr.toml (runtime monitoring) │
8080
│ deploy.k9.ncl (operational constraints) │
8181
│ VeriSimDB backing store (7 tests) │
82+
│ feedback-o-tron (18th cartridge — separate) │
8283
└───────────────────────────────────────────────────────────────┘
8384
```
8485

@@ -104,11 +105,10 @@ Proof │ ██ │ │ │ │ │ │
104105
LSP │ ██ │ ██ │ │ │ │ │ │ │ ██ │
105106
DAP │ ██ │ │ ██ │ │ │ │ │ │ ██ │
106107
BSP │ ██ │ │ │ ██ │ │ │ │ │ ██ │
107-
Feedback │ ██ │ │ │ │ │ │ │ │ ██ │
108108
└──────┴──────┴──────┴──────┴──────┴───────┴──────┴──────┴──────┘
109109
110110
██ = ABI + FFI + Adapter built and .so compiled (Grade D Alpha)
111-
gRPC on: database, agent, cloud, k8s, queues, observe (6/18)
111+
gRPC on: database, agent, cloud, k8s, queues, observe (6/17)
112112
All cells have backend="universal". Third axis (backend/provider)
113113
stubbed for community extensions — see docs/EXTENSIBILITY.md
114114
```
@@ -124,7 +124,7 @@ Feedback │ ██ │ │ │ │ │ │
124124
| Guardian module (Zig) | `███████░░░` 70% | D (Alpha) — 12 tests, no real failure scenarios |
125125
| V-lang Adapter (REST+gRPC+GQL) | `██████░░░░` 60% | D (Alpha) — compiles and routes, no external traffic |
126126
| C Headers (generated) | `███████░░░` 70% | D (Alpha) — generated, not tested via C consumer |
127-
| **Cartridges (18/18 built)** | | |
127+
| **Cartridges (17/17 built)** | | |
128128
| database-mcp | `███████░░░` 70% | D (Alpha) .so — e2e test exists, no real DB workload |
129129
| fleet-mcp | `██████░░░░` 60% | D (Alpha) .so |
130130
| nesy-mcp | `██████░░░░` 60% | D (Alpha) .so |
@@ -139,10 +139,11 @@ Feedback │ ██ │ │ │ │ │ │
139139
| observe-mcp | `██████░░░░` 60% | D (Alpha) .so |
140140
| ssg-mcp | `██████░░░░` 60% | D (Alpha) .so — Zola e2e test exists, not production |
141141
| proof-mcp | `██████░░░░` 60% | D (Alpha) .so |
142-
| lsp-mcp | `██████░░░░` 60% | D (Alpha) .so |
143-
| dap-mcp | `██████░░░░` 60% | D (Alpha) .so |
144-
| bsp-mcp | `██████░░░░` 60% | D (Alpha) .so |
145-
| feedback-mcp | `██████░░░░` 60% | D (Alpha) .so |
142+
| lsp-mcp | `██████░░░░` 60% | D (Alpha) .so — CI integration active |
143+
| dap-mcp | `██████░░░░` 60% | D (Alpha) .so — CI integration active |
144+
| bsp-mcp | `██████░░░░` 60% | D (Alpha) .so — CI integration active |
145+
| **Specialist Cartridges** | | |
146+
| feedback-o-tron (18th cartridge) | `██████░░░░` 60% | D (Alpha) — full ABI+FFI, not collecting real feedback |
146147
| **Federation & Distribution** | | |
147148
| Umoja federation (QUIC+UDP) | `██████░░░░` 60% | D (Alpha) — tests pass, no real multi-node deployment |
148149
| VeriSimDB backing store | `██████░░░░` 60% | D (Alpha) — 7 tests, no production persistence |

ffi/zig/src/catalogue.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ pub const CapabilityDomain = enum(c_int) {
5252
proof = 11,
5353
fleet_dom = 12,
5454
nesy_dom = 13,
55-
feedback = 14,
55+
agent = 14,
56+
lsp = 15,
57+
dap = 16,
58+
bsp = 17,
5659
};
5760

5861
/// Menu tier (Teranga/Shield/Ayo).

ffi/zig/src/e2e_order.zig

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,28 @@ test "e2e order-ticket: register, protocol, hash, mount, query, unmount" {
4747
// --- Step 1: Init ---
4848
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_init());
4949

50-
// --- Step 2: Register 4 cartridges with status=ready ---
50+
// --- Step 2: Register core cartridges with status=ready ---
5151
// database-mcp domain=database(3)
5252
// fleet-mcp domain=fleet_dom(12)
5353
// nesy-mcp domain=nesy_dom(13)
54-
// agent-mcp domain=cloud(1)
55-
const idx_database = registerReady("database-mcp", 3);
56-
const idx_fleet = registerReady("fleet-mcp", 12);
57-
const idx_nesy = registerReady("nesy-mcp", 13);
58-
const idx_agent = registerReady("agent-mcp", 1);
59-
60-
try std.testing.expectEqual(@as(usize, 4), catalogue.boj_catalogue_count());
61-
try std.testing.expectEqual(@as(usize, 4), catalogue.boj_catalogue_count_ready());
54+
// agent-mcp domain=agent(14)
55+
// lsp-mcp domain=lsp(15)
56+
// dap-mcp domain=dap(16)
57+
// bsp-mcp domain=bsp(17)
58+
_ = registerReady("database-mcp", 3);
59+
_ = registerReady("fleet-mcp", 12);
60+
_ = registerReady("nesy-mcp", 13);
61+
_ = registerReady("agent-mcp", 14);
62+
_ = registerReady("lsp-mcp", 15);
63+
_ = registerReady("dap-mcp", 16);
64+
_ = registerReady("bsp-mcp", 17);
65+
66+
try std.testing.expectEqual(@as(usize, 7), catalogue.boj_catalogue_count());
67+
try std.testing.expectEqual(@as(usize, 7), catalogue.boj_catalogue_count_ready());
6268

6369
// --- Step 3: Add protocols matching V adapter builtins ---
64-
// database-mcp: mcp(1)
65-
// fleet-mcp: mcp(1), fleet(7)
66-
// nesy-mcp: mcp(1), nesy(5)
67-
// agent-mcp: mcp(1), agentic(6)
68-
//
6970
// boj_catalogue_add_protocol applies to the *last* registered cartridge,
7071
// so we re-register in order and add protocols right after each.
71-
// Since we already registered above, we re-init and redo to keep the
72-
// add_protocol calls adjacent to registration.
7372
catalogue.boj_catalogue_deinit();
7473
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_init());
7574

@@ -110,26 +109,31 @@ test "e2e order-ticket: register, protocol, hash, mount, query, unmount" {
110109
const name = "agent-mcp";
111110
const ver = "1.0.0";
112111
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_register(
113-
name.ptr, name.len, ver.ptr, ver.len, 1, 0, 1,
112+
name.ptr, name.len, ver.ptr, ver.len, 1, 0, 14,
114113
));
115114
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_add_protocol(1)); // mcp
116115
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_add_protocol(6)); // agentic
117116
}
118117

119-
try std.testing.expectEqual(@as(usize, 4), catalogue.boj_catalogue_count());
120-
try std.testing.expectEqual(@as(usize, 4), catalogue.boj_catalogue_count_ready());
118+
// lsp-mcp
119+
{
120+
const name = "lsp-mcp";
121+
const ver = "1.0.0";
122+
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_register(
123+
name.ptr, name.len, ver.ptr, ver.len, 1, 0, 15,
124+
));
125+
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_add_protocol(2)); // lsp
126+
}
127+
128+
try std.testing.expectEqual(@as(usize, 5), catalogue.boj_catalogue_count());
129+
try std.testing.expectEqual(@as(usize, 5), catalogue.boj_catalogue_count_ready());
121130

122131
// Indices after fresh registration sequence:
123132
const db_idx: usize = 0; // database-mcp
124133
const fl_idx: usize = 1; // fleet-mcp
125134
const ne_idx: usize = 2; // nesy-mcp
126135
const ag_idx: usize = 3; // agent-mcp
127-
128-
// Suppress unused variable warnings from the first registration pass.
129-
_ = idx_database;
130-
_ = idx_fleet;
131-
_ = idx_nesy;
132-
_ = idx_agent;
136+
const ls_idx: usize = 4; // lsp-mcp
133137

134138
// --- Step 4: Set hash attestation on database-mcp ---
135139
const fake_hash = "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2";
@@ -144,40 +148,44 @@ test "e2e order-ticket: register, protocol, hash, mount, query, unmount" {
144148
try std.testing.expectEqual(fake_hash.len, hash_len);
145149
try std.testing.expectEqualSlices(u8, fake_hash, hash_buf[0..hash_len]);
146150

147-
// --- Step 5: Mount 3 cartridges (simulate an order) ---
148-
// Mount database-mcp, fleet-mcp, nesy-mcp (leave agent-mcp unmounted).
151+
// --- Step 5: Mount 4 cartridges (simulate an order) ---
152+
// Mount database-mcp, fleet-mcp, nesy-mcp, lsp-mcp (leave agent-mcp unmounted).
149153
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_mount(db_idx));
150154
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_mount(fl_idx));
151155
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_mount(ne_idx));
156+
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_mount(ls_idx));
152157

153-
// --- Step 6: Verify mounted count is 3 ---
154-
try std.testing.expectEqual(@as(usize, 3), catalogue.boj_catalogue_count_mounted());
158+
// --- Step 6: Verify mounted count is 4 ---
159+
try std.testing.expectEqual(@as(usize, 4), catalogue.boj_catalogue_count_mounted());
155160

156161
// --- Step 7: Verify each mounted cartridge via is_mounted ---
157162
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_is_mounted(db_idx));
158163
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_is_mounted(fl_idx));
159164
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_is_mounted(ne_idx));
165+
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_is_mounted(ls_idx));
160166
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_is_mounted(ag_idx)); // not mounted
161167

162168
// --- Step 8: Query catalogue to verify counts ---
163-
try std.testing.expectEqual(@as(usize, 4), catalogue.boj_catalogue_count());
164-
try std.testing.expectEqual(@as(usize, 4), catalogue.boj_catalogue_count_ready());
165-
try std.testing.expectEqual(@as(usize, 3), catalogue.boj_catalogue_count_mounted());
169+
try std.testing.expectEqual(@as(usize, 5), catalogue.boj_catalogue_count());
170+
try std.testing.expectEqual(@as(usize, 5), catalogue.boj_catalogue_count_ready());
171+
try std.testing.expectEqual(@as(usize, 4), catalogue.boj_catalogue_count_mounted());
166172

167173
// Verify statuses by index.
168174
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_status(db_idx)); // ready
169175
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_status(fl_idx)); // ready
170176
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_status(ne_idx)); // ready
171177
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_status(ag_idx)); // ready
178+
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_status(ls_idx)); // ready
172179

173180
// --- Step 9: Unmount one cartridge ---
174181
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_unmount(fl_idx));
175182

176-
// --- Step 10: Verify mounted count drops to 2 ---
177-
try std.testing.expectEqual(@as(usize, 2), catalogue.boj_catalogue_count_mounted());
183+
// --- Step 10: Verify mounted count drops to 3 ---
184+
try std.testing.expectEqual(@as(usize, 3), catalogue.boj_catalogue_count_mounted());
178185
try std.testing.expectEqual(@as(c_int, 0), catalogue.boj_catalogue_is_mounted(fl_idx));
179186
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_is_mounted(db_idx)); // still up
180187
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_is_mounted(ne_idx)); // still up
188+
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_is_mounted(ls_idx)); // still up
181189

182190
// --- Step 11: Deinit ---
183191
catalogue.boj_catalogue_deinit();

ffi/zig/src/seams.zig

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ test "seam: ProtocolType encoding matches Idris2 protocolToInt" {
5555
}
5656

5757
test "seam: CapabilityDomain encoding matches Idris2 domainToInt" {
58-
// Idris2: Cloud=1..Feedback=14
58+
// Idris2: Cloud=1..Bsp=17
5959
try std.testing.expectEqual(@as(c_int, 1), @intFromEnum(catalogue.CapabilityDomain.cloud));
6060
try std.testing.expectEqual(@as(c_int, 2), @intFromEnum(catalogue.CapabilityDomain.container));
6161
try std.testing.expectEqual(@as(c_int, 3), @intFromEnum(catalogue.CapabilityDomain.database));
@@ -69,7 +69,10 @@ test "seam: CapabilityDomain encoding matches Idris2 domainToInt" {
6969
try std.testing.expectEqual(@as(c_int, 11), @intFromEnum(catalogue.CapabilityDomain.proof));
7070
try std.testing.expectEqual(@as(c_int, 12), @intFromEnum(catalogue.CapabilityDomain.fleet_dom));
7171
try std.testing.expectEqual(@as(c_int, 13), @intFromEnum(catalogue.CapabilityDomain.nesy_dom));
72-
try std.testing.expectEqual(@as(c_int, 14), @intFromEnum(catalogue.CapabilityDomain.feedback));
72+
try std.testing.expectEqual(@as(c_int, 14), @intFromEnum(catalogue.CapabilityDomain.agent));
73+
try std.testing.expectEqual(@as(c_int, 15), @intFromEnum(catalogue.CapabilityDomain.lsp));
74+
try std.testing.expectEqual(@as(c_int, 16), @intFromEnum(catalogue.CapabilityDomain.dap));
75+
try std.testing.expectEqual(@as(c_int, 17), @intFromEnum(catalogue.CapabilityDomain.bsp));
7376
}
7477

7578
test "seam: MenuTier encoding matches Idris2" {
@@ -378,7 +381,7 @@ test "seam: all cartridges support MCP protocol" {
378381

379382
// Verify MCP protocol is present on all
380383
for (0..21) |i| {
381-
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_catalogue_has_protocol(i, 1));
384+
try std.testing.expectEqual(@as(c_int, 1), catalogue.boj_menu_has_protocol(i, 1));
382385
}
383386
}
384387

mcp-bridge/package-lock.json

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/abi/Boj/Domain.idr

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ data CapabilityDomain
2525
| Proof -- Formal proof assistants (Idris2, Lean, Coq)
2626
| FleetDom -- Gitbot fleet domain (rhodibot, echidnabot, etc.)
2727
| NeSyDom -- Neurosymbolic reasoning domain (hypatia, echidna)
28-
| Feedback -- Feedback collection (feedback-o-tron)
28+
| Agent -- Autonomous AI agents (autonomous-fleet, agentic-workflows)
29+
| Lsp -- Language Server Protocol domain
30+
| Dap -- Debug Adapter Protocol domain
31+
| Bsp -- Build Server Protocol domain
2932

3033
||| Human-readable label for display in the Teranga menu.
3134
public export
@@ -43,7 +46,10 @@ domainLabel SSG = "SSG"
4346
domainLabel Proof = "Proof"
4447
domainLabel FleetDom = "Fleet"
4548
domainLabel NeSyDom = "NeSy"
46-
domainLabel Feedback = "Feedback"
49+
domainLabel Agent = "Agent"
50+
domainLabel Lsp = "LSP"
51+
domainLabel Dap = "DAP"
52+
domainLabel Bsp = "BSP"
4753

4854
||| C-ABI encoding: domain to integer.
4955
public export
@@ -61,7 +67,10 @@ domainToInt SSG = 10
6167
domainToInt Proof = 11
6268
domainToInt FleetDom = 12
6369
domainToInt NeSyDom = 13
64-
domainToInt Feedback = 14
70+
domainToInt Agent = 14
71+
domainToInt Lsp = 15
72+
domainToInt Dap = 16
73+
domainToInt Bsp = 17
6574

6675
||| C-ABI decoding: integer to domain (with safe fallback).
6776
public export
@@ -79,7 +88,10 @@ intToDomain 10 = Just SSG
7988
intToDomain 11 = Just Proof
8089
intToDomain 12 = Just FleetDom
8190
intToDomain 13 = Just NeSyDom
82-
intToDomain 14 = Just Feedback
91+
intToDomain 14 = Just Agent
92+
intToDomain 15 = Just Lsp
93+
intToDomain 16 = Just Dap
94+
intToDomain 17 = Just Bsp
8395
intToDomain _ = Nothing
8496

8597
||| Equality for capability domains.
@@ -97,5 +109,10 @@ Eq CapabilityDomain where
97109
SSG == SSG = True
98110
Proof == Proof = True
99111
FleetDom == FleetDom = True
100-
NeSyDom == NeSyDom = True
112+
NeSyDom == NeSyDom = True
113+
Agent == Agent = True
114+
Lsp == Lsp = True
115+
Dap == Dap = True
116+
Bsp == Bsp = True
101117
_ == _ = False
118+

0 commit comments

Comments
 (0)