@moreih29/nexus-core 0.1.2 → 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 (43) hide show
  1. package/README.md +3 -3
  2. package/agents/architect/body.md +7 -6
  3. package/agents/designer/body.md +3 -3
  4. package/agents/engineer/body.md +8 -8
  5. package/agents/postdoc/body.md +4 -4
  6. package/agents/researcher/body.md +4 -4
  7. package/agents/reviewer/body.md +2 -2
  8. package/agents/strategist/body.md +4 -4
  9. package/agents/tester/body.md +2 -2
  10. package/agents/writer/body.md +1 -1
  11. package/conformance/README.md +125 -0
  12. package/conformance/scenarios/full-plan-cycle.json +132 -0
  13. package/conformance/scenarios/task-deps-ordering.json +83 -0
  14. package/conformance/schema/fixture.schema.json +224 -0
  15. package/conformance/state-schemas/agent-tracker.schema.json +58 -0
  16. package/conformance/state-schemas/history.schema.json +124 -0
  17. package/conformance/state-schemas/plan.schema.json +72 -0
  18. package/conformance/state-schemas/runtime.schema.json +25 -0
  19. package/conformance/state-schemas/tasks.schema.json +93 -0
  20. package/conformance/tools/plan-decide.json +70 -0
  21. package/conformance/tools/plan-start.json +67 -0
  22. package/conformance/tools/task-add.json +73 -0
  23. package/conformance/tools/task-close.json +98 -0
  24. package/docs/behavioral-contracts.md +145 -0
  25. package/docs/consumer-implementation-guide.md +844 -0
  26. package/docs/nexus-layout.md +234 -0
  27. package/docs/nexus-state-overview.md +185 -0
  28. package/docs/nexus-tools-contract.md +427 -0
  29. package/manifest.json +126 -113
  30. package/package.json +5 -1
  31. package/schema/common.schema.json +0 -4
  32. package/schema/skill.schema.json +16 -1
  33. package/schema/vocabulary.schema.json +14 -9
  34. package/skills/nx-init/body.md +6 -9
  35. package/skills/nx-init/meta.yml +1 -0
  36. package/skills/nx-plan/body.md +14 -11
  37. package/skills/nx-plan/meta.yml +3 -0
  38. package/skills/nx-run/body.md +4 -4
  39. package/skills/nx-run/meta.yml +3 -0
  40. package/skills/nx-setup/body.md +9 -9
  41. package/skills/nx-setup/meta.yml +1 -0
  42. package/skills/nx-sync/meta.yml +1 -0
  43. package/vocabulary/capabilities.yml +58 -25
