@moreih29/nexus-core 0.3.0 → 0.5.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 (40) hide show
  1. package/conformance/README.md +208 -16
  2. package/conformance/examples/plan.extension.schema.example.json +25 -0
  3. package/conformance/lifecycle/README.md +17 -0
  4. package/conformance/lifecycle/agent-complete.json +44 -0
  5. package/conformance/lifecycle/agent-resume.json +43 -0
  6. package/conformance/lifecycle/agent-spawn.json +42 -0
  7. package/conformance/lifecycle/session-end.json +32 -0
  8. package/conformance/lifecycle/session-start.json +38 -0
  9. package/conformance/scenarios/full-plan-cycle.json +17 -2
  10. package/conformance/scenarios/task-deps-ordering.json +12 -0
  11. package/conformance/schema/fixture.schema.json +139 -9
  12. package/conformance/state-schemas/agent-tracker.schema.json +10 -5
  13. package/conformance/state-schemas/history.schema.json +11 -1
  14. package/conformance/state-schemas/plan.schema.json +5 -0
  15. package/conformance/state-schemas/runtime.schema.json +13 -4
  16. package/conformance/state-schemas/tasks.schema.json +5 -0
  17. package/conformance/tools/artifact-write.json +97 -0
  18. package/conformance/tools/context.json +172 -0
  19. package/conformance/tools/history-search.json +219 -0
  20. package/conformance/tools/plan-decide.json +72 -3
  21. package/conformance/tools/plan-start.json +14 -0
  22. package/conformance/tools/plan-status.json +127 -0
  23. package/conformance/tools/plan-update.json +341 -0
  24. package/conformance/tools/task-add.json +89 -6
  25. package/conformance/tools/task-close.json +67 -4
  26. package/conformance/tools/task-list.json +20 -0
  27. package/conformance/tools/task-update.json +28 -0
  28. package/docs/consumer-implementation-guide.md +1 -1
  29. package/docs/nexus-outputs-contract.md +287 -0
  30. package/docs/nexus-tools-contract.md +12 -2
  31. package/manifest.json +54 -54
  32. package/package.json +6 -1
  33. package/scripts/.gitkeep +0 -0
  34. package/scripts/conformance-coverage.ts +466 -0
  35. package/scripts/import-from-claude-nexus.ts +403 -0
  36. package/scripts/lib/frontmatter.ts +71 -0
  37. package/scripts/lib/lint.ts +216 -0
  38. package/scripts/lib/structure.ts +159 -0
  39. package/scripts/lib/validate.ts +668 -0
  40. package/scripts/validate.ts +90 -0
@@ -7,8 +7,9 @@ Declarative behavioral tests for Nexus MCP tools. Each fixture describes a tool
7
7
  A conformance fixture is a JSON document that specifies:
8
8
 
9
9
  1. **Precondition** — the state files that must exist (or must not exist) before the test runs.
10
- 2. **Action** (or **Steps**) — one or more tool invocations with concrete parameters.
10
+ 2. **Action** (or **Steps** or **Event**) — one or more tool invocations, or a single lifecycle event, with concrete parameters.
11
11
  3. **Postcondition** — assertions on the tool return value and on state files after the invocation.
12
+ 4. **Covers** — a declaration of which state-schema fields and return-value paths this fixture verifies.
12
13
 
13
14
  Fixtures do not contain any test runner code. Consumers load the JSON, reconstruct precondition state, call their own tool implementation, and verify the postconditions.
14
15
 
@@ -16,12 +17,54 @@ Fixtures do not contain any test runner code. Consumers load the JSON, reconstru
16
17
 
17
18
  All fixtures must validate against [`schema/fixture.schema.json`](schema/fixture.schema.json).
18
19
 
