@moreih29/nexus-core 0.6.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.
@@ -136,7 +136,7 @@ Event fixture는 "harness가 특정 event를 실행한 후 state 파일의 구
136
136
  },
137
137
  "postcondition": {
138
138
  "state_files": {
139
- ".nexus/state/agent-tracker.json": { "$[0].status": "running" }
139
+ "{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json": { "$[0].status": "running" }
140
140
  }
141
141
  }
142
142
  }
@@ -167,6 +167,7 @@ Assertions are key/value objects where keys are JSONPath expressions and values
167
167
  | `"$.field": { "type": "string", "minLength": 5 }` | String with minimum length |
168
168
  | `".nexus/state/plan.json": null` | File must not exist |
169
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. |
170
171
 
171
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`.
172
173
 
@@ -230,14 +231,14 @@ exit code 2는 파일 파싱 등 fatal error를 의미한다.
230
231
  A conformance test runner does the following for each fixture:
231
232
 
232
233
  1. **Load** the fixture JSON file.
233
- 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.
234
235
  3. **Execute**:
235
236
  - For single-action fixtures: call the tool named by `action.tool` with `action.params`.
236
237
  - For event fixtures: trigger the harness session hook for the event type specified by `event.type`, passing `event.params`.
237
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.
238
239
  4. **Evaluate postconditions**:
239
240
  - Check `postcondition.return_value` assertions against the tool's return value.
240
- - 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`:
241
242
  - Value is `null` → assert the file does NOT exist.
242
243
  - Value is an empty object `{}` → assert the file EXISTS; do NOT parse content (use for non-JSON artifacts: .md, .txt, binary).
243
244
  - Value is a non-empty object `{...}` → parse file as JSON and evaluate each JSONPath assertion against the parsed content.
@@ -13,3 +13,30 @@
13
13
  ## Tool-action 대신 Event 트리거 사용
14
14
 
