@asobacloud/nehanda 0.0.0-stage → 0.2.0

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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSE.md +57 -0
  3. package/README.md +404 -2
  4. package/bin/agent.mjs +1260 -0
  5. package/bin/nehanda-ui.mjs +824 -0
  6. package/lib/anthropicHeaders.mjs +8 -0
  7. package/lib/app.mjs +313 -0
  8. package/lib/auth.mjs +255 -0
  9. package/lib/bashguard.mjs +159 -0
  10. package/lib/compact.mjs +306 -0
  11. package/lib/energy-middleware.mjs +318 -0
  12. package/lib/hookShapeOrder.mjs +30 -0
  13. package/lib/hookplane.mjs +228 -0
  14. package/lib/instructions.mjs +23 -0
  15. package/lib/jev_read.mjs +216 -0
  16. package/lib/jev_write.mjs +253 -0
  17. package/lib/laya.mjs +296 -0
  18. package/lib/laya_sidecar.mjs +198 -0
  19. package/lib/mcp-config.mjs +189 -0
  20. package/lib/mcp.mjs +169 -0
  21. package/lib/modelConfig.mjs +152 -0
  22. package/lib/modelDiscovery.mjs +205 -0
  23. package/lib/openaiCompat.mjs +147 -0
  24. package/lib/orchestrate.mjs +1163 -0
  25. package/lib/paths.mjs +20 -0
  26. package/lib/permissions.mjs +44 -0
  27. package/lib/scripts/__pycache__/laya_worker.cpython-314.pyc +0 -0
  28. package/lib/scripts/audit-code-integrity.py +437 -0
  29. package/lib/scripts/ensure-laya-env.sh +55 -0
  30. package/lib/scripts/js-safety-checker.cjs +308 -0
  31. package/lib/scripts/laya_worker.py +171 -0
  32. package/lib/scripts/odse-transform.py +97 -0
  33. package/lib/scripts/python-safety-checker.py +197 -0
  34. package/lib/scripts/shell-safety-checker.sh +306 -0
  35. package/lib/settings.mjs +147 -0
  36. package/lib/store.mjs +278 -0
  37. package/lib/team.mjs +69 -0
  38. package/lib/testgen.mjs +146 -0
  39. package/lib/tools/AuditCodeIntegrity.json +30 -0
  40. package/lib/tools/JsSafetyChecker.json +29 -0
  41. package/lib/tools/PythonSafetyChecker.json +29 -0
  42. package/lib/tools/ShellSafetyChecker.json +29 -0
  43. package/lib/tools.mjs +907 -0
  44. package/lib/transcript.mjs +223 -0
  45. package/lib/ui.mjs +286 -0
  46. package/lib/workflow.mjs +91 -0
  47. package/lib/worktree.mjs +56 -0
  48. package/package.json +50 -4
  49. package/schema.sql +181 -0
  50. package/scripts/postinstall.mjs +62 -0
  51. package/scripts/sdlc-acceptance.sh +477 -0
  52. package/scripts/verify-sdlc-hook-order.mjs +26 -0
  53. package/templates/test_e2e.sh +32 -0
  54. package/templates/test_file.sh +14 -0
  55. package/templates/test_hook.sh +27 -0
  56. package/templates/test_http.sh +17 -0
  57. package/templates/test_phase.sh +23 -0
  58. package/templates/test_process.sh +14 -0
  59. package/templates/test_tool.sh +24 -0
  60. package/templates/validate_test.sh +55 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Asoba Corp
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/LICENSE.md ADDED
@@ -0,0 +1,57 @@
1
+ # License
2
+
3
+ **SPDX-Identifier:** `AGPL-3.0-only`
4
+
5
+ Copyright (C) 2026 Asoba Corporation
6
+
7
+ nehanda-cli is free software: you may redistribute it and/or modify it under the
8
+ terms of the [GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl-3.0.html)
9
+ or (at your option) any later version.
10
+
11
+ The full license text is maintained verbatim in the [LICENSE](LICENSE) file at the
12
+ repository root. A copy is also available from the Free Software Foundation at
13
+ <https://www.gnu.org/licenses/agpl-3.0.txt>.
14
+
15
+ ## What this covers
16
+
17
+ This license applies to **nehanda-cli** — the open-source client and local server
18
+ stack in this repository, including:
19
+
20
+ - `nehanda`, `nehanda-server`, and `nehanda-kb` binaries built from this tree
21
+ - Nehanda-specific code under `src/`
22
+ - Patches under `patches/` and the `upstream/` aimee subtree as distributed here
23
+ - Documentation, configuration examples, and install scripts in this repository
24
+
25
+ If you modify nehanda-cli and make it available to users over a network, AGPL-3.0
26
+ requires you to provide corresponding source to those users. See Section 13 of the
27
+ AGPL for the network-use provision.
28
+
29
+ ## AGPL boundary
30
+
31
+ nehanda-cli is designed so that proprietary services communicate over standard HTTP
32
+ using the OpenAI/Anthropic wire protocol. The following are **not** part of this
33
+ repository and are **not** licensed under AGPL-3.0:
34
+
35
+ - Nehanda Gateway (HTTPS proxy in front of the inference endpoint)
36
+ - Nehanda model weights and fine-tune data
37
+ - Hosted inference at `nehanda.asoba.co`
38
+ - ONA/Zorora auth services (`ona-user-auth`, `ona-platform-users`, device pairing)
39
+
40
+ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the three-tier design and where
41
+ the AGPL line sits.
42
+
43
+ ## Upstream — aimee
44
+
45
+ nehanda-cli is a fork of [aimee](https://github.com/RakuenSoftware/aimee), Copyright
46
+ (C) 2026 The aimee authors, also licensed under AGPL-3.0. Upstream source is
47
+ tracked as a git subtree under `upstream/`. Nehanda-specific changes live in `src/`
48
+ and `patches/`.
49
+
50
+ ## Third-party components
51
+
52
+ Third-party licenses inherited from aimee and vendored dependencies are listed in
53
+ [NOTICE](NOTICE), including cJSON (MIT) and build-time tree-sitter grammars (MIT).
54
+
55
+ ## Questions
56
+
57
+ For licensing questions about nehanda-cli, contact **support@asoba.co**.
package/README.md CHANGED
@@ -1,3 +1,405 @@
1
- # Temporary Holding Version
1
+ # Nehanda Command-Line Interface (`nehanda-cli`)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ An agentic terminal REPL and single-process engine built for governed AI deep research and software development. `nehanda-cli` connects directly to our flagship [Nehanda v3](https://huggingface.co/asoba/nehanda-v3-27b), as well as local or cloud-based Ollama models, LM Studio instances, or any OpenAI-compatible API.
4
+
5
+ Every conversation turn, tool call, phase transition, and permission check is stored in a local, queryable SQLite database you own, ensuring complete transcripts exist for auditing and debugging.
6
+
7
+ ![Nehanda CLI](docs/tifo.svg)
8
+
9
+ ---
10
+
11
+ ## Getting Started
12
+
13
+ ### Requirements
14
+
15
+ * **Node.js**: v22.0.0 or higher
16
+ * **Python**: 3.10 or higher (for the Laya System-1 control plane)
17
+ * **SQLite**: Local SQLite runtime support
18
+
19
+ ### 1. Installation
20
+
21
+ ```bash
22
+ git clone https://github.com/AsobaCloud/nehanda-cli.git
23
+ cd nehanda-cli
24
+ npm install
25
+ ```
26
+
27
+ On first launch, the CLI automatically provisions a dedicated Python venv and downloads the [Laya](https://huggingface.co/convaiinnovations/laya) checkpoint (~808 MB). This happens once. Subsequent starts are instant.
28
+
29
+ ### 2. Launching the REPL
30
+
31
+ Launch the interactive Ink TUI:
32
+
33
+ ```bash
34
+ npm start
35
+ # or directly run:
36
+ node bin/nehanda-ui.mjs
37
+ ```
38
+
39
+ ### 3. Provider Setup
40
+
41
+ #### Option A: Nehanda Cloud (Default)
42
+
43
+ The CLI defaults to the primary Nehanda endpoint (`https://nehanda-ml.asoba.co/v1`). If an API key is required:
44
+
45
+ ```
46
+ ❯ /key
47
+ New Nehanda API key: <your-key>
48
+ ```
49
+
50
+ #### Option B: Local LM Studio
51
+
52
+ Start LM Studio locally on port `1234` or `8000`, then start the CLI. Select or switch models via:
53
+
54
+ ```
55
+ ❯ /model
56
+ ```
57
+
58
+ #### Option C: Remote Ollama over LAN
59
+
60
+ To connect to an Ollama instance running on your network:
61
+
62
+ ```
63
+ ❯ /config base_url http://AsobaCorp-1.local:11434/v1
64
+ ❯ /model ollama/deepseek-coder-v2:latest
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Key Features
70
+
71
+ * **In-Process Engine:** Executes turns directly inside the process via `runUserTurn`, eliminating separate server daemons or background HTTP relays.
72
+
73
+ * **Jev-Mem Memory Architecture:** Every turn, a System-1 control plane ([Laya](https://huggingface.co/convaiinnovations/laya)) classifies observations into a multi-relational memory graph (semantic / temporal / causal / entity edges), then adaptively retrieves evidence before each model call. System-2 receives a compact canonical header + retrieved evidence + last 2 turns, not a raw transcript — cutting prefill 70–85% on long sessions. See [Jev-Mem Architecture](#jev-mem-architecture) below.
74
+
75
+ * **Dynamic Tool Rescue (`[TOOL_CALL]`):** Native support for endpoints that strip OpenAI tool schemas (such as `nehandaMlProxy`). The engine dynamically injects active tool schemas directly into system prompts as `[TOOL_CALL]` blocks, parsing and executing tools locally without server-side function-calling support. Uses `[TOOL_CALL]` delimiters instead of `<tool_call>` XML to prevent vLLM's `--tool-call-parser qwen3_xml` stop-token interception.
76
+
77
+ * **Deterministic SDLC Workflow:** Enforces a 6-phase state machine (`idle` → `plan` → `implement` → `test` → `verify` → `done`) to prevent unapproved code changes, hallucinated test passes, or unverified implementations.
78
+
79
+ * **Interactive TUI & Pipe Support:** Rich Ink-based TUI (`bin/nehanda-ui.mjs`) for interactive development sessions, with headless pipe-mode support (`bin/agent.mjs`) for acceptance testing and automation.
80
+
81
+ * **Multi-Provider Switching:** Seamlessly switch between Nehanda 27B, local LM Studio, Ollama instances over LAN, Anthropic Claude, or any OpenAI-compatible API using `/model`.
82
+
83
+ ---
84
+
85
+ ## Architecture
86
+
87
+ `nehanda-cli` combines an Ink TUI with a deterministic orchestration engine:
88
+
89
+ ![Architecture](docs/architecture.svg)
90
+
91
+ ---
92
+
93
+ ## Jev-Mem Architecture
94
+
95
+ `nehanda-cli` implements the memory architecture from **"System-One-Controlled Agentic Memory for Efficient AI Agents"** (Jiang, Li & Li, UT Dallas — [arXiv:2609.23986](https://arxiv.org/abs/2609.23986)). The core insight: the frequent, structured decisions of memory management — typing, relation judgment, retrieval routing, sufficiency assessment — don't need an autoregressive LLM. They need a fast, calibrated System-1 model.
96
+
97
+ The System-1 control plane is [**Laya**](https://huggingface.co/convaiinnovations/laya) — a 421M-parameter, non-autoregressive decision model (open weights, Apache 2.0) that answers typed questions in a single forward pass (~33 ms on GPU, ~200 ms on CPU). It never generates text, so there is nothing to parse and nothing to hallucinate.
98
+
99
+ ```
100
+ Observation (user / tool / assistant turn)
101
+ │
102
+ ▼
103
+ ┌── WRITE PATH (System 1 — Laya) ───────────────────────────────┐
104
+ │ type scores: episodic / semantic / procedural / preference │
105
+ │ → deterministic TopK candidates (FTS + entities + recency) │
106
+ │ → Laya relation judgments (semantic/causal/episode/entity) │
107
+ │ → insert edges iff P(relation) ≥ θ_rel │
108
+ │ → update laya_jev_state (task_status, file_target, escalate) │
109
+ └───────────────────────────────────────────────────────────────┘
110
+ │
111
+ ▼ SQLite memory plane
112
+ nodes + edges (semantic | temporal | causal | entity)
113
+ + FTS/lexical index
114
+ │
115
+ ▼
116
+ ┌── READ PATH (System 1 — Laya) ────────────────────────────────┐
117
+ │ route: which graph views matter for this query │
118
+ │ → RRF anchors (FTS + recency) │
119
+ │ → assess sufficiency / utility / contradiction │
120
+ │ → expand under budget → rescore → stop │
121
+ └───────────────────────────────────────────────────────────────┘
122
+ │
123
+ ▼
124
+ ┌── SYSTEM 2 PROMPT ────────────────────────────────────────────┐
125
+ │ [CANONICAL SYSTEM 1 STATE] (task_status, file_target, ...) │
126
+ │ [RETRIEVED EVIDENCE] (top-K memories, not raw transcript) │
127
+ │ last 2 turns + last failed tool result │
128
+ └───────────────────────────────────────────────────────────────┘
129
+ ```
130
+
131
+ ### Paper invariants preserved
132
+
133
+ - Observations are always persisted on ingest — nothing is dropped on write.
134
+ - Candidate discovery is deterministic (FTS + recency) before any Laya relation judgments.
135
+ - Temporal and entity edges are derived from structure where possible; Laya is invoked only when needed.
136
+ - Retrieval is a closed loop: route → retrieve → assess → expand → reassess → stop on sufficiency.
137
+ - System-2 only synthesizes; it does not route, score, or stop the retrieval loop.
138
+
139
+ ### Laya: the System-1 model
140
+
141
+ | | |
142
+ |---|---|
143
+ | Weights | [convaiinnovations/laya](https://huggingface.co/convaiinnovations/laya) — Apache 2.0, open weights |
144
+ | Size | 421M parameters (ModernBERT-large backbone + decision head) |
145
+ | Latency | ~33 ms / question on GPU; ~200 ms on CPU (MPS on Apple Silicon) |
146
+ | Training | RLCD — reinforcement learning against strictly proper scoring rules; honest probabilities are the only way to maximise reward |
147
+ | Question types | `noul` (probability), `choice` (categorical), `score` (ordinal) |
148
+ | Languages | English checkpoint (root); `laya-multilingual` covers 100+ languages |
149
+
150
+ On first startup, `lib/scripts/ensure-laya-env.sh` creates a dedicated venv at `~/.nehanda/venv` and downloads the checkpoint. The sidecar is then warmed before the first turn so all subsequent predictions hit the hot path. If provisioning fails, the CLI exits with a clear error — Laya is not an optional feature.
151
+
152
+ ### Memory plane (SQLite)
153
+
154
+ The memory plane extends the existing `memories` table and adds `memory_edges` and `laya_jev_state`. All data lives in the same local SQLite database as the rest of the session state (`~/.config/nehanda/ona-session.db`).
155
+
156
+ | Table | Purpose |
157
+ |---|---|
158
+ | `memories` | Canonical node store — one row per observation, with overlapping type scores (episodic / semantic / procedural / preference), entity tags, and provenance |
159
+ | `memories_fts` | FTS5 index over memory content for lexical anchor retrieval |
160
+ | `memory_edges` | Multi-relational edges — same node pair may have independent semantic, temporal, causal, and entity edges |
161
+ | `laya_jev_state` | Session control block: `task_status`, `file_target`, `escalation_risk`, `confidence_score` |
162
+
163
+ ---
164
+
165
+ ## Tool Calling Architecture
166
+
167
+ The Nehanda vLLM deployment runs with `--tool-call-parser qwen3_xml` and `--enable-auto-tool-choice` flags. The `nehandaMlProxy` Lambda function strips `tools` and `tool_choice` from requests before forwarding to vLLM to avoid a Qwen3 chat template bug where the presence of a `tools` array causes system message ordering errors.
168
+
169
+ To enable tool calling despite this constraint, the engine uses a rescue path:
170
+
171
+ 1. **System Prompt Injection:** `buildXmlToolInstructions()` injects tool schemas into the system prompt using `[TOOL_CALL]...[/TOOL_CALL]` delimiters.
172
+ 2. **Late Directive Injection:** A `[SYSTEM DIRECTIVE]` is appended to the final user message to defeat token recency bias on reasoning models.
173
+ 3. **Model Generation:** The model emits tool calls in the `[TOOL_CALL]` format within its response text.
174
+ 4. **Local Parsing & Execution:** `parseXmlToolCalls()` extracts and executes these calls locally via `executeBuiltinTool()`, continuing the execution loop even when backends return `finish_reason: "stop"`.
175
+
176
+ ### Why `[TOOL_CALL]` Delimiters?
177
+
178
+ The vLLM `--tool-call-parser qwen3_xml` flag registers `<tool_call>` XML tags as stop/intercept tokens. When the model emits them in plain text, vLLM terminates generation mid-sentence and hands off to its native parser — which returns nothing because the plain-text path never populates `message.tool_calls`. This results in truncated responses containing only thinking traces.
179
+
180
+ Switching to `[TOOL_CALL]...[/TOOL_CALL]` delimiters bypasses vLLM's stop-token interception entirely, allowing the model to complete generation and return valid, parseable tool calls.
181
+
182
+ ---
183
+
184
+ ## Declarative Tool System
185
+
186
+ `nehanda-cli` supports a **zero-code tool configuration** pattern. Tools are registered by dropping a JSON config into `lib/tools/` and a corresponding script into `lib/scripts/`. No JavaScript changes are required.
187
+
188
+ ### How It Works
189
+
190
+ 1. On startup, `lib/tools.mjs` scans `lib/tools/*.json` and dynamically registers each tool.
191
+ 2. Tool schemas are injected into the API `tools` array so the model can call them.
192
+ 3. Phase visibility (`explore_only`, `planning_blocked`) and mandatory enforcement (`mandatory_in`) are driven by config metadata.
193
+ 4. Prompt injection (`prompt.mandatory_instruction`, `prompt.available_hint`) is read from the config and injected into the appropriate SDLC phase system prompts automatically.
194
+
195
+ ### Shipped Tools
196
+
197
+ | Tool | Script | What It Checks |
198
+ |---|---|---|
199
+ | `AuditCodeIntegrity` | `lib/scripts/audit-code-integrity.py` | Lifecycle teardown parity, mock-theater tests, naming invariants, swallowed exceptions |
200
+ | `ShellSafetyChecker` | `lib/scripts/shell-safety-checker.sh` | Missing `set -euo pipefail`, background job silent failure risk, hardcoded credentials |
201
+ | `JsSafetyChecker` | `lib/scripts/js-safety-checker.cjs` | Duplicate functions, duplicate HTML element IDs, script block syntax errors |
202
+ | `PythonSafetyChecker` | `lib/scripts/python-safety-checker.py` | Bandit security issues, ruff lint, mutable default args, `eval`/`exec`/`pickle` usage |
203
+
204
+ All four are **mandatory in the test phase** and **available on-demand** in explore and idle phases.
205
+
206
+ ### Adding a New Tool
207
+
208
+ Create a JSON config in `lib/tools/`:
209
+
210
+ ```json
211
+ {
212
+ "name": "MyNewTool",
213
+ "description": "What the tool does.",
214
+ "input_schema": {
215
+ "type": "object",
216
+ "properties": {
217
+ "target": { "type": "string", "description": "Target path" }
218
+ }
219
+ },
220
+ "phases": {
221
+ "explore_only": true,
222
+ "planning_blocked": false,
223
+ "mandatory_in": ["test"]
224
+ },
225
+ "prompt": {
226
+ "mandatory_instruction": "Run MyNewTool on the workspace to check for X.",
227
+ "available_hint": "Checks for X, Y, and Z"
228
+ },
229
+ "execution": {
230
+ "runtime": "python3",
231
+ "script": "lib/scripts/my-new-tool.py",
232
+ "args": ["{{target}}"],
233
+ "default_timeout": 120000,
234
+ "max_timeout": 600000
235
+ }
236
+ }
237
+ ```
238
+
239
+ Place the script at `lib/scripts/my-new-tool.py`. It will receive arguments interpolated from `args` and run with `cwd` set to the target workspace. **No JS code changes needed.**
240
+
241
+ ---
242
+
243
+ ## REPL Commands
244
+
245
+ | Command | Description |
246
+ |---|---|
247
+ | `/help` | Display available commands |
248
+ | `/model [name]` | Discover and switch active provider or model endpoint |
249
+ | `/key` | Save Nehanda API key |
250
+ | `/config` | View or set settings (e.g., `/config base_url <url>`) |
251
+ | `/mcp` | Manage MCP server connections (see below) |
252
+ | `/clear` | Clear conversation history and reset transcript state |
253
+ | `/retry` | Resend the last failed request |
254
+ | `/exit` | Exit the REPL |
255
+
256
+ ### `/mcp` Sub-commands
257
+
258
+ | Sub-command | Description |
259
+ |---|---|
260
+ | `/mcp status` | List all configured MCP servers and their commands |
261
+ | `/mcp list` | Connect to each server and enumerate available tools |
262
+ | `/mcp reload [server]` | Re-read `mcp.json` and bust the tool cache (optionally for one server) |
263
+ | `/mcp add <name> <command> [args…]` | Register a new server and save it to `~/.config/nehanda/mcp.json` |
264
+ | `/mcp env` | Show environment variables for all configured servers |
265
+ | `/mcp env <server>` | Show environment variables for a specific server |
266
+ | `/mcp env <server> <KEY> <value>` | Set an environment variable (e.g. an API key) |
267
+ | `/mcp env <server> <KEY>` | Clear an environment variable |
268
+
269
+ ---
270
+
271
+ ## MCP Client Configuration
272
+
273
+ `nehanda-cli` can consume tools from any external MCP server. Servers are configured in a standard `mcp.json` file using the same schema as Claude Desktop and other MCP clients.
274
+
275
+ **Config file locations** (both are read and merged at startup; project-local takes priority):
276
+
277
+ - `./mcp.json` — project-local, committed with the repo
278
+ - `~/.config/nehanda/mcp.json` — user global
279
+
280
+ **Example `mcp.json`:**
281
+
282
+ ```json
283
+ {
284
+ "mcpServers": {
285
+ "filesystem": {
286
+ "command": "npx",
287
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
288
+ },
289
+ "powermcp": {
290
+ "command": "npx",
291
+ "args": ["-y", "harvard-powermcp"],
292
+ "env": { "API_KEY": "your-key" }
293
+ }
294
+ }
295
+ }
296
+ ```
297
+
298
+ At startup, `nehanda-cli` loads `mcp.json`, spawns the configured servers, and calls `tools/list` on each. Discovered tools are injected into the model's tool list under the namespace `mcp__<server>__<tool>` and are available for the model to call during any conversation turn — no additional configuration required.
299
+
300
+ Use `/mcp list` to verify what tools are visible, and `/mcp reload` to pick up changes without restarting.
301
+
302
+ ### Setting API Keys for MCP Servers
303
+
304
+ Many MCP servers require an API key or other secrets. Rather than editing `mcp.json` by hand, use the `/mcp env` command directly from the REPL:
305
+
306
+ ```
307
+ ❯ /mcp env # show env vars for all servers
308
+ ❯ /mcp env asoba # show env vars for 'asoba' server
309
+ ❯ /mcp env asoba ASOBA_API_KEY sk-abc123... # set the key
310
+ ✓ Set ASOBA_API_KEY = ******** on asoba
311
+ Config file: ~/.config/nehanda/mcp.json
312
+ ```
313
+
314
+ This writes the value to the `mcp.json` file where the server is defined (project-local `./mcp.json` takes priority over global `~/.config/nehanda/mcp.json`), then automatically reloads the server so the change takes effect immediately.
315
+
316
+ To clear a key:
317
+
318
+ ```
319
+ ❯ /mcp env asoba ASOBA_API_KEY
320
+ ✓ Cleared ASOBA_API_KEY on asoba
321
+ ```
322
+
323
+ **Tip:** Keys are masked in `/mcp env` output. Only the first 6 and last 4 characters are shown.
324
+
325
+ ### General Config from the REPL
326
+
327
+ Use `/config set <dot.path> <value>` to set any configuration value without editing files:
328
+
329
+ ```
330
+ ❯ /config set model_config.base_url https://api.anthropic.com
331
+ ❯ /config set model_config.num_ctx 8192
332
+ ```
333
+
334
+ Numeric values are auto-converted. Changes persist in the local settings database.
335
+
336
+ ---
337
+
338
+ ## SDLC Workflow
339
+
340
+ The engine enforces state transitions across six distinct phases:
341
+
342
+ 1. **`idle`**: Discovery and triage. Mutating file tools are physically masked out. Safety and analysis tools are available on-demand.
343
+
344
+ 2. **`plan`**: Model formulates success criteria and implementation steps (`EnterPlanMode`). No tools available.
345
+
346
+ 3. **`implement`**: Code changes applied using file editing and shell execution (`ExitPlanMode`).
347
+
348
+ 4. **`test`**: Automated test generation and execution (`SubmitImplementation`). **After tests pass, all tools marked `mandatory_in: ["test"]` must be run.** The system prompt enforces this — the model cannot declare success until all mandatory safety checkers pass.
349
+
350
+ 5. **`verify`**: Inspection of test outputs and coverage verification (`SubmitTest`).
351
+
352
+ 6. **`done`**: Final sign-off and git commit creation.
353
+
354
+ ---
355
+
356
+ ## Database Schema
357
+
358
+ Session state is persisted locally at `~/.config/nehanda/ona-session.db`. Key tables include:
359
+
360
+ * `conversations`: Active workflow phases and project roots.
361
+ * `transcript_entries`: Sequence of user messages, assistant turns, tool calls, and results.
362
+ * `plans`: Content, hashes, and approval status for technical plans.
363
+ * `events`: SDLC milestones and test execution output.
364
+ * `memories`: Jev-Mem canonical node store with overlapping type scores and entity provenance.
365
+ * `memory_edges`: Multi-relational graph edges (semantic / temporal / causal / entity).
366
+ * `laya_jev_state`: System-1 session control block (task_status, file_target, escalation_risk).
367
+
368
+ ---
369
+
370
+ ## Testing & Verification
371
+
372
+ Run the acceptance suite:
373
+
374
+ ```bash
375
+ npm run acceptance
376
+ ```
377
+
378
+ Verify SDLC hook ordering:
379
+
380
+ ```bash
381
+ npm run verify
382
+ ```
383
+
384
+ Run the Jev-Mem behavioral suite directly:
385
+
386
+ ```bash
387
+ node tests/unit/jev_write_behavioral.mjs
388
+ node tests/unit/jev_read_behavioral.mjs
389
+ node tests/unit/compact_jev_behavioral.mjs
390
+ node tests/unit/orchestrate_jev_hotpath_behavioral.mjs
391
+ ```
392
+
393
+ ---
394
+
395
+ ## References
396
+
397
+ Jiang, Z., Li, Y., & Li, J. (2026). *System-One-Controlled Agentic Memory for Efficient AI Agents*. arXiv:2609.23986. https://arxiv.org/abs/2609.23986
398
+
399
+ Convai Innovations. *Laya: Multilingual, non-autoregressive System-1 decision model.* Hugging Face. https://huggingface.co/convaiinnovations/laya
400
+
401
+ ---
402
+
403
+ ## License
404
+
405
+ See [LICENSE](LICENSE) for details.