20
+ Every fixture must include a top-level `covers` field (required). An optional `uncovered_params` field may also appear.
21
+
22
+ ### `covers` field
23
+
24
+ `covers` declares which schema fields and return-value paths this fixture's postcondition actually verifies. The coverage validator uses this declaration to track completeness across the fixture suite.
25
+
26
+ ```json
27
+ "covers": {
28
+ "state_schemas": {
29
+ "plan.schema.json": ["id", "topic", "issues[].status"]
30
+ },
31
+ "return_value": {
32
+ "plan_start": ["created", "plan_id", "issueCount"]
33
+ },
34
+ "description": "Verifies plan creation fields and initial issue status."
35
+ }
36
+ ```
37
+
38
+ **Constraint**: at least one of `state_schemas` or `return_value` must be non-empty. Both may be present.
39
+
40
+ - `state_schemas` — map of state-schema filename (e.g. `plan.schema.json`) to an array of field paths verified by this fixture's postcondition. Field paths use dot-notation with array index notation (e.g. `issues[].status`).
41
+ - `return_value` — map of abstract tool name (e.g. `plan_start`) to an array of return-value field paths verified by this fixture's postcondition.
42
+ - `description` — optional human-readable explanation of coverage rationale or known gaps.
43
+
44
+ ### `uncovered_params` field
45
+
46
+ `uncovered_params` is an optional array of `action.params` keys that are intentionally not asserted in the postcondition. Entries listed here are treated as explicit exceptions by the coverage validator, preventing false anti-pattern warnings.
47
+
48
+ Use this field for routing or contextual input params whose effect is not directly observable via state-file or return-value assertions:
49
+
50
+ ```json
51
+ "uncovered_params": ["research_summary"]
52
+ ```
53
+
54
+ ### Schema `oneOf` constraint
55
+
56
+ Each fixture must contain exactly one of: `action` (single tool invocation), `event` (single lifecycle event), or `steps` (multi-step sequence). These three branches are mutually exclusive.
57
+
19
58
  ### Single-action fixture
20
59
 
21
60
  ```json
22
61
  {
23
62
  "test_id": "plan_start_happy_path",
24
63
  "description": "...",
64
+ "covers": {
65
+ "state_schemas": { "plan.schema.json": ["id", "topic", "issues[].status"] },
66
+ "return_value": { "plan_start": ["created", "plan_id", "issueCount"] }
67
+ },
25
68
  "precondition": {
26
69
  "state_files": {
27
70
  ".nexus/state/plan.json": null
@@ -46,6 +89,9 @@ All fixtures must validate against [`schema/fixture.schema.json`](schema/fixture
46
89
  {
47
90
  "test_id": "full_plan_cycle",
48
91
  "description": "...",
92
+ "covers": {
93
+ "state_schemas": { "plan.schema.json": ["id", "topic", "issues[].status"] }
94
+ },
49
95
  "steps": [
50
96
  {
51
97
  "description": "...",
@@ -57,6 +103,59 @@ All fixtures must validate against [`schema/fixture.schema.json`](schema/fixture
57
103
  }
58
104
  ```
59
105
 
