{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/team/state-paths.ts","../src/team/fs-utils.ts","../src/envelope/baseline.ts","../src/graphify/index.ts","../src/graphify/parse-exports.ts","../src/graphify/diff.ts","../src/envelope/index.ts"],"sourcesContent":["export { VERSION } from './version.js'\r\nexport * from './team/types.js'\r\nexport { TeamPaths, absPath, teamStateRoot } from './team/state-paths.js'\r\nexport { atomicWriteJson, ensureDir, appendLine } from './team/fs-utils.js'\r\nexport * from './envelope/baseline.js'\r\nexport { inferProjectGraph, type InferredInterface } from './graphify/index.js'\r\nexport { diffInterfaces } from './graphify/diff.js'\r\nexport { pathMatchesGlob } from './envelope/index.js'\r\n","export const VERSION = '0.1.0'\r\n\r\n/**\r\n * Semver-ish comparison. Returns >0 if a>b, 0 if equal, <0 if a<b.\r\n *\r\n * Strips pre-release (-rc.1) and build metadata (+sha.abc) suffixes before\r\n * comparing — for the toolkit's purposes \"1.0.0-rc.1\" and \"1.0.0\" are the\r\n * same release. Within a segment, numeric strings compare numerically;\r\n * non-numeric strings compare lexically (so \"alpha\" < \"beta\"). Mixed\r\n * numeric/non-numeric at the same position fall back to lexical on the\r\n * raw segment text.\r\n */\r\nexport function compareVersions(a: string, b: string): number {\r\n  const strip = (v: string) => String(v).split(/[-+]/)[0]\r\n  const pa = strip(a).split('.')\r\n  const pb = strip(b).split('.')\r\n  const len = Math.max(pa.length, pb.length)\r\n  for (let i = 0; i < len; i++) {\r\n    const sa = pa[i] ?? '0'\r\n    const sb = pb[i] ?? '0'\r\n    const na = parseInt(sa, 10)\r\n    const nb = parseInt(sb, 10)\r\n    const aIsNum = !Number.isNaN(na) && String(na) === sa\r\n    const bIsNum = !Number.isNaN(nb) && String(nb) === sb\r\n    if (aIsNum && bIsNum) {\r\n      if (na !== nb) return na - nb\r\n    } else {\r\n      // At least one is non-numeric → lexical compare on raw segment text.\r\n      if (sa !== sb) return sa < sb ? -1 : 1\r\n    }\r\n  }\r\n  return 0\r\n}\r\n\r\n/**\r\n * Resolve the latest published version from the remote registry.\r\n *\r\n * Default registry is the npm registry (`https://registry.npmjs.org`) using\r\n * the package's own `name` field from package.json. Override via `registry`\r\n * option or `HARNESS_TOOLKIT_REGISTRY` env var. Network failures degrade\r\n * silently to `null` — the caller (update-check) treats null as \"unknown\"\r\n * and falls back to the local-only comparison signal.\r\n */\r\nexport interface ResolveRemoteLatestOptions {\r\n  fetch?: typeof fetch\r\n  registry?: string\r\n  timeoutMs?: number\r\n}\r\n\r\ninterface PackageMetadata {\r\n  version?: unknown\r\n  'dist-tags'?: { latest?: unknown } | null\r\n}\r\n\r\nconst DEFAULT_REGISTRY = 'https://registry.npmjs.org'\r\n\r\nexport async function resolveRemoteLatest(\r\n  opts: ResolveRemoteLatestOptions = {},\r\n): Promise<string | null> {\r\n  const packageName = '@wefq1981/harness-toolkit'\r\n  const registryBase =\r\n    opts.registry ??\r\n    process.env.HARNESS_TOOLKIT_REGISTRY ??\r\n    DEFAULT_REGISTRY\r\n  const url = `${registryBase.replace(/\\/$/, '')}/${encodeURIComponent(packageName)}`\r\n  const timeoutMs = opts.timeoutMs ?? 5000\r\n  const fetchImpl = opts.fetch ?? fetch\r\n\r\n  try {\r\n    const controller = new AbortController()\r\n    const timer = setTimeout(() => controller.abort(), timeoutMs)\r\n    const res = await fetchImpl(url, {\r\n      signal: controller.signal,\r\n      headers: { 'accept': 'application/json' },\r\n    })\r\n    clearTimeout(timer)\r\n    if (!res.ok) {\r\n      return null\r\n    }\r\n    const json = (await res.json()) as PackageMetadata\r\n    const latestViaDistTags =\r\n      json?.['dist-tags'] && typeof json['dist-tags'].latest === 'string'\r\n        ? json['dist-tags'].latest\r\n        : null\r\n    if (latestViaDistTags) {\r\n      return latestViaDistTags\r\n    }\r\n    if (typeof json?.version === 'string') {\r\n      return json.version\r\n    }\r\n    return null\r\n  } catch {\r\n    return null\r\n  }\r\n}\r\n","import { isAbsolute, join } from 'path'\r\n\r\nfunction normalizeTaskFileStem(taskId: string): string {\r\n  const trimmed = String(taskId).trim().replace(/\\.json$/i, '')\r\n  if (/^task-\\d+$/.test(trimmed)) return trimmed\r\n  if (/^\\d+$/.test(trimmed)) return `task-${trimmed}`\r\n  return trimmed\r\n}\r\n\r\nexport const TeamPaths = {\r\n  root: (teamName: string) =>\r\n    `.harness/state/team/${teamName}`,\r\n\r\n  config: (teamName: string) =>\r\n    `.harness/state/team/${teamName}/config.json`,\r\n\r\n  tasks: (teamName: string) =>\r\n    `.harness/state/team/${teamName}/tasks`,\r\n\r\n  taskFile: (teamName: string, taskId: string) =>\r\n    `.harness/state/team/${teamName}/tasks/${normalizeTaskFileStem(taskId)}.json`,\r\n\r\n  workers: (teamName: string) =>\r\n    `.harness/state/team/${teamName}/workers`,\r\n\r\n  workerDir: (teamName: string, workerName: string) =>\r\n    `.harness/state/team/${teamName}/workers/${workerName}`,\r\n\r\n  heartbeat: (teamName: string, workerName: string) =>\r\n    `.harness/state/team/${teamName}/workers/${workerName}/heartbeat.json`,\r\n\r\n  inbox: (teamName: string, workerName: string) =>\r\n    `.harness/state/team/${teamName}/workers/${workerName}/inbox.md`,\r\n\r\n  outbox: (teamName: string, workerName: string) =>\r\n    `.harness/state/team/${teamName}/workers/${workerName}/outbox.jsonl`,\r\n} as const\r\n\r\nexport function absPath(cwd: string, relativePath: string): string {\r\n  return isAbsolute(relativePath) ? relativePath : join(cwd, relativePath)\r\n}\r\n\r\nexport function teamStateRoot(cwd: string, teamName: string): string {\r\n  return join(cwd, TeamPaths.root(teamName))\r\n}\r\n","import { writeFileSync, existsSync, mkdirSync, renameSync, openSync, writeSync, closeSync, constants } from 'fs'\r\nimport { dirname } from 'path'\r\n\r\nexport function atomicWriteJson(filePath: string, data: unknown): void {\r\n  const dir = dirname(filePath)\r\n  if (!existsSync(dir)) mkdirSync(dir, { recursive: true })\r\n  const tmpPath = `${filePath}.tmp.${process.pid}.${Date.now()}`\r\n  writeFileSync(tmpPath, JSON.stringify(data, null, 2) + '\\n', 'utf-8')\r\n  renameSync(tmpPath, filePath)\r\n}\r\n\r\nexport function ensureDir(dirPath: string): void {\r\n  if (!existsSync(dirPath)) mkdirSync(dirPath, { recursive: true })\r\n}\r\n\r\nexport function appendLine(filePath: string, line: string): void {\r\n  const dir = dirname(filePath)\r\n  if (!existsSync(dir)) mkdirSync(dir, { recursive: true })\r\n  const fd = openSync(filePath, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT, 0o644)\r\n  try {\r\n    writeSync(fd, line + '\\n', null, 'utf-8')\r\n  } finally {\r\n    closeSync(fd)\r\n  }\r\n}\r\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'\r\nimport { dirname } from 'path'\r\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml'\r\nimport {\r\n  type ArchitectureEnvelope,\r\n  type ModuleBoundary,\r\n  type ChangeLevel,\r\n  type EnvelopeValidation,\r\n} from './index.js'\r\n\r\nexport interface DeclaredInterface {\r\n  module: string\r\n  source_glob: string\r\n  exports: string[]\r\n}\r\n\r\nexport interface ArchitectureBaseline {\r\n  version: string\r\n  frozen_at: string\r\n  /**\r\n   * Git revision at freeze time (full 40-char SHA). Written by step-8 freeze\r\n   * via `git rev-parse HEAD`. Reconcile (step-7) uses this as the interface-diff\r\n   * baseline to compute per-file added/removed/changed exports. See ADR-0022.\r\n   * Optional for backward compatibility — when absent, reconcile falls back\r\n   * to `git rev-list --before=<frozen_at> -1`.\r\n   */\r\n  frozen_at_sha?: string\r\n  frozen_by_req: string\r\n  legal_layer?: ArchitectureEnvelope['legal_layer']\r\n  module_boundaries: {\r\n    writable: ModuleBoundary[]\r\n    read_only: ModuleBoundary[]\r\n    forbidden: ModuleBoundary[]\r\n  }\r\n  declared_interfaces: DeclaredInterface[]\r\n  absorption_budget: { max_parallel_slices: number }\r\n}\r\n\r\nexport type UpgradeFlag = 'none' | 'L2-escape' | 'L3-rewrite' | 'baseline-breaking'\r\n\r\nexport interface GateChange {\r\n  gate_id: string\r\n  change: string\r\n  reason: string\r\n}\r\n\r\nexport interface ArchitectureDelta {\r\n  request_id: string\r\n  based_on_baseline: string\r\n  delta: {\r\n    legal_layer?: ArchitectureEnvelope['legal_layer']\r\n    module_boundaries?: {\r\n      writable?: ModuleBoundary[]\r\n      read_only?: ModuleBoundary[]\r\n      forbidden?: ModuleBoundary[]\r\n    }\r\n    declared_interfaces?: DeclaredInterface[]\r\n    absorption_budget?: { max_parallel_slices: number }\r\n  }\r\n  理由: string\r\n  冲击不变量: string[]\r\n  gate_变更: GateChange[]\r\n  升级标记: UpgradeFlag\r\n}\r\n\r\nexport function loadBaseline(path: string): ArchitectureBaseline {\r\n  if (!existsSync(path)) {\r\n    throw new Error(`Baseline file not found: ${path}`)\r\n  }\r\n  const raw = readFileSync(path, 'utf-8')\r\n  const parsed = parseYaml(raw)\r\n  return normalizeBaseline(parsed)\r\n}\r\n\r\nexport function writeBaseline(path: string, baseline: ArchitectureBaseline): void {\r\n  const dir = dirname(path)\r\n  if (!existsSync(dir)) {\r\n    mkdirSync(dir, { recursive: true })\r\n  }\r\n  const yaml = stringifyYaml(baseline, { sortMapEntries: false })\r\n  writeFileSync(path, yaml, 'utf-8')\r\n}\r\n\r\nexport function loadDelta(path: string): ArchitectureDelta {\r\n  if (!existsSync(path)) {\r\n    throw new Error(`Delta file not found: ${path}`)\r\n  }\r\n  const raw = readFileSync(path, 'utf-8')\r\n  const parsed = parseYaml(raw)\r\n  return normalizeDelta(parsed)\r\n}\r\n\r\nexport function writeDelta(path: string, delta: ArchitectureDelta): void {\r\n  const dir = dirname(path)\r\n  if (!existsSync(dir)) {\r\n    mkdirSync(dir, { recursive: true })\r\n  }\r\n  const yaml = stringifyYaml(delta, { sortMapEntries: false })\r\n  writeFileSync(path, yaml, 'utf-8')\r\n}\r\n\r\nconst UPGRADE_FLAGS: readonly UpgradeFlag[] = ['none', 'L2-escape', 'L3-rewrite', 'baseline-breaking']\r\n\r\nexport function validateBaseline(baseline: ArchitectureBaseline): EnvelopeValidation {\r\n  const errors: string[] = []\r\n  const { writable, read_only, forbidden } = baseline.module_boundaries\r\n\r\n  if (writable.length === 0 && read_only.length === 0 && forbidden.length === 0) {\r\n    errors.push('module_boundaries has no entries — at least one writable path is required')\r\n  }\r\n  if (writable.length === 0) {\r\n    errors.push('module_boundaries.writable is empty — deny-by-default requires at least one allowed path')\r\n  }\r\n  if (!baseline.declared_interfaces) {\r\n    errors.push('declared_interfaces is missing — graphify diff requires declared interfaces')\r\n  } else if (!Array.isArray(baseline.declared_interfaces)) {\r\n    errors.push('declared_interfaces must be an array')\r\n  }\r\n  if (!baseline.frozen_by_req) {\r\n    errors.push('frozen_by_req is required (use the originating REQ-ID; empty string only for 0→1 baseline)')\r\n  }\r\n  if (!baseline.version) {\r\n    errors.push('version is required')\r\n  }\r\n\r\n  return { valid: errors.length === 0, errors }\r\n}\r\n\r\nexport function validateDelta(delta: ArchitectureDelta): EnvelopeValidation {\r\n  const errors: string[] = []\r\n\r\n  if (!delta.request_id) {\r\n    errors.push('request_id is required')\r\n  }\r\n  if (!delta.based_on_baseline) {\r\n    errors.push('based_on_baseline is required — delta must declare which baseline version it was authored against')\r\n  }\r\n  if (typeof delta.理由 !== 'string' || delta.理由.trim() === '') {\r\n    errors.push('理由 is required — explain why this update is needed')\r\n  }\r\n  if (!Array.isArray(delta.冲击不变量) || delta.冲击不变量.length === 0) {\r\n    errors.push('冲击不变量 is required — list impacted invariants (use [] only if explicitly none, but field must list them)')\r\n  }\r\n  if (!Array.isArray(delta.gate_变更)) {\r\n    errors.push('gate_变更 must be an array (may be empty)')\r\n  }\r\n  if (!UPGRADE_FLAGS.includes(delta.升级标记)) {\r\n    errors.push(`升级标记 must be one of: ${UPGRADE_FLAGS.join(', ')}`)\r\n  }\r\n  if (!delta.delta || typeof delta.delta !== 'object') {\r\n    errors.push('delta field is required — must contain the overlay on baseline')\r\n  }\r\n\r\n  return { valid: errors.length === 0, errors }\r\n}\r\n\r\nexport function mergeBaselineDelta(baseline: ArchitectureBaseline, delta: ArchitectureDelta): ArchitectureBaseline {\r\n  const d = delta.delta\r\n  const mergedWritable = d.module_boundaries?.writable\r\n    ? [...baseline.module_boundaries.writable, ...d.module_boundaries.writable]\r\n    : baseline.module_boundaries.writable\r\n  const mergedReadOnly = d.module_boundaries?.read_only\r\n    ? [...baseline.module_boundaries.read_only, ...d.module_boundaries.read_only]\r\n    : baseline.module_boundaries.read_only\r\n  const mergedForbidden = d.module_boundaries?.forbidden\r\n    ? [...baseline.module_boundaries.forbidden, ...d.module_boundaries.forbidden]\r\n    : baseline.module_boundaries.forbidden\r\n\r\n  const mergedInterfaces = d.declared_interfaces\r\n    ? mergeDeclaredInterfaces(baseline.declared_interfaces, d.declared_interfaces)\r\n    : baseline.declared_interfaces\r\n\r\n  return {\r\n    version: baseline.version,\r\n    frozen_at: baseline.frozen_at,\r\n    frozen_at_sha: baseline.frozen_at_sha,\r\n    frozen_by_req: baseline.frozen_by_req,\r\n    legal_layer: d.legal_layer ?? baseline.legal_layer,\r\n    module_boundaries: {\r\n      writable: mergedWritable,\r\n      read_only: mergedReadOnly,\r\n      forbidden: mergedForbidden,\r\n    },\r\n    declared_interfaces: mergedInterfaces,\r\n    absorption_budget: d.absorption_budget ?? baseline.absorption_budget,\r\n  }\r\n}\r\n\r\nexport function deriveEnvelope(\r\n  baseline: ArchitectureBaseline,\r\n  delta?: ArchitectureDelta,\r\n): ArchitectureEnvelope {\r\n  const merged = delta ? mergeBaselineDelta(baseline, delta) : baseline\r\n  return {\r\n    version: merged.version,\r\n    request_id: delta?.request_id ?? merged.frozen_by_req,\r\n    legal_layer: merged.legal_layer,\r\n    module_boundaries: merged.module_boundaries,\r\n    absorption_budget: merged.absorption_budget,\r\n  }\r\n}\r\n\r\nexport function seedBaselineFromEnvelope(\r\n  envelope: ArchitectureEnvelope,\r\n  reqId: string,\r\n): ArchitectureBaseline {\r\n  return {\r\n    version: envelope.version,\r\n    frozen_at: '',\r\n    frozen_by_req: reqId,\r\n    legal_layer: envelope.legal_layer,\r\n    module_boundaries: envelope.module_boundaries,\r\n    declared_interfaces: [],\r\n    absorption_budget: envelope.absorption_budget,\r\n  }\r\n}\r\n\r\nexport function freezeBaseline(\r\n  baseline: ArchitectureBaseline,\r\n  delta: ArchitectureDelta,\r\n  frozenAt: string,\r\n  frozenAtSha?: string,\r\n): ArchitectureBaseline {\r\n  const merged = mergeBaselineDelta(baseline, delta)\r\n  return {\r\n    ...merged,\r\n    frozen_at: frozenAt,\r\n    frozen_at_sha: frozenAtSha ?? merged.frozen_at_sha,\r\n    frozen_by_req: delta.request_id,\r\n  }\r\n}\r\n\r\nfunction mergeDeclaredInterfaces(\r\n  existing: DeclaredInterface[],\r\n  additions: DeclaredInterface[],\r\n): DeclaredInterface[] {\r\n  const byModule = new Map<string, DeclaredInterface>()\r\n  for (const i of existing) {\r\n    byModule.set(i.module, { ...i, exports: [...i.exports] })\r\n  }\r\n  for (const add of additions) {\r\n    const cur = byModule.get(add.module)\r\n    if (cur) {\r\n      const set = new Set([...cur.exports, ...add.exports])\r\n      cur.exports = [...set]\r\n      cur.source_glob = add.source_glob || cur.source_glob\r\n    } else {\r\n      byModule.set(add.module, { ...add, exports: [...add.exports] })\r\n    }\r\n  }\r\n  return [...byModule.values()]\r\n}\r\n\r\nfunction normalizeBaseline(raw: any): ArchitectureBaseline {\r\n  if (!raw || typeof raw !== 'object') {\r\n    throw new Error('Baseline YAML is empty or not an object')\r\n  }\r\n  if (!raw.module_boundaries) {\r\n    throw new Error('Baseline missing required field: module_boundaries')\r\n  }\r\n  const defaultLevel: ChangeLevel = 'L0'\r\n  return {\r\n    version: raw.version ?? '1.0',\r\n    frozen_at: raw.frozen_at ?? '',\r\n    frozen_at_sha: typeof raw.frozen_at_sha === 'string' && raw.frozen_at_sha.trim()\r\n      ? raw.frozen_at_sha.trim()\r\n      : undefined,\r\n    frozen_by_req: raw.frozen_by_req ?? '',\r\n    legal_layer: raw.legal_layer,\r\n    module_boundaries: {\r\n      writable: (raw.module_boundaries.writable ?? []).map((w: any) => ({\r\n        module: w.module,\r\n        paths: w.paths ?? [],\r\n        change_level: (w.change_level ?? defaultLevel) as ChangeLevel,\r\n      })),\r\n      read_only: (raw.module_boundaries.read_only ?? []).map((r: any) => ({\r\n        module: r.module,\r\n        paths: r.paths ?? [],\r\n      })),\r\n      forbidden: (raw.module_boundaries.forbidden ?? []).map((f: any) => ({\r\n        module: f.module,\r\n        paths: f.paths ?? [],\r\n      })),\r\n    },\r\n    declared_interfaces: (raw.declared_interfaces ?? []).map((i: any) => ({\r\n      module: i.module,\r\n      source_glob: i.source_glob ?? '',\r\n      exports: i.exports ?? [],\r\n    })),\r\n    absorption_budget: {\r\n      max_parallel_slices: raw.absorption_budget?.max_parallel_slices ?? 1,\r\n    },\r\n  }\r\n}\r\n\r\nfunction normalizeDelta(raw: any): ArchitectureDelta {\r\n  if (!raw || typeof raw !== 'object') {\r\n    throw new Error('Delta YAML is empty or not an object')\r\n  }\r\n  const d = raw.delta ?? {}\r\n  return {\r\n    request_id: raw.request_id ?? '',\r\n    based_on_baseline: raw.based_on_baseline ?? '',\r\n    delta: {\r\n      legal_layer: d.legal_layer,\r\n      module_boundaries: d.module_boundaries\r\n        ? {\r\n            writable: (d.module_boundaries.writable ?? []).map((w: any) => ({\r\n              module: w.module,\r\n              paths: w.paths ?? [],\r\n              change_level: (w.change_level ?? 'L0') as ChangeLevel,\r\n            })),\r\n            read_only: (d.module_boundaries.read_only ?? []).map((r: any) => ({\r\n              module: r.module,\r\n              paths: r.paths ?? [],\r\n            })),\r\n            forbidden: (d.module_boundaries.forbidden ?? []).map((f: any) => ({\r\n              module: f.module,\r\n              paths: f.paths ?? [],\r\n            })),\r\n          }\r\n        : undefined,\r\n      declared_interfaces: (d.declared_interfaces ?? []).map((i: any) => ({\r\n        module: i.module,\r\n        source_glob: i.source_glob ?? '',\r\n        exports: i.exports ?? [],\r\n      })),\r\n      absorption_budget: d.absorption_budget,\r\n    },\r\n    理由: raw['理由'] ?? '',\r\n    冲击不变量: raw['冲击不变量'] ?? [],\r\n    gate_变更: (raw['gate_变更'] ?? []).map((g: any) => ({\r\n      gate_id: g.gate_id ?? '',\r\n      change: g.change ?? '',\r\n      reason: g.reason ?? '',\r\n    })),\r\n    升级标记: (raw['升级标记'] ?? 'none') as UpgradeFlag,\r\n  }\r\n}\r\n","import { existsSync, readdirSync, readFileSync, statSync } from 'fs'\r\nimport { join, relative, sep, basename } from 'path'\r\nimport { parseExports } from './parse-exports.js'\r\n\r\nexport interface InferredInterface {\r\n  module: string\r\n  source_glob: string\r\n  exports: string[]\r\n}\r\n\r\n/**\r\n * Infer the project's module→export mapping.\r\n *\r\n * Priority: TypeScript first (flat src/ tree), then Maven/Java multi-module\r\n * (pom.xml <modules> → src/main/java), then a structured scan of the project\r\n * root for common source layouts.\r\n *\r\n * Returns empty array only when no source files are found in any recognized\r\n * layout — never silently returns empty for a real project.\r\n */\r\nexport async function inferProjectGraph(projectRoot: string): Promise<InferredInterface[]> {\r\n  if (!existsSync(projectRoot)) {\r\n    throw new Error(`Project root not found: ${projectRoot}`)\r\n  }\r\n\r\n  // 1. Try TypeScript (flat src/ with .ts files)\r\n  const tsSrcDir = join(projectRoot, 'src')\r\n  if (existsSync(tsSrcDir)) {\r\n    const tsFiles = collectTsFiles(tsSrcDir)\r\n    if (tsFiles.length > 0) {\r\n      return await inferTsGraph(projectRoot, tsFiles)\r\n    }\r\n  }\r\n\r\n  // 2. Try Maven multi-module Java (pom.xml with <modules>)\r\n  const pomPath = join(projectRoot, 'pom.xml')\r\n  if (existsSync(pomPath)) {\r\n    const javaGraph = await inferMavenJavaGraph(projectRoot, pomPath)\r\n    if (javaGraph.length > 0) return javaGraph\r\n  }\r\n\r\n  // 3. Generic recursive Java scan (no pom.xml, but .java files exist somewhere)\r\n  const javaFiles = collectJavaFilesRecursive(projectRoot)\r\n  if (javaFiles.length > 0) {\r\n    return await inferJavaGraphFromFiles(projectRoot, javaFiles)\r\n  }\r\n\r\n  return []\r\n}\r\n\r\n// ─── TypeScript pipeline ───────────────────────────────────────────────\r\n\r\nasync function inferTsGraph(\r\n  projectRoot: string,\r\n  files: string[],\r\n): Promise<InferredInterface[]> {\r\n  const byModule = new Map<string, InferredInterface>()\r\n\r\n  for (const absPath of files) {\r\n    const rel = relative(projectRoot, absPath).replace(/\\\\/g, '/')\r\n    if (!rel.startsWith('src/')) continue\r\n\r\n    let content: string\r\n    try {\r\n      content = readFileSync(absPath, 'utf-8')\r\n    } catch {\r\n      continue\r\n    }\r\n    if (!content.trim()) continue\r\n\r\n    const symbols = await parseExports(content, rel)\r\n    const moduleName = deriveModuleName(rel)\r\n\r\n    const existing = byModule.get(moduleName)\r\n    const names = symbols.map(s => s.name)\r\n    if (existing) {\r\n      existing.exports.push(...names)\r\n    } else {\r\n      byModule.set(moduleName, {\r\n        module: moduleName,\r\n        source_glob: `src/${moduleName}/**/*.ts`,\r\n        exports: [...names],\r\n      })\r\n    }\r\n  }\r\n\r\n  for (const iface of byModule.values()) {\r\n    iface.exports = [...new Set(iface.exports)].sort()\r\n  }\r\n\r\n  return [...byModule.values()].sort((a, b) => a.module.localeCompare(b.module))\r\n}\r\n\r\nfunction collectTsFiles(srcDir: string): string[] {\r\n  const out: string[] = []\r\n  const walk = (dir: string) => {\r\n    let entries: string[]\r\n    try {\r\n      entries = readdirSync(dir)\r\n    } catch {\r\n      return\r\n    }\r\n    for (const name of entries) {\r\n      if (name === 'node_modules') continue\r\n      const full = join(dir, name)\r\n      let st\r\n      try {\r\n        st = statSync(full)\r\n      } catch {\r\n        continue\r\n      }\r\n      if (st.isDirectory()) {\r\n        walk(full)\r\n      } else if (st.isFile() && full.endsWith('.ts') && !full.endsWith('.d.ts')) {\r\n        out.push(full)\r\n      }\r\n    }\r\n  }\r\n  walk(srcDir)\r\n  return out\r\n}\r\n\r\n// ─── Maven / Java pipeline ─────────────────────────────────────────────\r\n\r\n/**\r\n * Parse `<module>` entries from a Maven pom.xml.\r\n * Returns module directory names relative to project root.\r\n */\r\nfunction parseMavenModules(pomPath: string): string[] {\r\n  let content: string\r\n  try {\r\n    content = readFileSync(pomPath, 'utf-8')\r\n  } catch {\r\n    return []\r\n  }\r\n\r\n  const modules: string[] = []\r\n  // Match <module>name</module> — supports whitespace and optional <modules> wrapper\r\n  const re = /<module>\\s*([^<\\s]+)\\s*<\\/module>/gi\r\n  let match: RegExpExecArray | null\r\n  while ((match = re.exec(content)) !== null) {\r\n    modules.push(match[1])\r\n  }\r\n  return modules\r\n}\r\n\r\n/**\r\n * Build the graph from a Maven multi-module project.\r\n *\r\n * 1. Parse pom.xml for <module> entries.\r\n * 2. For each module, scan {module}/src/main/java/ for .java files.\r\n * 3. Extract public interface/class/enum/record declarations via regex.\r\n * 4. If no <module> entries, fall back to recursive .java scan from root.\r\n */\r\nasync function inferMavenJavaGraph(\r\n  projectRoot: string,\r\n  pomPath: string,\r\n): Promise<InferredInterface[]> {\r\n  const modules = parseMavenModules(pomPath)\r\n  const pomDir = join(pomPath, '..') // dirname\r\n\r\n  if (modules.length === 0) return []\r\n\r\n  const results: InferredInterface[] = []\r\n\r\n  for (const mod of modules) {\r\n    const modDir = join(pomDir, mod)\r\n    const javaSrcDir = join(modDir, 'src', 'main', 'java')\r\n    if (!existsSync(javaSrcDir)) continue\r\n\r\n    const javaFiles = collectJavaFiles(javaSrcDir)\r\n    if (javaFiles.length === 0) continue\r\n\r\n    const exports = extractJavaSymbolsFromFiles(javaFiles)\r\n    if (exports.length === 0) continue\r\n\r\n    results.push({\r\n      module: mod,\r\n      source_glob: `${mod}/src/main/java/**/*.java`,\r\n      exports: [...new Set(exports)].sort(),\r\n    })\r\n  }\r\n\r\n  return results.sort((a, b) => a.module.localeCompare(b.module))\r\n}\r\n\r\n/**\r\n * Collect .java files under a single source root (non-recursive into sub-modules,\r\n * since Maven modules are already split at the pom level).\r\n */\r\nfunction collectJavaFiles(srcDir: string): string[] {\r\n  const out: string[] = []\r\n  const walk = (dir: string) => {\r\n    let entries: string[]\r\n    try {\r\n      entries = readdirSync(dir)\r\n    } catch {\r\n      return\r\n    }\r\n    for (const name of entries) {\r\n      const full = join(dir, name)\r\n      let st\r\n      try {\r\n        st = statSync(full)\r\n      } catch {\r\n        continue\r\n      }\r\n      if (st.isDirectory()) {\r\n        walk(full)\r\n      } else if (st.isFile() && full.endsWith('.java')) {\r\n        out.push(full)\r\n      }\r\n    }\r\n  }\r\n  walk(srcDir)\r\n  return out\r\n}\r\n\r\n/**\r\n * Recursive .java scan from project root (fallback when no pom.xml or no <modules>).\r\n */\r\nfunction collectJavaFilesRecursive(projectRoot: string): string[] {\r\n  const out: string[] = []\r\n  const walk = (dir: string) => {\r\n    let entries: string[]\r\n    try {\r\n      entries = readdirSync(dir)\r\n    } catch {\r\n      return\r\n    }\r\n    for (const name of entries) {\r\n      if (name === 'node_modules' || name === '.git' || name === 'target') continue\r\n      const full = join(dir, name)\r\n      let st\r\n      try {\r\n        st = statSync(full)\r\n      } catch {\r\n        continue\r\n      }\r\n      if (st.isDirectory()) {\r\n        walk(full)\r\n      } else if (st.isFile() && full.endsWith('.java')) {\r\n        out.push(full)\r\n      }\r\n    }\r\n  }\r\n  walk(projectRoot)\r\n  return out\r\n}\r\n\r\n/**\r\n * Extract Java public type declarations (interface, class, enum, record)\r\n * from a list of .java file paths. Uses regex-based extraction — no full\r\n * Java parser dependency.\r\n *\r\n * Matches patterns like:\r\n *   public interface Foo\r\n *   public class Foo\r\n *   public abstract class Foo\r\n *   public enum Foo\r\n *   public record Foo\r\n *\r\n * Skips non-public types (package-private, protected, private).\r\n */\r\nfunction extractJavaSymbolsFromFiles(filePaths: string[]): string[] {\r\n  const symbols = new Set<string>()\r\n\r\n  for (const filePath of filePaths) {\r\n    let content: string\r\n    try {\r\n      content = readFileSync(filePath, 'utf-8')\r\n    } catch {\r\n      continue\r\n    }\r\n    if (!content.trim()) continue\r\n\r\n    // Match public (abstract)? (interface|class|enum|record) Name\r\n    // Using a simple regex — covers 95%+ of real-world Java declarations\r\n    const re = /public\\s+(?:abstract\\s+)?(interface|class|enum|record)\\s+(\\w+)/g\r\n    let match: RegExpExecArray | null\r\n    while ((match = re.exec(content)) !== null) {\r\n      // Skip inner classes (preceded by a type name on the same line before \"class\")\r\n      // and annotation declarations (@interface)\r\n      symbols.add(match[2])\r\n    }\r\n  }\r\n\r\n  return [...symbols].sort()\r\n}\r\n\r\n/**\r\n * Build graph from a flat collection of .java files (no Maven module structure).\r\n * Derives module names from the relative path: src/main/java → parent dir.\r\n */\r\nasync function inferJavaGraphFromFiles(\r\n  projectRoot: string,\r\n  javaFiles: string[],\r\n): Promise<InferredInterface[]> {\r\n  const byModule = new Map<string, { exports: Set<string>; sourceRoot: string }>()\r\n\r\n  for (const absPath of javaFiles) {\r\n    const rel = relative(projectRoot, absPath).replace(/\\\\/g, '/')\r\n    const moduleName = deriveJavaModuleName(rel)\r\n    const record = byModule.get(moduleName)\r\n\r\n    let content: string\r\n    try {\r\n      content = readFileSync(absPath, 'utf-8')\r\n    } catch {\r\n      continue\r\n    }\r\n    if (!content.trim()) continue\r\n\r\n    const re = /public\\s+(?:abstract\\s+)?(interface|class|enum|record)\\s+(\\w+)/g\r\n    let match: RegExpExecArray | null\r\n    const names: string[] = []\r\n    while ((match = re.exec(content)) !== null) {\r\n      names.push(match[2])\r\n    }\r\n\r\n    if (record) {\r\n      for (const n of names) record.exports.add(n)\r\n    } else {\r\n      byModule.set(moduleName, {\r\n        exports: new Set(names),\r\n        sourceRoot: deriveJavaSourceGlob(rel),\r\n      })\r\n    }\r\n  }\r\n\r\n  const results: InferredInterface[] = []\r\n  for (const [mod, rec] of byModule) {\r\n    if (rec.exports.size === 0) continue\r\n    results.push({\r\n      module: mod,\r\n      source_glob: rec.sourceRoot,\r\n      exports: [...rec.exports].sort(),\r\n    })\r\n  }\r\n\r\n  return results.sort((a, b) => a.module.localeCompare(b.module))\r\n}\r\n\r\n/**\r\n * Derive a module name from a relative Java file path.\r\n * For Maven: agent-bus/src/main/java/com/example/... → module = agent-bus\r\n * For flat: src/main/java/com/example/... → module = src (fallback)\r\n */\r\nfunction deriveJavaModuleName(relPath: string): string {\r\n  const parts = relPath.split('/')\r\n  // Maven style: {module}/src/main/java/...\r\n  const mainIdx = parts.indexOf('main')\r\n  if (mainIdx >= 2 && parts[mainIdx - 1] === 'src') {\r\n    // parts[0..mainIdx-2] is the module path\r\n    return parts.slice(0, mainIdx - 1).join('/')\r\n  }\r\n  // Flat: src/main/java/... or direct java files\r\n  const srcIdx = parts.indexOf('src')\r\n  if (srcIdx >= 0 && srcIdx < parts.length - 1) {\r\n    return parts.slice(0, srcIdx).join('/') || 'root'\r\n  }\r\n  return 'root'\r\n}\r\n\r\nfunction deriveJavaSourceGlob(relPath: string): string {\r\n  const parts = relPath.split('/')\r\n  const mainIdx = parts.indexOf('main')\r\n  if (mainIdx >= 2 && parts[mainIdx - 1] === 'src') {\r\n    const modPath = parts.slice(0, mainIdx - 1).join('/')\r\n    return `${modPath}/src/main/java/**/*.java`\r\n  }\r\n  return '**/*.java'\r\n}\r\n\r\n// ─── Shared helpers ────────────────────────────────────────────────────\r\n\r\nfunction deriveModuleName(relPath: string): string {\r\n  const parts = relPath.split('/')\r\n  if (parts.length >= 2 && parts[0] === 'src') {\r\n    return parts[1]\r\n  }\r\n  return 'root'\r\n}\r\n","import { execSync } from 'child_process'\r\nimport { readFileSync } from 'fs'\r\nimport { sep } from 'path'\r\n\r\n/**\r\n * A single exported symbol from a TypeScript source file.\r\n * Used by step-7 reconcile Y2 interface diff (baseline SHA vs HEAD).\r\n * See ADR-0022.\r\n */\r\nexport interface ExportSymbol {\r\n  name: string\r\n  /** 'function' | 'class' | 'interface' | 'type' | 'enum' | 'const' | 'other' */\r\n  kind: string\r\n}\r\n\r\n/**\r\n * Parse exports from TypeScript source content. Pure function — no file system access.\r\n *\r\n * Caller is responsible for providing the source string. For live files, use\r\n * readFileSync; for historical content, use parseExportsFromGitRevision which\r\n * shells out to `git show <sha>:<file>`.\r\n */\r\nexport async function parseExports(source: string, _fileName: string): Promise<ExportSymbol[]> {\r\n  const { Project } = await import('ts-morph')\r\n  const project = new Project({\r\n    compilerOptions: {\r\n      allowJs: false,\r\n      declaration: false,\r\n      skipLibCheck: true,\r\n      noEmit: true,\r\n    },\r\n    useInMemoryFileSystem: true,\r\n  })\r\n\r\n  // Memory FS path must end in .ts for ts-morph to parse as TS\r\n  const memPath = '/in-memory.ts'\r\n  const sourceFile = project.createSourceFile(memPath, source, { overwrite: true })\r\n\r\n    const symbols: ExportSymbol[] = []\r\n  for (const sym of sourceFile.getExportSymbols() as Array<{ getName(): string; getDeclarations(): Array<{ getKindName(): string | (() => string) }> }>) {\r\n    symbols.push({\r\n      name: sym.getName(),\r\n      kind: classifySymbolKind(sym),\r\n    })\r\n  }\r\n  return symbols\r\n}\r\n\r\n/**\r\n * Parse exports from a list of files at a specific git revision.\r\n *\r\n * For each file: `git show <sha>:<file>` to fetch historical content, then parseExports.\r\n * Deleted files (file exists at HEAD but not at <sha>) are skipped with the returned map\r\n * reflecting absence — caller can diff against HEAD exports to compute \"added\".\r\n *\r\n * Returns map keyed by repo-relative file path (forward slashes).\r\n */\r\nexport async function parseExportsFromGitRevision(\r\n  projectRoot: string,\r\n  sha: string,\r\n  files: string[],\r\n): Promise<Map<string, ExportSymbol[]>> {\r\n  const result = new Map<string, ExportSymbol[]>()\r\n\r\n  for (const file of files) {\r\n    let content: string\r\n    try {\r\n      content = execSync(`git show ${sha}:${file}`, {\r\n        cwd: projectRoot,\r\n        stdio: ['ignore', 'pipe', 'pipe'],\r\n        timeout: 5000,\r\n        maxBuffer: 5 * 1024 * 1024,\r\n      }).toString('utf-8')\r\n    } catch {\r\n      // File didn't exist at this revision (newly added at HEAD) — skip, will show as added\r\n      continue\r\n    }\r\n\r\n    if (!content.trim()) continue\r\n    const rel = normalizePath(file)\r\n    const symbols = await parseExports(content, rel)\r\n    result.set(rel, symbols)\r\n  }\r\n\r\n  return result\r\n}\r\n\r\n/**\r\n * Read current exports from the working tree for a list of files.\r\n */\r\nexport async function parseExportsFromWorkingTree(\r\n  projectRoot: string,\r\n  files: string[],\r\n): Promise<Map<string, ExportSymbol[]>> {\r\n  const result = new Map<string, ExportSymbol[]>()\r\n\r\n  for (const file of files) {\r\n    const rel = normalizePath(file)\r\n    let content: string\r\n    try {\r\n      content = readFileSync(`${projectRoot}${sep}${rel}`, 'utf-8')\r\n    } catch {\r\n      continue\r\n    }\r\n    if (!content.trim()) continue\r\n    const symbols = await parseExports(content, rel)\r\n    result.set(rel, symbols)\r\n  }\r\n\r\n  return result\r\n}\r\n\r\n/**\r\n * Resolve the git revision at baseline freeze time, per ADR-0022.\r\n *\r\n * 1. If baseline.frozen_at_sha is present, use it directly.\r\n * 2. Otherwise fall back to `git rev-list --before=<frozen_at> -1` and warn.\r\n *\r\n * Returns { sha, source } where source is 'baseline-field' | 'timestamp-fallback' | 'none'.\r\n */\r\nexport function resolveBaselineSha(\r\n  projectRoot: string,\r\n  frozenAtSha: string | undefined,\r\n  frozenAt: string,\r\n): { sha: string | null; source: 'baseline-field' | 'timestamp-fallback' | 'none'; warning?: string } {\r\n  if (frozenAtSha && /^[0-9a-f]{7,40}$/.test(frozenAtSha)) {\r\n    return { sha: frozenAtSha, source: 'baseline-field' }\r\n  }\r\n\r\n  if (!frozenAt) {\r\n    return {\r\n      sha: null,\r\n      source: 'none',\r\n      warning: 'baseline has no frozen_at_sha and no frozen_at — interface diff disabled',\r\n    }\r\n  }\r\n\r\n  try {\r\n    const sha = execSync(`git rev-list -1 --before=${frozenAt} --format=%H HEAD`, {\r\n      cwd: projectRoot,\r\n      stdio: ['ignore', 'pipe', 'pipe'],\r\n      timeout: 5000,\r\n    }).toString('utf-8').trim().split('\\n').filter(l => /^[0-9a-f]{40}$/.test(l))[0]\r\n\r\n    if (!sha) {\r\n      return {\r\n        sha: null,\r\n        source: 'none',\r\n        warning: `git rev-list --before=${frozenAt} returned no commit — interface diff disabled`,\r\n      }\r\n    }\r\n    return {\r\n      sha,\r\n      source: 'timestamp-fallback',\r\n      warning: `baseline.frozen_at_sha missing — using timestamp-fallback ${sha.slice(0, 8)} (precision may be off if same-second commits exist)`,\r\n    }\r\n  } catch (err: any) {\r\n    return {\r\n      sha: null,\r\n      source: 'none',\r\n      warning: `git rev-list failed: ${err.message?.split('\\n')[0] ?? err.message}`,\r\n    }\r\n  }\r\n}\r\n\r\n/**\r\n * Diff two snapshots of per-file exports. Returns per-file added/removed.\r\n * Signature change detection is left to future work (requires AST compare).\r\n */\r\nexport function diffExportSnapshots(\r\n  before: Map<string, ExportSymbol[]>,\r\n  after: Map<string, ExportSymbol[]>,\r\n): Array<{\r\n  file: string\r\n  added: ExportSymbol[]\r\n  removed: ExportSymbol[]\r\n  changed: ExportSymbol[]\r\n}> {\r\n  const allFiles = new Set<string>([...before.keys(), ...after.keys()])\r\n  const result: Array<{ file: string; added: ExportSymbol[]; removed: ExportSymbol[]; changed: ExportSymbol[] }> = []\r\n\r\n  for (const file of allFiles) {\r\n    const beforeSyms = before.get(file) ?? []\r\n    const afterSyms = after.get(file) ?? []\r\n    const beforeMap = new Map(beforeSyms.map(s => [s.name, s]))\r\n    const afterMap = new Map(afterSyms.map(s => [s.name, s]))\r\n\r\n    const added = afterSyms.filter(s => !beforeMap.has(s.name))\r\n    const removed = beforeSyms.filter(s => !afterMap.has(s.name))\r\n    const changed = afterSyms.filter(s => {\r\n      const old = beforeMap.get(s.name)\r\n      return old && old.kind !== s.kind\r\n    })\r\n\r\n    if (added.length || removed.length || changed.length) {\r\n      result.push({ file, added, removed, changed })\r\n    }\r\n  }\r\n\r\n  return result.sort((a, b) => a.file.localeCompare(b.file))\r\n}\r\n\r\nfunction normalizePath(p: string): string {\r\n  return p.replace(/\\\\/g, '/')\r\n}\r\n\r\nfunction classifySymbolKind(sym: { getDeclarations(): Array<{ getKindName(): string | (() => string) }> }): string {\r\n  try {\r\n    const decls = sym.getDeclarations()\r\n    if (!decls || decls.length === 0) return 'other'\r\n    const raw = decls[0].getKindName()\r\n    const kindName = typeof raw === 'function' ? (raw as () => string)() : raw\r\n    const lower = kindName.toLowerCase()\r\n    if (lower.includes('function')) return 'function'\r\n    if (lower.includes('class')) return 'class'\r\n    if (lower.includes('interface')) return 'interface'\r\n    if (lower.includes('typealias') || lower.includes('type')) return 'type'\r\n    if (lower.includes('enum')) return 'enum'\r\n    if (lower.includes('variable') || lower.includes('const')) return 'const'\r\n    return kindName || 'other'\r\n  } catch {\r\n    return 'other'\r\n  }\r\n}\r\n","import type { DeclaredInterface } from '../envelope/baseline.js'\r\nimport type { InterfaceDiff } from '../reconcile/types.js'\r\nimport type { InferredInterface } from './index.js'\r\n\r\nexport function diffInterfaces(\r\n  declared: DeclaredInterface[],\r\n  inferred: InferredInterface[],\r\n): InterfaceDiff[] {\r\n  const inferredByModule = new Map<string, InferredInterface>()\r\n  for (const i of inferred) {\r\n    inferredByModule.set(i.module, i)\r\n  }\r\n\r\n  const diffs: InterfaceDiff[] = []\r\n  const seenModules = new Set<string>()\r\n\r\n  for (const declared_i of declared) {\r\n    seenModules.add(declared_i.module)\r\n    const inferred_i = inferredByModule.get(declared_i.module)\r\n    const declaredExports = new Set(declared_i.exports)\r\n    const inferredExports = new Set(inferred_i?.exports ?? [])\r\n\r\n    const addedExports = [...inferredExports].filter(e => !declaredExports.has(e))\r\n    const removedExports = [...declaredExports].filter(e => !inferredExports.has(e))\r\n\r\n    if (addedExports.length > 0 || removedExports.length > 0) {\r\n      diffs.push({\r\n        module: declared_i.module,\r\n        addedExports,\r\n        removedExports,\r\n        changedSignatures: [],\r\n      })\r\n    }\r\n  }\r\n\r\n  for (const inferred_i of inferred) {\r\n    if (seenModules.has(inferred_i.module)) continue\r\n    if (inferred_i.exports.length > 0) {\r\n      diffs.push({\r\n        module: inferred_i.module,\r\n        addedExports: [...inferred_i.exports],\r\n        removedExports: [],\r\n        changedSignatures: [],\r\n      })\r\n    }\r\n  }\r\n\r\n  return diffs\r\n}\r\n","import { readFileSync, existsSync } from 'fs'\r\nimport { parse as parseYaml } from 'yaml'\r\n\r\nexport interface ModuleBoundary {\r\n  module: string\r\n  paths: string[]\r\n  change_level?: ChangeLevel\r\n}\r\n\r\nexport interface ContractPolicy {\r\n  allowed: string[]\r\n  forbidden: string[]\r\n  migration_required_when: string[]\r\n}\r\n\r\nexport interface StateOwnershipPolicy {\r\n  unchanged: string[]\r\n  allowed_new_state: string[]\r\n  forbidden: string[]\r\n}\r\n\r\nexport interface AutomationProjectionPolicy {\r\n  graphify?: string[]\r\n  openapi_swagger?: string[]\r\n  codegen?: string[]\r\n}\r\n\r\nexport type ProjectionToolName = 'graphify' | 'openapi_swagger' | 'codegen'\r\n\r\nexport interface ArchitectureEnvelope {\r\n  version: string\r\n  request_id: string\r\n  legal_layer?: {\r\n    architectural?: Array<{ scope: string; enforcement: string }>\r\n    code?: Array<{ scope: string; enforcement: string }>\r\n  }\r\n  module_boundaries: {\r\n    writable: ModuleBoundary[]\r\n    read_only: ModuleBoundary[]\r\n    forbidden: ModuleBoundary[]\r\n  }\r\n  absorption_budget: {\r\n    max_parallel_slices: number\r\n  }\r\n  /** Conditions under which AI must stop and request human adjudication. */\r\n  escalation_conditions?: string[]\r\n  /** What kinds of contract changes are allowed / forbidden / require migration. */\r\n  contract_policy?: ContractPolicy\r\n  /** State ownership boundaries AI must not cross. */\r\n  state_ownership?: StateOwnershipPolicy\r\n  /** Declared usage scope for automated projection tools (graphify / openapi / codegen). Use is denied by default if not declared. */\r\n  automation_projection_policy?: AutomationProjectionPolicy\r\n}\r\n\r\nexport type ChangeLevel = 'L0' | 'L1' | 'L2' | 'L3'\r\n\r\nexport interface DriftResult {\r\n  allowed: string[]\r\n  unexpected: Array<{ file: string; change_level?: ChangeLevel }>\r\n  passed: boolean\r\n}\r\n\r\nexport interface EnvelopeValidation {\r\n  valid: boolean\r\n  errors: string[]\r\n}\r\n\r\nexport function loadEnvelope(path: string): ArchitectureEnvelope {\r\n  if (!existsSync(path)) {\r\n    throw new Error(`Envelope file not found: ${path}`)\r\n  }\r\n  const raw = readFileSync(path, 'utf-8')\r\n  const parsed = parseYaml(raw)\r\n\r\n  if (!parsed.module_boundaries) {\r\n    throw new Error('Envelope missing required field: module_boundaries')\r\n  }\r\n\r\n  return {\r\n    version: parsed.version ?? '1.0',\r\n    request_id: parsed.request_id ?? '',\r\n    legal_layer: parsed.legal_layer,\r\n    module_boundaries: {\r\n      writable: (parsed.module_boundaries.writable ?? []).map((w: any) => ({\r\n        module: w.module,\r\n        paths: w.paths ?? [],\r\n        change_level: w.change_level ?? 'L0',\r\n      })),\r\n      read_only: (parsed.module_boundaries.read_only ?? []).map((r: any) => ({\r\n        module: r.module,\r\n        paths: r.paths ?? [],\r\n      })),\r\n      forbidden: (parsed.module_boundaries.forbidden ?? []).map((f: any) => ({\r\n        module: f.module,\r\n        paths: f.paths ?? [],\r\n      })),\r\n    },\r\n    absorption_budget: {\r\n      max_parallel_slices: parsed.absorption_budget?.max_parallel_slices ?? 1,\r\n    },\r\n    escalation_conditions: parsed.escalation_conditions,\r\n    contract_policy: parsed.contract_policy,\r\n    state_ownership: parsed.state_ownership,\r\n    automation_projection_policy: parsed.automation_projection_policy,\r\n  }\r\n}\r\n\r\nexport function validateEnvelope(envelope: ArchitectureEnvelope): EnvelopeValidation {\r\n  const errors: string[] = []\r\n  const { writable, read_only, forbidden } = envelope.module_boundaries\r\n\r\n  if (writable.length === 0 && read_only.length === 0 && forbidden.length === 0) {\r\n    errors.push('module_boundaries has no entries — at least one writable path is required')\r\n  }\r\n\r\n  if (writable.length === 0) {\r\n    errors.push('module_boundaries.writable is empty — deny-by-default requires at least one allowed path')\r\n  }\r\n\r\n  const allAllowedPatterns = [...writable, ...read_only].flatMap(b => b.paths)\r\n  const forbiddenPatterns = forbidden.flatMap(b => b.paths)\r\n  for (const fp of forbiddenPatterns) {\r\n    if (allAllowedPatterns.includes(fp)) {\r\n      errors.push(`conflict: path \"${fp}\" appears in both allowed and forbidden boundaries`)\r\n    }\r\n  }\r\n\r\n  // surface declared-but-empty projection tools — non-fatal, but signals intent without scope\r\n  const projPolicy = envelope.automation_projection_policy\r\n  if (projPolicy) {\r\n    for (const tool of ['graphify', 'openapi_swagger', 'codegen'] as const) {\r\n      const declared = projPolicy[tool as keyof AutomationProjectionPolicy]\r\n      if (declared !== undefined && Array.isArray(declared) && declared.length === 0) {\r\n        // These are warnings, not errors. Caller can choose to log them or ignore.\r\n        // We surface them in `errors` so existing callers still see them; severity is encoded in the message.\r\n        errors.push(`warning: automation_projection_policy.${tool} is declared but empty — tool will be denied by default`)\r\n      }\r\n    }\r\n  }\r\n\r\n  return { valid: errors.length === 0, errors }\r\n}\r\n\r\nexport function pathMatchesGlob(filePath: string, pattern: string): boolean {\r\n  const normalized = filePath.replace(/\\\\/g, '/')\r\n  if (pattern.endsWith('/**')) {\r\n    const prefix = pattern.slice(0, -3)\r\n    return normalized === prefix || normalized.startsWith(prefix + '/')\r\n  }\r\n  if (pattern.includes('*')) {\r\n    const regexStr = pattern\r\n      .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&')\r\n      .replace(/\\*\\*/g, '.*')\r\n      .replace(/\\*/g, '[^/]*')\r\n      .replace(/\\?/g, '[^/]')\r\n    return new RegExp(`^${regexStr}$`).test(normalized)\r\n  }\r\n  return normalized === pattern || normalized.startsWith(pattern + '/')\r\n}\r\n\r\nexport function checkDrift(envelope: ArchitectureEnvelope, changedFiles: string[]): DriftResult {\r\n  const allowed: string[] = []\r\n  const unexpected: Array<{ file: string; change_level?: ChangeLevel }> = []\r\n\r\n  const writablePatterns = envelope.module_boundaries.writable.flatMap(w => w.paths.map(p => ({ pattern: p, change_level: w.change_level ?? 'L0' as ChangeLevel })))\r\n  const readOnlyPatterns = envelope.module_boundaries.read_only.flatMap(r => r.paths)\r\n  const allAllowedPatterns = [...writablePatterns.map(w => w.pattern), ...readOnlyPatterns]\r\n\r\n  for (const file of changedFiles) {\r\n    const matchedWritable = writablePatterns.find(w => pathMatchesGlob(file, w.pattern))\r\n    if (matchedWritable) {\r\n      if (matchedWritable.change_level === 'L2' || matchedWritable.change_level === 'L3') {\r\n        unexpected.push({ file, change_level: matchedWritable.change_level })\r\n      } else {\r\n        allowed.push(file)\r\n      }\r\n    } else if (readOnlyPatterns.some(p => pathMatchesGlob(file, p))) {\r\n      unexpected.push({ file })\r\n    } else if (allAllowedPatterns.length === 0 || !allAllowedPatterns.some(p => pathMatchesGlob(file, p))) {\r\n      unexpected.push({ file })\r\n    } else {\r\n      allowed.push(file)\r\n    }\r\n  }\r\n\r\n  return { allowed, unexpected, passed: unexpected.length === 0 }\r\n}\r\n\r\nexport function getAllowedPaths(envelope: ArchitectureEnvelope, moduleName?: string): string[] {\r\n  const boundaries = [...envelope.module_boundaries.writable, ...envelope.module_boundaries.read_only]\r\n  if (moduleName) {\r\n    return boundaries.filter(b => b.module === moduleName).flatMap(b => b.paths)\r\n  }\r\n  return boundaries.flatMap(b => b.paths)\r\n}\r\n\r\nexport function getChangeLevel(envelope: ArchitectureEnvelope, path: string): ChangeLevel {\r\n  for (const w of envelope.module_boundaries.writable) {\r\n    if (w.paths.some(p => pathMatchesGlob(path, p))) {\r\n      return w.change_level ?? 'L0'\r\n    }\r\n  }\r\n  for (const r of envelope.module_boundaries.read_only) {\r\n    if (r.paths.some(p => pathMatchesGlob(path, p))) {\r\n      return 'L1'\r\n    }\r\n  }\r\n  for (const f of envelope.module_boundaries.forbidden) {\r\n    if (f.paths.some(p => pathMatchesGlob(path, p))) {\r\n      return 'L3'\r\n    }\r\n  }\r\n  return 'L3'\r\n}\r\n\r\nexport interface ProjectionUsageResult {\r\n  allowed: boolean\r\n  /** Declared usages that matched the requested usage; empty if the tool is not declared or the usage falls outside declared scope. */\r\n  matchedDeclarations: string[]\r\n  reason: string\r\n}\r\n\r\n/**\r\n * Verify that an automated projection tool usage (graphify / openapi_swagger / codegen) is declared in the envelope's\r\n * automation_projection_policy. Implements deny-by-default: undeclared tools are not allowed.\r\n *\r\n * The matching is intentionally permissive: a request matches if any declared entry contains the request string\r\n * (substring match), because declared entries are human-readable scopes (e.g. \"reverse-extract dependency graph for drift check\").\r\n */\r\nexport function checkProjectionToolUsage(\r\n  envelope: ArchitectureEnvelope,\r\n  tool: ProjectionToolName,\r\n  requestedUsage: string,\r\n): ProjectionUsageResult {\r\n  const policy = envelope.automation_projection_policy\r\n  if (!policy) {\r\n    return {\r\n      allowed: false,\r\n      matchedDeclarations: [],\r\n      reason: `automation_projection_policy not declared — tool \"${tool}\" denied by default`,\r\n    }\r\n  }\r\n  const declared = policy[tool]\r\n  if (!declared || declared.length === 0) {\r\n    return {\r\n      allowed: false,\r\n      matchedDeclarations: [],\r\n      reason: `tool \"${tool}\" has no declared allowed usages — denied by default`,\r\n    }\r\n  }\r\n  const matched = declared.filter(decl => decl.includes(requestedUsage) || requestedUsage.includes(decl))\r\n  if (matched.length === 0) {\r\n    return {\r\n      allowed: false,\r\n      matchedDeclarations: [],\r\n      reason: `requested usage \"${requestedUsage}\" not within declared scope for tool \"${tool}\": ${declared.join('; ')}`,\r\n    }\r\n  }\r\n  return {\r\n    allowed: true,\r\n    matchedDeclarations: matched,\r\n    reason: `matched ${matched.length} declaration(s)`,\r\n  }\r\n}\r\n\r\n/**\r\n * Check whether an escalation condition has been declared in the envelope.\r\n * AI agents consult this before deciding whether to stop and ask for human adjudication.\r\n */\r\nexport function isEscalationDeclared(envelope: ArchitectureEnvelope, condition: string): boolean {\r\n  if (!envelope.escalation_conditions) return false\r\n  return envelope.escalation_conditions.some(c => c.includes(condition) || condition.includes(c))\r\n}\r\n\r\n/**\r\n * Check whether a proposed state-ownership change is forbidden by the envelope.\r\n * Used to gate Level 3 changes that would alter state owners.\r\n */\r\nexport function isStateChangeForbidden(envelope: ArchitectureEnvelope, stateName: string): boolean {\r\n  if (!envelope.state_ownership) return false\r\n  return envelope.state_ownership.forbidden.some(s => s.includes(stateName) || stateName.includes(s))\r\n}\r\n"],"mappings":"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","names":["import_path","import_fs","import_path","parseYaml","stringifyYaml","import_fs","import_path","absPath","exports","import_yaml"]}