@@ -0,0 +1,427 @@
1
+ # Nexus MCP Tool Contracts
2
+
3
+ This document is the normative specification for the eleven Nexus MCP tools. Implementations in all consumer harnesses (claude-nexus, opencode-nexus, nexus-code) must conform to the parameter names, types, return shapes, side effects, and error conditions defined here. Harness-specific registration names (prefixes such as `nx_` or `mcp__plugin_*`) are implementation details and are not part of this specification.
4
+
5
+ ---
6
+
7
+ ## plan_start
8
+
9
+ Creates a new planning session. If a plan session is already active (i.e., `plan.json` exists), it is automatically archived to `history.json` before the new session is written.
10
+
11
+ ### Parameters
12
+
13
+ | Name | Type | Required | Description |
14
+ |------|------|----------|-------------|
15
+ | `topic` | `string` | yes | Theme or subject of the planning session |
16
+ | `issues` | `string[]` | yes | Ordered list of agenda items to resolve during the session |
17
+ | `research_summary` | `string` | yes | Evidence that prerequisite research has been completed; serves as a gate to enforce research before planning |
18
+
19
+ ### Return Value
20
+
21
+ | Field | Type | Description |
22
+ |-------|------|-------------|
23
+ | `created` | `boolean` | Always `true` on success |
24
+ | `plan_id` | `number` | Monotonically increasing identifier assigned to the new plan; derived by incrementing the highest `id` found across all archived cycles in `history.json` |
25
+ | `topic` | `string` | Echo of the `topic` parameter |
26
+ | `issueCount` | `number` | Number of issues registered in the new session |
27
+ | `previousArchived` | `boolean` | `true` if a pre-existing `plan.json` was archived before creating the new session |
28
+
29
+ ### Side Effects
30
+
31
+ - Creates `.nexus/state/plan.json` with `id`, `topic`, `issues` (each with `id`, `title`, `status: "pending"`), `research_summary`, and `created_at`.
32
+ - If a prior `plan.json` existed, appends a cycle record to `.nexus/history.json` (creating the file if absent), then deletes the prior `plan.json`.
33
+
34
+ ### Error Conditions
35
+
36
+ - No explicit error return; the tool always succeeds if called with valid parameters. Callers must ensure `research_summary` is a non-empty string — the parameter is required by schema, but an empty string is not rejected at the tool level.
37
+
38
+ ---
39
+
40
+ ## plan_status
41
+
42
+ Returns the current state of the active planning session.
43
+
44
+ ### Parameters
45
+
46
+ None.
47
+
48
+ ### Return Value
49
+
50
+ When no session is active:
51
+
52
+ | Field | Type | Description |
53
+ |-------|------|-------------|
54
+ | `active` | `boolean` | Always `false` |
55
+
56
+ When a session is active:
57
+
58
+ | Field | Type | Description |
59
+ |-------|------|-------------|
60
+ | `active` | `boolean` | Always `true` |
61
+ | `plan_id` | `number` | Identifier of the active plan |
62
+ | `topic` | `string` | Planning session theme |
63
+ | `issues` | `PlanIssue[]` | Full list of issues with their current state (see schema below) |
64
+ | `research_summary` | `string \| undefined` | Research evidence recorded at session creation |
65
+ | `summary.total` | `number` | Total number of issues |
66
+ | `summary.pending` | `number` | Issues not yet decided |
67
+ | `summary.decided` | `number` | Issues with a recorded decision |
68
+
69
+ **PlanIssue schema:**
70
+
71
+ | Field | Type | Description |
72
+ |-------|------|-------------|
73
+ | `id` | `number` | Issue identifier, unique within the plan |
74
+ | `title` | `string` | Issue description |
75
+ | `status` | `"pending" \| "decided"` | Current resolution state |
76
+ | `decision` | `string \| undefined` | Decision summary, present only when `status` is `"decided"` |
77
+ | `how_agents` | `string[] \| undefined` | Names of HOW agents that participated in analysis |
78
+ | `how_summary` | `Record<string, string> \| undefined` | Key positions per agent |
79
+ | `how_agent_ids` | `Record<string, string> \| undefined` | Agent name to agent-instance ID mapping, for session resume |
80
+
81
+ ### Side Effects
82
+
83
+ None. Read-only.
84
+
85
+ ### Error Conditions
86
+
87
+ None. Returns `{ active: false }` when `plan.json` does not exist.
88
+
89
+ ---
90
+
91
+ ## plan_update
92
+
93
+ Mutates the issue list of the active planning session. Supports four discrete actions.
94
+
95
+ ### Parameters
96
+
97
+ | Name | Type | Required | Description |
98
+ |------|------|----------|-------------|
99
+ | `action` | `"add" \| "remove" \| "edit" \| "reopen"` | yes | Operation to perform |
100
+ | `issue_id` | `number` | conditional | Target issue identifier; required for `remove`, `edit`, and `reopen` |
101
+ | `title` | `string` | conditional | Issue title text; required for `add` and `edit` |
102
+
103
+ ### Return Value
104
+
105
+ All responses include an `issue` field containing the affected `PlanIssue` object. The discriminating field varies by action:
106
+
107
+ | Action | Discriminating Field | Value |
108
+ |--------|----------------------|-------|
109
+ | `add` | `added` | `true` |
110
+ | `remove` | `removed` | `true` |
111
+ | `edit` | `edited` | `true` |
112
+ | `reopen` | `reopened` | `true` |
113
+
114
+ On error, returns `{ error: string }`.
115
+
116
+ ### Side Effects
117
+
118
+ - Writes the updated issue list back to `.nexus/state/plan.json`.
119
+ - For `reopen`: clears `status` to `"pending"` and removes the `decision` field from the target issue.
120
+
121
+ ### Error Conditions
122
+
123
+ | Condition | Error message |
124
+ |-----------|---------------|
125
+ | No active plan session | `"No active plan session"` |
126
+ | `remove` or `reopen` called without `issue_id` | `"issue_id is required for <action>"` |
127
+ | `edit` called without `issue_id` or `title` | `"issue_id and title are required for edit"` |
128
+ | `add` called without `title` | `"title is required for add"` |
129
+ | Referenced `issue_id` not found | `"Issue <id> not found"` |
130
+ | Unrecognized `action` value | `"Unknown action"` |
131
+
132
+ ---
133
+
134
+ ## plan_decide
135
+
136
+ Records a decision for a specific issue and marks it as `"decided"`. Triggered by the `[d]` tag convention.
137
+
138
+ ### Parameters
139
+
140
+ | Name | Type | Required | Description |
141
+ |------|------|----------|-------------|
142
+ | `issue_id` | `number` | yes | Identifier of the issue being decided |
143
+ | `summary` | `string` | yes | Decision summary to record against the issue |
144
+ | `how_agents` | `string[]` | no | Names of HOW agents that contributed analysis |
145
+ | `how_summary` | `Record<string, string>` | no | Per-agent key position summaries |
146
+ | `how_agent_ids` | `Record<string, string>` | no | Agent name to agent-instance ID mapping for future resume |
147
+
148
+ ### Return Value
149
+
150
+ | Field | Type | Description |
151
+ |-------|------|-------------|
152
+ | `decided` | `boolean` | Always `true` on success |
153
+ | `issue` | `string` | Title of the decided issue |
154
+ | `allComplete` | `boolean` | `true` if every issue in the plan now has `status: "decided"` |
155
+ | `message` | `string \| undefined` | Guidance for the next step, present only when `allComplete` is `true` |
156
+ | `remaining` | `Array<{id, title, status}>` \| undefined | List of undecided issues, present only when `allComplete` is `false` |
157
+
158
+ ### Side Effects
159
+
160
+ - Updates the target issue in `.nexus/state/plan.json`: sets `status` to `"decided"`, writes `decision`, and conditionally writes `how_agents`, `how_summary`, `how_agent_ids`.
161
+
162
+ ### Error Conditions
163
+
164
+ | Condition | Error message |
165
+ |-----------|---------------|
166
+ | No active plan session | `"No active plan session"` |
167
+ | Referenced `issue_id` not found | `"Issue <id> not found"` |
168
+
169
+ ---
170
+
171
+ ## task_list
172
+
173
+ Returns the full task list with a computed progress summary.
174
+
175
+ ### Parameters
176
+
177
+ None.
178
+
179
+ ### Return Value
180
+
181
+ When `tasks.json` does not exist:
182
+
183
+ | Field | Type | Description |
184
+ |-------|------|-------------|
185
+ | `exists` | `boolean` | Always `false` |
186
+
187
+ When `tasks.json` exists:
188
+
189
+ | Field | Type | Description |
190
+ |-------|------|-------------|
191
+ | `goal` | `string` | Top-level goal for this task cycle |
192
+ | `tasks` | `Task[]` | Full task list (see Task schema below) |
193
+ | `summary.total` | `number` | Total task count |
194
+ | `summary.completed` | `number` | Tasks with `status: "completed"` |
195
+ | `summary.pending` | `number` | Tasks with `status: "pending"` |
196
+ | `summary.blocked` | `number` | Tasks with `status: "in_progress"` |
197
+ | `summary.ready` | `number[]` | IDs of pending tasks whose dependencies are all completed |
198
+
199
+ **Task schema:**
200
+
201
+ | Field | Type | Description |
202
+ |-------|------|-------------|
203
+ | `id` | `number` | Task identifier, unique within the cycle |
204
+ | `title` | `string` | Task title |
205
+ | `context` | `string` | Background or description |
206
+ | `approach` | `string \| undefined` | Implementation approach |
207
+ | `acceptance` | `string \| undefined` | Definition of done |
208
+ | `risk` | `string \| undefined` | Known risks or caveats |
209
+ | `status` | `"pending" \| "in_progress" \| "completed"` | Current state |
210
+ | `deps` | `number[]` | IDs of tasks that must be completed before this one |
211
+ | `plan_issue` | `number \| undefined` | Source issue ID in the associated plan session |
212
+ | `owner` | `string \| undefined` | Assigned agent name |
213
+ | `owner_agent_id` | `string \| undefined` | Agent instance ID for session resume |
214
+ | `owner_reuse_policy` | `"fresh" \| "resume_if_same_artifact" \| "resume" \| undefined` | Agent spawn policy |
215
+ | `created_at` | `string \| undefined` | ISO 8601 creation timestamp |
216
+
217
+ ### Side Effects
218
+
219
+ None. Read-only.
220
+
221
+ ### Error Conditions
222
+
223
+ None. Returns `{ exists: false }` when `tasks.json` does not exist.
224
+
225
+ ---
226
+
227
+ ## task_add
228
+
229
+ Adds a new task to the active task list. Creates `tasks.json` if it does not exist.
230
+
231
+ ### Parameters
232
+
233
+ | Name | Type | Required | Description |
234
+ |------|------|----------|-------------|
235
+ | `title` | `string` | yes | Task title |
236
+ | `context` | `string` | yes | Background or description of the task |
237
+ | `deps` | `number[]` | no | IDs of prerequisite tasks; defaults to `[]` |
238
+ | `approach` | `string` | no | Proposed implementation approach |
239
+ | `acceptance` | `string` | no | Acceptance criteria defining done |
240
+ | `risk` | `string` | no | Known risks or caveats |
241
+ | `plan_issue` | `number` | no | Plan issue ID this task originates from |
242
+ | `goal` | `string` | no | Sets or replaces the top-level goal of the task list |
243
+ | `decisions` | `string[]` | no | Decision strings to append to the task list's `decisions` array |
244
+ | `owner` | `string` | no | Assignee agent name |
245
+ | `owner_agent_id` | `string` | no | Agent instance ID for resume; if absent, a fresh instance is spawned |
246
+ | `owner_reuse_policy` | `"fresh" \| "resume_if_same_artifact" \| "resume"` | no | Controls agent reuse: `fresh` forces a new spawn; `resume_if_same_artifact` resumes only if the prior agent touched the same target file; `resume` always resumes |
247
+
248
+ ### Return Value
249
+
250
+ | Field | Type | Description |
251
+ |-------|------|-------------|
252
+ | `task` | `Task` | The newly created task object |
253
+
254
+ ### Side Effects
255
+
256
+ - Creates `.nexus/state/tasks.json` if absent (initializing `goal: ""`, `decisions: []`, `tasks: []`).
257
+ - Appends the new task with an auto-incremented `id` (max existing `id` + 1).
258
+ - If `goal` is provided, overwrites the file-level `goal` field.
259
+ - If `decisions` is provided, appends to the file-level `decisions` array.
260
+
261
+ ### Error Conditions
262
+
263
+ None. The tool always succeeds when called with the required parameters.
264
+
265
+ ---
266
+
267
+ ## task_update
268
+
269
+ Updates the status of an existing task.
270
+
271
+ ### Parameters
272
+
273
+ | Name | Type | Required | Description |
274
+ |------|------|----------|-------------|
275
+ | `id` | `number` | yes | Identifier of the task to update |
276
+ | `status` | `"pending" \| "in_progress" \| "completed"` | yes | New status value |
277
+
278
+ ### Return Value
279
+
280
+ | Field | Type | Description |
281
+ |-------|------|-------------|
282
+ | `task` | `Task` | The updated task object |
283
+
284
+ ### Side Effects
285
+
286
+ - Writes the updated status back to `.nexus/state/tasks.json`.
287
+
288
+ ### Error Conditions
289
+
290
+ | Condition | Error message |
291
+ |-----------|---------------|
292
+ | `tasks.json` does not exist | `"tasks.json not found"` |
293
+ | Referenced `id` not found | `"Task id <id> not found"` |
294
+
295
+ ---
296
+
297
+ ## task_close
298
+
299
+ Closes the current work cycle by archiving the active plan and task list to `history.json`, then deleting all session-scoped state files.
300
+
301
+ ### Parameters
302
+
303
+ None.
304
+
305
+ ### Return Value
306
+
307
+ | Field | Type | Description |
308
+ |-------|------|-------------|
309
+ | `closed` | `boolean` | Always `true` |
310
+ | `cycle` | `string` | ISO 8601 timestamp of the closed cycle |
311
+ | `branch` | `string` | Git branch name at time of closure |
312
+ | `archived.plan` | `boolean` | `true` if a `plan.json` was present and archived |
313
+ | `archived.decisions` | `number` | Count of decided issues archived from the plan |
314
+ | `archived.tasks` | `number` | Count of tasks archived |
315
+ | `deleted` | `string[]` | Filenames of deleted session-state files |
316
+ | `total_cycles` | `number` | Total number of cycles in `history.json` after closure |
317
+ | `memoryHint.taskCount` | `number` | Number of tasks in the closed cycle |
318
+ | `memoryHint.decisionCount` | `number` | Number of decided issues in the closed cycle |
319
+ | `memoryHint.hadLoopDetection` | `boolean` | `true` if the edit tracker recorded three or more edits to any single file during the cycle |
320
+ | `memoryHint.cycleTopics` | `string[]` | Non-empty strings from `plan.topic` and `tasks.goal` |
321
+
322
+ ### Side Effects
323
+
324
+ - Appends a cycle record to `.nexus/history.json` (creating the file if absent). The record contains `completed_at`, `branch`, `plan` (full `PlanFile` or `null`), and `tasks` (full `Task[]`).
325
+ - Deletes the following session-scoped files if they exist: `plan.json`, `tasks.json`, `edit-tracker.json`, `reopen-tracker.json` (all within `.nexus/state/`).
326
+
327
+ ### Error Conditions
328
+
329
+ None. The tool succeeds even when no plan or tasks are active; it archives whatever state exists.
330
+
331
+ ---
332
+
333
+ ## history_search
334
+
335
+ Searches past plan/task cycles recorded in `history.json`.
336
+
337
+ ### Parameters
338
+
339
+ | Name | Type | Required | Description |
340
+ |------|------|----------|-------------|
341
+ | `query` | `string` | no | Search term matched case-insensitively against the full JSON of each cycle (topic, decisions, research_summary, task titles, etc.) |
342
+ | `last_n` | `number` | no | Return only the last N matching cycles; defaults to `10` |
343
+
344
+ ### Return Value
345
+
346
+ | Field | Type | Description |
347
+ |-------|------|-------------|
348
+ | `total` | `number` | Total number of matching cycles before limiting |
349
+ | `showing` | `number` | Number of cycles returned |
350
+ | `cycles` | `CycleSummary[]` | Summarized cycle records (see below) |
351
+
352
+ **CycleSummary schema:**
353
+
354
+ | Field | Type | Description |
355
+ |-------|------|-------------|
356
+ | `completed_at` | `string` | ISO 8601 timestamp of cycle closure |
357
+ | `branch` | `string` | Git branch at time of closure |
358
+ | `topic` | `string \| undefined` | Plan topic, if a plan was archived |
359
+ | `decisions` | `Array<{title, decision}>` \| undefined | Decided issues from the plan |
360
+ | `task_count` | `number \| undefined` | Number of tasks in the cycle |
361
+
362
+ ### Side Effects
363
+
364
+ None. Read-only.
365
+
366
+ ### Error Conditions
367
+
368
+ None. Returns `{ cycles: [], total: 0 }` when `history.json` does not exist.
369
+
370
+ ---
371
+
372
+ ## context
373
+
374
+ Returns a snapshot of the current session context: active task summary, decisions, and current branch.
375
+
376
+ ### Parameters
377
+
378
+ None.
379
+
380
+ ### Return Value
381
+
382
+ | Field | Type | Description |
383
+ |-------|------|-------------|
384
+ | `branch` | `string` | Current git branch |
385
+ | `activeMode` | `"team" \| null` | `"team"` if `tasks.json` is present; `null` otherwise |
386
+ | `goal` | `string \| undefined` | Top-level goal from `tasks.json`; present only when `activeMode` is `"team"` |
387
+ | `tasksSummary.total` | `number \| undefined` | Total task count; present only when `activeMode` is `"team"` |
388
+ | `tasksSummary.completed` | `number \| undefined` | Completed task count; present only when `activeMode` is `"team"` |
389
+ | `tasksSummary.pending` | `number \| undefined` | Pending task count; present only when `activeMode` is `"team"` |
390
+ | `decisions` | `string[]` | Decisions from `decisions.json`; empty array if the file does not exist |
391
+
392
+ ### Side Effects
393
+
394
+ None. Read-only.
395
+
396
+ ### Error Conditions
397
+
398
+ None. Partial data (e.g., malformed JSON in `tasks.json` or `decisions.json`) is silently ignored; the tool returns whatever it can read.
399
+
400
+ ---
401
+
402
+ ## artifact_write
403
+
404
+ Writes a named artifact file (report, synthesis, analysis output) to the session artifact directory.
405
+
406
+ ### Parameters
407
+
408
+ | Name | Type | Required | Description |
409
+ |------|------|----------|-------------|
410
+ | `filename` | `string` | yes | Name of the file to write (e.g., `"findings.md"`, `"synthesis.md"`) |
411
+ | `content` | `string` | yes | Full content to write to the file |
412
+
413
+ ### Return Value
414
+
415
+ | Field | Type | Description |
416
+ |-------|------|-------------|
417
+ | `success` | `boolean` | Always `true` on success |
418
+ | `path` | `string` | Absolute path to the written file |
419
+
420
+ ### Side Effects
421
+
422
+ - Creates `.nexus/state/artifacts/` if it does not exist.
423
+ - Writes (or overwrites) `.nexus/state/artifacts/<filename>` with `content`.
424
+
425
+ ### Error Conditions
426
+
427
+ None declared at the tool level. Filesystem errors (permissions, disk full) will surface as unhandled exceptions.