106
+ ## Event-based (Lifecycle) Fixtures
107
+
108
+ 일부 state 파일(`runtime.json`, `agent-tracker.json`)은 MCP tool이 아니라 harness의 session hook이 관리한다. 이 파일들의 구조적 정확성을 검증하기 위해 `action` 대신 `event` 필드를 사용하는 lifecycle fixture를 사용한다.
109
+
110
+ Event fixture는 "harness가 특정 event를 실행한 후 state 파일의 구조가 올바른가"를 선언적으로 명세한다. Tool invocation 없이 event 트리거만으로 postcondition을 검증한다.
111
+
112
+ ### Event types
113
+
114
+ `event.type`은 다음 5종 중 하나여야 한다:
115
+
116
+ | Event type | 책임 범위 |
117
+ |---|---|
118
+ | `session_start` | `runtime.json` 초기화, `agent-tracker.json` 빈 배열 생성 |
119
+ | `session_end` | `runtime.json` 삭제, `agent-tracker.json` 삭제 |
120
+ | `agent_spawn` | `agent-tracker.json`에 신규 항목 생성 (running 상태) |
121
+ | `agent_complete` | `agent-tracker.json` 항목을 완료 상태로 전환 |
122
+ | `agent_resume` | `agent-tracker.json` 재개 카운터 증가 및 상태 복귀 |
123
+
124
+ ### Lifecycle fixture 구조 예시
125
+
126
+ ```json
127
+ {
128
+ "test_id": "session_start_creates_runtime",
129
+ "description": "...",
130
+ "covers": {
131
+ "state_schemas": {
132
+ "runtime.schema.json": ["teams_enabled", "active_plan_id"]
133
+ }
134
+ },
135
+ "event": {
136
+ "type": "session_start",
137
+ "params": { ... }
138
+ },
139
+ "postcondition": {
140
+ "state_files": {
141
+ ".nexus/state/runtime.json": { "$.teams_enabled": false }
142
+ }
143
+ }
144
+ }
145
+ ```
146
+
147
+ ### Lifecycle fixture 목록
148
+
149
+ `conformance/lifecycle/` 디렉토리에 5개 파일이 존재한다:
150
+
151
+ | 파일 | Event type | 검증 대상 |
152
+ |---|---|---|
153
+ | `session-start.json` | `session_start` | `runtime.json` 초기화, `agent-tracker.json` 빈 배열 |
154
+ | `session-end.json` | `session_end` | `runtime.json` 삭제, `agent-tracker.json` 삭제 |
155
+ | `agent-spawn.json` | `agent_spawn` | `agent-tracker.json` 첫 항목 생성 (running 상태) |
156
+ | `agent-complete.json` | `agent_complete` | `agent-tracker.json` 항목 완료 상태 전환 |
157
+ | `agent-resume.json` | `agent_resume` | `agent-tracker.json` 재개 카운터 및 상태 복귀 |
158
+
60
159
  ## Assertion conventions
61
160
 
62
161
  Assertions are key/value objects where keys are JSONPath expressions and values are expected results or matchers.
@@ -71,9 +170,65 @@ Assertions are key/value objects where keys are JSONPath expressions and values
71
170
  | `"$.field": { "type": "number", "min": 1 }` | Numeric value >= 1 |
72
171
  | `"$.field": { "type": "string", "minLength": 5 }` | String with minimum length |
73
172
  | `".nexus/state/plan.json": null` | File must not exist |
173
+ | `".nexus/state/artifacts/findings.md": {}` | File must exist; content not inspected (use for non-JSON artifacts like .md, .txt, binary files) |
74
174
 
75
175
  For `state_files`, a `null` value at the file path key means the file must be absent. A `null` value at a JSONPath key within a file assertion means that field must be `null`.
76
176
 
177
+ ## Authoring Rules
178
+
179
+ Fixtures must satisfy the following rules. The coverage validator enforces Rules 1–3 at CI time.
180
+
181
+ **Rule 1 — Coverage**: 모든 state-schema 필드(required + optional)는 최소 1개 fixture의 `covers.state_schemas`에 등장해야 한다. 단 한 필드라도 누락되면 validator가 실패한다.
182
+
183
+ **Rule 2 — No Silent Drop**: `action.params`의 모든 key는 `postcondition`(state_files 또는 return_value)에서 assert되거나 `uncovered_params`에 명시되어야 한다. 두 조건 모두 충족하지 않는 param key는 anti-pattern으로 보고된다.
184
+
185
+ **Rule 3 — CI Gate**: fixture 추가 또는 수정 시 `validate:conformance` validator 통과가 release block이다. 실패 상태로 merge할 수 없다.
186
+
187
+ **Rule 4 — Truthful Covers**: `covers`는 실제로 postcondition에서 assert하는 필드만 나열해야 한다. 허위 claim 금지. validator는 covers 선언과 실제 assertion 간 교차 검증을 수행하지 않지만, review 시 수동 검증 대상이다.
188
+
189
+ ## Running the Coverage Validator
190
+
191
+ `conformance-coverage.ts`는 두 가지를 검증한다:
192
+
193
+ 1. **Schema field coverage** — `conformance/state-schemas/`의 모든 schema 파일에서 추출한 필드가 전체 fixture의 `covers.state_schemas` union에 포함되는지 확인한다.
194
+ 2. **Params anti-pattern** — single-action fixture의 `action.params` key가 `postcondition` assertion 또는 `uncovered_params`에 트레이스 가능한지 확인한다.
195
+
196
+ ### 실행 명령
197
+
198
+ ```
199
+ bun run validate:conformance
200
+ ```
201
+
202
+ 또는 직접 실행:
203
+
204
+ ```
205
+ bun run scripts/conformance-coverage.ts
206
+ ```
207
+
208
+ ### 출력 해석
209
+
210
+ **PASS** (exit code 0):
211
+
212
+ ```
213
+ ✓ All state-schema fields covered: 5 schemas, 54 fields across 48 fixtures
214
+ ```
215
+
216
+ **FAIL — schema field coverage 미달** (exit code 1):
217
+
218
+ ```
219
+ ✗ Schema field coverage incomplete:
220
+ plan.schema.json: missing fields [issues[].how_agents]
221
+ ```
222
+
223
+ **FAIL — params anti-pattern 감지** (exit code 1):
224
+
225
+ ```
226
+ ✗ Params anti-pattern detected (params not verified in postcondition):
227
+ conformance/tools/plan-start.json (plan_start_happy_path): uncovered params [research_summary]
228
+ ```
229
+
230
+ exit code 2는 파일 파싱 등 fatal error를 의미한다.
231
+
77
232
  ## Writing a test runner
