{"version":3,"file":"sync.cjs","names":["AGENT_FILES","parseJson","validatePolicy","decodeNative","mostRestrictiveMode","collectRules","deduplicateRules","CODECS"],"sources":["../src/sync.ts"],"sourcesContent":["/**\n * Permission policy sync — detect, merge, and write agent configs.\n *\n * Walks up the directory tree, detects all agent permission configs,\n * decodes into canonical rules, merges them, and writes back.\n *\n * Merge semantics:\n *   - rules: union with deny-first (deny > ask > allow for same tool/pattern)\n *   - defaultMode: most restrictive wins\n *   - agent-specific fields (sandbox, profiles, network): from canonical only\n *\n * Write-back:\n *   - `.agents/permissions.json` always gets the full merged canonical form\n *   - Native agent configs get their encoded form from the canonical merge\n *   - `.agents/permissions.local.json` is read but never written\n *   - Codex skipped (TOML), Crush skipped (no file)\n */\n\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { AgentPermissionPolicy, type Rule } from \"./schema.ts\";\nimport { CODECS, type AgentId } from \"./compat/codecs.ts\";\nimport {\n  collectRules,\n  deduplicateRules,\n  mostRestrictiveMode,\n} from \"./evaluate.ts\";\nimport {\n  AGENT_FILES,\n  type AgentFileDef,\n  parseJson,\n  validatePolicy,\n  decodeNative,\n} from \"./agent-files.ts\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SyncOptions {\n  /** Starting directory. */\n  cwd: string;\n  /** Number of parent directories to ascend (0 = cwd only). Infinity = root. */\n  up: number;\n  /** Agents to include in bidirectional sync. Empty = all detected. */\n  with: AgentId[];\n  /** Agents to exclude from bidirectional sync. */\n  without: AgentId[];\n  /** Apply changes without prompting. */\n  yes: boolean;\n  /** Show changes only, never write. */\n  dryRun: boolean;\n  /** Create config files that don't exist. */\n  create: boolean;\n  /** Show verbose output (rule provenance). */\n  verbose: boolean;\n  /** Write .bak files before overwriting. */\n  backup: boolean;\n}\n\nexport interface SyncResult {\n  /** Per-file changes that would be applied. */\n  changes: FileChange[];\n  /** Whether changes were applied. */\n  applied: boolean;\n}\n\nexport interface FileChange {\n  /** Absolute path to the file. */\n  path: string;\n  /** Agent this file belongs to. */\n  agent: AgentId | \"canonical\";\n  /** \"create\" | \"update\" */\n  kind: \"create\" | \"update\";\n  /** Current content (null for new files). */\n  current: string | null;\n  /** Proposed content. */\n  proposed: string;\n}\n\n// ---------------------------------------------------------------------------\n// Agent file detection\n// ---------------------------------------------------------------------------\n\ninterface AgentFile {\n  agent: AgentId | \"canonical\";\n  /** Absolute path to the config file. */\n  path: string;\n  /** Whether this is a local override (read-only, never written). */\n  local: boolean;\n}\n\n/** Detect which agent files exist in a directory. */\nfunction detectFiles(dir: string): AgentFile[] {\n  const found: AgentFile[] = [];\n\n  for (const [agent, def] of Object.entries(AGENT_FILES) as [\n    AgentId | \"canonical\",\n    AgentFileDef,\n  ][]) {\n    const main = join(dir, def.name);\n    if (existsSync(main)) {\n      found.push({ agent, path: main, local: false });\n    }\n    if (def.localName) {\n      const local = join(dir, def.localName);\n      if (existsSync(local)) {\n        found.push({ agent, path: local, local: true });\n      }\n    }\n  }\n\n  return found;\n}\n\n/** Walk up from cwd, collecting agent files. */\nfunction collectFiles(cwd: string, up: number): AgentFile[] {\n  const files: AgentFile[] = [];\n  let current = resolve(cwd);\n  let remaining = up === Infinity ? Number.MAX_SAFE_INTEGER : up + 1;\n\n  while (remaining > 0) {\n    const found = detectFiles(current);\n    files.push(...found);\n    remaining--;\n\n    const parent = dirname(current);\n    if (parent === current) break; // reached root\n\n    current = parent;\n  }\n\n  return files;\n}\n\n// ---------------------------------------------------------------------------\n// Reading and decoding\n// ---------------------------------------------------------------------------\n\ninterface DecodedSource {\n  file: AgentFile;\n  policy: AgentPermissionPolicy;\n}\n\nasync function readAndDecode(\n  file: AgentFile,\n  agentFilter: Set<string> | undefined,\n): Promise<DecodedSource | undefined> {\n  // Skip if --with/--without excludes this agent\n  if (\n    agentFilter &&\n    !agentFilter.has(file.agent) &&\n    file.agent !== \"canonical\"\n  ) {\n    return undefined;\n  }\n\n  const def = AGENT_FILES[file.agent];\n\n  // Skip agents without extract/wrap (crush, codex) or without a file def\n  if (def.extract === undefined) return undefined;\n\n  // Read and parse\n  let content: string;\n  try {\n    content = await readFile(file.path, \"utf-8\");\n  } catch {\n    return undefined;\n  }\n  const parsed = parseJson(content, file.path);\n  if (!parsed.ok) return undefined;\n\n  // Canonical files parse directly\n  if (file.agent === \"canonical\") {\n    const validated = validatePolicy(parsed.value);\n    if (!validated.ok) return undefined;\n    return { file, policy: validated.value };\n  }\n\n  // Native files — extract, decode, validate\n  const result = decodeNative(file.agent, parsed.value);\n  if (!result.ok) return undefined;\n  return { file, policy: result.value };\n}\n\n// ---------------------------------------------------------------------------\n// Merging\n// ---------------------------------------------------------------------------\n\nfunction mergePolicies(sources: DecodedSource[]): AgentPermissionPolicy {\n  if (sources.length === 0) {\n    return {};\n  }\n\n  let defaultMode: string | undefined;\n  const allRules: Rule[] = [];\n  const additionalDirectories: string[] = [];\n  let sandbox: AgentPermissionPolicy[\"sandbox\"];\n  let network: AgentPermissionPolicy[\"network\"];\n  let profiles: AgentPermissionPolicy[\"profiles\"];\n  let activeProfile: string | undefined;\n  let delegation: AgentPermissionPolicy[\"delegation\"];\n  let env: AgentPermissionPolicy[\"env\"];\n\n  for (const { policy } of sources) {\n    // defaultMode: most restrictive wins\n    defaultMode = mostRestrictiveMode(defaultMode, policy.defaultMode);\n\n    // Rules: collect then deduplicate with deny-first priority\n    allRules.push(...collectRules(policy));\n\n    // Additional directories: union\n    if (policy.permissions?.additionalDirectories) {\n      for (const dir of policy.permissions.additionalDirectories) {\n        if (!additionalDirectories.includes(dir)) {\n          additionalDirectories.push(dir);\n        }\n      }\n    }\n\n    // Agent-specific fields: take from canonical source if present,\n    // otherwise from the first source that has them\n    if (policy.sandbox) sandbox = { ...sandbox, ...policy.sandbox };\n    if (policy.network) network = { ...network, ...policy.network };\n    if (policy.profiles) profiles = { ...(profiles ?? {}), ...policy.profiles };\n    if (policy.activeProfile) activeProfile = policy.activeProfile;\n    if (policy.delegation) delegation = { ...delegation, ...policy.delegation };\n    if (policy.env) env = { ...(env ?? {}), ...policy.env };\n  }\n\n  const rules = deduplicateRules(allRules);\n\n  const result: AgentPermissionPolicy = {};\n\n  if (defaultMode)\n    result.defaultMode = defaultMode as AgentPermissionPolicy[\"defaultMode\"];\n\n  if (rules.length > 0) result.rules = rules;\n\n  if (additionalDirectories.length > 0) {\n    result.permissions = { additionalDirectories };\n  }\n\n  if (sandbox) result.sandbox = sandbox;\n  if (network) result.network = network;\n  if (profiles && Object.keys(profiles).length > 0) result.profiles = profiles;\n  if (activeProfile) result.activeProfile = activeProfile;\n  if (delegation) result.delegation = delegation;\n  if (env && Object.keys(env).length > 0) result.env = env;\n\n  return result;\n}\n\n// ---------------------------------------------------------------------------\n// Encoding and write-back\n// ---------------------------------------------------------------------------\n\ninterface WriteTarget {\n  agent: AgentId | \"canonical\";\n  path: string;\n  content: string;\n  exists: boolean;\n}\n\nfunction computeWriteTargets(\n  cwd: string,\n  merged: AgentPermissionPolicy,\n  sources: DecodedSource[],\n  agentFilter: Set<string> | undefined,\n  create: boolean,\n): WriteTarget[] {\n  const targets: WriteTarget[] = [];\n\n  // Always write canonical at cwd (unless excluded)\n  const canonicalPath = join(cwd, \".agents\", \"permissions.json\");\n  const schemaUrl =\n    \"https://github.com/Mearman/agent-permissions/releases/latest/download/agent-permissions.schema.json\";\n  const canonicalWithSchema = { $schema: schemaUrl, ...merged };\n  if (!agentFilter || agentFilter.has(\"canonical\")) {\n    targets.push({\n      agent: \"canonical\",\n      path: canonicalPath,\n      content: JSON.stringify(canonicalWithSchema, null, 2) + \"\\n\",\n      exists: existsSync(canonicalPath),\n    });\n  }\n\n  // Write native configs at cwd\n  for (const agent of Object.keys(CODECS) as AgentId[]) {\n    if (agentFilter && !agentFilter.has(agent)) continue;\n    if (agent === \"codex\" || agent === \"crush\") continue; // TOML / no file\n\n    const def = AGENT_FILES[agent];\n    const filePath = join(cwd, def.name);\n    const fileExists = existsSync(filePath);\n\n    if (!fileExists && !create) continue;\n\n    // Check if there's a source from this agent (or create is enabled)\n    const hasSource = sources.some((s) => s.file.agent === agent);\n    if (!hasSource && !create) continue;\n\n    const codec = CODECS[agent];\n    let encoded: unknown;\n    try {\n      encoded = codec.encode(merged);\n    } catch {\n      continue;\n    }\n\n    // Wrap in native config structure (e.g. { permissions: ... })\n    if (def.wrap) encoded = def.wrap(encoded);\n\n    targets.push({\n      agent,\n      path: filePath,\n      content: JSON.stringify(encoded, null, 2) + \"\\n\",\n      exists: fileExists,\n    });\n  }\n\n  return targets;\n}\n\n// ---------------------------------------------------------------------------\n// Diff display\n// ---------------------------------------------------------------------------\n\nfunction formatChange(change: FileChange): string {\n  const kind = change.kind === \"create\" ? \"+\" : \"~\";\n  const label = change.agent === \"canonical\" ? \"canonical\" : change.agent;\n\n  let output = `${kind} ${label}: ${change.path}\\n`;\n\n  if (change.kind === \"create\") {\n    output += \"  (new file)\\n\";\n    // Show first few lines\n    const lines = change.proposed.split(\"\\n\").slice(0, 10);\n    for (const line of lines) {\n      output += `  ${line}\\n`;\n    }\n    if (change.proposed.split(\"\\n\").length > 10) {\n      output += \"  ...\\n\";\n    }\n  } else {\n    // Show diff-like summary\n    const currentLines = (change.current ?? \"\").split(\"\\n\");\n    const proposedLines = change.proposed.split(\"\\n\");\n\n    const added = proposedLines.filter((l) => !currentLines.includes(l));\n    const removed = currentLines.filter((l) => !proposedLines.includes(l));\n\n    for (const line of removed.slice(0, 20)) {\n      if (line.trim()) output += `  - ${line}\\n`;\n    }\n    for (const line of added.slice(0, 20)) {\n      if (line.trim()) output += `  + ${line}\\n`;\n    }\n\n    if (added.length > 20 || removed.length > 20) {\n      output += `  ... (${String(added.length)} additions, ${String(removed.length)} removals)\\n`;\n    }\n  }\n\n  return output;\n}\n\n// ---------------------------------------------------------------------------\n// Main sync function\n// ---------------------------------------------------------------------------\n\nexport async function sync(options: SyncOptions): Promise<SyncResult> {\n  const {\n    cwd,\n    up,\n    with: withList,\n    without: withoutList,\n    yes,\n    dryRun,\n    create,\n    verbose,\n    backup,\n  } = options;\n\n  // Build agent filter from --with/--without\n  const agentFilter = buildAgentFilter(withList, withoutList);\n\n  // 1. Collect files by walking up\n  const files = collectFiles(cwd, up);\n\n  if (files.length === 0) {\n    process.stderr.write(\n      \"No permission configs found. Create .agents/permissions.json to get started.\\n\",\n    );\n    return { changes: [], applied: false };\n  }\n\n  if (verbose) {\n    process.stderr.write(\"Detected config files:\\n\");\n    for (const f of files) {\n      const local = f.local ? \" (local, read-only)\" : \"\";\n      process.stderr.write(`  ${f.agent}: ${f.path}${local}\\n`);\n    }\n    process.stderr.write(\"\\n\");\n  }\n\n  // 2. Read and decode all sources\n  const sources: DecodedSource[] = [];\n  for (const file of files) {\n    // Skip local files for write-back consideration\n    const decoded = await readAndDecode(file, agentFilter);\n    if (decoded) {\n      sources.push(decoded);\n      if (verbose) {\n        const rules = collectRules(decoded.policy);\n        process.stderr.write(\n          `  ${file.agent} (${file.path}): ${String(rules.length)} rules, mode=${decoded.policy.defaultMode ?? \"standard\"}\\n`,\n        );\n      }\n    }\n  }\n\n  if (sources.length === 0) {\n    process.stderr.write(\"No readable permission configs found.\\n\");\n    return { changes: [], applied: false };\n  }\n\n  // 3. Merge all sources\n  const merged = mergePolicies(sources);\n\n  if (verbose) {\n    const rules = collectRules(merged);\n    process.stderr.write(\n      `\\nMerged: ${String(rules.length)} rules, mode=${merged.defaultMode ?? \"standard\"}\\n`,\n    );\n  }\n\n  // 4. Compute write targets\n  const targets = computeWriteTargets(\n    cwd,\n    merged,\n    sources,\n    agentFilter,\n    create,\n  );\n\n  if (targets.length === 0) {\n    process.stderr.write(\"No write targets.\\n\");\n    return { changes: [], applied: false };\n  }\n\n  // 5. Build changes\n  const changes: FileChange[] = [];\n  for (const target of targets) {\n    let current: string | null = null;\n    if (target.exists) {\n      try {\n        current = await readFile(target.path, \"utf-8\");\n      } catch {\n        current = null;\n      }\n    }\n\n    // Skip if content is semantically identical (compare parsed JSON)\n    if (current !== null) {\n      try {\n        const currentParsed: unknown = JSON.parse(current);\n        const proposedParsed: unknown = JSON.parse(target.content);\n        if (JSON.stringify(currentParsed) === JSON.stringify(proposedParsed)) {\n          continue;\n        }\n      } catch {\n        // Fall through to string comparison if parse fails\n        if (current === target.content) continue;\n      }\n    } else if (target.content === \"\") {\n      continue;\n    }\n\n    changes.push({\n      path: target.path,\n      agent: target.agent,\n      kind: target.exists ? \"update\" : \"create\",\n      current,\n      proposed: target.content,\n    });\n  }\n\n  if (changes.length === 0) {\n    process.stderr.write(\"Already in sync — no changes needed.\\n\");\n    return { changes: [], applied: true };\n  }\n\n  // 6. Display changes\n  process.stderr.write(\"\\nChanges:\\n\\n\");\n  for (const change of changes) {\n    process.stderr.write(formatChange(change));\n    process.stderr.write(\"\\n\");\n  }\n\n  // 7. Apply or prompt\n  if (dryRun) {\n    process.stderr.write(\"(dry run — no changes written)\\n\");\n    return { changes, applied: false };\n  }\n\n  if (!yes) {\n    process.stderr.write(\"Apply these changes? [y/N] \");\n    const answer = await readLine();\n    if (answer.toLowerCase() !== \"y\" && answer.toLowerCase() !== \"yes\") {\n      process.stderr.write(\"Aborted.\\n\");\n      return { changes, applied: false };\n    }\n  }\n\n  // 8. Write files\n  for (const change of changes) {\n    // Backup if requested and file exists\n    if (backup && change.current !== null) {\n      await writeFile(change.path + \".bak\", change.current);\n    }\n\n    // Ensure directory exists\n    const dir = dirname(change.path);\n    await mkdir(dir, { recursive: true });\n\n    await writeFile(change.path, change.proposed);\n  }\n\n  process.stderr.write(`Applied ${String(changes.length)} change(s).\\n`);\n  return { changes, applied: true };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction readLine(): Promise<string> {\n  return new Promise((resolve) => {\n    process.stdin.setEncoding(\"utf-8\");\n    process.stdin.once(\"data\", (data: string) => {\n      resolve(data.trim());\n    });\n  });\n}\n\n/**\n * Build an agent filter from --with and --without lists.\n * Returns undefined when no filtering is needed (all agents included).\n * --with and --without are mutually exclusive.\n */\nfunction buildAgentFilter(\n  withList: AgentId[],\n  withoutList: AgentId[],\n): Set<string> | undefined {\n  if (withList.length > 0) {\n    // --with: only include listed agents + canonical\n    const filter = new Set<string>(withList);\n    filter.add(\"canonical\");\n    return filter;\n  }\n\n  if (withoutList.length > 0) {\n    // --without: include all except listed\n    const allAgents = [...Object.keys(CODECS), \"canonical\"];\n    const excluded = new Set(withoutList);\n    return new Set(allAgents.filter((a) => !excluded.has(a as AgentId)));\n  }\n\n  return undefined;\n}\n"],"mappings":"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"}