claude-nexus 0.26.4 → 0.27.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.en.md +1 -1
- package/README.md +1 -1
- package/VERSION +1 -1
- package/package.json +2 -2
- package/scripts/gate.cjs +32 -0
- package/scripts/gate.cjs.map +2 -2
- package/skills/nx-plan/SKILL.md +14 -5
package/README.en.md
CHANGED
|
@@ -189,7 +189,7 @@ Completed subagents can be resumed within the same parent session via `SendMessa
|
|
|
189
189
|
|
|
190
190
|
**Activation requirement**: environment variable `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`. When absent, automatically falls back to fresh spawn (no errors).
|
|
191
191
|
|
|
192
|
-
**Rationale**: Agents are classified by their dominant work surface. Reasoning surface (exists only in agent context) → `persistent` (HOW + Researcher). Mixed with artifact surface (persisted to filesystem) → `bounded` (Engineer, Writer). Verification independence as quality metric → `ephemeral` (Tester, Reviewer). See `.nexus/memory/persistence-surface-theory.md` for details.
|
|
192
|
+
**Rationale**: Agents are classified by their dominant work surface. Reasoning surface (exists only in agent context) → `persistent` (HOW + Researcher). Mixed with artifact surface (persisted to filesystem) → `bounded` (Engineer, Writer). Verification independence as quality metric → `ephemeral` (Tester, Reviewer). See `.nexus/memory/pattern-persistence-surface-theory.md` for details.
|
|
193
193
|
|
|
194
194
|
**Tracking**: `PostToolUse` hook appends subagent file edits to `tool-log.jsonl` → `SubagentStop` aggregates them into `files_touched` on `agent-tracker.json` → Lead uses this for bounded-tier conditional resume decisions.
|
|
195
195
|
|
package/README.md
CHANGED
|
@@ -176,7 +176,7 @@ Gate 단일 모듈로 동작합니다.
|
|
|
176
176
|
|
|
177
177
|
**활성화 요구사항**: 환경 변수 `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`. 미감지 시 자동 fresh spawn fallback (에러 없음).
|
|
178
178
|
|
|
179
|
-
**이론 근거**: 에이전트의 본질적 작업 층위를 두 surface로 구분합니다. Reasoning surface(에이전트 컨텍스트에만 존재)가 지배적인 HOW/Researcher는 `persistent`, Artifact surface(파일 시스템에 persist)에 걸친 Engineer/Writer는 `bounded`, 검증 독립성이 품질 지표인 Tester/Reviewer는 `ephemeral`. 자세한 내용은 `.nexus/memory/persistence-surface-theory.md`.
|
|
179
|
+
**이론 근거**: 에이전트의 본질적 작업 층위를 두 surface로 구분합니다. Reasoning surface(에이전트 컨텍스트에만 존재)가 지배적인 HOW/Researcher는 `persistent`, Artifact surface(파일 시스템에 persist)에 걸친 Engineer/Writer는 `bounded`, 검증 독립성이 품질 지표인 Tester/Reviewer는 `ephemeral`. 자세한 내용은 `.nexus/memory/pattern-persistence-surface-theory.md`.
|
|
180
180
|
|
|
181
181
|
**연계 추적**: `PostToolUse` 훅이 서브에이전트의 파일 수정을 `tool-log.jsonl`에 append → `SubagentStop`이 집계하여 `agent-tracker.json`의 `files_touched`에 주입 → Lead가 bounded tier 조건부 resume 판단에 활용.
|
|
182
182
|
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.27.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-nexus",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent orchestration plugin for Claude Code — optimized context injection per role",
|
|
6
6
|
"author": "kih",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@types/node": "^25.5.0",
|
|
40
40
|
"esbuild": "^0.25.0",
|
|
41
41
|
"typescript": "^5.8.0",
|
|
42
|
-
"@moreih29/nexus-core": "^0.
|
|
42
|
+
"@moreih29/nexus-core": "^0.10.0",
|
|
43
43
|
"yaml": "^2"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
package/scripts/gate.cjs
CHANGED
|
@@ -512,7 +512,39 @@ Record decision only. For implementation, use [run].`;
|
|
|
512
512
|
pass();
|
|
513
513
|
}
|
|
514
514
|
}
|
|
515
|
+
function handleMemoryAccessTracking(event) {
|
|
516
|
+
try {
|
|
517
|
+
if (event.tool_name !== "Read") return;
|
|
518
|
+
const filePath = event.tool_input?.file_path;
|
|
519
|
+
if (!filePath || !filePath.startsWith(MEMORY_ROOT)) return;
|
|
520
|
+
const logPath = (0, import_path3.join)(HARNESS_STATE_ROOT, "memory-access.jsonl");
|
|
521
|
+
const records = /* @__PURE__ */ new Map();
|
|
522
|
+
if ((0, import_fs3.existsSync)(logPath)) {
|
|
523
|
+
const content = (0, import_fs3.readFileSync)(logPath, "utf-8");
|
|
524
|
+
for (const line of content.split("\n")) {
|
|
525
|
+
if (!line) continue;
|
|
526
|
+
try {
|
|
527
|
+
const rec = JSON.parse(line);
|
|
528
|
+
records.set(rec.path, rec);
|
|
529
|
+
} catch {
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
const existing = records.get(filePath);
|
|
534
|
+
records.set(filePath, {
|
|
535
|
+
path: filePath,
|
|
536
|
+
last_accessed_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
537
|
+
access_count: (existing?.access_count ?? 0) + 1,
|
|
538
|
+
last_agent: event.agent_id ?? "lead"
|
|
539
|
+
});
|
|
540
|
+
ensureDir(HARNESS_STATE_ROOT);
|
|
541
|
+
const output = Array.from(records.values()).map((r) => JSON.stringify(r)).join("\n") + "\n";
|
|
542
|
+
(0, import_fs3.writeFileSync)(logPath, output);
|
|
543
|
+
} catch (e) {
|
|
544
|
+
}
|
|
545
|
+
}
|
|
515
546
|
function handlePostToolUse(event) {
|
|
547
|
+
handleMemoryAccessTracking(event);
|
|
516
548
|
try {
|
|
517
549
|
const agentId = event.agent_id;
|
|
518
550
|
if (!agentId) return;
|
package/scripts/gate.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/hooks/gate.ts", "../src/shared/hook-io.ts", "../src/shared/paths.ts", "../src/shared/tasks.ts", "../src/shared/matrix.ts"],
|
|
4
|
-
"sourcesContent": ["// Gate \uD6C5: Stop (Task \uCC28\uB2E8) + UserPromptSubmit (\uD0A4\uC6CC\uB4DC \uAC10\uC9C0)\nimport { readStdin, respond, pass } from '../shared/hook-io.js';\nimport { STATE_ROOT, HARNESS_STATE_ROOT, HARNESS_ID, MEMORY_ROOT, CONTEXT_ROOT, ensureDir, ensureNexusStructure } from '../shared/paths.js';\nimport { readTasksSummary } from '../shared/tasks.js';\nimport { extractRole } from '../shared/matrix.js';\nimport { existsSync, readFileSync, writeFileSync, appendFileSync, readdirSync } from 'fs';\nimport { join, basename } from 'path';\nimport { homedir } from 'os';\n\nconst TASK_PIPELINE = `\nTASK PIPELINE (mandatory for all file modifications):\n1. Check plan.json issues for prior decisions \u2014 reference relevant plan_issue IDs in nx_task_add(plan_issue=N).\n2. Decompose work into discrete tasks \u2192 call nx_task_add for EACH task.\n3. Edit/Write tools are BLOCKED without tasks.json.\n4. As each task completes \u2192 nx_task_update(id, \"completed\").\n5. All tasks done \u2192 ask user \"close\uD560\uAE4C\uC694?\" (team mode) or nx_task_close directly (Lead solo).`;\n\nfunction taskPipelineMessage(modeSpecific: string): string {\n // Insert TASK_PIPELINE before the closing </nexus> tag\n return modeSpecific.replace('</nexus>', `${TASK_PIPELINE}</nexus>`);\n}\n\n// --- CLAUDE.md \uC790\uB3D9 \uB3D9\uAE30\uD654 ---\n\nconst MARKER_START = '<!-- NEXUS:START -->';\nconst MARKER_END = '<!-- NEXUS:END -->';\nconst PLUGIN_ROOT = process.env.CLAUDE_PLUGIN_ROOT ?? '';\n\nfunction extractMarkerContent(fileContent: string): string | null {\n const startIdx = fileContent.indexOf(MARKER_START);\n const endIdx = fileContent.indexOf(MARKER_END);\n if (startIdx === -1 || endIdx === -1) return null;\n return fileContent.slice(startIdx + MARKER_START.length, endIdx).trim();\n}\n\nfunction replaceMarkerContent(fileContent: string, newContent: string): string {\n const startIdx = fileContent.indexOf(MARKER_START);\n const endIdx = fileContent.indexOf(MARKER_END);\n return fileContent.slice(0, startIdx + MARKER_START.length) + '\\n' + newContent + '\\n' + fileContent.slice(endIdx);\n}\n\nfunction handleClaudeMdSync(): string | null {\n // Read template\n const templatePath = join(PLUGIN_ROOT, 'templates', 'nexus-section.md');\n if (!PLUGIN_ROOT || !existsSync(templatePath)) return null;\n const template = readFileSync(templatePath, 'utf-8').trim();\n\n // --- Global CLAUDE.md auto-update ---\n const globalClaudeMd = join(homedir(), '.claude', 'CLAUDE.md');\n if (existsSync(globalClaudeMd)) {\n const globalContent = readFileSync(globalClaudeMd, 'utf-8');\n const globalMarker = extractMarkerContent(globalContent);\n if (globalMarker !== null && globalMarker !== template) {\n const updated = replaceMarkerContent(globalContent, template);\n writeFileSync(globalClaudeMd, updated);\n }\n }\n\n // --- Project CLAUDE.md auto-sync ---\n const projectClaudeMd = join(process.cwd(), 'CLAUDE.md');\n\n if (existsSync(projectClaudeMd)) {\n const projectContent = readFileSync(projectClaudeMd, 'utf-8');\n const projectMarker = extractMarkerContent(projectContent);\n\n if (projectMarker !== null && projectMarker !== template) {\n const updated = replaceMarkerContent(projectContent, template);\n writeFileSync(projectClaudeMd, updated);\n }\n }\n\n return null;\n}\n\n// --- Stop \uC774\uBCA4\uD2B8 \uCC98\uB9AC ---\n\n/** \uB9C8\uC9C0\uB9C9 nx-sync \uC774\uD6C4 N\uC0AC\uC774\uD074 \uACBD\uACFC \uC2DC \uB3D9\uAE30\uD654 \uB11B\uC9C0 \uBC18\uD658 */\nfunction getSyncNudge(): string | null {\n const historyPath = join(process.cwd(), '.nexus', 'history.json');\n if (!existsSync(historyPath)) return null;\n try {\n const history = JSON.parse(readFileSync(historyPath, 'utf-8'));\n const cycles = history.cycles ?? [];\n if (cycles.length === 0) return null;\n // \uB9C8\uC9C0\uB9C9 sync \uC0AC\uC774\uD074 \uCC3E\uAE30\n const lastSyncIdx = cycles.findLastIndex((c: { topics?: string[] }) =>\n c.topics?.some((t: string) => /sync/i.test(t))\n );\n const cyclesSinceSync = lastSyncIdx === -1 ? cycles.length : cycles.length - 1 - lastSyncIdx;\n if (cyclesSinceSync >= 3) {\n return `<nexus>Core knowledge may be outdated (${cyclesSinceSync} cycles since last sync). Consider running /claude-nexus:nx-sync.</nexus>`;\n }\n } catch {}\n return null;\n}\n\nfunction handleStop(event: Record<string, unknown>): void {\n const summary = readTasksSummary(STATE_ROOT);\n if (!summary.exists) {\n // \uB3D9\uAE30\uD654 \uB11B\uC9C0\uB9CC \uD655\uC778\n const syncNudge = getSyncNudge();\n if (syncNudge) {\n respond({ continue: true, additionalContext: syncNudge });\n return;\n }\n pass();\n return;\n }\n\n if (summary.pending > 0) {\n respond({\n continue: true,\n additionalContext: `<nexus>${summary.pending} tasks pending in tasks.json. Before stopping:\\n1. Review each pending task \u2014 verify if work is actually done.\\n2. Done \u2192 nx_task_update(id, \"completed\").\\n3. Not done \u2192 complete the work first.\\n4. When all completed \u2192 nx_task_close to archive.</nexus>`,\n });\n return;\n }\n\n // all completed \u2192 1\uD68C\uB9CC \uCC28\uB2E8 \uD6C4 \uD574\uC81C (\uBB34\uD55C \uB8E8\uD504 \uBC29\uC9C0)\n // stop_hook_active: \uD50C\uB7AB\uD3FC\uC774 \uC81C\uACF5\uD558\uB294 \uC7AC\uC9C4\uC785 \uD50C\uB798\uADF8 \u2014 true\uBA74 \uC774\uBBF8 \uACBD\uACE0 \uD6C4 \uC7AC\uC2DC\uB3C4\n if (event.stop_hook_active) {\n pass();\n return;\n }\n respond({\n continue: true,\n additionalContext: `<nexus>All tasks completed. Call nx_task_close now.</nexus>`,\n });\n}\n\n// --- PreToolUse \uC774\uBCA4\uD2B8 \uCC98\uB9AC: Edit/Write \uD0DC\uC2A4\uD06C \uD30C\uC774\uD504\uB77C\uC778 \uCC28\uB2E8 ---\n// NOTE: per-agent capability \uCC28\uB2E8\uC740 agents/*.md frontmatter\uC758 disallowedTools\n// \uD544\uB4DC\uB97C Claude Code \uB7F0\uD0C0\uC784\uC774 \uCC98\uB9AC. gate.ts PreToolUse\uB294 workflow \uC0C1\uD0DC\uB9CC \uB2F4\uB2F9.\n\n/** \uC608\uC678 \uACBD\uB85C: Nexus \uB0B4\uBD80 \uD30C\uC77C \uBC0F setup/sync \uB300\uC0C1 \uD30C\uC77C\uC740 tasks.json \uC5C6\uC774\uB3C4 \uC218\uC815 \uD5C8\uC6A9 */\nfunction isNexusInternalPath(filePath: string): boolean {\n // .nexus/state/ \uB7F0\uD0C0\uC784 \uC0C1\uD0DC \u2014 task \uC5C6\uC774 \uC218\uC815 \uD5C8\uC6A9\n if (/[\\\\/]\\.nexus[\\\\/]state[\\\\/]/.test(filePath)) return true;\n // .claude/settings.json \u2014 setup \uC2A4\uD0AC \uB300\uC0C1\n if (/[\\\\/]\\.claude[\\\\/]settings\\.json$/.test(filePath)) return true;\n // CLAUDE.md \u2014 sync \uC2A4\uD0AC \uB300\uC0C1\n if (/[\\\\/]CLAUDE\\.md$/.test(filePath)) return true;\n return false;\n}\n\nfunction handlePreToolUse(event: Record<string, unknown>): void {\n const toolName = (event.tool_name ?? '') as string;\n\n // Edit/Write \uB3C4\uAD6C: [run] \uBAA8\uB4DC(tasks.json \uC874\uC7AC)\uC5D0\uC11C\uB9CC \uCC28\uB2E8 (Nexus \uB0B4\uBD80 \uACBD\uB85C \uC81C\uC678)\n if (toolName === 'Edit' || toolName === 'Write') {\n const tasksPath = join(STATE_ROOT, 'tasks.json');\n if (!existsSync(tasksPath)) {\n // tasks.json \uC5C6\uC74C = [run] \uBAA8\uB4DC\uAC00 \uC544\uB2D8 \u2192 \uC790\uC720 \uC218\uC815 \uD5C8\uC6A9\n pass();\n return;\n }\n\n const toolInput = event.tool_input as Record<string, unknown> | undefined;\n const filePath = (toolInput?.file_path ?? '') as string;\n\n if (!isNexusInternalPath(filePath)) {\n const summary = readTasksSummary(STATE_ROOT);\n // [run] \uBAA8\uB4DC: \uBAA8\uB4E0 \uD0DC\uC2A4\uD06C \uC644\uB8CC \uC2DC nx_task_close \uAC15\uC81C\n if (summary.allCompleted || summary.total === 0) {\n respond({\n decision: 'block',\n reason: '<nexus>All tasks completed. Call nx_task_close to archive, or nx_task_add to register additional tasks.</nexus>',\n });\n return;\n }\n }\n\n pass();\n return;\n }\n\n pass();\n}\n\n// --- UserPromptSubmit \uC774\uBCA4\uD2B8 \uCC98\uB9AC: \uD0A4\uC6CC\uB4DC \uAC10\uC9C0 ---\n\ninterface KeywordMatch {\n primitive: 'plan' | 'run';\n skill: string;\n}\n\n/** All tag ids with inline handlers in handleUserPromptSubmit. Cross-checked against nexus-core vocabulary/tags.yml at build time. */\nexport const HANDLED_TAG_IDS = ['plan', 'run', 'sync', 'd', 'm', 'm-gc', 'rule'] as const;\n\nconst EXPLICIT_TAGS: Record<string, KeywordMatch> = {\n plan: { primitive: 'plan', skill: 'claude-nexus:nx-plan' },\n 'plan:auto': { primitive: 'plan', skill: 'claude-nexus:nx-plan' },\n run: { primitive: 'run', skill: 'claude-nexus:nx-run' },\n};\n\nfunction detectKeywords(prompt: string): KeywordMatch | null {\n // \uBA85\uC2DC\uC801 \uD0DC\uADF8 [plan] / [plan:auto] / [run] \u2014 \uD56D\uC0C1 \uD655\uC815\n const tagMatch = prompt.match(/\\[(plan(?::auto)?|run)\\]/i);\n if (tagMatch) {\n const tag = tagMatch[1].toLowerCase();\n if (tag in EXPLICIT_TAGS) return EXPLICIT_TAGS[tag];\n }\n return null;\n}\n\nfunction getTasksReminder(): string | null {\n const summary = readTasksSummary(STATE_ROOT);\n if (!summary.exists) return null;\n if (summary.pending > 0) {\n return `<nexus>${summary.pending} pending tasks. Complete work \u2192 nx_task_update(id, \"completed\") for each done task. Archive with nx_task_close when all complete.</nexus>`;\n }\n return `<nexus>All ${summary.total} tasks completed but not archived. MANDATORY: Call nx_task_close to archive this cycle.</nexus>`;\n}\n\nfunction getPlanReminder(): string | null {\n const planFilePath = join(STATE_ROOT, 'plan.json');\n if (!existsSync(planFilePath)) return null;\n try {\n const data = JSON.parse(readFileSync(planFilePath, 'utf-8'));\n const issues = data.issues ?? [];\n const pending = issues.filter((i: { status: string }) => i.status === 'pending');\n const current = pending.length > 0\n ? `Next: #${pending[0].id} \"${pending[0].title}\"`\n : 'All issues decided.';\n return `<nexus>Plan: \"${data.topic}\" | ${current} | ${pending.length} pending\\nPresent comparison table with pros/cons/recommendation. Record decisions with [d].</nexus>`;\n } catch {\n return null;\n }\n}\n\n// --- Core Knowledge \uC778\uB371\uC2A4 \uBE4C\uB4DC ---\n\nfunction scanFolderEntries(folderPath: string): string[] {\n if (!existsSync(folderPath)) return [];\n let files: string[];\n try {\n files = readdirSync(folderPath).filter(f => f.endsWith('.md'));\n } catch {\n return [];\n }\n const entries: string[] = [];\n for (const file of files) {\n const name = basename(file, '.md');\n const filePath = join(folderPath, file);\n let tags = '';\n try {\n const content = readFileSync(filePath, 'utf-8');\n const tagMatch = content.match(/<!--\\s*tags:\\s*([^-]+?)\\s*-->/);\n if (tagMatch) {\n const tagList = tagMatch[1].split(',').map(t => t.trim()).filter(Boolean);\n const shortTags = tagList.slice(0, 3).join(', ');\n tags = ` [${shortTags}]`;\n }\n } catch {}\n entries.push(`${name}${tags}`);\n }\n return entries;\n}\n\nfunction buildCoreIndex(): string {\n const nexusRoot = join(process.cwd(), '.nexus');\n const rulesRoot = join(nexusRoot, 'rules');\n\n const layerLines: string[] = [];\n\n const memoryEntries = scanFolderEntries(MEMORY_ROOT);\n if (memoryEntries.length > 0) {\n layerLines.push(`memory: ${memoryEntries.join(', ')}`);\n }\n\n const contextEntries = scanFolderEntries(CONTEXT_ROOT);\n if (contextEntries.length > 0) {\n layerLines.push(`context: ${contextEntries.join(', ')}`);\n }\n\n const rulesEntries = scanFolderEntries(rulesRoot);\n if (rulesEntries.length > 0) {\n layerLines.push(`rules: ${rulesEntries.join(', ')}`);\n }\n\n if (layerLines.length === 0) return '';\n\n const header = '[.nexus Knowledge]';\n const result = `${header}\\n${layerLines.join('\\n')}`;\n return result.length <= 2000 ? result : result.slice(0, 1997) + '...';\n}\n\n/** additionalContext\uC5D0 notices\uB97C \uC790\uB3D9 \uBCD1\uD569 */\nfunction withNotices(base: string, tasksReminder: string | null, claudeMdNotice: string | null, planReminder?: string | null): string {\n return [planReminder, tasksReminder, base, claudeMdNotice].filter(Boolean).join('\\n');\n}\n\n// --- \uAC1C\uBCC4 \uD504\uB9AC\uBBF8\uD2F0\uBE0C \uD578\uB4E4\uB7EC ---\n\ntype PrimitiveHandler = (params: {\n prompt: string;\n tasksReminder: string | null;\n claudeMdNotice: string | null;\n}) => void;\n\nfunction handleRuleMode({ tasksReminder, claudeMdNotice, ruleTags }: {\n prompt: string;\n tasksReminder: string | null;\n claudeMdNotice: string | null;\n ruleTags: string[] | null;\n}): void {\n const tagInfo = ruleTags\n ? `Tags: [${ruleTags.join(', ')}] \u2014 include at top of rule file as <!-- tags: ${ruleTags.join(', ')} -->.`\n : 'Tags: none \u2014 infer appropriate tags from rule content and add them.';\n\n const base = `<nexus>Rule mode \u2014 saving user instruction as a project rule.\n${tagInfo}\n1. Extract and clean up rule content from the user message.\n2. Save to .nexus/rules/{name}.md via the Write tool.\nRules are git-tracked and auto-delivered to agents via SubagentStart hook index injection.\nTask pipeline not required \u2014 save directly.</nexus>`;\n\n respond({\n continue: true,\n additionalContext: withNotices(base, tasksReminder, claudeMdNotice),\n });\n}\n\nfunction handlePlanMode({ prompt, tasksReminder, claudeMdNotice }: Parameters<PrimitiveHandler>[0]): void {\n // 2\uCC28 \uC548\uC804\uB9DD: \uC774\uC804 \uC0AC\uC774\uD074\uC758 stale tasks.json \uAC10\uC9C0\n const staleSummary = readTasksSummary(STATE_ROOT);\n if (staleSummary.exists && staleSummary.allCompleted) {\n respond({\n continue: true,\n additionalContext: `<nexus>\u26A0 Previous cycle not closed \u2014 tasks.json exists with all tasks completed. Call nx_task_close first to archive before starting a new plan.</nexus>`,\n });\n return;\n }\n\n const isAuto = /\\[plan:auto\\]/i.test(prompt);\n const planFile = join(STATE_ROOT, 'plan.json');\n const hasExistingSession = existsSync(planFile);\n\n let hints = '';\n if (hasExistingSession) {\n hints = '\\nExisting plan session detected \u2014 check nx_plan_status to resume.';\n }\n if (isAuto) {\n hints += '\\nAuto mode requested \u2014 pass args: \"auto\" to the skill.';\n }\n\n const base = `<nexus>BLOCKING: Invoke Skill tool with skill=\"claude-nexus:nx-plan\"${isAuto ? ', args: \"auto\"' : ''} BEFORE any other action. Do NOT attempt planning without loading the skill first.${hints}</nexus>`;\n const coreIndex = buildCoreIndex();\n const coreSection = coreIndex\n ? `\\n${coreIndex}\\nCheck core/reference/ BEFORE web searching for known topics.`\n : '';\n respond({\n continue: true,\n additionalContext: withNotices(base + coreSection, tasksReminder, claudeMdNotice, null),\n });\n}\n\nfunction handleRunMode({ tasksReminder, claudeMdNotice }: Parameters<PrimitiveHandler>[0]): void {\n const planReminder = getPlanReminder();\n const tasksSummary = readTasksSummary(STATE_ROOT);\n\n let hints = '';\n if (!tasksSummary.exists) {\n hints = '\\ntasks.json absent \u2014 plan required before execution. Suggest [plan:auto] or [plan].';\n } else {\n hints = `\\ntasks.json: ${tasksSummary.pending} pending, ${tasksSummary.total - tasksSummary.pending} completed of ${tasksSummary.total} tasks.`;\n }\n\n const coreIndex = buildCoreIndex();\n const coreSection = coreIndex ? `\\n${coreIndex}` : '';\n const base = `<nexus>BLOCKING: Invoke Skill tool with skill=\"claude-nexus:nx-run\" BEFORE any other action. Do NOT attempt execution without loading the skill first.${hints}</nexus>${coreSection}`;\n respond({\n continue: true,\n additionalContext: withNotices(taskPipelineMessage(base), tasksReminder, claudeMdNotice, planReminder),\n });\n}\n\nconst PRIMITIVE_HANDLERS: Record<string, PrimitiveHandler> = {\n plan: handlePlanMode,\n run: handleRunMode,\n};\n\nfunction handleUserPromptSubmit(event: Record<string, unknown>): void {\n const claudeMdNotice = handleClaudeMdSync();\n const tasksReminder = getTasksReminder();\n const planReminder = getPlanReminder();\n\n const raw = event.prompt ?? event.user_prompt ?? '';\n const prompt = typeof raw === 'string' ? raw : String(raw);\n if (!prompt) { pass(); return; }\n\n // [d] \uACB0\uC815 \uD0DC\uADF8 \uAC10\uC9C0 \u2014 plan.json \uC720\uBB34\uB85C \uB3C4\uAD6C \uBD84\uAE30 + \uD589\uB3D9 \uADDC\uCE59 \uC8FC\uC785\n const dTag = prompt.match(/\\[d\\]/i);\n if (dTag) {\n const postDecisionRules = `\\n\\nRecord decision only. For implementation, use [run].`;\n const planFile = join(STATE_ROOT, 'plan.json');\n if (existsSync(planFile)) {\n respond({\n continue: true,\n additionalContext: withNotices(`<nexus>Decision tag detected in plan mode. Use nx_plan_decide(issue_id, decision) to record.${postDecisionRules}</nexus>`, tasksReminder, claudeMdNotice, planReminder),\n });\n } else {\n respond({\n continue: true,\n additionalContext: withNotices(`<nexus>[d]\uB294 plan \uC138\uC158 \uC548\uC5D0\uC11C\uB9CC \uC720\uD6A8\uD569\uB2C8\uB2E4. [plan] \uD0DC\uADF8\uB85C \uD50C\uB798\uB2DD\uC744 \uBA3C\uC800 \uC2DC\uC791\uD558\uC138\uC694.${postDecisionRules}</nexus>`, tasksReminder, claudeMdNotice, null),\n });\n }\n return;\n }\n\n // [m] \uBA54\uBAA8\uB9AC \uC800\uC7A5 \uD0DC\uADF8 \uAC10\uC9C0\n const mTag = prompt.match(/\\[m(?::([^\\]]*))?\\]/i);\n if (mTag) {\n const subCmd = mTag[1]?.trim().toLowerCase();\n if (subCmd === 'gc') {\n respond({\n continue: true,\n additionalContext: withNotices(\n `<nexus>Memory GC mode \u2014 \uAE30\uC874 .nexus/memory/ \uD30C\uC77C\uC744 Glob\uC73C\uB85C \uD655\uC778\uD558\uACE0, \uAD00\uB828 \uBA54\uBAA8\uB97C \uBCD1\uD569/\uC0AD\uC81C\uD558\uC5EC \uC815\uB9AC\uD558\uB77C. Write \uB3C4\uAD6C\uB85C \uC800\uC7A5.</nexus>`,\n tasksReminder,\n claudeMdNotice,\n ),\n });\n } else {\n const userContent = prompt.replace(/\\[m(?::([^\\]]*))?\\]/i, '').trim();\n respond({\n continue: true,\n additionalContext: withNotices(\n `<nexus>Memory save mode \u2014 \uB2E4\uC74C \uB0B4\uC6A9\uC744 \uC555\uCD95\u00B7\uC815\uC81C\uD558\uC5EC .nexus/memory/{\uC801\uC808\uD55C_\uD1A0\uD53D}.md\uC5D0 Write\uB85C \uC800\uC7A5\uD558\uB77C. \uAE30\uC874 \uD30C\uC77C \uC911 \uAD00\uB828\uB41C \uAC83\uC774 \uC788\uC73C\uBA74 \uC5C5\uB370\uC774\uD2B8\uD558\uACE0, \uC5C6\uC73C\uBA74 \uC0C8 \uD30C\uC77C \uC0DD\uC131. \uC6D0\uBB38: ${userContent}</nexus>`,\n tasksReminder,\n claudeMdNotice,\n ),\n });\n }\n return;\n }\n\n // [rule] \uADDC\uCE59 \uC800\uC7A5 \uD0DC\uADF8 \uAC10\uC9C0\n const ruleMatch = prompt.match(/\\[rule(?::([^\\]]+))?\\]/i);\n if (ruleMatch) {\n const rawTags = ruleMatch[1];\n const ruleTags = rawTags ? rawTags.split(',').map(t => t.trim()).filter(Boolean) : null;\n handleRuleMode({ prompt, tasksReminder, claudeMdNotice, ruleTags });\n return;\n }\n\n // [sync] \uCEE8\uD14D\uC2A4\uD2B8 \uB3D9\uAE30\uD654 \uD0DC\uADF8 \uAC10\uC9C0\n if (/\\[sync\\]/i.test(prompt)) {\n respond({\n continue: true,\n additionalContext: withNotices(\n `<nexus>BLOCKING: Invoke Skill tool with skill=\"claude-nexus:nx-sync\" [before any other action].</nexus>`,\n tasksReminder,\n claudeMdNotice,\n ),\n });\n return;\n }\n\n const match = detectKeywords(prompt);\n if (match) {\n const handler = PRIMITIVE_HANDLERS[match.primitive];\n if (handler) {\n handler({ prompt, tasksReminder, claudeMdNotice });\n return;\n }\n }\n\n // \uD0DC\uADF8 \uC5C6\uC74C \u2014 \uC790\uC720 \uBAA8\uB4DC\n const summary = readTasksSummary(STATE_ROOT);\n\n // tasks.json \uC788\uC74C(=[run] \uC9C4\uD589 \uC911) + pending \u2192 \uC2A4\uB9C8\uD2B8 resume\n if (summary.exists && summary.pending > 0) {\n respond({\n continue: true,\n additionalContext: withNotices(`<nexus>Active [run] session detected (${summary.pending} pending tasks). Resume execution or use nx_task_close to archive.</nexus>`, tasksReminder, claudeMdNotice, planReminder),\n });\n return;\n }\n\n // tasks.json \uC788\uC74C + all completed \u2192 stale cycle\n if (summary.exists && (summary.allCompleted || summary.total === 0)) {\n respond({\n continue: true,\n additionalContext: withNotices(`<nexus>Stale tasks.json from previous [run]. Call nx_task_close to archive.</nexus>`, tasksReminder, claudeMdNotice, planReminder),\n });\n return;\n }\n\n // tasks.json \uC5C6\uC74C = \uC790\uC720 \uBAA8\uB4DC. \uCD5C\uC18C\uD55C\uC758 \uCEE8\uD14D\uC2A4\uD2B8\uB9CC \uC8FC\uC785.\n const notices = [planReminder, claudeMdNotice].filter(Boolean).join('\\n');\n if (notices) {\n respond({ continue: true, additionalContext: notices });\n } else {\n pass();\n }\n}\n\n// --- PostToolUse \uC774\uBCA4\uD2B8 \uCC98\uB9AC: tool-log.jsonl append ---\n\nfunction handlePostToolUse(event: any): void {\n try {\n const agentId = event.agent_id;\n if (!agentId) return; // Lead direct edit, skip\n if (!['Edit', 'Write', 'NotebookEdit'].includes(event.tool_name)) return;\n const filePath = event.tool_name === 'NotebookEdit'\n ? event.tool_input?.notebook_path\n : event.tool_input?.file_path;\n if (!filePath) return;\n const line = JSON.stringify({\n ts: new Date().toISOString(),\n agent_id: agentId,\n tool: event.tool_name,\n file: filePath,\n }) + '\\n';\n appendFileSync(join(HARNESS_STATE_ROOT, 'tool-log.jsonl'), line);\n } catch (e) {\n // silent fail\n }\n}\n\n// --- \uC138\uC158 \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC ---\n\nfunction handleSessionStart(_event: Record<string, unknown>): void {\n ensureNexusStructure();\n writeFileSync(join(HARNESS_STATE_ROOT, 'agent-tracker.json'), '[]');\n try {\n writeFileSync(join(HARNESS_STATE_ROOT, 'tool-log.jsonl'), '');\n } catch (e) {\n // silent fail\n }\n pass();\n}\n\nfunction handleSubagentStart(event: Record<string, unknown>): void {\n const agentType = String(event.agent_type ?? '');\n const agentId = String(event.agent_id ?? '');\n\n const trackerPath = join(HARNESS_STATE_ROOT, 'agent-tracker.json');\n let tracker: Record<string, unknown>[] = [];\n if (existsSync(trackerPath)) {\n try { tracker = JSON.parse(readFileSync(trackerPath, 'utf-8')); } catch {}\n }\n\n const existingIdx = tracker.findIndex((e) => e.agent_id === agentId);\n if (existingIdx !== -1) {\n const entry = tracker[existingIdx];\n entry.resume_count = ((entry.resume_count as number) || 0) + 1;\n entry.last_resumed_at = new Date().toISOString();\n entry.status = 'running';\n } else {\n tracker.push({ harness_id: HARNESS_ID, agent_name: agentType, agent_id: agentId, started_at: new Date().toISOString(), resume_count: 0, status: 'running' });\n }\n\n ensureDir(HARNESS_STATE_ROOT);\n writeFileSync(trackerPath, JSON.stringify(tracker, null, 2));\n\n const role = extractRole(agentType);\n if (role !== null) {\n const index = buildCoreIndex();\n if (index !== '') {\n respond({ continue: true, additionalContext: index });\n return;\n }\n }\n pass();\n}\n\nfunction handleSubagentStop(event: Record<string, unknown>): void {\n const agentId = String(event.agent_id ?? '');\n const agentType = String(event.agent_type ?? '');\n const lastMsg = String(event.last_assistant_message ?? event.last_message ?? '');\n\n const trackerPath = join(HARNESS_STATE_ROOT, 'agent-tracker.json');\n if (existsSync(trackerPath)) {\n try {\n const tracker = JSON.parse(readFileSync(trackerPath, 'utf-8')) as Record<string, unknown>[];\n const entry = tracker.find((a) => a.agent_id === agentId);\n if (entry) {\n entry.status = 'completed';\n entry.last_message = lastMsg;\n entry.stopped_at = new Date().toISOString();\n }\n try {\n const toolLogPath = join(HARNESS_STATE_ROOT, 'tool-log.jsonl');\n if (existsSync(toolLogPath)) {\n const lines = readFileSync(toolLogPath, 'utf-8').split('\\n').filter(Boolean);\n const filesSet = new Set<string>();\n for (const line of lines) {\n try {\n const logEntry = JSON.parse(line);\n if (logEntry.agent_id === agentId && logEntry.file) {\n filesSet.add(logEntry.file);\n }\n } catch (e) { /* skip malformed line */ }\n }\n if (entry) {\n entry.files_touched = Array.from(filesSet);\n }\n }\n } catch (e) {\n // silent fail\n }\n writeFileSync(trackerPath, JSON.stringify(tracker, null, 2));\n } catch {}\n }\n\n // [run] \uBAA8\uB4DC: \uC5D0\uC774\uC804\uD2B8\uC758 \uB2F4\uB2F9 \uD0DC\uC2A4\uD06C\uAC00 \uBBF8\uC644\uB8CC\uBA74 \uACBD\uACE0\n const tasksPath = join(STATE_ROOT, 'tasks.json');\n if (existsSync(tasksPath)) {\n try {\n const tasksData = JSON.parse(readFileSync(tasksPath, 'utf-8'));\n const tasks = tasksData.tasks ?? [];\n const ownedPending = tasks.filter((t: { owner?: string; status: string }) =>\n t.owner === agentType && (t.status === 'pending' || t.status === 'in_progress')\n );\n if (ownedPending.length > 0) {\n const ids = ownedPending.map((t: { id: number }) => `#${t.id}`).join(', ');\n respond({\n continue: true,\n additionalContext: `<nexus>Agent \"${agentType}\" stopped but has ${ownedPending.length} incomplete task(s): ${ids}. Re-spawn the agent or complete the work manually.</nexus>`,\n });\n return;\n }\n } catch {}\n }\n\n pass();\n}\n\n// --- PostCompact \uC774\uBCA4\uD2B8 \uCC98\uB9AC: \uCEF4\uD329\uC158 \uD6C4 \uC138\uC158 \uC0C1\uD0DC \uBCF5\uC6D0 ---\n\nfunction handlePostCompact(_event: Record<string, unknown>): void {\n const lines: string[] = ['Session restored after compaction.'];\n\n // Mode + tasks\n const summary = readTasksSummary(STATE_ROOT);\n if (summary.exists) {\n lines.push(`[Mode]: run (${summary.pending} pending / ${summary.completed} completed tasks)`);\n }\n\n // Plan\n const planFilePath = join(STATE_ROOT, 'plan.json');\n if (existsSync(planFilePath)) {\n try {\n const data = JSON.parse(readFileSync(planFilePath, 'utf-8'));\n const issues = data.issues ?? [];\n const discussing = issues.find((i: { status: string }) => i.status === 'discussing');\n const pending = issues.filter((i: { status: string }) => i.status === 'pending');\n let issueInfo: string;\n if (discussing) {\n issueInfo = `issue #${discussing.id} discussing, ${pending.length > 0 ? `#${pending.map((i: { id: number }) => i.id).join('-#')} pending` : 'none pending'}`;\n } else if (pending.length > 0) {\n issueInfo = `#${pending.map((i: { id: number }) => i.id).join('-#')} pending`;\n } else {\n issueInfo = 'all issues decided';\n }\n lines.push(`[Plan]: \"${data.topic}\" \u2014 ${issueInfo}`);\n } catch {}\n }\n\n // Knowledge file count (memory, context, rules)\n try {\n const nexusRoot = join(process.cwd(), '.nexus');\n const rulesRoot = join(nexusRoot, 'rules');\n const folders: Array<[string, string]> = [\n ['memory', MEMORY_ROOT],\n ['context', CONTEXT_ROOT],\n ['rules', rulesRoot],\n ];\n const folderCounts: string[] = [];\n let totalFiles = 0;\n for (const [label, folderPath] of folders) {\n if (existsSync(folderPath)) {\n const count = readdirSync(folderPath).filter(f => f.endsWith('.md')).length;\n if (count > 0) {\n folderCounts.push(`${count} ${label}`);\n totalFiles += count;\n }\n }\n }\n if (totalFiles > 0) {\n lines.push(`[Knowledge]: ${folderCounts.join(', ')}`);\n }\n } catch {}\n\n // Agents\n const trackerPath = join(HARNESS_STATE_ROOT, 'agent-tracker.json');\n if (existsSync(trackerPath)) {\n try {\n const tracker = JSON.parse(readFileSync(trackerPath, 'utf-8')) as Array<{ agent_type?: string; status?: string }>;\n if (tracker.length > 0) {\n const agentParts = tracker.map(a => `${a.agent_type ?? 'unknown'} (${a.status ?? 'unknown'})`);\n lines.push(`[Agents]: ${agentParts.join(', ')}`);\n }\n } catch {}\n }\n\n const snapshot = `<nexus>\\n${lines.join('\\n')}\\n</nexus>`;\n respond({ continue: true, additionalContext: snapshot });\n}\n\n// --- \uBA54\uC778 ---\n\nasync function main() {\n const input = await readStdin();\n const event = JSON.parse(input);\n\n const eventName = event.hook_event_name ?? '';\n\n switch (eventName) {\n case 'SessionStart':\n handleSessionStart(event);\n break;\n case 'SubagentStart':\n handleSubagentStart(event);\n break;\n case 'SubagentStop':\n handleSubagentStop(event);\n break;\n case 'PreToolUse':\n handlePreToolUse(event);\n break;\n case 'PostToolUse':\n handlePostToolUse(event);\n break;\n case 'UserPromptSubmit':\n handleUserPromptSubmit(event);\n break;\n case 'Stop':\n handleStop(event);\n break;\n case 'PreCompact':\n pass();\n break;\n case 'PostCompact':\n handlePostCompact(event);\n break;\n default:\n pass();\n }\n}\n\nmain().catch(() => {\n respond({ continue: true });\n});\n", "/** \uD6C5 \uC2A4\uD06C\uB9BD\uD2B8 \uACF5\uD1B5 I/O: stdin JSON \uC77D\uAE30 + stdout JSON \uC751\uB2F5 */\n\nexport function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n process.stdin.on('data', (chunk: Buffer) => (data += chunk));\n process.stdin.on('end', () => resolve(data));\n });\n}\n\nexport function respond(obj: Record<string, unknown>): void {\n process.stdout.write(JSON.stringify(obj));\n}\n\nexport function pass(): void {\n respond({ continue: true });\n}\n", "import { resolve, join } from 'path';\nimport { existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { execSync } from 'child_process';\n\n/** \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8 (.git\uC774 \uC788\uB294 \uB514\uB809\uD1A0\uB9AC) */\nexport function findProjectRoot(startDir?: string): string {\n let dir = startDir ?? process.cwd();\n while (dir !== '/') {\n if (existsSync(join(dir, '.git'))) return dir;\n dir = resolve(dir, '..');\n }\n return startDir ?? process.cwd();\n}\n\nconst PROJECT_ROOT = findProjectRoot();\n\n/** .nexus/ \u2014 \uB7F0\uD0C0\uC784 \uC0C1\uD0DC */\nexport const NEXUS_ROOT = process.env.NEXUS_RUNTIME_ROOT || join(PROJECT_ROOT, '.nexus');\n\n/** .nexus/state/ \u2014 \uB7F0\uD0C0\uC784 \uC0C1\uD0DC \uD30C\uC77C */\nexport const STATE_ROOT = join(NEXUS_ROOT, 'state');\n\n/** harness identifier (npm package name\uC758 \uB9C8\uC9C0\uB9C9 \uC138\uADF8\uBA3C\uD2B8) */\nexport const HARNESS_ID = 'claude-nexus';\n\n/** .nexus/state/claude-nexus/ \u2014 harness-local \uC0C1\uD0DC \uD30C\uC77C */\nexport const HARNESS_STATE_ROOT = join(STATE_ROOT, HARNESS_ID);\n\n/** .nexus/memory/ \u2014 \uC5D0\uC774\uC804\uD2B8 \uACF5\uC720 \uBA54\uBAA8\uB9AC */\nexport const MEMORY_ROOT = join(NEXUS_ROOT, 'memory');\n\n/** .nexus/context/ \u2014 \uD504\uB85C\uC81D\uD2B8 \uCEE8\uD14D\uC2A4\uD2B8 */\nexport const CONTEXT_ROOT = join(NEXUS_ROOT, 'context');\n\n/** \uB8F0 \uD30C\uC77C \uACBD\uB85C */\nexport function rulesPath(name: string): string {\n return join(NEXUS_ROOT, 'rules', `${name}.md`);\n}\n\n/** \uB514\uB809\uD1A0\uB9AC \uC0DD\uC131 (\uC7AC\uADC0) */\nexport function ensureDir(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\n/** \uD604\uC7AC git \uBE0C\uB79C\uCE58\uBA85 \uBC18\uD658. git \uC5C6\uC73C\uBA74 '_default' */\nexport function getCurrentBranch(): string {\n try {\n return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();\n } catch {\n try {\n return execSync('git symbolic-ref --short HEAD', { encoding: 'utf8' }).trim();\n } catch {\n return '_default';\n }\n }\n}\n\nconst GITIGNORE_CONTENT = `# Nexus: whitelist tracked files, ignore everything else\n*\n!.gitignore\n!memory/\n!memory/**\n!context/\n!context/**\n!history.json\n!rules/\n!rules/**\n`;\n\nexport function ensureNexusStructure(): void {\n ensureDir(NEXUS_ROOT);\n ensureDir(STATE_ROOT);\n ensureDir(HARNESS_STATE_ROOT);\n const gitignorePath = join(NEXUS_ROOT, '.gitignore');\n if (!existsSync(gitignorePath)) {\n writeFileSync(gitignorePath, GITIGNORE_CONTENT);\n }\n}\n", "import { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\n\nexport interface TasksSummary {\n exists: boolean;\n total: number;\n completed: number;\n pending: number;\n allCompleted: boolean;\n}\n\nexport function readTasksSummary(branchRoot: string): TasksSummary {\n const tasksPath = join(branchRoot, 'tasks.json');\n if (!existsSync(tasksPath)) return { exists: false, total: 0, completed: 0, pending: 0, allCompleted: false };\n try {\n const data = JSON.parse(readFileSync(tasksPath, 'utf-8'));\n const tasks: Array<{ status: string }> = data.tasks ?? [];\n const completed = tasks.filter(t => t.status === 'completed').length;\n const pending = tasks.length - completed;\n return {\n exists: true,\n total: tasks.length,\n completed,\n pending,\n allCompleted: tasks.length > 0 && pending === 0,\n };\n } catch {\n return { exists: false, total: 0, completed: 0, pending: 0, allCompleted: false };\n }\n}\n", "// \uBAA8\uB4E0 \uC5D0\uC774\uC804\uD2B8\uC5D0\uAC8C memory, context, rules \uD3F4\uB354\uAC00 \uB3D9\uC77C\uD558\uAC8C \uB178\uCD9C\uB428\nexport const AGENT_ROLES = [\n 'architect',\n 'postdoc',\n 'designer',\n 'strategist',\n 'engineer',\n 'researcher',\n 'writer',\n 'tester',\n 'reviewer',\n] as const;\n\nexport type AgentRole = typeof AGENT_ROLES[number];\n\n/** 'claude-nexus:engineer' \u2192 'engineer'. nexus \uC5D0\uC774\uC804\uD2B8\uAC00 \uC544\uB2C8\uBA74 null \uBC18\uD658 */\nexport function extractRole(agentType: string): string | null {\n const prefix = 'claude-nexus:';\n if (!agentType.startsWith(prefix)) return null;\n const role = agentType.slice(prefix.length);\n return (AGENT_ROLES as readonly string[]).includes(role) ? role : null;\n}\n\n/** @deprecated \uD50C\uB7AB \uAD6C\uC870\uB85C \uC804\uD658\uB428 \u2014 gate.ts \uC5C5\uB370\uC774\uD2B8 \uD6C4 \uC81C\uAC70 \uC608\uC815 */\nexport function getAllowedLayers(_role: string): string[] {\n return [];\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["// Gate \uD6C5: Stop (Task \uCC28\uB2E8) + UserPromptSubmit (\uD0A4\uC6CC\uB4DC \uAC10\uC9C0)\nimport { readStdin, respond, pass } from '../shared/hook-io.js';\nimport { STATE_ROOT, HARNESS_STATE_ROOT, HARNESS_ID, MEMORY_ROOT, CONTEXT_ROOT, ensureDir, ensureNexusStructure } from '../shared/paths.js';\nimport { readTasksSummary } from '../shared/tasks.js';\nimport { extractRole } from '../shared/matrix.js';\nimport { existsSync, readFileSync, writeFileSync, appendFileSync, readdirSync } from 'fs';\nimport { join, basename } from 'path';\nimport { homedir } from 'os';\n\nconst TASK_PIPELINE = `\nTASK PIPELINE (mandatory for all file modifications):\n1. Check plan.json issues for prior decisions \u2014 reference relevant plan_issue IDs in nx_task_add(plan_issue=N).\n2. Decompose work into discrete tasks \u2192 call nx_task_add for EACH task.\n3. Edit/Write tools are BLOCKED without tasks.json.\n4. As each task completes \u2192 nx_task_update(id, \"completed\").\n5. All tasks done \u2192 ask user \"close\uD560\uAE4C\uC694?\" (team mode) or nx_task_close directly (Lead solo).`;\n\nfunction taskPipelineMessage(modeSpecific: string): string {\n // Insert TASK_PIPELINE before the closing </nexus> tag\n return modeSpecific.replace('</nexus>', `${TASK_PIPELINE}</nexus>`);\n}\n\n// --- CLAUDE.md \uC790\uB3D9 \uB3D9\uAE30\uD654 ---\n\nconst MARKER_START = '<!-- NEXUS:START -->';\nconst MARKER_END = '<!-- NEXUS:END -->';\nconst PLUGIN_ROOT = process.env.CLAUDE_PLUGIN_ROOT ?? '';\n\nfunction extractMarkerContent(fileContent: string): string | null {\n const startIdx = fileContent.indexOf(MARKER_START);\n const endIdx = fileContent.indexOf(MARKER_END);\n if (startIdx === -1 || endIdx === -1) return null;\n return fileContent.slice(startIdx + MARKER_START.length, endIdx).trim();\n}\n\nfunction replaceMarkerContent(fileContent: string, newContent: string): string {\n const startIdx = fileContent.indexOf(MARKER_START);\n const endIdx = fileContent.indexOf(MARKER_END);\n return fileContent.slice(0, startIdx + MARKER_START.length) + '\\n' + newContent + '\\n' + fileContent.slice(endIdx);\n}\n\nfunction handleClaudeMdSync(): string | null {\n // Read template\n const templatePath = join(PLUGIN_ROOT, 'templates', 'nexus-section.md');\n if (!PLUGIN_ROOT || !existsSync(templatePath)) return null;\n const template = readFileSync(templatePath, 'utf-8').trim();\n\n // --- Global CLAUDE.md auto-update ---\n const globalClaudeMd = join(homedir(), '.claude', 'CLAUDE.md');\n if (existsSync(globalClaudeMd)) {\n const globalContent = readFileSync(globalClaudeMd, 'utf-8');\n const globalMarker = extractMarkerContent(globalContent);\n if (globalMarker !== null && globalMarker !== template) {\n const updated = replaceMarkerContent(globalContent, template);\n writeFileSync(globalClaudeMd, updated);\n }\n }\n\n // --- Project CLAUDE.md auto-sync ---\n const projectClaudeMd = join(process.cwd(), 'CLAUDE.md');\n\n if (existsSync(projectClaudeMd)) {\n const projectContent = readFileSync(projectClaudeMd, 'utf-8');\n const projectMarker = extractMarkerContent(projectContent);\n\n if (projectMarker !== null && projectMarker !== template) {\n const updated = replaceMarkerContent(projectContent, template);\n writeFileSync(projectClaudeMd, updated);\n }\n }\n\n return null;\n}\n\n// --- Stop \uC774\uBCA4\uD2B8 \uCC98\uB9AC ---\n\n/** \uB9C8\uC9C0\uB9C9 nx-sync \uC774\uD6C4 N\uC0AC\uC774\uD074 \uACBD\uACFC \uC2DC \uB3D9\uAE30\uD654 \uB11B\uC9C0 \uBC18\uD658 */\nfunction getSyncNudge(): string | null {\n const historyPath = join(process.cwd(), '.nexus', 'history.json');\n if (!existsSync(historyPath)) return null;\n try {\n const history = JSON.parse(readFileSync(historyPath, 'utf-8'));\n const cycles = history.cycles ?? [];\n if (cycles.length === 0) return null;\n // \uB9C8\uC9C0\uB9C9 sync \uC0AC\uC774\uD074 \uCC3E\uAE30\n const lastSyncIdx = cycles.findLastIndex((c: { topics?: string[] }) =>\n c.topics?.some((t: string) => /sync/i.test(t))\n );\n const cyclesSinceSync = lastSyncIdx === -1 ? cycles.length : cycles.length - 1 - lastSyncIdx;\n if (cyclesSinceSync >= 3) {\n return `<nexus>Core knowledge may be outdated (${cyclesSinceSync} cycles since last sync). Consider running /claude-nexus:nx-sync.</nexus>`;\n }\n } catch {}\n return null;\n}\n\nfunction handleStop(event: Record<string, unknown>): void {\n const summary = readTasksSummary(STATE_ROOT);\n if (!summary.exists) {\n // \uB3D9\uAE30\uD654 \uB11B\uC9C0\uB9CC \uD655\uC778\n const syncNudge = getSyncNudge();\n if (syncNudge) {\n respond({ continue: true, additionalContext: syncNudge });\n return;\n }\n pass();\n return;\n }\n\n if (summary.pending > 0) {\n respond({\n continue: true,\n additionalContext: `<nexus>${summary.pending} tasks pending in tasks.json. Before stopping:\\n1. Review each pending task \u2014 verify if work is actually done.\\n2. Done \u2192 nx_task_update(id, \"completed\").\\n3. Not done \u2192 complete the work first.\\n4. When all completed \u2192 nx_task_close to archive.</nexus>`,\n });\n return;\n }\n\n // all completed \u2192 1\uD68C\uB9CC \uCC28\uB2E8 \uD6C4 \uD574\uC81C (\uBB34\uD55C \uB8E8\uD504 \uBC29\uC9C0)\n // stop_hook_active: \uD50C\uB7AB\uD3FC\uC774 \uC81C\uACF5\uD558\uB294 \uC7AC\uC9C4\uC785 \uD50C\uB798\uADF8 \u2014 true\uBA74 \uC774\uBBF8 \uACBD\uACE0 \uD6C4 \uC7AC\uC2DC\uB3C4\n if (event.stop_hook_active) {\n pass();\n return;\n }\n respond({\n continue: true,\n additionalContext: `<nexus>All tasks completed. Call nx_task_close now.</nexus>`,\n });\n}\n\n// --- PreToolUse \uC774\uBCA4\uD2B8 \uCC98\uB9AC: Edit/Write \uD0DC\uC2A4\uD06C \uD30C\uC774\uD504\uB77C\uC778 \uCC28\uB2E8 ---\n// NOTE: per-agent capability \uCC28\uB2E8\uC740 agents/*.md frontmatter\uC758 disallowedTools\n// \uD544\uB4DC\uB97C Claude Code \uB7F0\uD0C0\uC784\uC774 \uCC98\uB9AC. gate.ts PreToolUse\uB294 workflow \uC0C1\uD0DC\uB9CC \uB2F4\uB2F9.\n\n/** \uC608\uC678 \uACBD\uB85C: Nexus \uB0B4\uBD80 \uD30C\uC77C \uBC0F setup/sync \uB300\uC0C1 \uD30C\uC77C\uC740 tasks.json \uC5C6\uC774\uB3C4 \uC218\uC815 \uD5C8\uC6A9 */\nfunction isNexusInternalPath(filePath: string): boolean {\n // .nexus/state/ \uB7F0\uD0C0\uC784 \uC0C1\uD0DC \u2014 task \uC5C6\uC774 \uC218\uC815 \uD5C8\uC6A9\n if (/[\\\\/]\\.nexus[\\\\/]state[\\\\/]/.test(filePath)) return true;\n // .claude/settings.json \u2014 setup \uC2A4\uD0AC \uB300\uC0C1\n if (/[\\\\/]\\.claude[\\\\/]settings\\.json$/.test(filePath)) return true;\n // CLAUDE.md \u2014 sync \uC2A4\uD0AC \uB300\uC0C1\n if (/[\\\\/]CLAUDE\\.md$/.test(filePath)) return true;\n return false;\n}\n\nfunction handlePreToolUse(event: Record<string, unknown>): void {\n const toolName = (event.tool_name ?? '') as string;\n\n // Edit/Write \uB3C4\uAD6C: [run] \uBAA8\uB4DC(tasks.json \uC874\uC7AC)\uC5D0\uC11C\uB9CC \uCC28\uB2E8 (Nexus \uB0B4\uBD80 \uACBD\uB85C \uC81C\uC678)\n if (toolName === 'Edit' || toolName === 'Write') {\n const tasksPath = join(STATE_ROOT, 'tasks.json');\n if (!existsSync(tasksPath)) {\n // tasks.json \uC5C6\uC74C = [run] \uBAA8\uB4DC\uAC00 \uC544\uB2D8 \u2192 \uC790\uC720 \uC218\uC815 \uD5C8\uC6A9\n pass();\n return;\n }\n\n const toolInput = event.tool_input as Record<string, unknown> | undefined;\n const filePath = (toolInput?.file_path ?? '') as string;\n\n if (!isNexusInternalPath(filePath)) {\n const summary = readTasksSummary(STATE_ROOT);\n // [run] \uBAA8\uB4DC: \uBAA8\uB4E0 \uD0DC\uC2A4\uD06C \uC644\uB8CC \uC2DC nx_task_close \uAC15\uC81C\n if (summary.allCompleted || summary.total === 0) {\n respond({\n decision: 'block',\n reason: '<nexus>All tasks completed. Call nx_task_close to archive, or nx_task_add to register additional tasks.</nexus>',\n });\n return;\n }\n }\n\n pass();\n return;\n }\n\n pass();\n}\n\n// --- UserPromptSubmit \uC774\uBCA4\uD2B8 \uCC98\uB9AC: \uD0A4\uC6CC\uB4DC \uAC10\uC9C0 ---\n\ninterface KeywordMatch {\n primitive: 'plan' | 'run';\n skill: string;\n}\n\n/** All tag ids with inline handlers in handleUserPromptSubmit. Cross-checked against nexus-core vocabulary/tags.yml at build time. */\nexport const HANDLED_TAG_IDS = ['plan', 'run', 'sync', 'd', 'm', 'm-gc', 'rule'] as const;\n\nconst EXPLICIT_TAGS: Record<string, KeywordMatch> = {\n plan: { primitive: 'plan', skill: 'claude-nexus:nx-plan' },\n 'plan:auto': { primitive: 'plan', skill: 'claude-nexus:nx-plan' },\n run: { primitive: 'run', skill: 'claude-nexus:nx-run' },\n};\n\nfunction detectKeywords(prompt: string): KeywordMatch | null {\n // \uBA85\uC2DC\uC801 \uD0DC\uADF8 [plan] / [plan:auto] / [run] \u2014 \uD56D\uC0C1 \uD655\uC815\n const tagMatch = prompt.match(/\\[(plan(?::auto)?|run)\\]/i);\n if (tagMatch) {\n const tag = tagMatch[1].toLowerCase();\n if (tag in EXPLICIT_TAGS) return EXPLICIT_TAGS[tag];\n }\n return null;\n}\n\nfunction getTasksReminder(): string | null {\n const summary = readTasksSummary(STATE_ROOT);\n if (!summary.exists) return null;\n if (summary.pending > 0) {\n return `<nexus>${summary.pending} pending tasks. Complete work \u2192 nx_task_update(id, \"completed\") for each done task. Archive with nx_task_close when all complete.</nexus>`;\n }\n return `<nexus>All ${summary.total} tasks completed but not archived. MANDATORY: Call nx_task_close to archive this cycle.</nexus>`;\n}\n\nfunction getPlanReminder(): string | null {\n const planFilePath = join(STATE_ROOT, 'plan.json');\n if (!existsSync(planFilePath)) return null;\n try {\n const data = JSON.parse(readFileSync(planFilePath, 'utf-8'));\n const issues = data.issues ?? [];\n const pending = issues.filter((i: { status: string }) => i.status === 'pending');\n const current = pending.length > 0\n ? `Next: #${pending[0].id} \"${pending[0].title}\"`\n : 'All issues decided.';\n return `<nexus>Plan: \"${data.topic}\" | ${current} | ${pending.length} pending\\nPresent comparison table with pros/cons/recommendation. Record decisions with [d].</nexus>`;\n } catch {\n return null;\n }\n}\n\n// --- Core Knowledge \uC778\uB371\uC2A4 \uBE4C\uB4DC ---\n\nfunction scanFolderEntries(folderPath: string): string[] {\n if (!existsSync(folderPath)) return [];\n let files: string[];\n try {\n files = readdirSync(folderPath).filter(f => f.endsWith('.md'));\n } catch {\n return [];\n }\n const entries: string[] = [];\n for (const file of files) {\n const name = basename(file, '.md');\n const filePath = join(folderPath, file);\n let tags = '';\n try {\n const content = readFileSync(filePath, 'utf-8');\n const tagMatch = content.match(/<!--\\s*tags:\\s*([^-]+?)\\s*-->/);\n if (tagMatch) {\n const tagList = tagMatch[1].split(',').map(t => t.trim()).filter(Boolean);\n const shortTags = tagList.slice(0, 3).join(', ');\n tags = ` [${shortTags}]`;\n }\n } catch {}\n entries.push(`${name}${tags}`);\n }\n return entries;\n}\n\nfunction buildCoreIndex(): string {\n const nexusRoot = join(process.cwd(), '.nexus');\n const rulesRoot = join(nexusRoot, 'rules');\n\n const layerLines: string[] = [];\n\n const memoryEntries = scanFolderEntries(MEMORY_ROOT);\n if (memoryEntries.length > 0) {\n layerLines.push(`memory: ${memoryEntries.join(', ')}`);\n }\n\n const contextEntries = scanFolderEntries(CONTEXT_ROOT);\n if (contextEntries.length > 0) {\n layerLines.push(`context: ${contextEntries.join(', ')}`);\n }\n\n const rulesEntries = scanFolderEntries(rulesRoot);\n if (rulesEntries.length > 0) {\n layerLines.push(`rules: ${rulesEntries.join(', ')}`);\n }\n\n if (layerLines.length === 0) return '';\n\n const header = '[.nexus Knowledge]';\n const result = `${header}\\n${layerLines.join('\\n')}`;\n return result.length <= 2000 ? result : result.slice(0, 1997) + '...';\n}\n\n/** additionalContext\uC5D0 notices\uB97C \uC790\uB3D9 \uBCD1\uD569 */\nfunction withNotices(base: string, tasksReminder: string | null, claudeMdNotice: string | null, planReminder?: string | null): string {\n return [planReminder, tasksReminder, base, claudeMdNotice].filter(Boolean).join('\\n');\n}\n\n// --- \uAC1C\uBCC4 \uD504\uB9AC\uBBF8\uD2F0\uBE0C \uD578\uB4E4\uB7EC ---\n\ntype PrimitiveHandler = (params: {\n prompt: string;\n tasksReminder: string | null;\n claudeMdNotice: string | null;\n}) => void;\n\nfunction handleRuleMode({ tasksReminder, claudeMdNotice, ruleTags }: {\n prompt: string;\n tasksReminder: string | null;\n claudeMdNotice: string | null;\n ruleTags: string[] | null;\n}): void {\n const tagInfo = ruleTags\n ? `Tags: [${ruleTags.join(', ')}] \u2014 include at top of rule file as <!-- tags: ${ruleTags.join(', ')} -->.`\n : 'Tags: none \u2014 infer appropriate tags from rule content and add them.';\n\n const base = `<nexus>Rule mode \u2014 saving user instruction as a project rule.\n${tagInfo}\n1. Extract and clean up rule content from the user message.\n2. Save to .nexus/rules/{name}.md via the Write tool.\nRules are git-tracked and auto-delivered to agents via SubagentStart hook index injection.\nTask pipeline not required \u2014 save directly.</nexus>`;\n\n respond({\n continue: true,\n additionalContext: withNotices(base, tasksReminder, claudeMdNotice),\n });\n}\n\nfunction handlePlanMode({ prompt, tasksReminder, claudeMdNotice }: Parameters<PrimitiveHandler>[0]): void {\n // 2\uCC28 \uC548\uC804\uB9DD: \uC774\uC804 \uC0AC\uC774\uD074\uC758 stale tasks.json \uAC10\uC9C0\n const staleSummary = readTasksSummary(STATE_ROOT);\n if (staleSummary.exists && staleSummary.allCompleted) {\n respond({\n continue: true,\n additionalContext: `<nexus>\u26A0 Previous cycle not closed \u2014 tasks.json exists with all tasks completed. Call nx_task_close first to archive before starting a new plan.</nexus>`,\n });\n return;\n }\n\n const isAuto = /\\[plan:auto\\]/i.test(prompt);\n const planFile = join(STATE_ROOT, 'plan.json');\n const hasExistingSession = existsSync(planFile);\n\n let hints = '';\n if (hasExistingSession) {\n hints = '\\nExisting plan session detected \u2014 check nx_plan_status to resume.';\n }\n if (isAuto) {\n hints += '\\nAuto mode requested \u2014 pass args: \"auto\" to the skill.';\n }\n\n const base = `<nexus>BLOCKING: Invoke Skill tool with skill=\"claude-nexus:nx-plan\"${isAuto ? ', args: \"auto\"' : ''} BEFORE any other action. Do NOT attempt planning without loading the skill first.${hints}</nexus>`;\n const coreIndex = buildCoreIndex();\n const coreSection = coreIndex\n ? `\\n${coreIndex}\\nCheck core/reference/ BEFORE web searching for known topics.`\n : '';\n respond({\n continue: true,\n additionalContext: withNotices(base + coreSection, tasksReminder, claudeMdNotice, null),\n });\n}\n\nfunction handleRunMode({ tasksReminder, claudeMdNotice }: Parameters<PrimitiveHandler>[0]): void {\n const planReminder = getPlanReminder();\n const tasksSummary = readTasksSummary(STATE_ROOT);\n\n let hints = '';\n if (!tasksSummary.exists) {\n hints = '\\ntasks.json absent \u2014 plan required before execution. Suggest [plan:auto] or [plan].';\n } else {\n hints = `\\ntasks.json: ${tasksSummary.pending} pending, ${tasksSummary.total - tasksSummary.pending} completed of ${tasksSummary.total} tasks.`;\n }\n\n const coreIndex = buildCoreIndex();\n const coreSection = coreIndex ? `\\n${coreIndex}` : '';\n const base = `<nexus>BLOCKING: Invoke Skill tool with skill=\"claude-nexus:nx-run\" BEFORE any other action. Do NOT attempt execution without loading the skill first.${hints}</nexus>${coreSection}`;\n respond({\n continue: true,\n additionalContext: withNotices(taskPipelineMessage(base), tasksReminder, claudeMdNotice, planReminder),\n });\n}\n\nconst PRIMITIVE_HANDLERS: Record<string, PrimitiveHandler> = {\n plan: handlePlanMode,\n run: handleRunMode,\n};\n\nfunction handleUserPromptSubmit(event: Record<string, unknown>): void {\n const claudeMdNotice = handleClaudeMdSync();\n const tasksReminder = getTasksReminder();\n const planReminder = getPlanReminder();\n\n const raw = event.prompt ?? event.user_prompt ?? '';\n const prompt = typeof raw === 'string' ? raw : String(raw);\n if (!prompt) { pass(); return; }\n\n // [d] \uACB0\uC815 \uD0DC\uADF8 \uAC10\uC9C0 \u2014 plan.json \uC720\uBB34\uB85C \uB3C4\uAD6C \uBD84\uAE30 + \uD589\uB3D9 \uADDC\uCE59 \uC8FC\uC785\n const dTag = prompt.match(/\\[d\\]/i);\n if (dTag) {\n const postDecisionRules = `\\n\\nRecord decision only. For implementation, use [run].`;\n const planFile = join(STATE_ROOT, 'plan.json');\n if (existsSync(planFile)) {\n respond({\n continue: true,\n additionalContext: withNotices(`<nexus>Decision tag detected in plan mode. Use nx_plan_decide(issue_id, decision) to record.${postDecisionRules}</nexus>`, tasksReminder, claudeMdNotice, planReminder),\n });\n } else {\n respond({\n continue: true,\n additionalContext: withNotices(`<nexus>[d]\uB294 plan \uC138\uC158 \uC548\uC5D0\uC11C\uB9CC \uC720\uD6A8\uD569\uB2C8\uB2E4. [plan] \uD0DC\uADF8\uB85C \uD50C\uB798\uB2DD\uC744 \uBA3C\uC800 \uC2DC\uC791\uD558\uC138\uC694.${postDecisionRules}</nexus>`, tasksReminder, claudeMdNotice, null),\n });\n }\n return;\n }\n\n // [m] \uBA54\uBAA8\uB9AC \uC800\uC7A5 \uD0DC\uADF8 \uAC10\uC9C0\n const mTag = prompt.match(/\\[m(?::([^\\]]*))?\\]/i);\n if (mTag) {\n const subCmd = mTag[1]?.trim().toLowerCase();\n if (subCmd === 'gc') {\n respond({\n continue: true,\n additionalContext: withNotices(\n `<nexus>Memory GC mode \u2014 \uAE30\uC874 .nexus/memory/ \uD30C\uC77C\uC744 Glob\uC73C\uB85C \uD655\uC778\uD558\uACE0, \uAD00\uB828 \uBA54\uBAA8\uB97C \uBCD1\uD569/\uC0AD\uC81C\uD558\uC5EC \uC815\uB9AC\uD558\uB77C. Write \uB3C4\uAD6C\uB85C \uC800\uC7A5.</nexus>`,\n tasksReminder,\n claudeMdNotice,\n ),\n });\n } else {\n const userContent = prompt.replace(/\\[m(?::([^\\]]*))?\\]/i, '').trim();\n respond({\n continue: true,\n additionalContext: withNotices(\n `<nexus>Memory save mode \u2014 \uB2E4\uC74C \uB0B4\uC6A9\uC744 \uC555\uCD95\u00B7\uC815\uC81C\uD558\uC5EC .nexus/memory/{\uC801\uC808\uD55C_\uD1A0\uD53D}.md\uC5D0 Write\uB85C \uC800\uC7A5\uD558\uB77C. \uAE30\uC874 \uD30C\uC77C \uC911 \uAD00\uB828\uB41C \uAC83\uC774 \uC788\uC73C\uBA74 \uC5C5\uB370\uC774\uD2B8\uD558\uACE0, \uC5C6\uC73C\uBA74 \uC0C8 \uD30C\uC77C \uC0DD\uC131. \uC6D0\uBB38: ${userContent}</nexus>`,\n tasksReminder,\n claudeMdNotice,\n ),\n });\n }\n return;\n }\n\n // [rule] \uADDC\uCE59 \uC800\uC7A5 \uD0DC\uADF8 \uAC10\uC9C0\n const ruleMatch = prompt.match(/\\[rule(?::([^\\]]+))?\\]/i);\n if (ruleMatch) {\n const rawTags = ruleMatch[1];\n const ruleTags = rawTags ? rawTags.split(',').map(t => t.trim()).filter(Boolean) : null;\n handleRuleMode({ prompt, tasksReminder, claudeMdNotice, ruleTags });\n return;\n }\n\n // [sync] \uCEE8\uD14D\uC2A4\uD2B8 \uB3D9\uAE30\uD654 \uD0DC\uADF8 \uAC10\uC9C0\n if (/\\[sync\\]/i.test(prompt)) {\n respond({\n continue: true,\n additionalContext: withNotices(\n `<nexus>BLOCKING: Invoke Skill tool with skill=\"claude-nexus:nx-sync\" [before any other action].</nexus>`,\n tasksReminder,\n claudeMdNotice,\n ),\n });\n return;\n }\n\n const match = detectKeywords(prompt);\n if (match) {\n const handler = PRIMITIVE_HANDLERS[match.primitive];\n if (handler) {\n handler({ prompt, tasksReminder, claudeMdNotice });\n return;\n }\n }\n\n // \uD0DC\uADF8 \uC5C6\uC74C \u2014 \uC790\uC720 \uBAA8\uB4DC\n const summary = readTasksSummary(STATE_ROOT);\n\n // tasks.json \uC788\uC74C(=[run] \uC9C4\uD589 \uC911) + pending \u2192 \uC2A4\uB9C8\uD2B8 resume\n if (summary.exists && summary.pending > 0) {\n respond({\n continue: true,\n additionalContext: withNotices(`<nexus>Active [run] session detected (${summary.pending} pending tasks). Resume execution or use nx_task_close to archive.</nexus>`, tasksReminder, claudeMdNotice, planReminder),\n });\n return;\n }\n\n // tasks.json \uC788\uC74C + all completed \u2192 stale cycle\n if (summary.exists && (summary.allCompleted || summary.total === 0)) {\n respond({\n continue: true,\n additionalContext: withNotices(`<nexus>Stale tasks.json from previous [run]. Call nx_task_close to archive.</nexus>`, tasksReminder, claudeMdNotice, planReminder),\n });\n return;\n }\n\n // tasks.json \uC5C6\uC74C = \uC790\uC720 \uBAA8\uB4DC. \uCD5C\uC18C\uD55C\uC758 \uCEE8\uD14D\uC2A4\uD2B8\uB9CC \uC8FC\uC785.\n const notices = [planReminder, claudeMdNotice].filter(Boolean).join('\\n');\n if (notices) {\n respond({ continue: true, additionalContext: notices });\n } else {\n pass();\n }\n}\n\n// --- Memory access observation (nexus-core v0.10.0 canonical) ---\n// .nexus/memory/ Read \uC774\uBCA4\uD2B8\uB97C \uAD00\uCC30\uD574 memory-access.jsonl\uC5D0 upsert by path.\n// Schema: conformance/state-schemas/memory-access.schema.json (4 required fields).\n// Lead \uACBD\uB85C\uB3C4 \uD3EC\uD568 \u2014 memory \uC720\uD6A8\uC131\uC740 \uC2E4\uC81C read \uC5EC\uBD80\uAC00 \uAE30\uC900 (agent_id ?? 'lead').\n\ninterface MemoryAccessRecord {\n path: string;\n last_accessed_ts: string;\n access_count: number;\n last_agent: string;\n}\n\nfunction handleMemoryAccessTracking(event: any): void {\n try {\n if (event.tool_name !== 'Read') return;\n const filePath: string | undefined = event.tool_input?.file_path;\n if (!filePath || !filePath.startsWith(MEMORY_ROOT)) return;\n\n const logPath = join(HARNESS_STATE_ROOT, 'memory-access.jsonl');\n const records = new Map<string, MemoryAccessRecord>();\n if (existsSync(logPath)) {\n const content = readFileSync(logPath, 'utf-8');\n for (const line of content.split('\\n')) {\n if (!line) continue;\n try {\n const rec = JSON.parse(line) as MemoryAccessRecord;\n records.set(rec.path, rec);\n } catch {}\n }\n }\n\n const existing = records.get(filePath);\n records.set(filePath, {\n path: filePath,\n last_accessed_ts: new Date().toISOString(),\n access_count: (existing?.access_count ?? 0) + 1,\n last_agent: event.agent_id ?? 'lead',\n });\n\n ensureDir(HARNESS_STATE_ROOT);\n const output = Array.from(records.values()).map(r => JSON.stringify(r)).join('\\n') + '\\n';\n writeFileSync(logPath, output);\n } catch (e) {\n // silent fail\n }\n}\n\n// --- PostToolUse \uC774\uBCA4\uD2B8 \uCC98\uB9AC: tool-log.jsonl append + memory-access tracking ---\n\nfunction handlePostToolUse(event: any): void {\n handleMemoryAccessTracking(event);\n try {\n const agentId = event.agent_id;\n if (!agentId) return; // Lead direct edit, skip\n if (!['Edit', 'Write', 'NotebookEdit'].includes(event.tool_name)) return;\n const filePath = event.tool_name === 'NotebookEdit'\n ? event.tool_input?.notebook_path\n : event.tool_input?.file_path;\n if (!filePath) return;\n const line = JSON.stringify({\n ts: new Date().toISOString(),\n agent_id: agentId,\n tool: event.tool_name,\n file: filePath,\n }) + '\\n';\n appendFileSync(join(HARNESS_STATE_ROOT, 'tool-log.jsonl'), line);\n } catch (e) {\n // silent fail\n }\n}\n\n// --- \uC138\uC158 \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC ---\n\nfunction handleSessionStart(_event: Record<string, unknown>): void {\n ensureNexusStructure();\n writeFileSync(join(HARNESS_STATE_ROOT, 'agent-tracker.json'), '[]');\n try {\n writeFileSync(join(HARNESS_STATE_ROOT, 'tool-log.jsonl'), '');\n } catch (e) {\n // silent fail\n }\n pass();\n}\n\nfunction handleSubagentStart(event: Record<string, unknown>): void {\n const agentType = String(event.agent_type ?? '');\n const agentId = String(event.agent_id ?? '');\n\n const trackerPath = join(HARNESS_STATE_ROOT, 'agent-tracker.json');\n let tracker: Record<string, unknown>[] = [];\n if (existsSync(trackerPath)) {\n try { tracker = JSON.parse(readFileSync(trackerPath, 'utf-8')); } catch {}\n }\n\n const existingIdx = tracker.findIndex((e) => e.agent_id === agentId);\n if (existingIdx !== -1) {\n const entry = tracker[existingIdx];\n entry.resume_count = ((entry.resume_count as number) || 0) + 1;\n entry.last_resumed_at = new Date().toISOString();\n entry.status = 'running';\n } else {\n tracker.push({ harness_id: HARNESS_ID, agent_name: agentType, agent_id: agentId, started_at: new Date().toISOString(), resume_count: 0, status: 'running' });\n }\n\n ensureDir(HARNESS_STATE_ROOT);\n writeFileSync(trackerPath, JSON.stringify(tracker, null, 2));\n\n const role = extractRole(agentType);\n if (role !== null) {\n const index = buildCoreIndex();\n if (index !== '') {\n respond({ continue: true, additionalContext: index });\n return;\n }\n }\n pass();\n}\n\nfunction handleSubagentStop(event: Record<string, unknown>): void {\n const agentId = String(event.agent_id ?? '');\n const agentType = String(event.agent_type ?? '');\n const lastMsg = String(event.last_assistant_message ?? event.last_message ?? '');\n\n const trackerPath = join(HARNESS_STATE_ROOT, 'agent-tracker.json');\n if (existsSync(trackerPath)) {\n try {\n const tracker = JSON.parse(readFileSync(trackerPath, 'utf-8')) as Record<string, unknown>[];\n const entry = tracker.find((a) => a.agent_id === agentId);\n if (entry) {\n entry.status = 'completed';\n entry.last_message = lastMsg;\n entry.stopped_at = new Date().toISOString();\n }\n try {\n const toolLogPath = join(HARNESS_STATE_ROOT, 'tool-log.jsonl');\n if (existsSync(toolLogPath)) {\n const lines = readFileSync(toolLogPath, 'utf-8').split('\\n').filter(Boolean);\n const filesSet = new Set<string>();\n for (const line of lines) {\n try {\n const logEntry = JSON.parse(line);\n if (logEntry.agent_id === agentId && logEntry.file) {\n filesSet.add(logEntry.file);\n }\n } catch (e) { /* skip malformed line */ }\n }\n if (entry) {\n entry.files_touched = Array.from(filesSet);\n }\n }\n } catch (e) {\n // silent fail\n }\n writeFileSync(trackerPath, JSON.stringify(tracker, null, 2));\n } catch {}\n }\n\n // [run] \uBAA8\uB4DC: \uC5D0\uC774\uC804\uD2B8\uC758 \uB2F4\uB2F9 \uD0DC\uC2A4\uD06C\uAC00 \uBBF8\uC644\uB8CC\uBA74 \uACBD\uACE0\n const tasksPath = join(STATE_ROOT, 'tasks.json');\n if (existsSync(tasksPath)) {\n try {\n const tasksData = JSON.parse(readFileSync(tasksPath, 'utf-8'));\n const tasks = tasksData.tasks ?? [];\n const ownedPending = tasks.filter((t: { owner?: string; status: string }) =>\n t.owner === agentType && (t.status === 'pending' || t.status === 'in_progress')\n );\n if (ownedPending.length > 0) {\n const ids = ownedPending.map((t: { id: number }) => `#${t.id}`).join(', ');\n respond({\n continue: true,\n additionalContext: `<nexus>Agent \"${agentType}\" stopped but has ${ownedPending.length} incomplete task(s): ${ids}. Re-spawn the agent or complete the work manually.</nexus>`,\n });\n return;\n }\n } catch {}\n }\n\n pass();\n}\n\n// --- PostCompact \uC774\uBCA4\uD2B8 \uCC98\uB9AC: \uCEF4\uD329\uC158 \uD6C4 \uC138\uC158 \uC0C1\uD0DC \uBCF5\uC6D0 ---\n\nfunction handlePostCompact(_event: Record<string, unknown>): void {\n const lines: string[] = ['Session restored after compaction.'];\n\n // Mode + tasks\n const summary = readTasksSummary(STATE_ROOT);\n if (summary.exists) {\n lines.push(`[Mode]: run (${summary.pending} pending / ${summary.completed} completed tasks)`);\n }\n\n // Plan\n const planFilePath = join(STATE_ROOT, 'plan.json');\n if (existsSync(planFilePath)) {\n try {\n const data = JSON.parse(readFileSync(planFilePath, 'utf-8'));\n const issues = data.issues ?? [];\n const discussing = issues.find((i: { status: string }) => i.status === 'discussing');\n const pending = issues.filter((i: { status: string }) => i.status === 'pending');\n let issueInfo: string;\n if (discussing) {\n issueInfo = `issue #${discussing.id} discussing, ${pending.length > 0 ? `#${pending.map((i: { id: number }) => i.id).join('-#')} pending` : 'none pending'}`;\n } else if (pending.length > 0) {\n issueInfo = `#${pending.map((i: { id: number }) => i.id).join('-#')} pending`;\n } else {\n issueInfo = 'all issues decided';\n }\n lines.push(`[Plan]: \"${data.topic}\" \u2014 ${issueInfo}`);\n } catch {}\n }\n\n // Knowledge file count (memory, context, rules)\n try {\n const nexusRoot = join(process.cwd(), '.nexus');\n const rulesRoot = join(nexusRoot, 'rules');\n const folders: Array<[string, string]> = [\n ['memory', MEMORY_ROOT],\n ['context', CONTEXT_ROOT],\n ['rules', rulesRoot],\n ];\n const folderCounts: string[] = [];\n let totalFiles = 0;\n for (const [label, folderPath] of folders) {\n if (existsSync(folderPath)) {\n const count = readdirSync(folderPath).filter(f => f.endsWith('.md')).length;\n if (count > 0) {\n folderCounts.push(`${count} ${label}`);\n totalFiles += count;\n }\n }\n }\n if (totalFiles > 0) {\n lines.push(`[Knowledge]: ${folderCounts.join(', ')}`);\n }\n } catch {}\n\n // Agents\n const trackerPath = join(HARNESS_STATE_ROOT, 'agent-tracker.json');\n if (existsSync(trackerPath)) {\n try {\n const tracker = JSON.parse(readFileSync(trackerPath, 'utf-8')) as Array<{ agent_type?: string; status?: string }>;\n if (tracker.length > 0) {\n const agentParts = tracker.map(a => `${a.agent_type ?? 'unknown'} (${a.status ?? 'unknown'})`);\n lines.push(`[Agents]: ${agentParts.join(', ')}`);\n }\n } catch {}\n }\n\n const snapshot = `<nexus>\\n${lines.join('\\n')}\\n</nexus>`;\n respond({ continue: true, additionalContext: snapshot });\n}\n\n// --- \uBA54\uC778 ---\n\nasync function main() {\n const input = await readStdin();\n const event = JSON.parse(input);\n\n const eventName = event.hook_event_name ?? '';\n\n switch (eventName) {\n case 'SessionStart':\n handleSessionStart(event);\n break;\n case 'SubagentStart':\n handleSubagentStart(event);\n break;\n case 'SubagentStop':\n handleSubagentStop(event);\n break;\n case 'PreToolUse':\n handlePreToolUse(event);\n break;\n case 'PostToolUse':\n handlePostToolUse(event);\n break;\n case 'UserPromptSubmit':\n handleUserPromptSubmit(event);\n break;\n case 'Stop':\n handleStop(event);\n break;\n case 'PreCompact':\n pass();\n break;\n case 'PostCompact':\n handlePostCompact(event);\n break;\n default:\n pass();\n }\n}\n\nmain().catch(() => {\n respond({ continue: true });\n});\n", "/** \uD6C5 \uC2A4\uD06C\uB9BD\uD2B8 \uACF5\uD1B5 I/O: stdin JSON \uC77D\uAE30 + stdout JSON \uC751\uB2F5 */\n\nexport function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n process.stdin.on('data', (chunk: Buffer) => (data += chunk));\n process.stdin.on('end', () => resolve(data));\n });\n}\n\nexport function respond(obj: Record<string, unknown>): void {\n process.stdout.write(JSON.stringify(obj));\n}\n\nexport function pass(): void {\n respond({ continue: true });\n}\n", "import { resolve, join } from 'path';\nimport { existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { execSync } from 'child_process';\n\n/** \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8 (.git\uC774 \uC788\uB294 \uB514\uB809\uD1A0\uB9AC) */\nexport function findProjectRoot(startDir?: string): string {\n let dir = startDir ?? process.cwd();\n while (dir !== '/') {\n if (existsSync(join(dir, '.git'))) return dir;\n dir = resolve(dir, '..');\n }\n return startDir ?? process.cwd();\n}\n\nconst PROJECT_ROOT = findProjectRoot();\n\n/** .nexus/ \u2014 \uB7F0\uD0C0\uC784 \uC0C1\uD0DC */\nexport const NEXUS_ROOT = process.env.NEXUS_RUNTIME_ROOT || join(PROJECT_ROOT, '.nexus');\n\n/** .nexus/state/ \u2014 \uB7F0\uD0C0\uC784 \uC0C1\uD0DC \uD30C\uC77C */\nexport const STATE_ROOT = join(NEXUS_ROOT, 'state');\n\n/** harness identifier (npm package name\uC758 \uB9C8\uC9C0\uB9C9 \uC138\uADF8\uBA3C\uD2B8) */\nexport const HARNESS_ID = 'claude-nexus';\n\n/** .nexus/state/claude-nexus/ \u2014 harness-local \uC0C1\uD0DC \uD30C\uC77C */\nexport const HARNESS_STATE_ROOT = join(STATE_ROOT, HARNESS_ID);\n\n/** .nexus/memory/ \u2014 \uC5D0\uC774\uC804\uD2B8 \uACF5\uC720 \uBA54\uBAA8\uB9AC */\nexport const MEMORY_ROOT = join(NEXUS_ROOT, 'memory');\n\n/** .nexus/context/ \u2014 \uD504\uB85C\uC81D\uD2B8 \uCEE8\uD14D\uC2A4\uD2B8 */\nexport const CONTEXT_ROOT = join(NEXUS_ROOT, 'context');\n\n/** \uB8F0 \uD30C\uC77C \uACBD\uB85C */\nexport function rulesPath(name: string): string {\n return join(NEXUS_ROOT, 'rules', `${name}.md`);\n}\n\n/** \uB514\uB809\uD1A0\uB9AC \uC0DD\uC131 (\uC7AC\uADC0) */\nexport function ensureDir(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\n/** \uD604\uC7AC git \uBE0C\uB79C\uCE58\uBA85 \uBC18\uD658. git \uC5C6\uC73C\uBA74 '_default' */\nexport function getCurrentBranch(): string {\n try {\n return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();\n } catch {\n try {\n return execSync('git symbolic-ref --short HEAD', { encoding: 'utf8' }).trim();\n } catch {\n return '_default';\n }\n }\n}\n\nconst GITIGNORE_CONTENT = `# Nexus: whitelist tracked files, ignore everything else\n*\n!.gitignore\n!memory/\n!memory/**\n!context/\n!context/**\n!history.json\n!rules/\n!rules/**\n`;\n\nexport function ensureNexusStructure(): void {\n ensureDir(NEXUS_ROOT);\n ensureDir(STATE_ROOT);\n ensureDir(HARNESS_STATE_ROOT);\n const gitignorePath = join(NEXUS_ROOT, '.gitignore');\n if (!existsSync(gitignorePath)) {\n writeFileSync(gitignorePath, GITIGNORE_CONTENT);\n }\n}\n", "import { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\n\nexport interface TasksSummary {\n exists: boolean;\n total: number;\n completed: number;\n pending: number;\n allCompleted: boolean;\n}\n\nexport function readTasksSummary(branchRoot: string): TasksSummary {\n const tasksPath = join(branchRoot, 'tasks.json');\n if (!existsSync(tasksPath)) return { exists: false, total: 0, completed: 0, pending: 0, allCompleted: false };\n try {\n const data = JSON.parse(readFileSync(tasksPath, 'utf-8'));\n const tasks: Array<{ status: string }> = data.tasks ?? [];\n const completed = tasks.filter(t => t.status === 'completed').length;\n const pending = tasks.length - completed;\n return {\n exists: true,\n total: tasks.length,\n completed,\n pending,\n allCompleted: tasks.length > 0 && pending === 0,\n };\n } catch {\n return { exists: false, total: 0, completed: 0, pending: 0, allCompleted: false };\n }\n}\n", "// \uBAA8\uB4E0 \uC5D0\uC774\uC804\uD2B8\uC5D0\uAC8C memory, context, rules \uD3F4\uB354\uAC00 \uB3D9\uC77C\uD558\uAC8C \uB178\uCD9C\uB428\nexport const AGENT_ROLES = [\n 'architect',\n 'postdoc',\n 'designer',\n 'strategist',\n 'engineer',\n 'researcher',\n 'writer',\n 'tester',\n 'reviewer',\n] as const;\n\nexport type AgentRole = typeof AGENT_ROLES[number];\n\n/** 'claude-nexus:engineer' \u2192 'engineer'. nexus \uC5D0\uC774\uC804\uD2B8\uAC00 \uC544\uB2C8\uBA74 null \uBC18\uD658 */\nexport function extractRole(agentType: string): string | null {\n const prefix = 'claude-nexus:';\n if (!agentType.startsWith(prefix)) return null;\n const role = agentType.slice(prefix.length);\n return (AGENT_ROLES as readonly string[]).includes(role) ? role : null;\n}\n\n/** @deprecated \uD50C\uB7AB \uAD6C\uC870\uB85C \uC804\uD658\uB428 \u2014 gate.ts \uC5C5\uB370\uC774\uD2B8 \uD6C4 \uC81C\uAC70 \uC608\uC815 */\nexport function getAllowedLayers(_role: string): string[] {\n return [];\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["resolve", "import_fs", "import_path", "import_fs", "import_path"]
|
|
7
7
|
}
|
package/skills/nx-plan/SKILL.md
CHANGED
|
@@ -227,12 +227,21 @@ All issues decided → generate the plan document (tasks.json) immediately:
|
|
|
227
227
|
| Design analysis / review | **architect** etc. HOW | Technical trade-off judgment |
|
|
228
228
|
| Sequential edits to same file | **lead** | Parallel subagents risk conflict |
|
|
229
229
|
|
|
230
|
-
**
|
|
231
|
-
- Any task with `owner: "engineer"` + `acceptance` field → pair a **tester** task (verify acceptance criteria)
|
|
232
|
-
- Any task with `owner: "writer"` → pair a **reviewer** task (verify deliverable)
|
|
233
|
-
- Paired verification tasks are linked via `deps` to the original task
|
|
230
|
+
**Primary metric — artifact-coherence**: a well-scoped task targets a single artifact or a tightly coupled artifact cluster and makes a single coherent change. A change is coherent when (a) it can be described in one sentence, (b) reverting it leaves all other artifacts consistent, and (c) its acceptance can be verified by inspecting its outputs alone.
|
|
234
231
|
|
|
235
|
-
**
|
|
232
|
+
**Verification auto-pairing (conditional)** — create a CHECK task only when the DO task's acceptance includes the appropriate verification trigger:
|
|
233
|
+
- `owner: "engineer"` + acceptance contains a runtime-behavior criterion → pair a **tester** task.
|
|
234
|
+
- `owner: "writer"` + acceptance contains a verifiable deliverable criterion → pair a **reviewer** task.
|
|
235
|
+
- Exclusions: pure refactor (behavior-preserving), type-only changes, docs-adjacent tasks (.md or frontmatter-only, classified under `docs_only` entries in `vocabulary/task-exceptions.yml`), and researcher tasks. Researcher tasks never receive an auto-paired CHECK — research outputs feed Lead or HOW agents directly, not tester or reviewer.
|
|
236
|
+
- Paired verification tasks are linked via `deps` to the original task.
|
|
237
|
+
|
|
238
|
+
**Exception catalog**: task decomposition exceptions are defined in `vocabulary/task-exceptions.yml` (`docs_only.coherent`, `docs_only.independent`, `same_file_bundle`, `generated_artifacts`). When an exception applies to a task, record its id in the task's `context` field so downstream tooling can trace the classification.
|
|
239
|
+
|
|
240
|
+
**Dedup Layer 1 (plan-time static merge)**: before finalizing the task list, scan draft tasks for overlapping target_files. Overlapping tasks are merged into a single owner task via the `same_file_bundle` exception from `vocabulary/task-exceptions.yml` to prevent parallel write conflicts during execution.
|
|
241
|
+
|
|
242
|
+
**DO/CHECK decomposition principle**: DO agents (engineer, writer, researcher) and CHECK agents (tester, reviewer) accumulate less per-task context than HOW agents. When a task involves multiple independent artifacts, decompose across multiple parallel DO/CHECK subagents rather than bundling. HOW agents benefit from consolidated context and should generally remain as single sessions. Parallel decomposition is worthwhile when there are at least three independent artifacts; below that, bundling under one owner is preferable to avoid parallelization overhead.
|
|
243
|
+
|
|
244
|
+
**HOW decomposition rule**: split HOW analysis across multiple subagents only when the issue crosses different rows of the domain-agent mapping table (architect vs designer vs strategist vs postdoc). Sub-concerns within a single domain row belong in one HOW session.
|
|
236
245
|
|
|
237
246
|
4. **Populate tasks.json** via `nx_task_add`:
|
|
238
247
|
- Set `goal` from the plan topic
|