78
233
 
79
234
  A conformance test runner does the following for each fixture:
@@ -82,10 +237,14 @@ A conformance test runner does the following for each fixture:
82
237
  2. **Establish precondition**: for each entry in `precondition.state_files`, write the content object as JSON to the specified path, or delete the file if the value is `null`.
83
238
  3. **Execute**:
84
239
  - For single-action fixtures: call the tool named by `action.tool` with `action.params`.
85
- - For multi-step scenarios: iterate `steps` in order, calling each `action` and evaluating `assert_return` and `assert_state` after each step before proceeding.
240
+ - For event fixtures: trigger the harness session hook for the event type specified by `event.type`, passing `event.params`.
241
+ - For multi-step scenarios: iterate `steps` in order, calling each `action` (or triggering each `event`) and evaluating `assert_return` and `assert_state` after each step before proceeding.
86
242
  4. **Evaluate postconditions**:
87
243
  - Check `postcondition.return_value` assertions against the tool's return value.
88
- - Check `postcondition.state_files` assertions against the actual file system state.
244
+ - Check `postcondition.state_files` assertions against the actual file system state. For each entry in `state_files`:
245
+ - Value is `null` → assert the file does NOT exist.
246
+ - Value is an empty object `{}` → assert the file EXISTS; do NOT parse content (use for non-JSON artifacts: .md, .txt, binary).
247
+ - Value is a non-empty object `{...}` → parse file as JSON and evaluate each JSONPath assertion against the parsed content.
89
248
  - If `postcondition.error` is `true`, the tool call must have produced an error.
90
249
  - If `postcondition.error_contains` is set, the error message must contain that substring.
91
250
  5. **Report** pass/fail per `test_id`.
