claude-nexus 0.20.0 → 0.21.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.
@@ -7,7 +7,7 @@
7
7
  {
8
8
  "name": "claude-nexus",
9
9
  "description": "Agent orchestration plugin for Claude Code. Injects optimized context per agent role with minimal overhead.",
10
- "version": "0.20.0",
10
+ "version": "0.21.0",
11
11
  "author": {
12
12
  "name": "kih"
13
13
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-nexus",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "description": "Agent orchestration plugin for Claude Code — optimized context injection per role",
5
5
  "author": {
6
6
  "name": "kih"
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.20.0
1
+ 0.21.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-nexus",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "type": "module",
5
5
  "description": "Agent orchestration plugin for Claude Code — optimized context injection per role",
6
6
  "author": "kih",
package/scripts/gate.cjs CHANGED
@@ -342,24 +342,14 @@ function handlePlanMode({ prompt, tasksReminder, claudeMdNotice }) {
342
342
  const isAuto = /\[plan:auto\]/i.test(prompt);
343
343
  const planFile = (0, import_path3.join)(STATE_ROOT, "plan.json");
344
344
  const hasExistingSession = (0, import_fs3.existsSync)(planFile);
345
- let base;
345
+ let hints = "";
346
346
  if (hasExistingSession) {
347
- base = `<nexus>Plan mode \u2014 existing session found.
348
- STEP 1: Check current status with nx_plan_status.
349
- STEP 2: Spawn Explore+researcher subagents in parallel for additional code+external research.
350
- STEP 3: Lead synthesizes multi-perspective analysis based on research results. Spawn HOW subagents (architect, strategist, etc.) for independent analysis if needed.
351
- STEP 4: Present comparison table with pros/cons/recommendation. Record decisions with [d].</nexus>`;
352
- } else {
353
- base = `<nexus>Plan mode.
354
- STEP 1: Spawn researcher+Explore subagents in parallel for code+external research.
355
- STEP 2: Call nx_plan_start with findings to organize issues.
356
- Do not call nx_plan_start before research is complete.
357
- STEP 3: Lead synthesizes multi-perspective analysis. Spawn HOW subagents for independent analysis if complex.
358
- STEP 4: Present comparison table \u2192 user decides \u2192 [d] to record. Suggest follow-up issues if decisions create new questions.</nexus>`;
347
+ hints = "\nExisting plan session detected \u2014 check nx_plan_status to resume.";
359
348
  }
360
349
  if (isAuto) {
361
- base += "\n<nexus>AUTO MODE: Skip user confirmation. For each issue, select the recommended option and decide automatically. Output plan document (tasks.json) directly.</nexus>";
350
+ hints += '\nAuto mode requested \u2014 pass args: "auto" to the skill.';
362
351
  }
352
+ 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>`;
363
353
  const coreIndex = buildCoreIndex();
364
354
  const coreSection = coreIndex ? `
365
355
  ${coreIndex}
@@ -371,13 +361,18 @@ Check core/reference/ BEFORE web searching for known topics.` : "";
371
361
  }
372
362
  function handleRunMode({ tasksReminder, claudeMdNotice }) {
373
363
  const planReminder = getPlanReminder();
364
+ const tasksSummary = readTasksSummary(STATE_ROOT);
365
+ let hints = "";
366
+ if (!tasksSummary.exists) {
367
+ hints = "\ntasks.json absent \u2014 plan required before execution. Suggest [plan:auto] or [plan].";
368
+ } else {
369
+ hints = `
370
+ tasks.json: ${tasksSummary.pending} pending, ${tasksSummary.total - tasksSummary.pending} completed of ${tasksSummary.total} tasks.`;
371
+ }
374
372
  const coreIndex = buildCoreIndex();
375
373
  const coreSection = coreIndex ? `
376
374
  ${coreIndex}` : "";
377
- const base = `<nexus>Run mode \u2014 full pipeline execution requested.
378
- MANDATORY: Invoke Skill tool with skill="claude-nexus:nx-run" to load the full orchestration pipeline.
379
- Do NOT skip any phases. Do NOT attempt direct execution. Follow nx-run SKILL.md strictly.
380
- For multi-task work, spawn subagents in parallel (one per task). Do NOT handle multi-task work as Lead solo.</nexus>${coreSection}`;
375
+ 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}`;
381
376
  respond({
382
377
  continue: true,
383
378
  additionalContext: withNotices(taskPipelineMessage(base), tasksReminder, claudeMdNotice, planReminder)
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/shared/hook-io.ts", "../src/shared/paths.ts", "../src/shared/tasks.ts", "../src/hooks/gate.ts"],
4
- "sourcesContent": ["/** \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/core/ \u2014 4\uACC4\uCE35 \uAD6C\uC870 \uB8E8\uD2B8 */\nexport const CORE_ROOT = join(NEXUS_ROOT, 'core');\n\n/** .nexus/state/ \u2014 \uB7F0\uD0C0\uC784 \uC0C1\uD0DC \uD30C\uC77C */\nexport const STATE_ROOT = join(NEXUS_ROOT, 'state');\n\nexport const LAYERS = ['identity', 'codebase', 'reference', 'memory'] as const;\nexport type Layer = typeof LAYERS[number];\n\n/** core \uACC4\uCE35 \uB0B4 \uD2B9\uC815 \uD1A0\uD53D \uD30C\uC77C \uACBD\uB85C */\nexport function corePath(layer: string, topic: string): string {\n return join(CORE_ROOT, layer, `${topic}.md`);\n}\n\n/** core \uACC4\uCE35 \uB514\uB809\uD1A0\uB9AC \uACBD\uB85C */\nexport function coreLayerDir(layer: string): string {\n return join(CORE_ROOT, layer);\n}\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!core/\n!core/**\n!config.json\n!history.json\n!rules/\n!rules/**\n`;\n\nexport function ensureNexusStructure(): void {\n ensureDir(NEXUS_ROOT);\n ensureDir(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", "// Gate \uD6C5: Stop (Task \uCC28\uB2E8) + UserPromptSubmit (\uD0A4\uC6CC\uB4DC \uAC10\uC9C0)\nimport { readStdin, respond, pass } from '../shared/hook-io.js';\nimport { STATE_ROOT, ensureDir, getCurrentBranch, ensureNexusStructure } from '../shared/paths.js';\nimport { readTasksSummary } from '../shared/tasks.js';\nimport { existsSync, readFileSync, writeFileSync, 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: Agent \uC9C1\uC811 \uD638\uCD9C \uCC28\uB2E8 + Edit/Write \uD0DC\uC2A4\uD06C \uAC15\uC81C ---\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 // .nexus/config.json \u2014 setup \uC2A4\uD0AC \uB300\uC0C1\n if (/[\\\\/]\\.nexus[\\\\/]config\\.json$/.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\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\nconst NATURAL_PATTERNS: Array<{ patterns: RegExp[]; match: KeywordMatch }> = [\n {\n patterns: [\n /\\bplan\\b/i, /\uACC4\uD68D/, /\uC124\uACC4/, /\uBD84\uC11D\uD574/, /\uAC80\uD1A0\uD574/,\n /\uC5B4\uB5BB\uAC8C\\s*\uD558\uBA74\\s*\uC88B\uC744\uAE4C/, /\uBB50\uAC00\\s*\uC88B\uC744\uAE4C/, /\uBC29\uBC95\uC744?\\s*\uCC3E\uC544/,\n ],\n match: { primitive: 'plan', skill: 'claude-nexus:nx-plan' },\n },\n];\n\n// \uD504\uB9AC\uBBF8\uD2F0\uBE0C \uC774\uB984\uC774 \uC5D0\uB7EC/\uBC84\uADF8 \uB9E5\uB77D\uC5D0\uC11C \uC5B8\uAE09\uB418\uBA74 \uD65C\uC131\uD654\uAC00 \uC544\uB2CC \"\uB300\uD654\" \u2014 \uC624\uD0D0 \uBC29\uC9C0\nconst ERROR_CONTEXT = /\uC5D0\uB7EC|\uBC84\uADF8|\uC624\uB958|\\bfix\\b|\\bbug\\b|\\berror\\b|\uC774\uC288|\\bissue\\b/i;\nconst PRIMITIVE_NAMES = /\\b(plan|run)\\b/i;\n\n/** \uD504\uB9AC\uBBF8\uD2F0\uBE0C \uC774\uB984\uC774 \uC5D0\uB7EC/\uBC84\uADF8 \uB9E5\uB77D\uACFC \uD568\uAED8 \uB4F1\uC7A5\uD558\uAC70\uB098, \uB2E8\uC21C \uC9C8\uBB38/\uC778\uC6A9 \uB9E5\uB77D\uC778\uC9C0 \uD310\uBCC4 */\nfunction isPrimitiveMention(prompt: string): boolean {\n if (PRIMITIVE_NAMES.test(prompt) && ERROR_CONTEXT.test(prompt)) return true;\n if (PRIMITIVE_NAMES.test(prompt) && /\uBB50\uC57C|\uBB54\uAC00\uC694|what\\s+is|what\\s+does|\uC124\uBA85\uD574|explain/i.test(prompt)) return true;\n if (/[`\"'](?:plan)[`\"']/i.test(prompt)) return true;\n return false;\n}\n\nfunction detectKeywords(prompt: string): KeywordMatch | null {\n // 1\uCC28: \uBA85\uC2DC\uC801 \uD0DC\uADF8 [plan] / [plan:auto] \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\n // 2\uCC28: \uC790\uC5F0\uC5B4 \uD328\uD134 (\uD504\uB9AC\uBBF8\uD2F0\uBE0C \uC774\uB984 + \uC5D0\uB7EC \uB9E5\uB77D\uC77C \uB54C\uB9CC \uD544\uD130)\n for (const { patterns, match } of NATURAL_PATTERNS) {\n if (patterns.some((p) => p.test(prompt))) {\n if (isPrimitiveMention(prompt)) continue;\n return match;\n }\n }\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\nconst CORE_LAYERS = ['identity', 'codebase', 'reference', 'memory'] as const;\n\nfunction buildCoreIndex(): string {\n const coreRoot = join(process.cwd(), '.nexus', 'core');\n if (!existsSync(coreRoot)) return '';\n\n const layerLines: string[] = [];\n\n for (const layer of CORE_LAYERS) {\n const layerDir = join(coreRoot, layer);\n if (!existsSync(layerDir)) continue;\n\n let files: string[];\n try {\n files = readdirSync(layerDir).filter(f => f.endsWith('.md'));\n } catch {\n continue;\n }\n if (files.length === 0) continue;\n\n const entries: string[] = [];\n for (const file of files) {\n const name = basename(file, '.md');\n const filePath = join(layerDir, 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 // keep only the most distinctive tags (up to 3, skip redundant ones)\n const shortTags = tagList.slice(0, 3).join(', ');\n tags = ` [${shortTags}]`;\n }\n } catch {}\n entries.push(`${name}${tags}`);\n }\n layerLines.push(`${layer}: ${entries.join(', ')}`);\n }\n\n if (layerLines.length === 0) return '';\n\n const header = '[Core Knowledge] (call nx_core_read for details)';\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 nx_rules_write(name, content).\nRules are git-tracked and auto-delivered to agents via nx_briefing hint tag filtering.\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 let base: string;\n if (hasExistingSession) {\n base = `<nexus>Plan mode \u2014 existing session found.\nSTEP 1: Check current status with nx_plan_status.\nSTEP 2: Spawn Explore+researcher subagents in parallel for additional code+external research.\nSTEP 3: Lead synthesizes multi-perspective analysis based on research results. Spawn HOW subagents (architect, strategist, etc.) for independent analysis if needed.\nSTEP 4: Present comparison table with pros/cons/recommendation. Record decisions with [d].</nexus>`;\n } else {\n base = `<nexus>Plan mode.\nSTEP 1: Spawn researcher+Explore subagents in parallel for code+external research.\nSTEP 2: Call nx_plan_start with findings to organize issues.\nDo not call nx_plan_start before research is complete.\nSTEP 3: Lead synthesizes multi-perspective analysis. Spawn HOW subagents for independent analysis if complex.\nSTEP 4: Present comparison table \u2192 user decides \u2192 [d] to record. Suggest follow-up issues if decisions create new questions.</nexus>`;\n }\n if (isAuto) {\n base += '\\n<nexus>AUTO MODE: Skip user confirmation. For each issue, select the recommended option and decide automatically. Output plan document (tasks.json) directly.</nexus>';\n }\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 coreIndex = buildCoreIndex();\n const coreSection = coreIndex ? `\\n${coreIndex}` : '';\n const base = `<nexus>Run mode \u2014 full pipeline execution requested.\nMANDATORY: Invoke Skill tool with skill=\"claude-nexus:nx-run\" to load the full orchestration pipeline.\nDo NOT skip any phases. Do NOT attempt direct execution. Follow nx-run SKILL.md strictly.\nFor multi-task work, spawn subagents in parallel (one per task). Do NOT handle multi-task work as Lead solo.</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, summary) 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 // [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 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// --- \uC138\uC158 \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC ---\n\nfunction handleSessionStart(_event: Record<string, unknown>): void {\n ensureNexusStructure();\n writeFileSync(join(STATE_ROOT, 'agent-tracker.json'), '[]');\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(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 tracker.push({ agent_type: agentType, agent_id: agentId, started_at: new Date().toISOString(), status: 'running' });\n\n ensureDir(STATE_ROOT);\n writeFileSync(trackerPath, JSON.stringify(tracker, null, 2));\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(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 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 // Core knowledge file count\n const coreRoot = join(process.cwd(), '.nexus', 'core');\n if (existsSync(coreRoot)) {\n try {\n let totalFiles = 0;\n for (const layer of CORE_LAYERS) {\n const layerDir = join(coreRoot, layer);\n if (existsSync(layerDir)) {\n totalFiles += readdirSync(layerDir).filter(f => f.endsWith('.md')).length;\n }\n }\n if (totalFiles > 0) {\n lines.push(`[Core]: ${totalFiles} files across ${CORE_LAYERS.length} layers`);\n }\n } catch {}\n }\n\n // Agents\n const trackerPath = join(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 '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"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/** \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/core/ \u2014 4\uACC4\uCE35 \uAD6C\uC870 \uB8E8\uD2B8 */\nexport const CORE_ROOT = join(NEXUS_ROOT, 'core');\n\n/** .nexus/state/ \u2014 \uB7F0\uD0C0\uC784 \uC0C1\uD0DC \uD30C\uC77C */\nexport const STATE_ROOT = join(NEXUS_ROOT, 'state');\n\nexport const LAYERS = ['identity', 'codebase', 'reference', 'memory'] as const;\nexport type Layer = typeof LAYERS[number];\n\n/** core \uACC4\uCE35 \uB0B4 \uD2B9\uC815 \uD1A0\uD53D \uD30C\uC77C \uACBD\uB85C */\nexport function corePath(layer: string, topic: string): string {\n return join(CORE_ROOT, layer, `${topic}.md`);\n}\n\n/** core \uACC4\uCE35 \uB514\uB809\uD1A0\uB9AC \uACBD\uB85C */\nexport function coreLayerDir(layer: string): string {\n return join(CORE_ROOT, layer);\n}\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!core/\n!core/**\n!config.json\n!history.json\n!rules/\n!rules/**\n`;\n\nexport function ensureNexusStructure(): void {\n ensureDir(NEXUS_ROOT);\n ensureDir(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", "// Gate \uD6C5: Stop (Task \uCC28\uB2E8) + UserPromptSubmit (\uD0A4\uC6CC\uB4DC \uAC10\uC9C0)\nimport { readStdin, respond, pass } from '../shared/hook-io.js';\nimport { STATE_ROOT, ensureDir, getCurrentBranch, ensureNexusStructure } from '../shared/paths.js';\nimport { readTasksSummary } from '../shared/tasks.js';\nimport { existsSync, readFileSync, writeFileSync, 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: Agent \uC9C1\uC811 \uD638\uCD9C \uCC28\uB2E8 + Edit/Write \uD0DC\uC2A4\uD06C \uAC15\uC81C ---\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 // .nexus/config.json \u2014 setup \uC2A4\uD0AC \uB300\uC0C1\n if (/[\\\\/]\\.nexus[\\\\/]config\\.json$/.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\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\nconst NATURAL_PATTERNS: Array<{ patterns: RegExp[]; match: KeywordMatch }> = [\n {\n patterns: [\n /\\bplan\\b/i, /\uACC4\uD68D/, /\uC124\uACC4/, /\uBD84\uC11D\uD574/, /\uAC80\uD1A0\uD574/,\n /\uC5B4\uB5BB\uAC8C\\s*\uD558\uBA74\\s*\uC88B\uC744\uAE4C/, /\uBB50\uAC00\\s*\uC88B\uC744\uAE4C/, /\uBC29\uBC95\uC744?\\s*\uCC3E\uC544/,\n ],\n match: { primitive: 'plan', skill: 'claude-nexus:nx-plan' },\n },\n];\n\n// \uD504\uB9AC\uBBF8\uD2F0\uBE0C \uC774\uB984\uC774 \uC5D0\uB7EC/\uBC84\uADF8 \uB9E5\uB77D\uC5D0\uC11C \uC5B8\uAE09\uB418\uBA74 \uD65C\uC131\uD654\uAC00 \uC544\uB2CC \"\uB300\uD654\" \u2014 \uC624\uD0D0 \uBC29\uC9C0\nconst ERROR_CONTEXT = /\uC5D0\uB7EC|\uBC84\uADF8|\uC624\uB958|\\bfix\\b|\\bbug\\b|\\berror\\b|\uC774\uC288|\\bissue\\b/i;\nconst PRIMITIVE_NAMES = /\\b(plan|run)\\b/i;\n\n/** \uD504\uB9AC\uBBF8\uD2F0\uBE0C \uC774\uB984\uC774 \uC5D0\uB7EC/\uBC84\uADF8 \uB9E5\uB77D\uACFC \uD568\uAED8 \uB4F1\uC7A5\uD558\uAC70\uB098, \uB2E8\uC21C \uC9C8\uBB38/\uC778\uC6A9 \uB9E5\uB77D\uC778\uC9C0 \uD310\uBCC4 */\nfunction isPrimitiveMention(prompt: string): boolean {\n if (PRIMITIVE_NAMES.test(prompt) && ERROR_CONTEXT.test(prompt)) return true;\n if (PRIMITIVE_NAMES.test(prompt) && /\uBB50\uC57C|\uBB54\uAC00\uC694|what\\s+is|what\\s+does|\uC124\uBA85\uD574|explain/i.test(prompt)) return true;\n if (/[`\"'](?:plan)[`\"']/i.test(prompt)) return true;\n return false;\n}\n\nfunction detectKeywords(prompt: string): KeywordMatch | null {\n // 1\uCC28: \uBA85\uC2DC\uC801 \uD0DC\uADF8 [plan] / [plan:auto] \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\n // 2\uCC28: \uC790\uC5F0\uC5B4 \uD328\uD134 (\uD504\uB9AC\uBBF8\uD2F0\uBE0C \uC774\uB984 + \uC5D0\uB7EC \uB9E5\uB77D\uC77C \uB54C\uB9CC \uD544\uD130)\n for (const { patterns, match } of NATURAL_PATTERNS) {\n if (patterns.some((p) => p.test(prompt))) {\n if (isPrimitiveMention(prompt)) continue;\n return match;\n }\n }\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\nconst CORE_LAYERS = ['identity', 'codebase', 'reference', 'memory'] as const;\n\nfunction buildCoreIndex(): string {\n const coreRoot = join(process.cwd(), '.nexus', 'core');\n if (!existsSync(coreRoot)) return '';\n\n const layerLines: string[] = [];\n\n for (const layer of CORE_LAYERS) {\n const layerDir = join(coreRoot, layer);\n if (!existsSync(layerDir)) continue;\n\n let files: string[];\n try {\n files = readdirSync(layerDir).filter(f => f.endsWith('.md'));\n } catch {\n continue;\n }\n if (files.length === 0) continue;\n\n const entries: string[] = [];\n for (const file of files) {\n const name = basename(file, '.md');\n const filePath = join(layerDir, 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 // keep only the most distinctive tags (up to 3, skip redundant ones)\n const shortTags = tagList.slice(0, 3).join(', ');\n tags = ` [${shortTags}]`;\n }\n } catch {}\n entries.push(`${name}${tags}`);\n }\n layerLines.push(`${layer}: ${entries.join(', ')}`);\n }\n\n if (layerLines.length === 0) return '';\n\n const header = '[Core Knowledge] (call nx_core_read for details)';\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 nx_rules_write(name, content).\nRules are git-tracked and auto-delivered to agents via nx_briefing hint tag filtering.\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, summary) 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 // [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 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// --- \uC138\uC158 \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC ---\n\nfunction handleSessionStart(_event: Record<string, unknown>): void {\n ensureNexusStructure();\n writeFileSync(join(STATE_ROOT, 'agent-tracker.json'), '[]');\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(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 tracker.push({ agent_type: agentType, agent_id: agentId, started_at: new Date().toISOString(), status: 'running' });\n\n ensureDir(STATE_ROOT);\n writeFileSync(trackerPath, JSON.stringify(tracker, null, 2));\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(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 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 // Core knowledge file count\n const coreRoot = join(process.cwd(), '.nexus', 'core');\n if (existsSync(coreRoot)) {\n try {\n let totalFiles = 0;\n for (const layer of CORE_LAYERS) {\n const layerDir = join(coreRoot, layer);\n if (existsSync(layerDir)) {\n totalFiles += readdirSync(layerDir).filter(f => f.endsWith('.md')).length;\n }\n }\n if (totalFiles > 0) {\n lines.push(`[Core]: ${totalFiles} files across ${CORE_LAYERS.length} layers`);\n }\n } catch {}\n }\n\n // Agents\n const trackerPath = join(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 '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"],
5
+ "mappings": "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",
6
6
  "names": ["resolve", "import_fs", "import_path", "import_fs", "import_path"]
7
7
  }
@@ -3,7 +3,7 @@ name: nx-plan
3
3
  description: Structured multi-perspective analysis to decompose issues, align on decisions, and produce an enriched plan before execution. Plan only — does not execute.
4
4
  trigger_display: "[plan]"
5
5
  purpose: "Structured planning — subagent-based analysis, deliberate decisions, produce execution plan"
6
- triggers: ["plan", "계획", "설계", "분석하자", "어떻게 하면 좋을까", "뭐가 좋을까", "방법을 찾아줘", "접근법", "어떻게 접근"]
6
+ triggers: ["[plan]", "plan", "계획", "설계", "분석하자", "어떻게 하면 좋을까", "뭐가 좋을까", "방법을 찾아줘", "접근법", "어떻게 접근"]
7
7
  ---
8
8
 
9
9
  <role>
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: nx-run
3
3
  description: Execution — user-directed agent composition.
4
- trigger_display: "nx-run"
4
+ trigger_display: "[run]"
5
5
  purpose: "Execution — user-directed agent composition"
6
- triggers: ["실행", "개발", "구현", "연구", "조사"]
6
+ triggers: ["[run]", "run", "실행", "개발", "구현", "연구", "조사"]
7
7
  ---
8
8
 
9
9
  <role>
@@ -33,7 +33,7 @@ Execution norm that Lead follows when the user invokes the [run] tag. Composes s
33
33
  - **Branch Guard**: if on main/master, create a branch appropriate to the task type before proceeding (prefix: `feat/`, `fix/`, `chore/`, `research/`, etc. — Lead's judgment). Auto-create without user confirmation.
34
34
  - Check for `tasks.json`:
35
35
  - **Exists** → read it and proceed to Step 2.
36
- - **Absent** → inform the user: "계획서가 없습니다. [plan:auto]로 자동 계획을 생성하거나, [plan]으로 대화형 플래닝을 시작하세요." If the user chooses `[plan:auto]`, invoke `nx-plan` skill in auto mode via Skill tool. After plan generation, proceed to Step 2.
36
+ - **Absent** → auto-invoke `Skill({ skill: "claude-nexus:nx-plan", args: "auto" })` to generate tasks.json. Do NOT ask `[run]` implies execution intent. After plan generation, proceed to Step 2.
37
37
  - If tasks.json exists, check prior decisions with `nx_plan_status`.
38
38
 
39
39
  ### Step 1.5: TUI Progress
@@ -28,7 +28,7 @@ Lead는 사용자와 직접 대화하는 메인 에이전트. tasks.json에서 `
28
28
  |-------|---------|---------|
29
29
  | nx-init | /claude-nexus:nx-init | Full project onboarding: scan codebase, establish identity, generate core knowledge |
30
30
  | nx-plan | [plan] | Structured planning — subagent-based analysis, deliberate decisions, produce execution plan |
31
- | nx-run | nx-run | Execution — user-directed agent composition |
31
+ | nx-run | [run] | Execution — user-directed agent composition |
32
32
  | nx-setup | /claude-nexus:nx-setup | Configure Nexus interactively |
33
33
  | nx-sync | /claude-nexus:nx-sync | Synchronize core knowledge with current project state |
34
34