{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/services/scaffold/upgrade-audit/index.ts"],"sourcesContent":["/**\n * v1 → v2 upgrade train (NEARBuilders/everything-dev#455).\n *\n * Audits an everything-dev v1 child app for upgrade readiness (hardline\n * mount-conformance gate, config surface, legacy imports) and applies the\n * deterministic v2 transforms (authored descriptor, bun→pnpm catalog\n * migration, consumerized refs, import rewrites, obsolete-file deletion,\n * plugin dep declarations). State-aware: a tree with an authored\n * `bos.app.ts` is already on the v2 train — the audit reads\n * `bos.config.json` and is for pre-upgrade trees only.\n */\nimport { existsSync } from \"node:fs\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { Effect } from \"effect\";\nimport { apply } from \"./apply\";\nimport { audit } from \"./audit\";\nimport {\n  AUTH_FIXTURE_PATH,\n  type ComposeProbe,\n  composeFindings,\n  probeComposeSeam,\n  readEveryPluginVersion,\n} from \"./checks/compose-seam\";\nimport type { Manifest, RouterSeam, Finding as RuntimeFinding } from \"./domain\";\nimport { GateBlocked } from \"./domain\";\nimport type { StepResult } from \"./steps/author-config\";\nimport { migrateI18nSeam } from \"./steps/migrate-i18n-seam\";\nimport { migrateRouteMounts } from \"./steps/migrate-route-mounts\";\nimport { patchDbTopology } from \"./steps/patch-db-topology\";\nimport { portRouteGuards } from \"./steps/port-route-guards\";\nexport type UpgradeAuditStep =\n  | \"port-route-guards\"\n  | \"db-topology\"\n  | \"i18n-seam\"\n  | \"compose-seam\"\n  | \"route-mounts\";\n\nexport type PlainFinding = {\n  readonly check: string;\n  readonly path: string;\n  readonly severity: \"blocker\" | \"warn\";\n  readonly message: string;\n};\n\nexport type AuditManifest = Manifest;\n\nexport type AuditOutcome = {\n  readonly tier: \"A\" | \"B\";\n  readonly gateBlocked: boolean;\n  readonly findings: readonly PlainFinding[];\n  readonly manifest: AuditManifest;\n};\n\nexport type ApplyOutcome = {\n  readonly migrated: string[];\n  readonly notes: string[];\n};\n\nconst toPlainFinding = (finding: RuntimeFinding): PlainFinding => ({\n  check: finding.check,\n  path: finding.path,\n  severity: finding.severity,\n  message: finding.message,\n});\n\nexport const isV2Tree = (projectDir: string): boolean => existsSync(join(projectDir, \"bos.app.ts\"));\n\nconst writeManifestFile = async (projectDir: string, manifest: Manifest): Promise<void> => {\n  await mkdir(join(projectDir, \".bos\"), { recursive: true });\n  await writeFile(\n    join(projectDir, \".bos/v2-upgrade-manifest.json\"),\n    `${JSON.stringify(manifest, null, 2)}\\n`,\n  );\n};\n\n/** Run the v1 audit: gate findings, manifest emit, no tree writes. */\nexport const auditV1Tree = async (projectDir: string): Promise<AuditOutcome> => {\n  const report = await Effect.runPromise(audit(projectDir));\n  const findings = report.findings.map(toPlainFinding);\n  await writeManifestFile(projectDir, report.manifest);\n  return {\n    tier: report.tier,\n    gateBlocked: report.manifest.blockerCount > 0,\n    findings,\n    manifest: report.manifest,\n  };\n};\n\n/** Apply the v2 transforms; the hardline gate must pass first. */\nexport const applyV1Tree = async (\n  projectDir: string,\n  dryRun: boolean,\n): Promise<\n  { ok: true; outcome: ApplyOutcome } | { ok: false; blockers: readonly PlainFinding[] }\n> => {\n  try {\n    const logs = await Effect.runPromise(apply(projectDir, dryRun));\n    const migrated: string[] = [];\n    const notes: string[] = [];\n    for (const log of logs) {\n      for (const path of log.result.writes) migrated.push(`${log.name}: ${path}`);\n      for (const path of log.result.deletes) migrated.push(`${log.name}: deleted ${path}`);\n      for (const note of log.result.notes) notes.push(`${log.name}: ${note}`);\n    }\n    return { ok: true, outcome: { migrated, notes } };\n  } catch (error) {\n    if (error instanceof GateBlocked) {\n      return { ok: false, blockers: error.findings.map(toPlainFinding) };\n    }\n    throw error;\n  }\n};\n\n/** Re-run a post-upgrade maintenance step (regression guard after `bos sync`). */\nexport const maintainV1Tree = async (\n  projectDir: string,\n  step: UpgradeAuditStep,\n  dryRun: boolean,\n): Promise<StepResult> => {\n  switch (step) {\n    case \"route-mounts\": {\n      return await Effect.runPromise(migrateRouteMounts(projectDir, dryRun));\n    }\n    case \"port-route-guards\":\n      return await Effect.runPromise(portRouteGuards(projectDir, dryRun));\n    case \"db-topology\":\n      return await Effect.runPromise(patchDbTopology(projectDir, dryRun));\n    case \"i18n-seam\":\n      return await Effect.runPromise(migrateI18nSeam(projectDir, dryRun));\n    case \"compose-seam\": {\n      const probe = await Effect.runPromise(probeComposeSeam(projectDir, { live: false }));\n      const version = await Effect.runPromise(readEveryPluginVersion(projectDir));\n      const findings = composeFindings(probe, version);\n      return {\n        writes: [],\n        deletes: [],\n        notes: [\n          `every-plugin ${version}, auth manifest: ${AUTH_FIXTURE_PATH}`,\n          `seam: ${describeComposeProbe(probe)}`,\n          ...probe.composeLog,\n          ...(probe.error ? [`error: ${probe.error}`] : []),\n          ...findings.map((finding) => `[${finding.severity}] ${finding.message}`),\n        ],\n      };\n    }\n  }\n};\n\nexport const describeComposeProbe = (probe: ComposeProbe): string => {\n  switch (probe.seam) {\n    case \"ok\":\n      return probe.composeLog.some((line) => line.includes(\"core ui wins\"))\n        ? \"compose ok — core ui wins; shadowed auth routes skipped cleanly\"\n        : \"compose ok — note: no /login shadow exercised (core ui no longer claims /login)\";\n    case \"absent-ui-manifest\":\n      return \"ui/src/manifest.gen.json absent — run `bos types gen` first\";\n    case \"cascade-bug\":\n      return 'KNOWN BUG — false \"unresolvable parentage\" for the /login shadow cascade';\n    case \"path-collision\":\n      return \"REGRESSION — the /login shadow is treated as a hard path collision\";\n    case \"compose-failed\":\n      return \"compose failed\";\n  }\n};\n\nexport type { Manifest, RouterSeam, StepResult };\n"],"mappings":"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"}