@@ -104,22 +263,55 @@ for (const fixture of fixtures) {
104
263
 
105
264
  ## Coverage
106
265
 
107
- These fixtures cover the 11 Nexus-core abstract tool names:
266
+ ### Abstract tools (11/11 커버됨)
108
267
 
109
- | Abstract name | Description |
268
+ 11개 abstract tool 모두 전용 fixture 파일을 갖는다. 각 fixture는 tool의 happy path, error path, optional 파라미터 경로를 포함한다.
269
+
270
+ | Abstract name | Description | Fixture file |
271
+ |---|---|---|
272
+ | `plan_start` | Start a new plan session | `tools/plan-start.json` |
273
+ | `plan_decide` | Record a decision on a plan issue | `tools/plan-decide.json` |
274
+ | `plan_status` | Query the current plan state | `tools/plan-status.json` |
275
+ | `plan_update` | Add, remove, edit, or reopen plan issues | `tools/plan-update.json` |
276
+ | `task_add` | Add a task to the task list | `tools/task-add.json` |
277
+ | `task_update` | Update a task's status | `tools/task-update.json` |
278
+ | `task_list` | List tasks with dependency-aware ready set | `tools/task-list.json` |
279
+ | `task_close` | Archive cycle into history and delete source files | `tools/task-close.json` |
280
+ | `history_search` | Search past cycles in history.json | `tools/history-search.json` |
281
+ | `context` | Read or write .nexus/context/ knowledge files | `tools/context.json` |
282
+ | `artifact_write` | Write an artifact output file | `tools/artifact-write.json` |
283
+
284
+ ### Lifecycle events (5/5 커버됨)
285
+
286
+ | Event type | Fixture file |
287
+ |---|---|
288
+ | `session_start` | `lifecycle/session-start.json` |
289
+ | `session_end` | `lifecycle/session-end.json` |
290
+ | `agent_spawn` | `lifecycle/agent-spawn.json` |
291
+ | `agent_complete` | `lifecycle/agent-complete.json` |
292
+ | `agent_resume` | `lifecycle/agent-resume.json` |
293
+
294
+ ### State-schema field coverage
295
+
296
+ 5개 state-schema의 모든 필드가 100% 커버된다:
297
+
298
+ | Schema | 검증 도구 |
110
299
  |---|---|
111
- | `plan_start` | Start a new plan session |
112
- | `plan_decide` | Record a decision on a plan issue |
113
- | `plan_status` | Query the current plan state |
114
- | `plan_update` | Add, remove, edit, or reopen plan issues |
115
- | `task_add` | Add a task to the task list |
116
- | `task_update` | Update a task's status |
117
- | `task_list` | List tasks with dependency-aware ready set |
118
- | `task_close` | Archive cycle into history and delete source files |
119
- | `history_search` | Search past cycles in history.json |
120
- | `context` | Read or write .nexus/context/ knowledge files |
121
- | `artifact_write` | Write an artifact output file |
300
+ | `plan.schema.json` | `tools/plan-*.json` fixtures |
301
+ | `tasks.schema.json` | `tools/task-*.json` fixtures |
302
+ | `history.schema.json` | `tools/history-search.json`, `tools/task-close.json` |
303
+ | `runtime.schema.json` | `lifecycle/session-*.json` fixtures |
304
+ | `agent-tracker.schema.json` | `lifecycle/agent-*.json` fixtures |
305
+
306
+ 현재 validator 통과 결과: `✓ All state-schema fields covered: 5 schemas, 54 fields across 48 fixtures`
122
307
 
123
308
  ## Excluded tools
124
309
 
125
310
  AST and LSP tools (`ast_search`, `ast_replace`, `lsp_diagnostics`, `lsp_goto_definition`, etc.) are harness utilities that depend on language server infrastructure. They are not ecosystem contracts and are excluded from conformance coverage.
311
+
312
+ ## 관련 문서
313
+
314
+ - `docs/nexus-outputs-contract.md` — harness 산출물 계약 (artifact 경로, 파일 형식)
315
+ - `docs/nexus-state-overview.md` — state file 기술 스펙 (schema 정의, 파일 위치)
316
+ - `docs/nexus-tools-contract.md` — 11개 abstract tool 계약 (params, return value)
317
+ - `CONSUMING.md §Conformance Obligation` — consumer가 준수해야 하는 conformance 의무
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "conformance/examples/plan.extension.schema.example.json",
4
+ "title": "Example: Harness-local plan state extension",
5
+ "description": "Non-normative reference example of a harness-local extension schema for plan.json. Harnesses MAY add supplemental fields via {base}.extension.json files in .nexus/state/{harness-id}/. Consumers replace harness_specific_field_example with their own fields. See docs/nexus-outputs-contract.md §Harness-local State Extension for the pattern definition.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["extends"],
9
+ "properties": {
10
+ "extends": {
11
+ "type": "string",
12
+ "const": "conformance/state-schemas/plan.schema.json",
13
+ "description": "Reference to the parent common-schema this extension supplements"
14
+ },
15
+ "harness_id": {
16
+ "type": "string",
17
+ "pattern": "^[a-z][a-z0-9-]*$",
18
+ "description": "Identifier of the harness that produced this extension file"
19
+ },
20
+ "harness_specific_field_example": {
21
+ "type": "string",
22
+ "description": "Placeholder — replace with your harness's actual extension fields as needed"
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,17 @@
1
+ # Lifecycle Fixtures
2
+
3
+ 이 fixture들은 harness의 session hook이 event를 재현한 후의 state 파일을 검증한다.
4
+
5
+ ## Event Types
6
+
7
+ | Fixture | Event Type | 검증 대상 |
8
+ |---|---|---|
9
+ | `session-start.json` | `session_start` | `runtime.json` 초기화, `agent-tracker.json` 빈 배열 |
10
+ | `session-end.json` | `session_end` | `runtime.json` 삭제, `agent-tracker.json` 삭제 |
11
+ | `agent-spawn.json` | `agent_spawn` | `agent-tracker.json` 첫 항목 생성 (running 상태) |
12
+ | `agent-complete.json` | `agent_complete` | `agent-tracker.json` 항목 완료 상태 전환 |
13
+ | `agent-resume.json` | `agent_resume` | `agent-tracker.json` 재개 카운터 및 상태 복귀 |
14
+
15
+ ## Tool-action 대신 Event 트리거 사용
16
+
17
+ 각 fixture는 `action` (tool invocation) 대신 `event` 필드를 사용한다. `runtime.json`과 `agent-tracker.json`은 harness의 session hook이 관리하며, MCP tool이 직접 쓰지 않는다. Event fixture는 "harness가 event를 실행한 후 state 파일의 구조가 올바른가"를 선언적으로 명세한다.
@@ -0,0 +1,44 @@
1
+ {
2
+ "test_id": "agent_complete",
3
+ "description": "Verifies that agent_complete transitions an agent to completed status and records stopped_at, last_message, and files_touched in agent-tracker.json",
4
+ "precondition": {
5
+ "state_files": {
6
+ ".nexus/state/agent-tracker.json": [
7
+ {
8
+ "harness_id": "claude-nexus",
9
+ "agent_name": "architect",
10
+ "agent_id": "uuid-eng01",
11
+ "started_at": "2026-04-13T00:00:00.000Z",
12
+ "resume_count": 0,
13
+ "status": "running"
14
+ }
15
+ ]
16
+ }
17
+ },
18
+ "event": {
19
+ "type": "agent_complete",
20
+ "params": {
21
+ "agent_id": "uuid-eng01",
22
+ "last_message": "Implementation complete",
23
+ "files_touched": ["src/foo.ts", "src/bar.ts"]
24
+ },
25
+ "description": "Harness records agent completion with output summary and list of modified files"
26
+ },
27
+ "postcondition": {
28
+ "state_files": {
29
+ ".nexus/state/agent-tracker.json": {
30
+ "$.length": 1,
31
+ "$[0].status": "completed",
32
+ "$[0].stopped_at": { "type": "iso8601" },
33
+ "$[0].last_message": "Implementation complete",
34
+ "$[0].files_touched.length": 2,
35
+ "$[0].files_touched[0]": "src/foo.ts"
36
+ }
37
+ }
38
+ },
39
+ "covers": {
40
+ "state_schemas": {
41
+ "agent-tracker.schema.json": ["status", "stopped_at", "last_message", "files_touched", "files_touched[]"]
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "test_id": "agent_resume",
3
+ "description": "Verifies that agent_resume transitions a completed agent back to running status and increments resume_count and sets last_resumed_at",
4
+ "precondition": {
5
+ "state_files": {
6
+ ".nexus/state/agent-tracker.json": [
7
+ {
8
+ "harness_id": "claude-nexus",
9
+ "agent_name": "architect",
10
+ "agent_id": "uuid-eng01",
11
+ "started_at": "2026-04-13T00:00:00.000Z",
12
+ "resume_count": 0,
13
+ "status": "completed",
14
+ "stopped_at": "2026-04-13T01:00:00.000Z",
15
+ "last_message": "Implementation complete",
16
+ "files_touched": ["src/foo.ts", "src/bar.ts"]
17
+ }
18
+ ]
19
+ }
20
+ },
21
+ "event": {
22
+ "type": "agent_resume",
23
+ "params": {
24
+ "agent_id": "uuid-eng01"
25
+ },
26
+ "description": "Harness resumes a previously completed agent, incrementing the resume counter and updating lifecycle timestamps"
27
+ },
28
+ "postcondition": {
29
+ "state_files": {
30
+ ".nexus/state/agent-tracker.json": {
31
+ "$.length": 1,
32
+ "$[0].status": "running",
33
+ "$[0].resume_count": 1,
34
+ "$[0].last_resumed_at": { "type": "iso8601" }
35
+ }
36
+ }
37
+ },
38
+ "covers": {
39
+ "state_schemas": {
40
+ "agent-tracker.schema.json": ["last_resumed_at", "resume_count", "status"]
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "test_id": "agent_spawn",
3
+ "description": "Verifies that agent_spawn appends a new running agent entry to agent-tracker.json with required fields initialized correctly",
4
+ "precondition": {
5
+ "state_files": {
6
+ ".nexus/state/runtime.json": {
7
+ "teams_enabled": true,
8
+ "session_started_at": "2026-04-13T00:00:00.000Z",
9
+ "harness_id": "claude-nexus",
10
+ "harness_version": "0.25.0"
11
+ },
12
+ ".nexus/state/agent-tracker.json": []
13
+ }
14
+ },
15
+ "event": {
16
+ "type": "agent_spawn",
17
+ "params": {
18
+ "harness_id": "claude-nexus",
19
+ "agent_name": "architect",
20
+ "agent_id": "uuid-eng01"
21
+ },
22
+ "description": "Harness spawns an agent instance and records its initial state in the agent registry"
23
+ },
24
+ "postcondition": {
25
+ "state_files": {
26
+ ".nexus/state/agent-tracker.json": {
27
+ "$.length": 1,
28
+ "$[0].harness_id": "claude-nexus",
29
+ "$[0].agent_name": "architect",
30
+ "$[0].agent_id": "uuid-eng01",
31
+ "$[0].started_at": { "type": "iso8601" },
32
+ "$[0].resume_count": 0,
33
+ "$[0].status": "running"
34
+ }
35
+ }
36
+ },
37
+ "covers": {
38
+ "state_schemas": {
39
+ "agent-tracker.schema.json": ["harness_id", "agent_name", "agent_id", "started_at", "resume_count", "status"]
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "test_id": "session_end",
3
+ "description": "Verifies that session_end removes runtime.json and agent-tracker.json, completing the full session lifecycle deletion",
4
+ "precondition": {
5
+ "state_files": {
6
+ ".nexus/state/runtime.json": {
7
+ "teams_enabled": true,
8
+ "session_started_at": "2026-04-13T00:00:00.000Z",
9
+ "harness_id": "claude-nexus",
10
+ "harness_version": "0.25.0"
11
+ },
12
+ ".nexus/state/agent-tracker.json": []
13
+ }
14
+ },
15
+ "event": {
16
+ "type": "session_end",
17
+ "description": "Harness session hook fires at shutdown, cleaning up all runtime state files"
18
+ },
19
+ "postcondition": {
20
+ "state_files": {
21
+ ".nexus/state/runtime.json": null,
22
+ ".nexus/state/agent-tracker.json": null
23
+ }
24
+ },
25
+ "covers": {
26
+ "state_schemas": {
27
+ "runtime.schema.json": ["teams_enabled", "session_started_at", "harness_id", "harness_version"],
28
+ "agent-tracker.schema.json": []
29
+ },
30
+ "description": "Covers deletion aspect of the full runtime/agent-tracker lifecycle — absence of both files after session_end"
31
+ }
32
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "test_id": "session_start",
3
+ "description": "Verifies that session_start writes runtime.json with required fields and initializes agent-tracker.json as an empty array",
4
+ "precondition": {
5
+ "state_files": {
6
+ ".nexus/state/runtime.json": null,
7
+ ".nexus/state/agent-tracker.json": null
8
+ }
9
+ },
10
+ "event": {
11
+ "type": "session_start",
12
+ "params": {
13
+ "teams_enabled": true,
14
+ "harness_id": "claude-nexus",
15
+ "harness_version": "0.25.0"
16
+ },
17
+ "description": "Harness session hook fires at startup, injecting runtime configuration and initializing the agent registry"
18
+ },
19
+ "postcondition": {
20
+ "state_files": {
21
+ ".nexus/state/runtime.json": {
22
+ "$.teams_enabled": true,
23
+ "$.session_started_at": { "type": "iso8601" },
24
+ "$.harness_id": "claude-nexus",
25
+ "$.harness_version": { "type": "string", "minLength": 1 }
26
+ },
27
+ ".nexus/state/agent-tracker.json": {
28
+ "$.length": 0
29
+ }
30
+ }
31
+ },
32
+ "covers": {
33
+ "state_schemas": {
34
+ "runtime.schema.json": ["schema_version", "teams_enabled", "session_started_at", "harness_id", "harness_version"],
35
+ "agent-tracker.schema.json": []
36
+ }
37
+ }
38
+ }
@@ -1,6 +1,21 @@
1
1
  {
2
2
  "test_id": "full_plan_cycle",
3
3
  "description": "Verifies the complete plan → decide → task_add → close lifecycle across 5 sequential tool invocations",
4
+ "covers": {
5
+ "state_schemas": {
6
+ "plan.schema.json": ["id", "topic", "issues[].id", "issues[].title", "issues[].status", "issues[].decision", "research_summary", "created_at"],
7
+ "tasks.schema.json": ["goal", "decisions", "tasks[].id", "tasks[].title", "tasks[].status", "tasks[].plan_issue"],
8
+ "history.schema.json": ["cycles[].completed_at", "cycles[].plan", "cycles[].plan.issues[].status", "cycles[].tasks[].id"]
9
+ },
10
+ "return_value": {
11
+ "plan_start": ["created", "plan_id", "issueCount"],
12
+ "plan_decide": ["decided", "allComplete", "remaining"],
13
+ "task_add": ["task.id", "task.status", "task.plan_issue"],
14
+ "task_close": ["closed", "archived.plan", "archived.decisions", "archived.tasks", "total_cycles"]
15
+ },
16
+ "description": "End-to-end lifecycle scenario: plan/task/history state transitions and each tool's return value across 5 sequential invocations."
17
+ },
18
+ "uncovered_params": ["research_summary", "issue_id", "decision", "title", "context", "deps"],
4
19
  "precondition": {
5
20
  "state_files": {
6
21
  ".nexus/state/plan.json": null,
@@ -41,7 +56,7 @@
41
56
  "tool": "plan_decide",
42
57
  "params": {
43
58
  "issue_id": 1,
44
- "summary": "Keep .nexus/state/ as the canonical location. Documented in state-schemas README."
59
+ "decision": "Keep .nexus/state/ as the canonical location. Documented in state-schemas README."
45
60
  }
46
61
  },
47
62
  "assert_return": {
@@ -63,7 +78,7 @@
63
78
  "tool": "plan_decide",
64
79
  "params": {
65
80
  "issue_id": 2,
66
- "summary": "Ship a one-shot migration script as a standalone npm script. Document in RELEASING.md."
81
+ "decision": "Ship a one-shot migration script as a standalone npm script. Document in RELEASING.md."
67
82
  }
68
83
  },
69
84
  "assert_return": {
@@ -1,6 +1,18 @@
1
1
  {
2
2
  "test_id": "task_deps_ordering",
3
3
  "description": "Verifies that dependency ordering is enforced by task_list: a task with an incomplete dep is not ready, and becomes ready after the dep is completed",
4
+ "covers": {
5
+ "state_schemas": {
6
+ "tasks.schema.json": ["goal", "tasks[].id", "tasks[].title", "tasks[].status", "tasks[].deps"]
7
+ },
8
+ "return_value": {
9
+ "task_add": ["task.id", "task.status", "task.deps"],
10
+ "task_list": ["summary.total", "summary.ready", "summary.completed"],
11
+ "task_update": ["task.id", "task.status"]
12
+ },
13
+ "description": "Dependency-aware ready set computation: validates that task_list correctly unblocks dependents after prerequisites complete."
14
+ },
15
+ "uncovered_params": ["title", "context", "goal"],
4
16
  "precondition": {
5
17
  "state_files": {
6
18
  ".nexus/state/tasks.json": null