15
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
- ".nexus/state/agent-tracker.json": [
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
- ".nexus/state/agent-tracker.json": {
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
- ".nexus/state/agent-tracker.json": [
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
- ".nexus/state/agent-tracker.json": {
30
+ "{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json": {
31
31
  "$.length": 1,
32
32
  "$[0].status": "running",
33
33
  "$[0].resume_count": 1,
@@ -3,7 +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
- ".nexus/state/agent-tracker.json": []
6
+ "{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json": []
7
7
  }
8
8
  },
9
9
  "event": {
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "postcondition": {
19
19
  "state_files": {
20
- ".nexus/state/agent-tracker.json": {
20
+ "{STATE_ROOT}/{HARNESS_ID}/agent-tracker.json": {
21
21
  "$.length": 1,
22
22
  "$[0].harness_id": "claude-nexus",
23
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" },
@@ -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", "agent_name", "agent_id", "started_at", "resume_count", "status"],
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": "Unique agent instance identifier (UUID)"
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",
@@ -159,11 +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
- │ ├── agent-tracker.json
163
162
  │ ├── tool-log.jsonl
164
163
  │ ├── edit-tracker.json
165
164
  │ ├── reopen-tracker.json
166
- └── artifacts/
165
+ ├── artifacts/
166
+ │ └── {harness-id}/ ← harness namespace (see §Harness-local State Extension)
167
+ │ └── agent-tracker.json
167
168
  ├── history.json ← project-scoped (git-tracked, append-only)
168
169
  ├── memory/ ← project-scoped (git-tracked)
169
170
  │ └── *.md
@@ -181,7 +182,7 @@ At session start, your harness must:
181
182
  1. Create `.nexus/` if it does not exist.
182
183
  2. Create `.nexus/state/` if it does not exist.
183
184
  3. Write `.nexus/.gitignore` with content `state/` if the file does not exist.
184
- 4. Initialize `.nexus/state/agent-tracker.json` as an empty array `[]`.
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.)
185
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.
186
187
 
187
188
  ### Key state files
@@ -190,7 +191,7 @@ At session start, your harness must:
190
191
  |------|-------|------------|------------|------------|
191
192
  | `state/plan.json` | Session | No | `plan_start` tool | `task_close` tool |
192
193
  | `state/tasks.json` | Session | No | `task_add` tool (first call) | `task_close` tool |
193
- | `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 |
194
195
  | `state/tool-log.jsonl` | Session | No | post_tool_use hook | session_end hook |
195
196
  | `state/edit-tracker.json` | Session | No | post_tool_use hook (first edit) | task_close / session_end |
196
197
  | `history.json` | Project | Yes | `plan_start` or `task_close` (first archive) | Never |
@@ -523,7 +524,8 @@ Identify the equivalent events in your harness's plugin system and implement the
523
524
  **Expected consumer behavior:**
524
525
  - Create `.nexus/` and `.nexus/state/` directories if they do not exist.
525
526
  - Write `.nexus/.gitignore` with `state/` if it does not exist.
526
- - Initialize `.nexus/state/agent-tracker.json` as `[]`.
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.
527
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.
528
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.
529
531
 
@@ -551,7 +553,7 @@ Identify the equivalent events in your harness's plugin system and implement the
551
553
  **When it fires:** Lead spawns a subagent to execute a task.
552
554
 
553
555
  **Expected consumer behavior:**
554
- - Record the new agent entry in `agent-tracker.json`: `{ harness_id, agent_name, agent_id, task_id, started_at }`.
556
+ - Record the new agent entry in `.nexus/state/{harness-id}/agent-tracker.json`: `{ harness_id, agent_name, agent_id, task_id, started_at }`.
555
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.
556
558
  - Apply capability restrictions: resolve `effective_capabilities` for this agent type and configure the subagent's tool access accordingly (see §6).
557
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).
@@ -564,7 +566,7 @@ Identify the equivalent events in your harness's plugin system and implement the
564
566
  **When it fires:** A subagent finishes its assigned work and returns control to Lead.
565
567
 
566
568
  **Expected consumer behavior:**
567
- - Update `agent-tracker.json`: set `status=completed`, record `stopped_at` timestamp.
569
+ - Update `.nexus/state/{harness-id}/agent-tracker.json`: set `status=completed`, record `stopped_at` timestamp.
568
570
  - Compute `files_touched` from your tool-log or the subagent's tool usage record. Record which files were created or modified.
569
571
  - Update `edit-tracker.json` with the files touched by this agent. This data feeds the bounded-tier resume evaluation on subsequent spawns.
570
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.
@@ -603,7 +605,7 @@ Read-only tools (query tools, status reads) are never blocked by capability gate
603
605
  **Expected consumer behavior:**
604
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.
605
607
  - Check for an active plan: if `plan.json` exists, warn that the plan session will be lost if not archived.
606
- - Delete `agent-tracker.json` (a session-scoped file that has no value beyond the session).
608
+ - Delete `.nexus/state/{harness-id}/agent-tracker.json` (a session-scoped file that has no value beyond the session).
607
609
  - Optionally rotate or archive `tool-log.jsonl` if your harness supports log retention.
608
610
  - Do not delete `history.json`, `memory/`, `context/`, or `rules/` — these are project-scoped and must persist.
609
611
 
@@ -619,7 +621,7 @@ Read-only tools (query tools, status reads) are never blocked by capability gate
619
621
  - Plan status: if `plan.json` exists, re-inject the issue list with pending/decided status.
620
622
  - Task progress: if `tasks.json` exists, re-inject the task list with status and ready-task set.
621
623
  - Knowledge file index: re-inject the list of files in `.nexus/memory/`, `.nexus/context/`, `.nexus/rules/`.
622
- - Active agent list: re-inject which subagents are currently tracked in `agent-tracker.json`.
624
+ - Active agent list: re-inject which subagents are currently tracked in `.nexus/state/{harness-id}/agent-tracker.json`.
623
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.
624
626
  - Read state files fresh from disk — do not rely on in-memory caches that may also have been cleared.
625
627
 
@@ -701,7 +703,7 @@ Before spawning an agent, evaluate whether to spawn fresh or resume a prior sess
701
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.
702
704
 
703
705
  For `bounded` agents evaluating resume eligibility:
704
- - Check `agent-tracker.json` for the prior agent ID assigned to this task.
706
+ - Check `.nexus/state/{harness-id}/agent-tracker.json` for the prior agent ID assigned to this task.
705
707
  - Check `edit-tracker.json` to determine if any other agent has modified the target files since the last session.
706
708
  - If any intervening edit is found, use a fresh spawn regardless of `owner_reuse_policy`.
707
709
 
@@ -803,7 +805,7 @@ Implement tag detection in your `user_message` hook. When `[plan]` is detected,
803
805
 
804
806
  | Event | Minimum required behavior |
805
807
  |-------|--------------------------|
806
- | `session_start` | Create `.nexus/state/` directory; initialize `agent-tracker.json` as `[]` |
808
+ | `session_start` | Create `.nexus/state/{harness-id}/` directory; initialize `agent-tracker.json` as `[]` |
807
809
  | `user_message` | Detect `[plan]` tag; load `skills/nx-plan/body.md`; inject into Lead's context |
808
810
  | `session_end` | Check for `tasks.json`; if present with incomplete tasks, warn the user |
809
811
 
@@ -11,11 +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
- │ ├── agent-tracker.json
15
14
  │ ├── tool-log.jsonl
16
15
  │ ├── edit-tracker.json
17
16
  │ ├── reopen-tracker.json
18
- └── artifacts/
17
+ ├── artifacts/
18
+ │ ├── claude-nexus/ ← harness-namespaced directory (example)
19
+ │ │ └── agent-tracker.json
20
+ │ └── opencode-nexus/ ← harness-namespaced directory (example)
21
+ │ └── agent-tracker.json
19
22
  ├── history.json ← project-scoped (git-tracked, append-only)
20
23
  ├── memory/ ← project-scoped (git-tracked)
21
24
  │ └── *.md
@@ -72,15 +75,15 @@ This document is the canonical reference for the `.nexus/` directory structure u
72
75
 
73
76
  ---
74
77
 
75
- #### `state/agent-tracker.json`
78
+ #### `state/{harness-id}/agent-tracker.json`
76
79
 
77
- **Purpose.** Records which subagents have been spawned in the current session, their assigned tasks, and their resume-tier classification.
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.
78
81
 
79
82
  **Scope.** Session-scoped.
80
83
 
81
84
  **Git tracking.** Ignored.
82
85
 
83
- **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.
84
87
 
85
88
  **Owner.** Harness agent-management layer.
86
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 (하네스 구현 책임) | `agent-tracker.json` |
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다.
@@ -90,6 +90,8 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
90
90
 
91
91
  ### `agent-tracker.json` — 에이전트 인스턴스 추적
92
92
 
93
+ **경로**: `.nexus/state/{harness-id}/agent-tracker.json`
94
+
93
95
  **책임 주체**: Session hook (하네스 구현 책임). 어떤 MCP tool도 이 파일에 직접 write해서는 안 된다.
94
96
 
95
97
  **생성 trigger**: 하네스는 세션 초기화 시 MUST `agent-tracker.json`을 생성해야 한다. 파일 구조는 세션 중 에이전트 인스턴스 spawn 정보를 기록할 수 있어야 한다.
@@ -100,11 +102,15 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
100
102
 
101
103
  **Interop requirement**:
102
104
  - 하네스는 `agent-tracker.json`을 기록할 때 MUST `conformance/state-schemas/agent-tracker.schema.json`에 유효한 JSON을 기록해야 한다.
103
- - `task_add` 도구가 `owner_agent_id` 필드를 읽어 harness에 전달하는 방식으로 간접 연계된다. 하네스는 이 연계가 동작하도록 MUST `owner_agent_id` 기반 agent 재개 로직을 구현해야 한다.
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 해석 대상이 아니다.
104
108
  - `agent-tracker.json`은 MUST NOT git-tracked 상태로 commit되어서는 안 된다.
105
109
 
106
110
  **Conformance fixture reference**: 해당 없음. `agent-tracker.json`은 MCP tool behavioral fixture 범위 외에 있으며 하네스 session hook이 전적으로 책임진다.
107
111
 
112
+ §Shared filename convention 섹션도 참조하라.
113
+
108
114
  ---
109
115
 
110
116
  ## Agent-produced 산출물 (ephemeral)
@@ -142,7 +148,7 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
142
148
 
143
149
  4. **append-only ledger 보전**: `history.json`은 모든 하네스 간에 MUST append-only로 처리되어야 한다. 기존 cycle 레코드를 수정하거나 삭제하는 하네스는 cross-harness 호환성 보장 대상에서 제외된다.
144
150
 
145
- 5. **session-scoped 파일 격리**: `plan.json`, `tasks.json`, `agent-tracker.json`, `artifacts/` 디렉토리는 MUST git-tracked 상태로 commit되어서는 안 된다. 이 파일들은 세션 범위에 속하며 프로젝트 영구 기록이 아니다. 하네스는 MUST `.gitignore`에 이 경로들을 포함해야 한다.
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`에 이 경로들을 포함해야 한다.
146
152
 
147
153
  6. **Tool 이름 참조 금지**: 산출물 파일 내용 안에 harness-specific tool 이름(하네스별 MCP prefix, 하네스별 도구 식별자 등)을 MUST NOT 기록해서는 안 된다. 산출물은 harness-neutral해야 한다.
148
154
 
@@ -152,13 +158,16 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
152
158
 
153
159
  하네스가 nexus-core 공통 schema로 수렴되지 않는 자체 state 파일을 필요로 할 때의 normative 규약이다.
154
160
 
155
- ### 3 파일 유형 분류
161
+ ### 4 파일 유형 분류
156
162
 
157
- | 유형 | 경로 패턴 | Schema 소유 | Lifecycle 책임 |
158
- |---|---|---|---|
159
- | 공통 state | `.nexus/state/{name}.json` | nexus-core `conformance/state-schemas/` | nexus-core MCP tool |
160
- | 하네스 extension | `.nexus/state/{harness-id}/{base}.extension.json` | 하네스 repo `state-schemas/` | 하네스 session hook |
161
- | 하네스 독립 파일 | `.nexus/state/{harness-id}/{any}.json` | 하네스 repo `state-schemas/` | 하네스 session hook |
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 정의를 제공한다.
162
171
 
163
172
  ### Harness-id 식별 규약
164
173
 
@@ -185,7 +194,8 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
185
194
  - **MUST**: 하네스 고유 파일(독립 파일 + extension)은 모두 `.nexus/state/{harness-id}/` 하위에만 배치한다.
186
195
  - **MUST NOT**: `.nexus/state/` 루트에 신규 하네스 파일을 추가한다.
187
196
  - **MUST NOT**: 다른 하네스의 namespace 디렉토리에 쓰거나 읽는다.
188
- - **MUST NOT**: `{harness-id}/` 하위에서 공통 schema 파일명(plan.json, tasks.json, history.json, agent-tracker.json)을 재사용한다. 예: `.nexus/state/claude-nexus/plan.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 유형으로 별도 분류된다.
189
199
  - **예외**: v0.3.x 이하에 루트 경로로 등록된 legacy 2종(`edit-tracker.json`, `reopen-tracker.json`)은 `task_close` tool 계약에 묶여 있어 backward-compat으로 루트 유지 허용한다. 신규 파일에는 예외 편승 금지.
190
200
 
191
201
  ### Archive 정책
@@ -205,15 +215,18 @@ Nexus 산출물은 생성 책임 주체에 따라 세 카테고리로 분류된
205
215
  .nexus/state/
206
216
  ├── plan.json ← 공통, strict
207
217
  ├── tasks.json
208
- ├── agent-tracker.json
209
218
  ├── artifacts/
210
- └── claude-nexus/ ← namespace 디렉토리
211
- ├── plan.extension.json plan.json의 확장 (priority, estimated_effort )
212
- ├── tasks.extension.json
213
- ├── history.extension.json ← 하네스 자체 archive
214
- ├── edit-tracker.json 독립 파일
215
- ├── reopen-tracker.json ← 독립 파일
216
- └── tool-log.jsonl
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
+ └── ...
217
230
  ```
218
231
 
219
232
  (루트 레벨 `edit-tracker.json`/`reopen-tracker.json`은 legacy carve-out으로 v0.3.x 이하 호환 유지)
@@ -230,6 +243,44 @@ consumer는 이 파일을 starting point로 삼아 자신의 실제 extension
230
243
 
231
244
  ---
232
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
+
233
284
  ## Conformance 의무와의 연결
234
285
 
235
286
  ### CONSUMING.md §Conformance Obligation
@@ -240,7 +291,7 @@ fixture 통과 = schema field 100% coverage ≠ 산출물 제어 의무 이행.
240
291
 
241
292
  fixture는 도구 호출의 반환값과 state file postcondition을 검증하지만, 아래 항목은 fixture만으로 검증되지 않는다.
242
293
 
243
- - Harness-produced 산출물(`agent-tracker.json`)의 생성·삭제 타이밍
294
+ - Harness-produced 산출물(`{harness-id}/agent-tracker.json`)의 생성·삭제 타이밍
244
295
  - Cross-harness interop 의무(다른 하네스가 생성한 파일을 읽을 수 있는가)
245
296
  - Forward-compatible schema 유지 의무
246
297
  - git-tracking 격리 의무
@@ -251,7 +302,7 @@ fixture는 도구 호출의 반환값과 state file postcondition을 검증하
251
302
 
252
303
  `conformance/README.md`가 정의하는 schema field coverage 의무: 모든 state-schema field는 최소 하나의 fixture의 `covers` 항목에 등장해야 한다. 이 의무는 fixture suite가 schema 전체를 검증함을 보장한다.
253
304
 
254
- 본 문서는 이 의무가 **Tool-produced 산출물에 대해서만** 적용됨을 명시한다. Harness-produced 산출물(`agent-tracker.json`)의 field coverage는 하네스 자체 테스트 suite의 책임이다.
305
+ 본 문서는 이 의무가 **Tool-produced 산출물에 대해서만** 적용됨을 명시한다. Harness-produced 산출물(`{harness-id}/agent-tracker.json`)의 field coverage는 하네스 자체 테스트 suite의 책임이다.
255
306
 
256
307
  schema field가 신규 추가되었을 때, nexus-core 관리자는 MUST 해당 field를 cover하는 fixture를 추가하거나 기존 fixture를 갱신해야 한다. field를 schema에 추가하면서 fixture를 갱신하지 않는 것은 coverage 의무 위반이다.
257
308
 
@@ -91,7 +91,7 @@ The Nexus state layout is divided into two categories:
91
91
 
92
92
  ---
93
93
 
94
- ### `.nexus/state/agent-tracker.json`
94
+ ### `.nexus/state/{harness-id}/agent-tracker.json`
95
95
 
96
96
  | Attribute | Value |
97
97
  |-----------|-------|
@@ -100,13 +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.** 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.
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
- **Creation trigger.** Initialized by the harness at session start.
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
+
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.
108
+
109
+ **Creation trigger.** Initialized by the harness at session start. The harness creates the `{harness-id}/` subdirectory if it does not already exist.
106
110
 
107
111
  **Deletion trigger.** Removed by the harness upon session teardown.
108
112
 
109
- **Tool access.** Managed exclusively by harness hooks. No Nexus MCP tool listed in this specification writes to this file; `task_add` reads the `owner_agent_id` field from tasks to inform the harness, but does not access `agent-tracker.json` directly.
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.
110
114
 
111
115
  ---
112
116
 
package/manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "nexus_core_version": "0.6.0",
3
- "nexus_core_commit": "bcde383b56308b86006babe73f87fed9222c0761",
2
+ "nexus_core_version": "0.7.0",
3
+ "nexus_core_commit": "ea8c194dc2e6f358317af252d3823d3f58ce757d",
4
4
  "schema_contract_version": "2.0",
5
5
  "agents": [
6
6
  {
@@ -19,6 +19,20 @@
19
19
  "id": "architect",
20
20
  "body_hash": "sha256:85f9a3de419f32cdae284436eb1d902bff19a2230c50fe3068ffc642949a63b7"
21
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
+ },
22
36
  {
23
37
  "name": "reviewer",
24
38
  "description": "Content verification — validates accuracy, checks facts, confirms grammar and format of non-code deliverables",
@@ -35,20 +49,19 @@
35
49
  "body_hash": "sha256:f04d15249601b14046e7e40a4475defb289436c4474afbd89986964f8c3e7c2f"
36
50
  },
37
51
  {
38
- "name": "designer",
39
- "description": "UX/UI designevaluates user experience, interaction patterns, and how users will experience the product",
40
- "task": "UI/UX design, interaction patterns, user experience",
41
- "alias_ko": "디자이너",
42
- "category": "how",
52
+ "name": "researcher",
53
+ "description": "Independent investigationconducts web searches, gathers evidence, and reports findings with citations",
54
+ "task": "Web search, independent investigation",
55
+ "alias_ko": "리서처",
56
+ "category": "do",
43
57
  "resume_tier": "persistent",
44
- "model_tier": "high",
58
+ "model_tier": "standard",
45
59
  "capabilities": [
46
60
  "no_file_edit",
47
- "no_task_create",
48
- "no_task_update"
61
+ "no_task_create"
49
62
  ],
50
- "id": "designer",
51
- "body_hash": "sha256:88ac56147d0e5bdf23fa591ce570a9c2d0eb1338df4ec2219f6238ddfcb65df4"
63
+ "id": "researcher",
64
+ "body_hash": "sha256:fc79bafec05503327bd51a0b84b6e642d304bd79c45b78db6448b112793c143e"
52
65
  },
53
66
  {
54
67
  "name": "strategist",
@@ -67,33 +80,20 @@
67
80
  "body_hash": "sha256:0254b4144a22c66209bd68119553d9057a4fb7f9b1ff7ebb9878687d99583465"
68
81
  },
69
82
  {
70
- "name": "engineer",
71
- "description": "Implementationwrites code, debugs issues, follows specifications from Lead and architect",
72
- "task": "Code implementation, edits, debugging",
73
- "alias_ko": "엔지니어",
74
- "category": "do",
75
- "resume_tier": "bounded",
76
- "model_tier": "standard",
77
- "capabilities": [
78
- "no_task_create"
79
- ],
80
- "id": "engineer",
81
- "body_hash": "sha256:3d58b1b490c2f93cace2eedd0f04ec000f84514388eb086768cf53f8fa33db01"
82
- },
83
- {
84
- "name": "researcher",
85
- "description": "Independent investigation — conducts web searches, gathers evidence, and reports findings with citations",
86
- "task": "Web search, independent investigation",
87
- "alias_ko": "리서처",
88
- "category": "do",
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",
89
88
  "resume_tier": "persistent",
90
- "model_tier": "standard",
89
+ "model_tier": "high",
91
90
  "capabilities": [
92
91
  "no_file_edit",
93
- "no_task_create"
92
+ "no_task_create",
93
+ "no_task_update"
94
94
  ],
95
- "id": "researcher",
96
- "body_hash": "sha256:fc79bafec05503327bd51a0b84b6e642d304bd79c45b78db6448b112793c143e"
95
+ "id": "designer",
96
+ "body_hash": "sha256:88ac56147d0e5bdf23fa591ce570a9c2d0eb1338df4ec2219f6238ddfcb65df4"
97
97
  },
98
98
  {
99
99
  "name": "postdoc",
@@ -155,6 +155,19 @@
155
155
  "id": "nx-run",
156
156
  "body_hash": "sha256:6c8d1a36626d4034209ff83780dec6238297ec4710612441b2ef09daac714ca8"
157
157
  },
158
+ {
159
+ "name": "nx-plan",
160
+ "description": "Structured multi-perspective analysis to decompose issues, align on decisions, and produce an enriched plan before execution. Plan only — does not execute.",
161
+ "summary": "Structured planning — subagent-based analysis, deliberate decisions, produce execution plan",
162
+ "triggers": [
163
+ "plan"
164
+ ],
165
+ "harness_docs_refs": [
166
+ "resume_invocation"
167
+ ],
168
+ "id": "nx-plan",
169
+ "body_hash": "sha256:85b858089bd3dc276be61baa3f5265bc107a85470f169983e710fecb404bb4b1"
170
+ },
158
171
  {
159
172
  "name": "nx-sync",
160
173
  "description": "Context knowledge synchronization — scans project state and updates .nexus/context/ design documents",
@@ -175,19 +188,6 @@
175
188
  ],
176
189
  "id": "nx-init",
177
190
  "body_hash": "sha256:3c8230ecc0f87c541ec0ff80492a28f28bf173d0b9781901adadfae69a54b8ed"
178
- },
179
- {
180
- "name": "nx-plan",
181
- "description": "Structured multi-perspective analysis to decompose issues, align on decisions, and produce an enriched plan before execution. Plan only — does not execute.",
182
- "summary": "Structured planning — subagent-based analysis, deliberate decisions, produce execution plan",
183
- "triggers": [
184
- "plan"
185
- ],
186
- "harness_docs_refs": [
187
- "resume_invocation"
188
- ],
189
- "id": "nx-plan",
190
- "body_hash": "sha256:85b858089bd3dc276be61baa3f5265bc107a85470f169983e710fecb404bb4b1"
191
191
  }
192
192
  ],
193
193
  "vocabulary": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moreih29/nexus-core",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Nexus ecosystem Authoring layer — canonical prompts, neutral metadata, and vocabulary shared by Nexus harnesses",
5
5
  "license": "MIT",
6
6
  "repository": {