#!/usr/bin/env node
/**
 * Guard 3: Tool Path Guard
 * Records current tool call entry points. Soft warning — no hard fail yet.
 * 
 * → Architecture Freeze v2 (PR-1): docs/architecture-freeze-v2.md
 * → Adapter §3.2: Tool Adapters
 * 
 * ToolCore not yet implemented — this guard inventories the current state
 * and will FAIL only if a NEW unknown tool path appears.
 * 
 * Known tool paths:
 *   - native tool (dist/commands/*)
 *   - MCP tool (dist/mcp/*)
 *   - plugin tool (dist/extensions plugin.json contracts.tools)
 *   - codex tool (dist/extensions/codex-supervisor/*)
 */

import { readdirSync, readFileSync, existsSync } from "node:fs";
import { join } from "node:path";

const OPENCLAW_HOME = process.env.OPENCLAW_HOME || "/opt/homebrew/lib/node_modules/openclaw";
const DIST_DIR = join(OPENCLAW_HOME, "dist");
const EXTENSIONS_DIR = join(DIST_DIR, "extensions");

function guardToolPaths() {
  const issues = [];
  const inventory = { native: [], mcp: [], plugin: [], codex: [], unknown: [] };
  const knownToolPaths = new Set([
    "native", "mcp", "plugin", "codex"
  ]);

  // 1. Native tools — look for tool registrations in commands
  const commandsDir = join(DIST_DIR, "commands");
  if (existsSync(commandsDir)) {
    try {
      const entries = readdirSync(commandsDir, { withFileTypes: true });
      for (const entry of entries) {
        if (entry.isDirectory()) {
          inventory.native.push(`commands/${entry.name}`);
        }
      }
    } catch (e) {
      issues.push({ level: "WARN", msg: `Could not scan commands dir: ${e.message}` });
    }
  }

  // 2. MCP tools
  const mcpDir = join(DIST_DIR, "mcp");
  if (existsSync(mcpDir)) {
    try {
      const files = readdirSync(mcpDir).filter(f => f.endsWith(".js"));
      inventory.mcp.push(...files.map(f => `mcp/${f}`));
    } catch (e) {
      issues.push({ level: "WARN", msg: `Could not scan mcp dir: ${e.message}` });
    }
  }

  // 3. Plugin tools (from openclaw.plugin.json contracts)
  if (existsSync(EXTENSIONS_DIR)) {
    try {
      const extDirs = readdirSync(EXTENSIONS_DIR, { withFileTypes: true })
        .filter(d => d.isDirectory());
      
      for (const extDir of extDirs) {
        const pluginJsonPath = join(EXTENSIONS_DIR, extDir.name, "openclaw.plugin.json");
        if (!existsSync(pluginJsonPath)) continue;
        
        try {
          const plugin = JSON.parse(readFileSync(pluginJsonPath, "utf8"));
          const tools = plugin.contracts?.tools || [];
          
          if (tools.length > 0) {
            // Categorize
            if (extDir.name.includes("codex") || extDir.name.includes("supervisor")) {
              inventory.codex.push(`${extDir.name}: [${tools.join(", ")}]`);
            } else {
              inventory.plugin.push(`${extDir.name}: [${tools.join(", ")}]`);
            }
          }
        } catch {}
      }
    } catch (e) {
      issues.push({ level: "WARN", msg: `Could not scan extensions: ${e.message}` });
    }
  }

  // 4. Check for unknown tool paths in key files
  const keyFiles = readdirSync(DIST_DIR).filter(f => 
    f.endsWith(".js") && (f.includes("tool") || f.includes("command") || f.includes("mcp"))
  );
  for (const f of keyFiles) {
    const name = f.replace(/\.js$/, "").replace(/-[A-Za-z0-9]{8}$/, "");
    // Categorize based on naming
    if (name.includes("mcp") || name.includes("codex-mcp")) {
      if (!inventory.mcp.some(t => t.includes(name.substring(0, 10)))) {
        inventory.mcp.push(`dist/${f}`);
      }
    } else if (name.includes("tool")) {
      if (!inventory.native.some(t => t.includes(name.substring(0, 10)))) {
        inventory.native.push(`dist/${f}`);
      }
    }
  }

  // Report
  console.log("");
  console.log("═══════════════════════════════════════");
  console.log("  Guard 3: Tool Path Guard");
  console.log("═══════════════════════════════════════");
  console.log("");

  console.log("  Tool Path Inventory:");
  console.log(`    Native tools:   ${inventory.native.length} entries`);
  console.log(`    MCP tools:      ${inventory.mcp.length} entries`);
  console.log(`    Plugin tools:   ${inventory.plugin.length} plugins`);
  console.log(`    Codex tools:    ${inventory.codex.length} plugins`);

  if (inventory.plugin.length > 0) {
    console.log("\n  Plugin tool contracts:");
    for (const p of inventory.plugin) {
      console.log(`    • ${p}`);
    }
  }
  
  if (inventory.codex.length > 0) {
    console.log("\n  Codex tool contracts:");
    for (const p of inventory.codex) {
      console.log(`    • ${p}`);
    }
  }

  // This guard is WARN-only for now (ToolCore not yet implemented)
  console.log("");
  console.log("  ⚠ WARN: ToolCore not yet enforced");
  console.log("    This guard currently inventories tool paths.");
  console.log("    After PR-8/PR-9 (ToolCore), it will enforce all tools go through ToolExecutor.");
  
  // No hard fail — informational only at this stage
  process.exit(0);
}

guardToolPaths();
