claude-nexus 0.26.0 → 0.26.2
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.en.md +5 -5
- package/README.md +5 -5
- package/VERSION +1 -1
- package/bridge/mcp-server.cjs +12 -27
- package/bridge/mcp-server.cjs.map +2 -2
- package/package.json +2 -2
- package/scripts/gate.cjs +64 -85
- package/scripts/gate.cjs.map +4 -4
- package/scripts/statusline.cjs +2 -0
- package/scripts/statusline.cjs.map +2 -2
package/README.en.md
CHANGED
|
@@ -128,7 +128,7 @@ Nexus registers a single Gate module as a Claude Code hook.
|
|
|
128
128
|
|
|
129
129
|
| Event | Role |
|
|
130
130
|
|-------|------|
|
|
131
|
-
| `SessionStart` | Initialize `.nexus/` structure, reset agent-tracker,
|
|
131
|
+
| `SessionStart` | Initialize `.nexus/` structure, reset agent-tracker, init `tool-log.jsonl` |
|
|
132
132
|
| `UserPromptSubmit` | Tag detection → mode activation + TASK_PIPELINE injection + additionalContext guidance |
|
|
133
133
|
| `PreToolUse` | Edit/Write: blocks when incomplete tasks exist |
|
|
134
134
|
| `PostToolUse` | On Edit/Write/NotebookEdit, append subagent file edits to `tool-log.jsonl` (only when agent_id present) |
|
|
@@ -168,10 +168,10 @@ Runtime state is stored under `.nexus/state/` and is excluded from git.
|
|
|
168
168
|
.nexus/state/
|
|
169
169
|
├── tasks.json ← Task list ([run] cycle)
|
|
170
170
|
├── plan.json ← Planning session ([plan] cycle)
|
|
171
|
-
|
|
172
|
-
├──
|
|
173
|
-
├── tool-log.jsonl ← Subagent Edit/Write/NotebookEdit call log (append-only)
|
|
174
|
-
└── artifacts/ ← Artifacts
|
|
171
|
+
└── claude-nexus/ ← harness-local namespace
|
|
172
|
+
├── agent-tracker.json ← Subagent lifecycle tracking (resume_count, files_touched)
|
|
173
|
+
├── tool-log.jsonl ← Subagent Edit/Write/NotebookEdit call log (append-only)
|
|
174
|
+
└── artifacts/ ← Artifacts
|
|
175
175
|
```
|
|
176
176
|
|
|
177
177
|
</details>
|
package/README.md
CHANGED
|
@@ -115,7 +115,7 @@ Gate 단일 모듈로 동작합니다.
|
|
|
115
115
|
|
|
116
116
|
| 이벤트 | 역할 |
|
|
117
117
|
|--------|------|
|
|
118
|
-
| `SessionStart` | `.nexus/` 구조 초기화, agent-tracker 리셋, `
|
|
118
|
+
| `SessionStart` | `.nexus/` 구조 초기화, agent-tracker 리셋, `tool-log.jsonl` 초기화 |
|
|
119
119
|
| `UserPromptSubmit` | 태그 감지 → 모드 활성화 + TASK_PIPELINE 주입 + additionalContext 안내 |
|
|
120
120
|
| `PreToolUse` | Edit/Write: tasks.json 미완료 시 차단 |
|
|
121
121
|
| `PostToolUse` | Edit/Write/NotebookEdit 호출 시 서브에이전트의 파일 수정을 `tool-log.jsonl`에 append (agent_id 있을 때만) |
|
|
@@ -155,10 +155,10 @@ Gate 단일 모듈로 동작합니다.
|
|
|
155
155
|
.nexus/state/
|
|
156
156
|
├── tasks.json ← 태스크 목록 ([run] 사이클)
|
|
157
157
|
├── plan.json ← 플랜 세션 ([plan] 사이클)
|
|
158
|
-
|
|
159
|
-
├──
|
|
160
|
-
├── tool-log.jsonl ← 서브에이전트 Edit/Write/NotebookEdit 호출 로그 (append-only)
|
|
161
|
-
└── artifacts/ ← 산출물
|
|
158
|
+
└── claude-nexus/ ← harness-local 네임스페이스
|
|
159
|
+
├── agent-tracker.json ← 서브에이전트 라이프사이클 (resume_count, files_touched 포함)
|
|
160
|
+
├── tool-log.jsonl ← 서브에이전트 Edit/Write/NotebookEdit 호출 로그 (append-only)
|
|
161
|
+
└── artifacts/ ← 산출물
|
|
162
162
|
```
|
|
163
163
|
|
|
164
164
|
</details>
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.26.
|
|
1
|
+
0.26.2
|
package/bridge/mcp-server.cjs
CHANGED
|
@@ -21020,6 +21020,8 @@ function findProjectRoot(startDir) {
|
|
|
21020
21020
|
var PROJECT_ROOT = findProjectRoot();
|
|
21021
21021
|
var NEXUS_ROOT = process.env.NEXUS_RUNTIME_ROOT || (0, import_path2.join)(PROJECT_ROOT, ".nexus");
|
|
21022
21022
|
var STATE_ROOT = (0, import_path2.join)(NEXUS_ROOT, "state");
|
|
21023
|
+
var HARNESS_ID = "claude-nexus";
|
|
21024
|
+
var HARNESS_STATE_ROOT = (0, import_path2.join)(STATE_ROOT, HARNESS_ID);
|
|
21023
21025
|
var MEMORY_ROOT = (0, import_path2.join)(NEXUS_ROOT, "memory");
|
|
21024
21026
|
var CONTEXT_ROOT = (0, import_path2.join)(NEXUS_ROOT, "context");
|
|
21025
21027
|
function ensureDir(dir) {
|
|
@@ -21056,6 +21058,7 @@ function registerContextTool(server2) {
|
|
|
21056
21058
|
{},
|
|
21057
21059
|
async () => {
|
|
21058
21060
|
let teamStatus = { activeMode: null };
|
|
21061
|
+
let decisions = [];
|
|
21059
21062
|
const tasksFile = (0, import_path3.join)(STATE_ROOT, "tasks.json");
|
|
21060
21063
|
if ((0, import_fs3.existsSync)(tasksFile)) {
|
|
21061
21064
|
try {
|
|
@@ -21063,20 +21066,12 @@ function registerContextTool(server2) {
|
|
|
21063
21066
|
const tasks = Array.isArray(data.tasks) ? data.tasks : [];
|
|
21064
21067
|
const total = tasks.length;
|
|
21065
21068
|
const completed = tasks.filter((t) => t.status === "completed").length;
|
|
21066
|
-
const pending =
|
|
21069
|
+
const pending = tasks.filter((t) => t.status === "pending").length;
|
|
21067
21070
|
teamStatus = {
|
|
21068
21071
|
activeMode: "team",
|
|
21069
21072
|
goal: data.goal ?? "",
|
|
21070
21073
|
tasksSummary: { total, completed, pending }
|
|
21071
21074
|
};
|
|
21072
|
-
} catch {
|
|
21073
|
-
}
|
|
21074
|
-
}
|
|
21075
|
-
let decisions = [];
|
|
21076
|
-
const decisionsFile = (0, import_path3.join)(STATE_ROOT, "decisions.json");
|
|
21077
|
-
if ((0, import_fs3.existsSync)(decisionsFile)) {
|
|
21078
|
-
try {
|
|
21079
|
-
const data = JSON.parse(await (0, import_promises.readFile)(decisionsFile, "utf-8"));
|
|
21080
21075
|
decisions = Array.isArray(data.decisions) ? data.decisions : [];
|
|
21081
21076
|
} catch {
|
|
21082
21077
|
}
|
|
@@ -22039,12 +22034,12 @@ function registerPlanTools(server2) {
|
|
|
22039
22034
|
"\uC548\uAC74 \uACB0\uC815 \uAE30\uB85D \u2014 [d] \uD0DC\uADF8\uB85C \uD2B8\uB9AC\uAC70",
|
|
22040
22035
|
{
|
|
22041
22036
|
issue_id: external_exports.number().describe("\uACB0\uC815\uD560 \uC548\uAC74 ID"),
|
|
22042
|
-
|
|
22037
|
+
decision: external_exports.string().describe("\uACB0\uC815 \uB0B4\uC6A9"),
|
|
22043
22038
|
how_agents: external_exports.array(external_exports.string()).optional().describe('\uC774\uC288 \uBD84\uC11D\uC5D0 \uCC38\uC5EC\uD55C HOW \uC5D0\uC774\uC804\uD2B8 \uC774\uB984 \uBAA9\uB85D (\uC608: ["architect", "designer"])'),
|
|
22044
22039
|
how_summary: external_exports.record(external_exports.string(), external_exports.string()).optional().describe('\uC5D0\uC774\uC804\uD2B8\uBCC4 \uD575\uC2EC \uC758\uACAC \uC694\uC57D (\uC608: { "architect": "...", "designer": "..." })'),
|
|
22045
22040
|
how_agent_ids: external_exports.record(external_exports.string(), external_exports.string()).optional().describe('\uC5D0\uC774\uC804\uD2B8 \uC774\uB984 \u2192 agentId \uB9E4\uD551 (resume\uC6A9). \uC608: { "architect": "ac01819f1cd295cb8" }')
|
|
22046
22041
|
},
|
|
22047
|
-
async ({ issue_id,
|
|
22042
|
+
async ({ issue_id, decision, how_agents, how_summary, how_agent_ids }) => {
|
|
22048
22043
|
const data = await readPlan();
|
|
22049
22044
|
if (!data) {
|
|
22050
22045
|
return textResult({ error: "No active plan session" });
|
|
@@ -22054,7 +22049,7 @@ function registerPlanTools(server2) {
|
|
|
22054
22049
|
return textResult({ error: `Issue ${issue_id} not found` });
|
|
22055
22050
|
}
|
|
22056
22051
|
issue2.status = "decided";
|
|
22057
|
-
issue2.decision =
|
|
22052
|
+
issue2.decision = decision;
|
|
22058
22053
|
if (how_agents !== void 0) issue2.how_agents = how_agents;
|
|
22059
22054
|
if (how_summary !== void 0) issue2.how_summary = how_summary;
|
|
22060
22055
|
if (how_agent_ids !== void 0) issue2.how_agent_ids = how_agent_ids;
|
|
@@ -22196,17 +22191,17 @@ function registerTaskTools(server2) {
|
|
|
22196
22191
|
const root = STATE_ROOT;
|
|
22197
22192
|
const projectHistoryPath = (0, import_path8.join)(NEXUS_ROOT, "history.json");
|
|
22198
22193
|
const planJsonPath = (0, import_path8.join)(root, "plan.json");
|
|
22199
|
-
const reopenTrackerPath = (0, import_path8.join)(root, "reopen-tracker.json");
|
|
22200
22194
|
const plan = await readPlan();
|
|
22201
22195
|
const tasksData = await readTasks();
|
|
22202
22196
|
const tasks = tasksData?.tasks ?? [];
|
|
22203
22197
|
const branch = getCurrentBranch();
|
|
22204
|
-
let history = { cycles: [] };
|
|
22198
|
+
let history = { schema_version: "0.5", cycles: [] };
|
|
22205
22199
|
if ((0, import_fs8.existsSync)(projectHistoryPath)) {
|
|
22206
22200
|
const raw = await (0, import_promises3.readFile)(projectHistoryPath, "utf-8");
|
|
22207
22201
|
history = JSON.parse(raw);
|
|
22208
22202
|
}
|
|
22209
22203
|
const cycle = {
|
|
22204
|
+
schema_version: "0.5",
|
|
22210
22205
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22211
22206
|
branch,
|
|
22212
22207
|
plan,
|
|
@@ -22215,24 +22210,14 @@ function registerTaskTools(server2) {
|
|
|
22215
22210
|
history.cycles.push(cycle);
|
|
22216
22211
|
ensureDir(NEXUS_ROOT);
|
|
22217
22212
|
await (0, import_promises3.writeFile)(projectHistoryPath, JSON.stringify(history, null, 2));
|
|
22218
|
-
const editTrackerPath = (0, import_path8.join)(root, "edit-tracker.json");
|
|
22219
|
-
let hadLoopDetection = false;
|
|
22220
|
-
if ((0, import_fs8.existsSync)(editTrackerPath)) {
|
|
22221
|
-
try {
|
|
22222
|
-
const trackerData = JSON.parse(await (0, import_promises3.readFile)(editTrackerPath, "utf-8"));
|
|
22223
|
-
hadLoopDetection = Object.values(trackerData).some((count) => count >= 3);
|
|
22224
|
-
} catch {
|
|
22225
|
-
}
|
|
22226
|
-
}
|
|
22227
22213
|
const decisionCount = plan?.issues.filter((i) => i.status === "decided").length ?? 0;
|
|
22228
22214
|
const memoryHint = {
|
|
22229
22215
|
taskCount: tasks.length,
|
|
22230
22216
|
decisionCount,
|
|
22231
|
-
hadLoopDetection,
|
|
22232
22217
|
cycleTopics: [plan?.topic, tasksData?.goal].filter(Boolean)
|
|
22233
22218
|
};
|
|
22234
22219
|
const deleted = [];
|
|
22235
|
-
for (const p of [planJsonPath, tasksPath()
|
|
22220
|
+
for (const p of [planJsonPath, tasksPath()]) {
|
|
22236
22221
|
if ((0, import_fs8.existsSync)(p)) {
|
|
22237
22222
|
(0, import_fs8.unlinkSync)(p);
|
|
22238
22223
|
deleted.push(p.split("/").pop());
|
|
@@ -22258,7 +22243,7 @@ function registerTaskTools(server2) {
|
|
|
22258
22243
|
},
|
|
22259
22244
|
async ({ query, last_n }) => {
|
|
22260
22245
|
const historyPath = (0, import_path8.join)(NEXUS_ROOT, "history.json");
|
|
22261
|
-
if (!(0, import_fs8.existsSync)(historyPath)) return textResult({ cycles: [], total: 0 });
|
|
22246
|
+
if (!(0, import_fs8.existsSync)(historyPath)) return textResult({ cycles: [], total: 0, showing: 0 });
|
|
22262
22247
|
const raw = await (0, import_promises3.readFile)(historyPath, "utf-8");
|
|
22263
22248
|
const history = JSON.parse(raw);
|
|
22264
22249
|
let cycles = history.cycles || [];
|
|
@@ -22292,7 +22277,7 @@ function registerArtifactTools(server2) {
|
|
|
22292
22277
|
content: external_exports.string().describe("File content to write")
|
|
22293
22278
|
},
|
|
22294
22279
|
async ({ filename, content }) => {
|
|
22295
|
-
const artifactsDir = (0, import_path9.join)(
|
|
22280
|
+
const artifactsDir = (0, import_path9.join)(HARNESS_STATE_ROOT, "artifacts");
|
|
22296
22281
|
ensureDir(artifactsDir);
|
|
22297
22282
|
const path = (0, import_path9.join)(artifactsDir, filename);
|
|
22298
22283
|
await (0, import_promises4.writeFile)(path, content);
|