@moreih29/nexus-core 0.5.0 → 0.7.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.
- package/conformance/README.md +13 -19
- package/conformance/lifecycle/README.md +28 -3
- package/conformance/lifecycle/agent-complete.json +2 -2
- package/conformance/lifecycle/agent-resume.json +2 -2
- package/conformance/lifecycle/agent-spawn.json +2 -8
- package/conformance/schema/fixture.schema.json +5 -5
- package/conformance/state-schemas/agent-tracker.schema.json +2 -2
- package/docs/consumer-implementation-guide.md +16 -18
- package/docs/nexus-layout.md +8 -20
- package/docs/nexus-outputs-contract.md +71 -40
- package/docs/nexus-state-overview.md +6 -21
- package/manifest.json +43 -43
- package/package.json +1 -1
- package/conformance/lifecycle/session-end.json +0 -32
- package/conformance/lifecycle/session-start.json +0 -38
- package/conformance/state-schemas/runtime.schema.json +0 -34
package/conformance/README.md
CHANGED
|
@@ -105,18 +105,16 @@ Each fixture must contain exactly one of: `action` (single tool invocation), `ev
|
|
|
105
105
|
|
|
106
106
|
## Event-based (Lifecycle) Fixtures
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
`agent-tracker.json`은 MCP tool이 아니라 harness의 session hook이 관리한다. 이 파일의 구조적 정확성을 검증하기 위해 `action` 대신 `event` 필드를 사용하는 lifecycle fixture를 사용한다.
|
|
109
109
|
|
|
110
110
|
Event fixture는 "harness가 특정 event를 실행한 후 state 파일의 구조가 올바른가"를 선언적으로 명세한다. Tool invocation 없이 event 트리거만으로 postcondition을 검증한다.
|
|
111
111
|
|
|
112
112
|
### Event types
|
|
113
113
|
|
|
114
|
-
`event.type`은 다음
|
|
114
|
+
`event.type`은 다음 3종 중 하나여야 한다:
|
|
115
115
|
|
|
116
116
|
| Event type | 책임 범위 |
|
|
117
117
|
|---|---|
|
|
118
|
-
| `session_start` | `runtime.json` 초기화, `agent-tracker.json` 빈 배열 생성 |
|
|
119
|
-
| `session_end` | `runtime.json` 삭제, `agent-tracker.json` 삭제 |
|
|
120
118
|
| `agent_spawn` | `agent-tracker.json`에 신규 항목 생성 (running 상태) |
|
|
121
119
|
| `agent_complete` | `agent-tracker.json` 항목을 완료 상태로 전환 |
|
|
122
120
|
| `agent_resume` | `agent-tracker.json` 재개 카운터 증가 및 상태 복귀 |
|
|
@@ -125,20 +123,20 @@ Event fixture는 "harness가 특정 event를 실행한 후 state 파일의 구
|
|
|
125
123
|
|
|
126
124
|
```json
|
|
127
125
|
{
|
|
128
|
-
"test_id": "
|
|
126
|
+
"test_id": "agent_spawn_creates_entry",
|
|
129
127
|
"description": "...",
|
|
130
128
|
"covers": {
|
|
131
129
|
"state_schemas": {
|
|
132
|
-
"
|
|
130
|
+
"agent-tracker.schema.json": ["harness_id", "agent_name", "agent_id", "status"]
|
|
133
131
|
}
|
|
134
132
|
},
|
|
135
133
|
"event": {
|
|
136
|
-
"type": "
|
|
134
|
+
"type": "agent_spawn",
|
|
137
135
|
"params": { ... }
|
|
138
136
|
},
|
|
139
137
|
"postcondition": {
|
|
140
138
|
"state_files": {
|
|
141
|
-
"
|
|
139
|
+
"{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json": { "$[0].status": "running" }
|
|
142
140
|
}
|
|
143
141
|
}
|
|
144
142
|
}
|
|
@@ -146,12 +144,10 @@ Event fixture는 "harness가 특정 event를 실행한 후 state 파일의 구
|
|
|
146
144
|
|
|
147
145
|
### Lifecycle fixture 목록
|
|
148
146
|
|
|
149
|
-
`conformance/lifecycle/` 디렉토리에
|
|
147
|
+
`conformance/lifecycle/` 디렉토리에 3개 파일이 존재한다:
|
|
150
148
|
|
|
151
149
|
| 파일 | Event type | 검증 대상 |
|
|
152
150
|
|---|---|---|
|
|
153
|
-
| `session-start.json` | `session_start` | `runtime.json` 초기화, `agent-tracker.json` 빈 배열 |
|
|
154
|
-
| `session-end.json` | `session_end` | `runtime.json` 삭제, `agent-tracker.json` 삭제 |
|
|
155
151
|
| `agent-spawn.json` | `agent_spawn` | `agent-tracker.json` 첫 항목 생성 (running 상태) |
|
|
156
152
|
| `agent-complete.json` | `agent_complete` | `agent-tracker.json` 항목 완료 상태 전환 |
|
|
157
153
|
| `agent-resume.json` | `agent_resume` | `agent-tracker.json` 재개 카운터 및 상태 복귀 |
|
|
@@ -171,6 +167,7 @@ Assertions are key/value objects where keys are JSONPath expressions and values
|
|
|
171
167
|
| `"$.field": { "type": "string", "minLength": 5 }` | String with minimum length |
|
|
172
168
|
| `".nexus/state/plan.json": null` | File must not exist |
|
|
173
169
|
| `".nexus/state/artifacts/findings.md": {}` | File must exist; content not inspected (use for non-JSON artifacts like .md, .txt, binary files) |
|
|
170
|
+
| `"{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json"` | State file path with substitutable tokens. Test runner MUST substitute `{STATE_ROOT}` with `.nexus/state` and `{HARNESS_ID}` with the harness identifier (from `event.params.harness_id` or runner configuration) before applying assertions. Only `{STATE_ROOT}` and `{HARNESS_ID}` are recognized; arbitrary tokens are forbidden. |
|
|
174
171
|
|
|
175
172
|
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`.
|
|
176
173
|
|
|
@@ -234,14 +231,14 @@ exit code 2는 파일 파싱 등 fatal error를 의미한다.
|
|
|
234
231
|
A conformance test runner does the following for each fixture:
|
|
235
232
|
|
|
236
233
|
1. **Load** the fixture JSON file.
|
|
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`.
|
|
234
|
+
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`. Before resolving any path, substitute placeholder tokens: replace `{STATE_ROOT}` with `.nexus/state` and `{HARNESS_ID}` with the harness identifier found in `event.params.harness_id` (for lifecycle fixtures) or runner configuration (for general fixtures). Only `{STATE_ROOT}` and `{HARNESS_ID}` are recognized tokens; treat any other `{…}` token in a path as an authoring error.
|
|
238
235
|
3. **Execute**:
|
|
239
236
|
- For single-action fixtures: call the tool named by `action.tool` with `action.params`.
|
|
240
237
|
- For event fixtures: trigger the harness session hook for the event type specified by `event.type`, passing `event.params`.
|
|
241
238
|
- 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.
|
|
242
239
|
4. **Evaluate postconditions**:
|
|
243
240
|
- Check `postcondition.return_value` assertions against the tool's return value.
|
|
244
|
-
- Check `postcondition.state_files` assertions against the actual file system state. For each entry in `state_files`:
|
|
241
|
+
- Check `postcondition.state_files` assertions against the actual file system state. Apply the same `{STATE_ROOT}` / `{HARNESS_ID}` substitution to path keys before resolving (same rule as precondition). For each entry in `state_files`:
|
|
245
242
|
- Value is `null` → assert the file does NOT exist.
|
|
246
243
|
- Value is an empty object `{}` → assert the file EXISTS; do NOT parse content (use for non-JSON artifacts: .md, .txt, binary).
|
|
247
244
|
- Value is a non-empty object `{...}` → parse file as JSON and evaluate each JSONPath assertion against the parsed content.
|
|
@@ -281,29 +278,26 @@ for (const fixture of fixtures) {
|
|
|
281
278
|
| `context` | Read or write .nexus/context/ knowledge files | `tools/context.json` |
|
|
282
279
|
| `artifact_write` | Write an artifact output file | `tools/artifact-write.json` |
|
|
283
280
|
|
|
284
|
-
### Lifecycle events (
|
|
281
|
+
### Lifecycle events (3/3 커버됨)
|
|
285
282
|
|
|
286
283
|
| Event type | Fixture file |
|
|
287
284
|
|---|---|
|
|
288
|
-
| `session_start` | `lifecycle/session-start.json` |
|
|
289
|
-
| `session_end` | `lifecycle/session-end.json` |
|
|
290
285
|
| `agent_spawn` | `lifecycle/agent-spawn.json` |
|
|
291
286
|
| `agent_complete` | `lifecycle/agent-complete.json` |
|
|
292
287
|
| `agent_resume` | `lifecycle/agent-resume.json` |
|
|
293
288
|
|
|
294
289
|
### State-schema field coverage
|
|
295
290
|
|
|
296
|
-
|
|
291
|
+
4개 state-schema의 모든 필드가 100% 커버된다:
|
|
297
292
|
|
|
298
293
|
| Schema | 검증 도구 |
|
|
299
294
|
|---|---|
|
|
300
295
|
| `plan.schema.json` | `tools/plan-*.json` fixtures |
|
|
301
296
|
| `tasks.schema.json` | `tools/task-*.json` fixtures |
|
|
302
297
|
| `history.schema.json` | `tools/history-search.json`, `tools/task-close.json` |
|
|
303
|
-
| `runtime.schema.json` | `lifecycle/session-*.json` fixtures |
|
|
304
298
|
| `agent-tracker.schema.json` | `lifecycle/agent-*.json` fixtures |
|
|
305
299
|
|
|
306
|
-
|
|
300
|
+
Validator 통과 결과 예시: `✓ All state-schema fields covered: 4 schemas across fixture suite`
|
|
307
301
|
|
|
308
302
|
## Excluded tools
|
|
309
303
|
|
|
@@ -6,12 +6,37 @@
|
|
|
6
6
|
|
|
7
7
|
| Fixture | Event Type | 검증 대상 |
|
|
8
8
|
|---|---|---|
|
|
9
|
-
| `session-start.json` | `session_start` | `runtime.json` 초기화, `agent-tracker.json` 빈 배열 |
|
|
10
|
-
| `session-end.json` | `session_end` | `runtime.json` 삭제, `agent-tracker.json` 삭제 |
|
|
11
9
|
| `agent-spawn.json` | `agent_spawn` | `agent-tracker.json` 첫 항목 생성 (running 상태) |
|
|
12
10
|
| `agent-complete.json` | `agent_complete` | `agent-tracker.json` 항목 완료 상태 전환 |
|
|
13
11
|
| `agent-resume.json` | `agent_resume` | `agent-tracker.json` 재개 카운터 및 상태 복귀 |
|
|
14
12
|
|
|
15
13
|
## Tool-action 대신 Event 트리거 사용
|
|
16
14
|
|
|
17
|
-
각 fixture는 `action` (tool invocation) 대신 `event` 필드를 사용한다. `
|
|
15
|
+
각 fixture는 `action` (tool invocation) 대신 `event` 필드를 사용한다. `agent-tracker.json`은 harness의 session hook이 관리하며, MCP tool이 직접 쓰지 않는다. Event fixture는 "harness가 event를 실행한 후 state 파일의 구조가 올바른가"를 선언적으로 명세한다.
|
|
16
|
+
|
|
17
|
+
## Placeholder token 경로
|
|
18
|
+
|
|
19
|
+
이 lifecycle fixture 3종의 `precondition.state_files` 및 `postcondition.state_files` 키는 모두 placeholder token 형식을 사용한다:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Test runner는 이 키를 파일 시스템 경로로 해석하기 전에 다음 치환을 수행해야 한다:
|
|
26
|
+
|
|
27
|
+
| Token | 치환 값 | 출처 |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| `{STATE_ROOT}` | `.nexus/state` | 고정 상수 |
|
|
30
|
+
| `{HARNESS_ID}` | harness 식별자 (예: `claude-nexus`) | 해당 fixture의 `event.params.harness_id` |
|
|
31
|
+
|
|
32
|
+
치환 규약:
|
|
33
|
+
- `{STATE_ROOT}`와 `{HARNESS_ID}` 두 token만 인식된다. 그 외 `{…}` 형태의 token이 경로에 등장하면 authoring 오류로 처리한다.
|
|
34
|
+
- 공통 파일 fixture (`plan-*`, `task-*`, `history-*`, `artifact-write`)는 하드코딩된 경로를 사용하며 이 token 규약이 적용되지 않는다. Token 경로는 lifecycle fixture 3종에만 적용된다.
|
|
35
|
+
|
|
36
|
+
### Fixture별 경로 요약
|
|
37
|
+
|
|
38
|
+
| Fixture | `event.params.harness_id` 예시 | 해석된 경로 |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `agent-spawn.json` | `claude-nexus` | `.nexus/state/claude-nexus/agent-tracker.json` |
|
|
41
|
+
| `agent-complete.json` | `claude-nexus` | `.nexus/state/claude-nexus/agent-tracker.json` |
|
|
42
|
+
| `agent-resume.json` | `claude-nexus` | `.nexus/state/claude-nexus/agent-tracker.json` |
|
|
@@ -3,7 +3,7 @@
|
|
|
3
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
4
|
"precondition": {
|
|
5
5
|
"state_files": {
|
|
6
|
-
"
|
|
6
|
+
"{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json": [
|
|
7
7
|
{
|
|
8
8
|
"harness_id": "claude-nexus",
|
|
9
9
|
"agent_name": "architect",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"postcondition": {
|
|
28
28
|
"state_files": {
|
|
29
|
-
"
|
|
29
|
+
"{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json": {
|
|
30
30
|
"$.length": 1,
|
|
31
31
|
"$[0].status": "completed",
|
|
32
32
|
"$[0].stopped_at": { "type": "iso8601" },
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Verifies that agent_resume transitions a completed agent back to running status and increments resume_count and sets last_resumed_at",
|
|
4
4
|
"precondition": {
|
|
5
5
|
"state_files": {
|
|
6
|
-
"
|
|
6
|
+
"{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json": [
|
|
7
7
|
{
|
|
8
8
|
"harness_id": "claude-nexus",
|
|
9
9
|
"agent_name": "architect",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"postcondition": {
|
|
29
29
|
"state_files": {
|
|
30
|
-
"
|
|
30
|
+
"{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json": {
|
|
31
31
|
"$.length": 1,
|
|
32
32
|
"$[0].status": "running",
|
|
33
33
|
"$[0].resume_count": 1,
|
|
@@ -3,13 +3,7 @@
|
|
|
3
3
|
"description": "Verifies that agent_spawn appends a new running agent entry to agent-tracker.json with required fields initialized correctly",
|
|
4
4
|
"precondition": {
|
|
5
5
|
"state_files": {
|
|
6
|
-
"
|
|
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": []
|
|
6
|
+
"{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json": []
|
|
13
7
|
}
|
|
14
8
|
},
|
|
15
9
|
"event": {
|
|
@@ -23,7 +17,7 @@
|
|
|
23
17
|
},
|
|
24
18
|
"postcondition": {
|
|
25
19
|
"state_files": {
|
|
26
|
-
"
|
|
20
|
+
"{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json": {
|
|
27
21
|
"$.length": 1,
|
|
28
22
|
"$[0].harness_id": "claude-nexus",
|
|
29
23
|
"$[0].agent_name": "architect",
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"properties": {
|
|
113
113
|
"state_files": {
|
|
114
114
|
"type": "object",
|
|
115
|
-
"description": "Map of file path to content object. null = file must not exist; empty object {} = file must exist but content is not inspected (use for non-JSON artifacts like .md, .txt, binary files); non-empty object = precondition content written as-is (typically JSON).",
|
|
115
|
+
"description": "Map of file path to content object. File path keys may contain placeholder tokens that a conformance runner must expand before resolving paths. Allowed tokens: {STATE_ROOT} (the root directory for all harness state, e.g. '.nexus/state') and {HARNESS_ID} (the harness identifier, resolved from event.params.harness_id or equivalent context). No other arbitrary tokens are permitted. Example key: '{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json'. null value = file must not exist; empty object {} = file must exist but content is not inspected (use for non-JSON artifacts like .md, .txt, binary files); non-empty object = precondition content written as-is (typically JSON).",
|
|
116
116
|
"additionalProperties": {
|
|
117
117
|
"oneOf": [
|
|
118
118
|
{ "type": "object" },
|
|
@@ -160,14 +160,14 @@
|
|
|
160
160
|
},
|
|
161
161
|
"event": {
|
|
162
162
|
"type": "object",
|
|
163
|
-
"description": "A lifecycle event that triggers harness-level behavior without a direct tool call. Used for verifying
|
|
163
|
+
"description": "A lifecycle event that triggers harness-level behavior without a direct tool call. Used for verifying agent-tracker.json state changes.",
|
|
164
164
|
"additionalProperties": false,
|
|
165
165
|
"required": ["type"],
|
|
166
166
|
"properties": {
|
|
167
167
|
"type": {
|
|
168
168
|
"type": "string",
|
|
169
|
-
"enum": ["
|
|
170
|
-
"description": "Lifecycle event type.
|
|
169
|
+
"enum": ["agent_spawn", "agent_complete", "agent_resume"],
|
|
170
|
+
"description": "Lifecycle event type. agent_spawn/agent_complete/agent_resume: agent instance lifecycle."
|
|
171
171
|
},
|
|
172
172
|
"params": {
|
|
173
173
|
"type": "object",
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
"properties": {
|
|
188
188
|
"state_files": {
|
|
189
189
|
"type": "object",
|
|
190
|
-
"description": "Map of file path to assertion object. null = file must not exist after the action; empty object {} = file must exist but content is not inspected (use for non-JSON artifacts like .md, .txt, binary files); non-empty object = JSONPath assertions on parsed JSON content.",
|
|
190
|
+
"description": "Map of file path to assertion object. File path keys may contain placeholder tokens that a conformance runner must expand before resolving paths. Allowed tokens: {STATE_ROOT} and {HARNESS_ID} only — no other arbitrary tokens are permitted. See precondition.state_files for token semantics. null = file must not exist after the action; empty object {} = file must exist but content is not inspected (use for non-JSON artifacts like .md, .txt, binary files); non-empty object = JSONPath assertions on parsed JSON content.",
|
|
191
191
|
"additionalProperties": {
|
|
192
192
|
"oneOf": [
|
|
193
193
|
{
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"items": {
|
|
8
8
|
"type": "object",
|
|
9
9
|
"additionalProperties": false,
|
|
10
|
-
"required": ["harness_id", "
|
|
10
|
+
"required": ["harness_id", "started_at"],
|
|
11
11
|
"properties": {
|
|
12
12
|
"harness_id": {
|
|
13
13
|
"type": "string",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"agent_id": {
|
|
23
23
|
"type": "string",
|
|
24
24
|
"minLength": 1,
|
|
25
|
-
"description": "
|
|
25
|
+
"description": "Harness-specific opaque agent instance identifier. Format is defined by the writing harness (UUID, composite string, etc.). Consumers MUST treat the value as opaque — do not parse or infer agent identity across harness namespaces."
|
|
26
26
|
},
|
|
27
27
|
"started_at": {
|
|
28
28
|
"type": "string",
|
|
@@ -97,7 +97,7 @@ A complete Nexus consumer comprises nine components. They have hard dependencies
|
|
|
97
97
|
| # | Component | Description |
|
|
98
98
|
|---|-----------|-------------|
|
|
99
99
|
| 1 | `.nexus/` Directory Initialization | Create the required directory tree and `.gitignore` at session start |
|
|
100
|
-
| 2 | State File Management | Read/write plan.json, tasks.json, history.json,
|
|
100
|
+
| 2 | State File Management | Read/write plan.json, tasks.json, history.json, agent-tracker.json |
|
|
101
101
|
| 3 | MCP Tool Implementation | Concrete implementations of the 11 abstract Nexus tools |
|
|
102
102
|
| 4 | Capability Mapping | Local file translating abstract capability IDs to concrete disallowed tools |
|
|
103
103
|
| 5 | Agent Catalog | Load nexus-core agents, apply capability-map, register with harness |
|
|
@@ -159,12 +159,12 @@ Nexus state is split into two categories with different scopes, persistence, and
|
|
|
159
159
|
├── state/ ← session-scoped (not git-tracked)
|
|
160
160
|
│ ├── plan.json
|
|
161
161
|
│ ├── tasks.json
|
|
162
|
-
│ ├── runtime.json
|
|
163
|
-
│ ├── agent-tracker.json
|
|
164
162
|
│ ├── tool-log.jsonl
|
|
165
163
|
│ ├── edit-tracker.json
|
|
166
164
|
│ ├── reopen-tracker.json
|
|
167
|
-
│
|
|
165
|
+
│ ├── artifacts/
|
|
166
|
+
│ └── {harness-id}/ ← harness namespace (see §Harness-local State Extension)
|
|
167
|
+
│ └── agent-tracker.json
|
|
168
168
|
├── history.json ← project-scoped (git-tracked, append-only)
|
|
169
169
|
├── memory/ ← project-scoped (git-tracked)
|
|
170
170
|
│ └── *.md
|
|
@@ -182,9 +182,8 @@ At session start, your harness must:
|
|
|
182
182
|
1. Create `.nexus/` if it does not exist.
|
|
183
183
|
2. Create `.nexus/state/` if it does not exist.
|
|
184
184
|
3. Write `.nexus/.gitignore` with content `state/` if the file does not exist.
|
|
185
|
-
4.
|
|
186
|
-
5.
|
|
187
|
-
6. Check for stale state files from a prior crashed session. If `plan.json` or `tasks.json` exist without a running session, warn the user that a previous session may not have closed cleanly.
|
|
185
|
+
4. Create `.nexus/state/{harness-id}/` if it does not exist, then initialize `.nexus/state/{harness-id}/agent-tracker.json` as an empty array `[]`. (`{harness-id}` is the last segment of your npm package name; see [nexus-outputs-contract.md §Shared filename convention](./nexus-outputs-contract.md) for the namespace convention.)
|
|
186
|
+
5. Check for stale state files from a prior crashed session. If `plan.json` or `tasks.json` exist without a running session, warn the user that a previous session may not have closed cleanly.
|
|
188
187
|
|
|
189
188
|
### Key state files
|
|
190
189
|
|
|
@@ -192,15 +191,14 @@ At session start, your harness must:
|
|
|
192
191
|
|------|-------|------------|------------|------------|
|
|
193
192
|
| `state/plan.json` | Session | No | `plan_start` tool | `task_close` tool |
|
|
194
193
|
| `state/tasks.json` | Session | No | `task_add` tool (first call) | `task_close` tool |
|
|
195
|
-
| `state/
|
|
196
|
-
| `state/agent-tracker.json` | Session | No | session_start hook | session_end hook |
|
|
194
|
+
| `state/{harness-id}/agent-tracker.json` | Session | No | session_start hook | session_end hook |
|
|
197
195
|
| `state/tool-log.jsonl` | Session | No | post_tool_use hook | session_end hook |
|
|
198
196
|
| `state/edit-tracker.json` | Session | No | post_tool_use hook (first edit) | task_close / session_end |
|
|
199
197
|
| `history.json` | Project | Yes | `plan_start` or `task_close` (first archive) | Never |
|
|
200
198
|
|
|
201
199
|
### Schema validation
|
|
202
200
|
|
|
203
|
-
JSON Schema definitions for all state files are available in `conformance/state-schemas/`. The schemas cover `plan.json`, `tasks.json`, `history.json`,
|
|
201
|
+
JSON Schema definitions for all state files are available in `conformance/state-schemas/`. The schemas cover `plan.json`, `tasks.json`, `history.json`, and `agent-tracker.json`. Validate state files against these schemas in your test suite.
|
|
204
202
|
|
|
205
203
|
For full lifecycle and tool access details, see [nexus-state-overview.md](./nexus-state-overview.md) and [nexus-layout.md](./nexus-layout.md).
|
|
206
204
|
|
|
@@ -526,8 +524,8 @@ Identify the equivalent events in your harness's plugin system and implement the
|
|
|
526
524
|
**Expected consumer behavior:**
|
|
527
525
|
- Create `.nexus/` and `.nexus/state/` directories if they do not exist.
|
|
528
526
|
- Write `.nexus/.gitignore` with `state/` if it does not exist.
|
|
529
|
-
-
|
|
530
|
-
-
|
|
527
|
+
- Create `.nexus/state/{harness-id}/` if it does not exist, then initialize `.nexus/state/{harness-id}/agent-tracker.json` as `[]`. `agent-tracker.json` is a shared-purpose session file whose path is namespaced per harness to prevent cross-harness collisions (see [nexus-outputs-contract.md §Shared filename convention](./nexus-outputs-contract.md)).
|
|
528
|
+
- On v0.7.0+, harnesses SHOULD silently remove any legacy `.nexus/state/agent-tracker.json` (root) at session start. The file is session-scoped and legacy records are safely discarded.
|
|
531
529
|
- Check for stale state from a prior crashed session: if `plan.json` or `tasks.json` exist, warn the user that these may be leftover from an unclean shutdown.
|
|
532
530
|
- Load the knowledge index: list files in `.nexus/memory/`, `.nexus/context/`, and `.nexus/rules/` to build the reference index that will be injected into subagent spawns.
|
|
533
531
|
|
|
@@ -555,7 +553,7 @@ Identify the equivalent events in your harness's plugin system and implement the
|
|
|
555
553
|
**When it fires:** Lead spawns a subagent to execute a task.
|
|
556
554
|
|
|
557
555
|
**Expected consumer behavior:**
|
|
558
|
-
- Record the new agent entry in
|
|
556
|
+
- Record the new agent entry in `.nexus/state/{harness-id}/agent-tracker.json`: `{ harness_id, agent_name, agent_id, task_id, started_at }`.
|
|
559
557
|
- Inject the knowledge index into the subagent's initial context: the list of files in `.nexus/memory/`, `.nexus/context/`, and `.nexus/rules/` so the agent knows what project knowledge is available.
|
|
560
558
|
- Apply capability restrictions: resolve `effective_capabilities` for this agent type and configure the subagent's tool access accordingly (see §6).
|
|
561
559
|
- Apply the resume evaluation: check `owner_reuse_policy` on the task and the agent's `resume_tier` to determine whether to spawn fresh or resume a prior session (see §10).
|
|
@@ -568,7 +566,7 @@ Identify the equivalent events in your harness's plugin system and implement the
|
|
|
568
566
|
**When it fires:** A subagent finishes its assigned work and returns control to Lead.
|
|
569
567
|
|
|
570
568
|
**Expected consumer behavior:**
|
|
571
|
-
- Update
|
|
569
|
+
- Update `.nexus/state/{harness-id}/agent-tracker.json`: set `status=completed`, record `stopped_at` timestamp.
|
|
572
570
|
- Compute `files_touched` from your tool-log or the subagent's tool usage record. Record which files were created or modified.
|
|
573
571
|
- Update `edit-tracker.json` with the files touched by this agent. This data feeds the bounded-tier resume evaluation on subsequent spawns.
|
|
574
572
|
- Check if the completed task has pending acceptance criteria that were not verified. If the task has `acceptance` defined and no `tester` or `reviewer` subagent has been scheduled, surface a reminder to Lead.
|
|
@@ -607,7 +605,7 @@ Read-only tools (query tools, status reads) are never blocked by capability gate
|
|
|
607
605
|
**Expected consumer behavior:**
|
|
608
606
|
- Check for pending tasks: if `tasks.json` exists and contains incomplete tasks (status `pending` or `in_progress`), warn the user that the session is ending with unfinished work and suggest calling `task_close` to archive before exiting.
|
|
609
607
|
- Check for an active plan: if `plan.json` exists, warn that the plan session will be lost if not archived.
|
|
610
|
-
- Delete
|
|
608
|
+
- Delete `.nexus/state/{harness-id}/agent-tracker.json` (a session-scoped file that has no value beyond the session).
|
|
611
609
|
- Optionally rotate or archive `tool-log.jsonl` if your harness supports log retention.
|
|
612
610
|
- Do not delete `history.json`, `memory/`, `context/`, or `rules/` — these are project-scoped and must persist.
|
|
613
611
|
|
|
@@ -623,7 +621,7 @@ Read-only tools (query tools, status reads) are never blocked by capability gate
|
|
|
623
621
|
- Plan status: if `plan.json` exists, re-inject the issue list with pending/decided status.
|
|
624
622
|
- Task progress: if `tasks.json` exists, re-inject the task list with status and ready-task set.
|
|
625
623
|
- Knowledge file index: re-inject the list of files in `.nexus/memory/`, `.nexus/context/`, `.nexus/rules/`.
|
|
626
|
-
- Active agent list: re-inject which subagents are currently tracked in
|
|
624
|
+
- Active agent list: re-inject which subagents are currently tracked in `.nexus/state/{harness-id}/agent-tracker.json`.
|
|
627
625
|
- Context compaction is a context loss event. The LLM cannot reconstruct session state from its compressed context alone. Your consumer must restore state from the state files on disk.
|
|
628
626
|
- Read state files fresh from disk — do not rely on in-memory caches that may also have been cleared.
|
|
629
627
|
|
|
@@ -705,7 +703,7 @@ Before spawning an agent, evaluate whether to spawn fresh or resume a prior sess
|
|
|
705
703
|
Before attempting to resume, verify that your harness supports the resume mechanism for the current context. If the mechanism is unavailable (the harness cannot reopen a prior session, or no session ID was recorded for this agent), fall back to a fresh spawn silently. Do not surface a resume failure as an error to the user.
|
|
706
704
|
|
|
707
705
|
For `bounded` agents evaluating resume eligibility:
|
|
708
|
-
- Check
|
|
706
|
+
- Check `.nexus/state/{harness-id}/agent-tracker.json` for the prior agent ID assigned to this task.
|
|
709
707
|
- Check `edit-tracker.json` to determine if any other agent has modified the target files since the last session.
|
|
710
708
|
- If any intervening edit is found, use a fresh spawn regardless of `owner_reuse_policy`.
|
|
711
709
|
|
|
@@ -807,7 +805,7 @@ Implement tag detection in your `user_message` hook. When `[plan]` is detected,
|
|
|
807
805
|
|
|
808
806
|
| Event | Minimum required behavior |
|
|
809
807
|
|-------|--------------------------|
|
|
810
|
-
| `session_start` | Create `.nexus/state/` directory;
|
|
808
|
+
| `session_start` | Create `.nexus/state/{harness-id}/` directory; initialize `agent-tracker.json` as `[]` |
|
|
811
809
|
| `user_message` | Detect `[plan]` tag; load `skills/nx-plan/body.md`; inject into Lead's context |
|
|
812
810
|
| `session_end` | Check for `tasks.json`; if present with incomplete tasks, warn the user |
|
|
813
811
|
|
package/docs/nexus-layout.md
CHANGED
|
@@ -11,12 +11,14 @@ This document is the canonical reference for the `.nexus/` directory structure u
|
|
|
11
11
|
├── state/ ← session/branch-scoped (ephemeral)
|
|
12
12
|
│ ├── plan.json
|
|
13
13
|
│ ├── tasks.json
|
|
14
|
-
│ ├── runtime.json
|
|
15
|
-
│ ├── agent-tracker.json
|
|
16
14
|
│ ├── tool-log.jsonl
|
|
17
15
|
│ ├── edit-tracker.json
|
|
18
16
|
│ ├── reopen-tracker.json
|
|
19
|
-
│
|
|
17
|
+
│ ├── artifacts/
|
|
18
|
+
│ ├── claude-nexus/ ← harness-namespaced directory (example)
|
|
19
|
+
│ │ └── agent-tracker.json
|
|
20
|
+
│ └── opencode-nexus/ ← harness-namespaced directory (example)
|
|
21
|
+
│ └── agent-tracker.json
|
|
20
22
|
├── history.json ← project-scoped (git-tracked, append-only)
|
|
21
23
|
├── memory/ ← project-scoped (git-tracked)
|
|
22
24
|
│ └── *.md
|
|
@@ -73,29 +75,15 @@ This document is the canonical reference for the `.nexus/` directory structure u
|
|
|
73
75
|
|
|
74
76
|
---
|
|
75
77
|
|
|
76
|
-
#### `state/
|
|
78
|
+
#### `state/{harness-id}/agent-tracker.json`
|
|
77
79
|
|
|
78
|
-
**Purpose.**
|
|
80
|
+
**Purpose.** Records which subagents have been spawned in the current session, their assigned tasks, and their resume-tier classification. Each harness writes into its own subdirectory under `state/` (for example, `state/claude-nexus/` or `state/opencode-nexus/`), keeping agent-tracker records isolated across harness namespaces.
|
|
79
81
|
|
|
80
82
|
**Scope.** Session-scoped.
|
|
81
83
|
|
|
82
84
|
**Git tracking.** Ignored.
|
|
83
85
|
|
|
84
|
-
**Lifecycle.** Created
|
|
85
|
-
|
|
86
|
-
**Owner.** Harness runtime.
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
#### `state/agent-tracker.json`
|
|
91
|
-
|
|
92
|
-
**Purpose.** Records which subagents have been spawned in the current session, their assigned tasks, and their resume-tier classification.
|
|
93
|
-
|
|
94
|
-
**Scope.** Session-scoped.
|
|
95
|
-
|
|
96
|
-
**Git tracking.** Ignored.
|
|
97
|
-
|
|
98
|
-
**Lifecycle.** Created when the first subagent is spawned. Cleared at session end.
|
|
86
|
+
**Lifecycle.** Created when the first subagent is spawned in the session. The harness creates the `{harness-id}/` subdirectory if it does not already exist. Cleared at session end.
|
|
99
87
|
|
|
100
88
|
**Owner.** Harness agent-management layer.
|
|
101
89
|
|
|
@@ -18,7 +18,7 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
|
|
|
18
18
|
| 카테고리 | 책임 주체 | 예시 파일 |
|
|
19
19
|
|---|---|---|
|
|
20
20
|
| Tool-produced | MCP tool 계약 (nexus-tools-contract.md 정의) | `plan.json`, `tasks.json`, `history.json` |
|
|
21
|
-
| Harness-produced | Session hook (하네스 구현 책임) |
|
|
21
|
+
| Harness-produced | Session hook (하네스 구현 책임) | `.nexus/state/{harness-id}/agent-tracker.json` |
|
|
22
22
|
| Agent-produced (ephemeral) | `artifact_write` 도구 (에이전트가 호출) | `artifacts/*.md` (등 임의 파일명) |
|
|
23
23
|
|
|
24
24
|
카테고리 간 경계는 "누가 파일을 만드는가"로 정의된다. MCP tool이 직접 write하면 Tool-produced, 하네스 hook이 세션 초기화·종료 시 관리하면 Harness-produced, 에이전트가 `artifact_write`를 통해 기록하면 Agent-produced다.
|
|
@@ -88,27 +88,10 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
|
|
|
88
88
|
|
|
89
89
|
## Harness-produced 산출물
|
|
90
90
|
|
|
91
|
-
### `runtime.json` — 세션 런타임 메타데이터
|
|
92
|
-
|
|
93
|
-
**책임 주체**: Session hook (하네스 구현 책임). 어떤 MCP tool도 이 파일을 write해서는 안 된다.
|
|
94
|
-
|
|
95
|
-
**생성 trigger**: 하네스는 세션 초기화 시 MUST `runtime.json`을 생성해야 한다. 이 파일은 MCP tool 호출이 시작되기 전에 존재해야 한다.
|
|
96
|
-
|
|
97
|
-
**삭제 trigger**: 하네스는 세션 종료 시 MUST `runtime.json`을 삭제해야 한다.
|
|
98
|
-
|
|
99
|
-
**Schema reference**: `conformance/state-schemas/runtime.schema.json`
|
|
100
|
-
|
|
101
|
-
**Interop requirement**:
|
|
102
|
-
- 하네스는 `runtime.json`을 기록할 때 MUST `conformance/state-schemas/runtime.schema.json`에 유효한 JSON을 기록해야 한다.
|
|
103
|
-
- 다른 하네스의 session hook이 이 파일을 read할 경우 schema에 정의된 필드에만 의존해야 한다. MUST NOT schema 외부의 하네스 전용 필드에 의존해서는 안 된다.
|
|
104
|
-
- `runtime.json`은 MUST NOT git-tracked 상태로 commit되어서는 안 된다.
|
|
105
|
-
|
|
106
|
-
**Conformance fixture reference**: 해당 없음. `runtime.json`은 MCP tool behavioral fixture 범위 외에 있으며 하네스 session hook이 전적으로 책임진다.
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
91
|
### `agent-tracker.json` — 에이전트 인스턴스 추적
|
|
111
92
|
|
|
93
|
+
**경로**: `.nexus/state/{harness-id}/agent-tracker.json`
|
|
94
|
+
|
|
112
95
|
**책임 주체**: Session hook (하네스 구현 책임). 어떤 MCP tool도 이 파일에 직접 write해서는 안 된다.
|
|
113
96
|
|
|
114
97
|
**생성 trigger**: 하네스는 세션 초기화 시 MUST `agent-tracker.json`을 생성해야 한다. 파일 구조는 세션 중 에이전트 인스턴스 spawn 정보를 기록할 수 있어야 한다.
|
|
@@ -119,11 +102,15 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
|
|
|
119
102
|
|
|
120
103
|
**Interop requirement**:
|
|
121
104
|
- 하네스는 `agent-tracker.json`을 기록할 때 MUST `conformance/state-schemas/agent-tracker.schema.json`에 유효한 JSON을 기록해야 한다.
|
|
122
|
-
-
|
|
105
|
+
- MUST required 2 필드(`harness_id`, `started_at`)를 포함해야 한다.
|
|
106
|
+
- SHOULD cross-harness display/liveness를 위한 추가 필드(`agent_name`, `status`)를 제공한다.
|
|
107
|
+
- `owner_agent_id`는 MUST harness-scoped opaque string으로 취급되어야 한다 — 다른 하네스의 `agent_id`를 parse하거나 추론하는 것은 MUST NOT 허용되어서는 안 된다. `agent_id`는 하네스별 내부 식별자이며 cross-harness 해석 대상이 아니다.
|
|
123
108
|
- `agent-tracker.json`은 MUST NOT git-tracked 상태로 commit되어서는 안 된다.
|
|
124
109
|
|
|
125
110
|
**Conformance fixture reference**: 해당 없음. `agent-tracker.json`은 MCP tool behavioral fixture 범위 외에 있으며 하네스 session hook이 전적으로 책임진다.
|
|
126
111
|
|
|
112
|
+
§Shared filename convention 섹션도 참조하라.
|
|
113
|
+
|
|
127
114
|
---
|
|
128
115
|
|
|
129
116
|
## Agent-produced 산출물 (ephemeral)
|
|
@@ -161,7 +148,7 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
|
|
|
161
148
|
|
|
162
149
|
4. **append-only ledger 보전**: `history.json`은 모든 하네스 간에 MUST append-only로 처리되어야 한다. 기존 cycle 레코드를 수정하거나 삭제하는 하네스는 cross-harness 호환성 보장 대상에서 제외된다.
|
|
163
150
|
|
|
164
|
-
5. **session-scoped 파일 격리**: `plan.json`, `tasks.json`, `
|
|
151
|
+
5. **session-scoped 파일 격리**: `plan.json`, `tasks.json`, `{harness-id}/agent-tracker.json`, `artifacts/` 디렉토리는 MUST git-tracked 상태로 commit되어서는 안 된다. 이 파일들은 세션 범위에 속하며 프로젝트 영구 기록이 아니다. `agent-tracker.json`은 각 하네스의 namespace 하위(`{harness-id}/agent-tracker.json`)에 위치하지만 session-scoped 속성은 동일하게 적용된다. 하네스는 MUST `.gitignore`에 이 경로들을 포함해야 한다.
|
|
165
152
|
|
|
166
153
|
6. **Tool 이름 참조 금지**: 산출물 파일 내용 안에 harness-specific tool 이름(하네스별 MCP prefix, 하네스별 도구 식별자 등)을 MUST NOT 기록해서는 안 된다. 산출물은 harness-neutral해야 한다.
|
|
167
154
|
|
|
@@ -171,13 +158,16 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
|
|
|
171
158
|
|
|
172
159
|
하네스가 nexus-core 공통 schema로 수렴되지 않는 자체 state 파일을 필요로 할 때의 normative 규약이다.
|
|
173
160
|
|
|
174
|
-
###
|
|
161
|
+
### 4 파일 유형 분류
|
|
175
162
|
|
|
176
|
-
| 유형 | 경로 패턴 | Schema 소유 | Lifecycle 책임 |
|
|
177
|
-
|
|
178
|
-
| 공통 state | `.nexus/state/{name}.json` | nexus-core `conformance/state-schemas/` | nexus-core MCP tool |
|
|
179
|
-
|
|
|
180
|
-
| 하네스
|
|
163
|
+
| 유형 | 경로 패턴 | Schema 소유 | Lifecycle 책임 | 예시 |
|
|
164
|
+
|---|---|---|---|---|
|
|
165
|
+
| 공통 state | `.nexus/state/{name}.json` | nexus-core `conformance/state-schemas/` | nexus-core MCP tool | `plan.json`, `tasks.json` |
|
|
166
|
+
| shared-purpose 공통 state (harness-local) | `.nexus/state/{harness-id}/{shared-base}.json` | nexus-core `conformance/state-schemas/` | 하네스 session hook | `agent-tracker.json` |
|
|
167
|
+
| 하네스 extension | `.nexus/state/{harness-id}/{base}.extension.json` | 하네스 repo `state-schemas/` | 하네스 session hook | `plan.extension.json` |
|
|
168
|
+
| 하네스 독립 파일 | `.nexus/state/{harness-id}/{any}.json` | 하네스 repo `state-schemas/` | 하네스 session hook | `edit-tracker.json` |
|
|
169
|
+
|
|
170
|
+
**shared-purpose 공통 state**는 두 개 이상의 하네스가 같은 목적으로 같은 파일명을 사용하되 각자의 harness-local namespace에 두는 파일 유형이다. nexus-core가 최소 공통 schema contract를 선언하고 각 하네스 session hook이 lifecycle 책임을 진다. §Shared filename convention 섹션이 이 유형의 normative 정의를 제공한다.
|
|
181
171
|
|
|
182
172
|
### Harness-id 식별 규약
|
|
183
173
|
|
|
@@ -204,7 +194,8 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
|
|
|
204
194
|
- **MUST**: 하네스 고유 파일(독립 파일 + extension)은 모두 `.nexus/state/{harness-id}/` 하위에만 배치한다.
|
|
205
195
|
- **MUST NOT**: `.nexus/state/` 루트에 신규 하네스 파일을 추가한다.
|
|
206
196
|
- **MUST NOT**: 다른 하네스의 namespace 디렉토리에 쓰거나 읽는다.
|
|
207
|
-
- **MUST NOT**: `{harness-id}/` 하위에서 공통 schema 파일명(plan.json, tasks.json, history.json
|
|
197
|
+
- **MUST NOT**: `{harness-id}/` 하위에서 공통 schema 파일명(plan.json, tasks.json, history.json)을 재사용한다. 예: `.nexus/state/claude-nexus/plan.json` 금지.
|
|
198
|
+
- **허용**: `.nexus/state/claude-nexus/agent-tracker.json` ✓ — shared-purpose file이며 §Shared filename convention에 등록된 첫 사례. 공통 schema 파일명 재사용 금지 규칙의 예외가 아니라, shared-purpose 유형으로 별도 분류된다.
|
|
208
199
|
- **예외**: v0.3.x 이하에 루트 경로로 등록된 legacy 2종(`edit-tracker.json`, `reopen-tracker.json`)은 `task_close` tool 계약에 묶여 있어 backward-compat으로 루트 유지 허용한다. 신규 파일에는 예외 편승 금지.
|
|
209
200
|
|
|
210
201
|
### Archive 정책
|
|
@@ -224,16 +215,18 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
|
|
|
224
215
|
.nexus/state/
|
|
225
216
|
├── plan.json ← 공통, strict
|
|
226
217
|
├── tasks.json
|
|
227
|
-
├── runtime.json
|
|
228
|
-
├── agent-tracker.json
|
|
229
218
|
├── artifacts/
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
219
|
+
├── claude-nexus/ ← namespace 디렉토리
|
|
220
|
+
│ ├── agent-tracker.json ← shared-purpose file (§Shared filename convention)
|
|
221
|
+
│ ├── plan.extension.json ← plan.json의 확장 (priority, estimated_effort 등)
|
|
222
|
+
│ ├── tasks.extension.json
|
|
223
|
+
│ ├── history.extension.json ← 하네스 자체 archive
|
|
224
|
+
│ ├── edit-tracker.json ← 독립 파일
|
|
225
|
+
│ ├── reopen-tracker.json ← 독립 파일
|
|
226
|
+
│ └── tool-log.jsonl
|
|
227
|
+
└── opencode-nexus/ ← sibling 하네스 namespace 디렉토리
|
|
228
|
+
├── agent-tracker.json ← shared-purpose file (동일 파일명, harness-local)
|
|
229
|
+
└── ...
|
|
237
230
|
```
|
|
238
231
|
|
|
239
232
|
(루트 레벨 `edit-tracker.json`/`reopen-tracker.json`은 legacy carve-out으로 v0.3.x 이하 호환 유지)
|
|
@@ -250,6 +243,44 @@ consumer는 이 파일을 starting point로 삼아 자신의 실제 extension
|
|
|
250
243
|
|
|
251
244
|
---
|
|
252
245
|
|
|
246
|
+
## Shared filename convention
|
|
247
|
+
|
|
248
|
+
이 섹션은 `rule:harness-state-namespace`가 참조하는 referred source다.
|
|
249
|
+
|
|
250
|
+
### 정의
|
|
251
|
+
|
|
252
|
+
**shared-purpose file**이란 두 개 이상의 하네스가 **같은 목적**(예: agent lifecycle tracking)을 위해 **같은 파일명**으로 **각자의 harness-local namespace**에 두는 파일이다. 공통 state(`plan.json`, `tasks.json`)와 달리 단일 공유 경로가 아니라 하네스별 namespace 하위에 각각 존재한다.
|
|
253
|
+
|
|
254
|
+
nexus-core는 shared-purpose file에 대해 **최소 공통 schema contract**를 선언한다. 이 contract는 cross-harness aggregator(예: nexus-code의 Supervision UI)가 여러 하네스의 파일을 일관되게 읽을 수 있도록 보장한다.
|
|
255
|
+
|
|
256
|
+
### 최소 공통 필드 contract
|
|
257
|
+
|
|
258
|
+
| 레벨 | 필드 | 타입 / 패턴 | 설명 |
|
|
259
|
+
|---|---|---|---|
|
|
260
|
+
| MUST (required) | `harness_id` | string, pattern `^[a-z][a-z0-9-]*$` | 이 파일을 기록한 하네스 식별자 |
|
|
261
|
+
| MUST (required) | `started_at` | string, ISO 8601 | 세션 시작 시각 |
|
|
262
|
+
| SHOULD (recommended) | `agent_name` | string | cross-harness display를 위한 에이전트 표시명 |
|
|
263
|
+
| SHOULD (recommended) | `status` | string | cross-harness liveness 판단을 위한 상태값 |
|
|
264
|
+
| MAY (extension) | 하네스별 자유 필드 | — | schema `additionalProperties: false` 범위 내에서 optional로 선언된 항목만 허용 |
|
|
265
|
+
|
|
266
|
+
### agent_id opaque 속성
|
|
267
|
+
|
|
268
|
+
`owner_agent_id` 및 모든 agent 식별자 필드는 MUST harness-scoped opaque string으로 취급해야 한다. 다른 하네스가 생성한 `agent_id`를 parse하거나 내부 구조를 추론하는 것은 MUST NOT 허용되어서는 안 된다. aggregator는 `agent_id`를 display key 또는 equality check 용도로만 사용하며, 하네스별 식별자 구조에 의존해서는 안 된다.
|
|
269
|
+
|
|
270
|
+
### 등록된 shared-purpose 파일
|
|
271
|
+
|
|
272
|
+
| 파일명 | schema | 목적 | 최초 적용 |
|
|
273
|
+
|---|---|---|---|
|
|
274
|
+
| `agent-tracker.json` | `conformance/state-schemas/agent-tracker.schema.json` | 에이전트 인스턴스 lifecycle tracking | v0.7.0 |
|
|
275
|
+
|
|
276
|
+
향후 신규 shared-purpose file을 추가할 때는 반드시 이 섹션에 등록해야 한다. 등록 없이 여러 하네스가 동일 파일명을 독립적으로 사용하는 것은 MUST NOT 허용되어서는 안 된다.
|
|
277
|
+
|
|
278
|
+
### Supervision(nexus-code) aggregation 전제
|
|
279
|
+
|
|
280
|
+
nexus-code가 cross-harness aggregation을 구현할 경우, `.nexus/state/*/agent-tracker.json` glob 모델로 각 하네스의 파일을 개별적으로 읽는다. 단일 공통 경로 파일 모델이 아니다. 이 glob 모델이 동작하려면 각 하네스가 정확히 `{harness-id}/agent-tracker.json` 경로에 파일을 기록해야 한다.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
253
284
|
## Conformance 의무와의 연결
|
|
254
285
|
|
|
255
286
|
### CONSUMING.md §Conformance Obligation
|
|
@@ -260,7 +291,7 @@ fixture 통과 = schema field 100% coverage ≠ 산출물 제어 의무 이행.
|
|
|
260
291
|
|
|
261
292
|
fixture는 도구 호출의 반환값과 state file postcondition을 검증하지만, 아래 항목은 fixture만으로 검증되지 않는다.
|
|
262
293
|
|
|
263
|
-
- Harness-produced 산출물(`
|
|
294
|
+
- Harness-produced 산출물(`{harness-id}/agent-tracker.json`)의 생성·삭제 타이밍
|
|
264
295
|
- Cross-harness interop 의무(다른 하네스가 생성한 파일을 읽을 수 있는가)
|
|
265
296
|
- Forward-compatible schema 유지 의무
|
|
266
297
|
- git-tracking 격리 의무
|
|
@@ -271,7 +302,7 @@ fixture는 도구 호출의 반환값과 state file postcondition을 검증하
|
|
|
271
302
|
|
|
272
303
|
`conformance/README.md`가 정의하는 schema field coverage 의무: 모든 state-schema field는 최소 하나의 fixture의 `covers` 항목에 등장해야 한다. 이 의무는 fixture suite가 schema 전체를 검증함을 보장한다.
|
|
273
304
|
|
|
274
|
-
본 문서는 이 의무가 **Tool-produced 산출물에 대해서만** 적용됨을 명시한다. Harness-produced 산출물(`
|
|
305
|
+
본 문서는 이 의무가 **Tool-produced 산출물에 대해서만** 적용됨을 명시한다. Harness-produced 산출물(`{harness-id}/agent-tracker.json`)의 field coverage는 하네스 자체 테스트 suite의 책임이다.
|
|
275
306
|
|
|
276
307
|
schema field가 신규 추가되었을 때, nexus-core 관리자는 MUST 해당 field를 cover하는 fixture를 추가하거나 기존 fixture를 갱신해야 한다. field를 schema에 추가하면서 fixture를 갱신하지 않는 것은 coverage 의무 위반이다.
|
|
277
308
|
|
|
@@ -91,7 +91,7 @@ The Nexus state layout is divided into two categories:
|
|
|
91
91
|
|
|
92
92
|
---
|
|
93
93
|
|
|
94
|
-
### `.nexus/state/
|
|
94
|
+
### `.nexus/state/{harness-id}/agent-tracker.json`
|
|
95
95
|
|
|
96
96
|
| Attribute | Value |
|
|
97
97
|
|-----------|-------|
|
|
@@ -100,32 +100,17 @@ The Nexus state layout is divided into two categories:
|
|
|
100
100
|
| Created by | Session start (harness hook) |
|
|
101
101
|
| Deleted by | Session end (harness hook) |
|
|
102
102
|
|
|
103
|
-
**Purpose.**
|
|
103
|
+
**Purpose.** Tracks agent instance activity during the session — which agents were spawned, their instance IDs, and what artifacts they touched. Used by the harness to evaluate `owner_reuse_policy` on subsequent `task_add` calls and to support agent resume. Each harness writes its own file under a harness-specific subdirectory, keeping records isolated across harness namespaces.
|
|
104
104
|
|
|
105
|
-
**
|
|
105
|
+
**Schema.** The file contains a JSON object. Required fields: `harness_id` (string, identifies the writing harness) and `started_at` (ISO 8601 timestamp of session start). The following fields are optional: `agent_id`, `tasks`, `artifacts`, and any harness-defined extension fields.
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
**Tool access.** Read-only by the harness infrastructure. No Nexus MCP tool listed in this specification reads or writes this file directly.
|
|
110
|
-
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
### `.nexus/state/agent-tracker.json`
|
|
114
|
-
|
|
115
|
-
| Attribute | Value |
|
|
116
|
-
|-----------|-------|
|
|
117
|
-
| Scope | Session |
|
|
118
|
-
| Git-tracked | No |
|
|
119
|
-
| Created by | Session start (harness hook) |
|
|
120
|
-
| Deleted by | Session end (harness hook) |
|
|
121
|
-
|
|
122
|
-
**Purpose.** Tracks agent instance activity during the session — which agents were spawned, their instance IDs, and what artifacts they touched. Used by the harness to evaluate `owner_reuse_policy` on subsequent `task_add` calls and to support agent resume.
|
|
107
|
+
The `agent_id` field, when present, is a harness-specific opaque agent instance identifier. Its format is defined by the writing harness (for example, a UUID, a composite string, or another harness-native scheme). Consumers of this file treat the value as opaque — they do not parse it or infer agent identity across harness namespaces.
|
|
123
108
|
|
|
124
|
-
**Creation trigger.** Initialized by the harness at session start.
|
|
109
|
+
**Creation trigger.** Initialized by the harness at session start. The harness creates the `{harness-id}/` subdirectory if it does not already exist.
|
|
125
110
|
|
|
126
111
|
**Deletion trigger.** Removed by the harness upon session teardown.
|
|
127
112
|
|
|
128
|
-
**Tool access.** Managed exclusively by harness hooks. No Nexus MCP tool listed in this specification writes to this file
|
|
113
|
+
**Tool access.** Managed exclusively by harness hooks. No Nexus MCP tool listed in this specification writes to this file. When `task_add` records an `owner_agent_id` on a task, it stores the value as received from the harness without parsing or interpreting it — the value is passed through opaquely to the harness on subsequent reads.
|
|
129
114
|
|
|
130
115
|
---
|
|
131
116
|
|
package/manifest.json
CHANGED
|
@@ -1,24 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"nexus_core_version": "0.
|
|
3
|
-
"nexus_core_commit": "
|
|
2
|
+
"nexus_core_version": "0.7.0",
|
|
3
|
+
"nexus_core_commit": "ea8c194dc2e6f358317af252d3823d3f58ce757d",
|
|
4
4
|
"schema_contract_version": "2.0",
|
|
5
5
|
"agents": [
|
|
6
|
-
{
|
|
7
|
-
"name": "designer",
|
|
8
|
-
"description": "UX/UI design — evaluates user experience, interaction patterns, and how users will experience the product",
|
|
9
|
-
"task": "UI/UX design, interaction patterns, user experience",
|
|
10
|
-
"alias_ko": "디자이너",
|
|
11
|
-
"category": "how",
|
|
12
|
-
"resume_tier": "persistent",
|
|
13
|
-
"model_tier": "high",
|
|
14
|
-
"capabilities": [
|
|
15
|
-
"no_file_edit",
|
|
16
|
-
"no_task_create",
|
|
17
|
-
"no_task_update"
|
|
18
|
-
],
|
|
19
|
-
"id": "designer",
|
|
20
|
-
"body_hash": "sha256:88ac56147d0e5bdf23fa591ce570a9c2d0eb1338df4ec2219f6238ddfcb65df4"
|
|
21
|
-
},
|
|
22
6
|
{
|
|
23
7
|
"name": "architect",
|
|
24
8
|
"description": "Technical design — evaluates How, reviews architecture, advises on implementation approach",
|
|
@@ -35,6 +19,20 @@
|
|
|
35
19
|
"id": "architect",
|
|
36
20
|
"body_hash": "sha256:85f9a3de419f32cdae284436eb1d902bff19a2230c50fe3068ffc642949a63b7"
|
|
37
21
|
},
|
|
22
|
+
{
|
|
23
|
+
"name": "engineer",
|
|
24
|
+
"description": "Implementation — writes code, debugs issues, follows specifications from Lead and architect",
|
|
25
|
+
"task": "Code implementation, edits, debugging",
|
|
26
|
+
"alias_ko": "엔지니어",
|
|
27
|
+
"category": "do",
|
|
28
|
+
"resume_tier": "bounded",
|
|
29
|
+
"model_tier": "standard",
|
|
30
|
+
"capabilities": [
|
|
31
|
+
"no_task_create"
|
|
32
|
+
],
|
|
33
|
+
"id": "engineer",
|
|
34
|
+
"body_hash": "sha256:3d58b1b490c2f93cace2eedd0f04ec000f84514388eb086768cf53f8fa33db01"
|
|
35
|
+
},
|
|
38
36
|
{
|
|
39
37
|
"name": "reviewer",
|
|
40
38
|
"description": "Content verification — validates accuracy, checks facts, confirms grammar and format of non-code deliverables",
|
|
@@ -50,6 +48,21 @@
|
|
|
50
48
|
"id": "reviewer",
|
|
51
49
|
"body_hash": "sha256:f04d15249601b14046e7e40a4475defb289436c4474afbd89986964f8c3e7c2f"
|
|
52
50
|
},
|
|
51
|
+
{
|
|
52
|
+
"name": "researcher",
|
|
53
|
+
"description": "Independent investigation — conducts web searches, gathers evidence, and reports findings with citations",
|
|
54
|
+
"task": "Web search, independent investigation",
|
|
55
|
+
"alias_ko": "리서처",
|
|
56
|
+
"category": "do",
|
|
57
|
+
"resume_tier": "persistent",
|
|
58
|
+
"model_tier": "standard",
|
|
59
|
+
"capabilities": [
|
|
60
|
+
"no_file_edit",
|
|
61
|
+
"no_task_create"
|
|
62
|
+
],
|
|
63
|
+
"id": "researcher",
|
|
64
|
+
"body_hash": "sha256:fc79bafec05503327bd51a0b84b6e642d304bd79c45b78db6448b112793c143e"
|
|
65
|
+
},
|
|
53
66
|
{
|
|
54
67
|
"name": "strategist",
|
|
55
68
|
"description": "Business strategy — evaluates market positioning, competitive landscape, and business viability of decisions",
|
|
@@ -67,18 +80,20 @@
|
|
|
67
80
|
"body_hash": "sha256:0254b4144a22c66209bd68119553d9057a4fb7f9b1ff7ebb9878687d99583465"
|
|
68
81
|
},
|
|
69
82
|
{
|
|
70
|
-
"name": "
|
|
71
|
-
"description": "
|
|
72
|
-
"task": "
|
|
73
|
-
"alias_ko": "
|
|
74
|
-
"category": "
|
|
75
|
-
"resume_tier": "
|
|
76
|
-
"model_tier": "
|
|
83
|
+
"name": "designer",
|
|
84
|
+
"description": "UX/UI design — evaluates user experience, interaction patterns, and how users will experience the product",
|
|
85
|
+
"task": "UI/UX design, interaction patterns, user experience",
|
|
86
|
+
"alias_ko": "디자이너",
|
|
87
|
+
"category": "how",
|
|
88
|
+
"resume_tier": "persistent",
|
|
89
|
+
"model_tier": "high",
|
|
77
90
|
"capabilities": [
|
|
78
|
-
"
|
|
91
|
+
"no_file_edit",
|
|
92
|
+
"no_task_create",
|
|
93
|
+
"no_task_update"
|
|
79
94
|
],
|
|
80
|
-
"id": "
|
|
81
|
-
"body_hash": "sha256:
|
|
95
|
+
"id": "designer",
|
|
96
|
+
"body_hash": "sha256:88ac56147d0e5bdf23fa591ce570a9c2d0eb1338df4ec2219f6238ddfcb65df4"
|
|
82
97
|
},
|
|
83
98
|
{
|
|
84
99
|
"name": "postdoc",
|
|
@@ -111,21 +126,6 @@
|
|
|
111
126
|
"id": "tester",
|
|
112
127
|
"body_hash": "sha256:4dd04e1c93ff9c0c9fa6aebb60ece3f9719e82f9714b13feea01b6163633caec"
|
|
113
128
|
},
|
|
114
|
-
{
|
|
115
|
-
"name": "researcher",
|
|
116
|
-
"description": "Independent investigation — conducts web searches, gathers evidence, and reports findings with citations",
|
|
117
|
-
"task": "Web search, independent investigation",
|
|
118
|
-
"alias_ko": "리서처",
|
|
119
|
-
"category": "do",
|
|
120
|
-
"resume_tier": "persistent",
|
|
121
|
-
"model_tier": "standard",
|
|
122
|
-
"capabilities": [
|
|
123
|
-
"no_file_edit",
|
|
124
|
-
"no_task_create"
|
|
125
|
-
],
|
|
126
|
-
"id": "researcher",
|
|
127
|
-
"body_hash": "sha256:fc79bafec05503327bd51a0b84b6e642d304bd79c45b78db6448b112793c143e"
|
|
128
|
-
},
|
|
129
129
|
{
|
|
130
130
|
"name": "writer",
|
|
131
131
|
"description": "Technical writing — transforms research findings, code, and analysis into clear documents and presentations for the intended audience",
|
package/package.json
CHANGED
|
@@ -1,32 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
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,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "conformance/state-schemas/runtime.schema.json",
|
|
4
|
-
"title": "Nexus Runtime State",
|
|
5
|
-
"description": "Schema for .nexus/state/runtime.json — ephemeral runtime configuration written by the harness at session start",
|
|
6
|
-
"type": "object",
|
|
7
|
-
"additionalProperties": false,
|
|
8
|
-
"required": ["teams_enabled", "session_started_at", "harness_id", "harness_version"],
|
|
9
|
-
"properties": {
|
|
10
|
-
"schema_version": {
|
|
11
|
-
"type": "string",
|
|
12
|
-
"pattern": "^\\d+\\.\\d+$",
|
|
13
|
-
"description": "nexus-core version that introduced this schema shape (e.g. '0.5'). Optional in v0.5.0 — candidate for required in v1.0.0 (Phase 2 entry)."
|
|
14
|
-
},
|
|
15
|
-
"teams_enabled": {
|
|
16
|
-
"type": "boolean",
|
|
17
|
-
"description": "Whether multi-agent team orchestration is active in this session"
|
|
18
|
-
},
|
|
19
|
-
"session_started_at": {
|
|
20
|
-
"type": "string",
|
|
21
|
-
"format": "date-time",
|
|
22
|
-
"description": "ISO 8601 timestamp when the current harness session was started"
|
|
23
|
-
},
|
|
24
|
-
"harness_id": {
|
|
25
|
-
"type": "string",
|
|
26
|
-
"pattern": "^[a-z][a-z0-9-]*$",
|
|
27
|
-
"description": "Identifier of the harness that owns this runtime state (e.g. 'claude-nexus', 'opencode-nexus'). Free string — nexus-core does not enumerate harnesses."
|
|
28
|
-
},
|
|
29
|
-
"harness_version": {
|
|
30
|
-
"type": "string",
|
|
31
|
-
"description": "Semver-like version string of the harness plugin that wrote this file."
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|