@biffo/cli 0.281.0 → 0.282.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.
package/dist/index.js CHANGED
@@ -7756,6 +7756,13 @@ var ToolDeclarationSchema = z7.object({
7756
7756
  description: z7.string(),
7757
7757
  parameters: z7.record(z7.string(), z7.unknown()).default({})
7758
7758
  });
7759
+ var SeedDeclarationSchema = z7.object({
7760
+ dir: z7.string().regex(
7761
+ REL_DIR,
7762
+ "must be a plugin-relative path with no leading slash or traversal, e.g. db/seed"
7763
+ ),
7764
+ baseline_tables: z7.array(z7.string()).default([])
7765
+ }).strict();
7759
7766
  var ChatAgentDeclarationSchema = z7.object({
7760
7767
  key: z7.string().regex(/^[a-z][a-z0-9-]*$/, "must be a lowercase kebab-case slug"),
7761
7768
  agent_name: z7.string().optional(),
@@ -7794,7 +7801,11 @@ var PluginManifestSchema = z7.object({
7794
7801
  tools: z7.array(ToolDeclarationSchema).default([]),
7795
7802
  // Chat agents the plugin registers with Core (ADR-0017). Default empty — an
7796
7803
  // ordinary plugin declares none.
7797
- chat_agents: z7.array(ChatAgentDeclarationSchema).default([])
7804
+ chat_agents: z7.array(ChatAgentDeclarationSchema).default([]),
7805
+ // The plugin's tenant-scoped baseline-row seed (ADR-0005, biffo-template#1554).
7806
+ // Optional — a plugin with no baseline data omits this entirely, and
7807
+ // `biffo plugin install`/`upgrade` vendor nothing for it.
7808
+ seed: SeedDeclarationSchema.optional()
7798
7809
  }).superRefine((manifest, ctx) => {
7799
7810
  const tableNames = new Set(manifest.tables.map((t) => t.name));
7800
7811
  for (const route of manifest.api_routes) {
@@ -7805,6 +7816,16 @@ var PluginManifestSchema = z7.object({
7805
7816
  });
7806
7817
  }
7807
7818
  }
7819
+ if (manifest.seed) {
7820
+ for (const table of manifest.seed.baseline_tables) {
7821
+ if (!tableNames.has(table)) {
7822
+ ctx.addIssue({
7823
+ code: z7.ZodIssueCode.custom,
7824
+ message: `seed.baseline_tables references table '${table}', which is not declared in this manifest's 'tables' (${[...tableNames].sort().join(", ") || "none"})`
7825
+ });
7826
+ }
7827
+ }
7828
+ }
7808
7829
  });
7809
7830
  function validateManifest(raw) {
7810
7831
  const result = PluginManifestSchema.safeParse(raw);
@@ -8319,6 +8340,14 @@ var RegistryPluginEntrySchema = z8.object({
8319
8340
  description: z8.string().optional(),
8320
8341
  author: z8.string().optional(),
8321
8342
  tags: z8.array(z8.string()).optional(),
8343
+ // Summary-form mirror of the manifest's `seed.baseline_tables` (see
8344
+ // ../../lib/plugin-manifest.ts's SeedDeclarationSchema and
8345
+ // _skeletons/registry/registry-schema.json's `seed`, biffo-template#1554).
8346
+ // The registry entry only ever needs to know WHICH tables a plugin promises
8347
+ // baseline rows for, never the seed `dir` itself — that only matters to the
8348
+ // install/upgrade vendoring step, which reads it from the plugin's own
8349
+ // biffo.plugin.json after cloning, not from this summary.
8350
+ baseline_tables: z8.array(z8.string()).optional(),
8322
8351
  required_core_version: z8.string().optional(),
8323
8352
  infra_modules: z8.array(z8.string()).optional(),
8324
8353
  api_routes: z8.array(z8.string()).optional(),
@@ -8445,8 +8474,8 @@ function printEntry(entry) {
8445
8474
  }
8446
8475
 
8447
8476
  // src/commands/plugin-install.ts
8448
- import { cpSync as cpSync4, existsSync as existsSync29, mkdirSync as mkdirSync10, readFileSync as readFileSync22, statSync as statSync6 } from "fs";
8449
- import { join as join31, relative as relative3, resolve as resolve12 } from "path";
8477
+ import { cpSync as cpSync5, existsSync as existsSync30, mkdirSync as mkdirSync11, readFileSync as readFileSync22, statSync as statSync6 } from "fs";
8478
+ import { join as join32, relative as relative3, resolve as resolve12 } from "path";
8450
8479
  import chalk15 from "chalk";
8451
8480
  import { Command as Command15 } from "commander";
8452
8481
 
@@ -8572,9 +8601,48 @@ async function tryGit(cwd, args) {
8572
8601
  }
8573
8602
  }
8574
8603
 
8604
+ // src/lib/plugin-seed-vendor.ts
8605
+ import { cpSync as cpSync3, existsSync as existsSync28, mkdirSync as mkdirSync9, readdirSync as readdirSync12, rmSync as rmSync8 } from "fs";
8606
+ import { join as join29 } from "path";
8607
+ var VENDOR_PREFIX = "_plugin-";
8608
+ function pluginSeedImportDir(pluginName) {
8609
+ return `db/imports/${VENDOR_PREFIX}${pluginName}`;
8610
+ }
8611
+ function vendorPluginSeed(pluginSourceDir, manifest, cwd) {
8612
+ if (!manifest.seed) {
8613
+ return { vendored: false };
8614
+ }
8615
+ const sourceSeedDir = join29(pluginSourceDir, manifest.seed.dir);
8616
+ if (!existsSync28(sourceSeedDir)) {
8617
+ throw new Error(
8618
+ `${manifest.name}'s manifest declares seed.dir '${manifest.seed.dir}', but ${sourceSeedDir} does not exist in the plugin's source.`
8619
+ );
8620
+ }
8621
+ const sqlFiles = readdirSync12(sourceSeedDir).filter((f) => f.endsWith(".sql"));
8622
+ if (sqlFiles.length === 0) {
8623
+ throw new Error(
8624
+ `${manifest.name}'s manifest declares seed.dir '${manifest.seed.dir}', but ${sourceSeedDir} contains no *.sql files.`
8625
+ );
8626
+ }
8627
+ const relTargetDir = pluginSeedImportDir(manifest.name);
8628
+ const targetDir = join29(cwd, relTargetDir);
8629
+ rmSync8(targetDir, { recursive: true, force: true });
8630
+ mkdirSync9(targetDir, { recursive: true });
8631
+ for (const file of sqlFiles) {
8632
+ cpSync3(join29(sourceSeedDir, file), join29(targetDir, file));
8633
+ }
8634
+ log.success(
8635
+ `Vendored ${sqlFiles.length} seed file(s) to ${relTargetDir}/ (baseline_tables: ${manifest.seed.baseline_tables.join(", ") || "none declared"})`
8636
+ );
8637
+ log.info(
8638
+ `${relTargetDir}/*.sql are checksum-tracked once applied (ADR-0005 section 4) \u2014 a later version must ship a new, additively-numbered file for a changed seed, never edit one already released, or the next deploy fails loudly.`
8639
+ );
8640
+ return { vendored: true, stagedPath: relTargetDir };
8641
+ }
8642
+
8575
8643
  // src/lib/plugin-source-copy.ts
8576
- import { copyFileSync as copyFileSync2, cpSync as cpSync3, mkdirSync as mkdirSync9 } from "fs";
8577
- import { basename, dirname as dirname9, join as join29 } from "path";
8644
+ import { copyFileSync as copyFileSync2, cpSync as cpSync4, mkdirSync as mkdirSync10 } from "fs";
8645
+ import { basename, dirname as dirname9, join as join30 } from "path";
8578
8646
  import { execa as execa6 } from "execa";
8579
8647
  var LOCAL_COPY_EXCLUDES = /* @__PURE__ */ new Set([
8580
8648
  ".git",
@@ -8591,17 +8659,17 @@ async function copyPluginSource(sourceDir, targetDir) {
8591
8659
  if (await isGitWorkingTree2(sourceDir)) {
8592
8660
  const files = await listGitFiles(sourceDir);
8593
8661
  for (const relPath of files) {
8594
- const destPath = join29(targetDir, relPath);
8595
- mkdirSync9(dirname9(destPath), { recursive: true });
8596
- copyFileSync2(join29(sourceDir, relPath), destPath);
8662
+ const destPath = join30(targetDir, relPath);
8663
+ mkdirSync10(dirname9(destPath), { recursive: true });
8664
+ copyFileSync2(join30(sourceDir, relPath), destPath);
8597
8665
  }
8598
8666
  return { usedGitIgnoreRules: true };
8599
8667
  }
8600
8668
  log.warn(
8601
8669
  `${sourceDir} is not a git working tree \u2014 cannot honour .gitignore. Falling back to a fixed exclude list (.git, .venv, node_modules, caches); anything else it does not know about (e.g. an unfamiliar cache directory) will be copied.`
8602
8670
  );
8603
- mkdirSync9(targetDir, { recursive: true });
8604
- cpSync3(sourceDir, targetDir, {
8671
+ mkdirSync10(targetDir, { recursive: true });
8672
+ cpSync4(sourceDir, targetDir, {
8605
8673
  recursive: true,
8606
8674
  filter: (src) => !LOCAL_COPY_EXCLUDES.has(basename(src))
8607
8675
  });
@@ -8625,8 +8693,8 @@ async function listGitFiles(dir) {
8625
8693
  }
8626
8694
 
8627
8695
  // src/lib/plugin-workspace-sources.ts
8628
- import { existsSync as existsSync28, readdirSync as readdirSync12, readFileSync as readFileSync21, writeFileSync as writeFileSync11 } from "fs";
8629
- import { join as join30 } from "path";
8696
+ import { existsSync as existsSync29, readdirSync as readdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync11 } from "fs";
8697
+ import { join as join31 } from "path";
8630
8698
  function readTomlStringArray(text, key) {
8631
8699
  const open = new RegExp(`^${key}\\s*=\\s*\\[`, "m").exec(text);
8632
8700
  if (!open) return [];
@@ -8670,8 +8738,8 @@ function readDependencyNames(text) {
8670
8738
  return readTomlStringArray(text, "dependencies").map((dep) => /^\s*([A-Za-z0-9._-]+)/.exec(dep)?.[1] ?? "").filter(Boolean);
8671
8739
  }
8672
8740
  function workspaceMemberNames(instanceRoot) {
8673
- const rootPyproject = join30(instanceRoot, "pyproject.toml");
8674
- if (!existsSync28(rootPyproject)) return /* @__PURE__ */ new Set();
8741
+ const rootPyproject = join31(instanceRoot, "pyproject.toml");
8742
+ if (!existsSync29(rootPyproject)) return /* @__PURE__ */ new Set();
8675
8743
  const text = readFileSync21(rootPyproject, "utf8");
8676
8744
  const members = readTomlStringArray(text, "members");
8677
8745
  const excluded = new Set(readTomlStringArray(text, "exclude"));
@@ -8681,7 +8749,7 @@ function workspaceMemberNames(instanceRoot) {
8681
8749
  const base = member.slice(0, -2);
8682
8750
  let entries;
8683
8751
  try {
8684
- entries = readdirSync12(join30(instanceRoot, base), { withFileTypes: true });
8752
+ entries = readdirSync13(join31(instanceRoot, base), { withFileTypes: true });
8685
8753
  } catch {
8686
8754
  continue;
8687
8755
  }
@@ -8695,8 +8763,8 @@ function workspaceMemberNames(instanceRoot) {
8695
8763
  }
8696
8764
  const names = /* @__PURE__ */ new Set();
8697
8765
  for (const dir of dirs) {
8698
- const pp = join30(instanceRoot, dir, "pyproject.toml");
8699
- if (!existsSync28(pp)) continue;
8766
+ const pp = join31(instanceRoot, dir, "pyproject.toml");
8767
+ if (!existsSync29(pp)) continue;
8700
8768
  const name = readProjectName(readFileSync21(pp, "utf8"));
8701
8769
  if (name) names.add(name);
8702
8770
  }
@@ -8708,7 +8776,7 @@ function existingWorkspaceSources(text) {
8708
8776
  );
8709
8777
  }
8710
8778
  function ensureWorkspaceSources(pluginPyprojectPath, memberNames) {
8711
- if (!existsSync28(pluginPyprojectPath) || memberNames.size === 0) return [];
8779
+ if (!existsSync29(pluginPyprojectPath) || memberNames.size === 0) return [];
8712
8780
  const text = readFileSync21(pluginPyprojectPath, "utf8");
8713
8781
  const already = existingWorkspaceSources(text);
8714
8782
  const toAdd = readDependencyNames(text).filter((n) => memberNames.has(n) && !already.has(n));
@@ -8733,8 +8801,8 @@ ${lines.join("\n")}
8733
8801
  return toAdd;
8734
8802
  }
8735
8803
  function applyWorkspaceSources(targetDir, cwd, relTargetDir) {
8736
- const pluginPyproject = join30(targetDir, "pyproject.toml");
8737
- if (!existsSync28(pluginPyproject)) return;
8804
+ const pluginPyproject = join31(targetDir, "pyproject.toml");
8805
+ if (!existsSync29(pluginPyproject)) return;
8738
8806
  const sourced = ensureWorkspaceSources(pluginPyproject, workspaceMemberNames(cwd));
8739
8807
  if (sourced.length > 0) {
8740
8808
  log.info(
@@ -8774,14 +8842,14 @@ var pluginInstallCommand = new Command15("install").description(
8774
8842
  }
8775
8843
  );
8776
8844
  function resolveLocalPlugin(localPath) {
8777
- if (!existsSync29(localPath)) {
8845
+ if (!existsSync30(localPath)) {
8778
8846
  throw new Error(`--local path does not exist: ${localPath}`);
8779
8847
  }
8780
8848
  if (!statSync6(localPath).isDirectory()) {
8781
8849
  throw new Error(`--local path is not a directory: ${localPath}`);
8782
8850
  }
8783
- const manifestPath = join31(localPath, "biffo.plugin.json");
8784
- if (!existsSync29(manifestPath)) {
8851
+ const manifestPath = join32(localPath, "biffo.plugin.json");
8852
+ if (!existsSync30(manifestPath)) {
8785
8853
  throw new Error(
8786
8854
  `${localPath} does not contain a biffo.plugin.json manifest at its root \u2014 is it a plugin directory? (Scaffold one with \`biffo plugin create <name>\`.)`
8787
8855
  );
@@ -8807,8 +8875,8 @@ function parsePluginTarget(target) {
8807
8875
  async function cloneAndValidatePlugin(entry, git) {
8808
8876
  const tmpDir = await git.cloneToTemp(entry.repo, `biffo-plugin-${entry.name}`);
8809
8877
  try {
8810
- const manifestPath = join31(tmpDir, "biffo.plugin.json");
8811
- if (!existsSync29(manifestPath)) {
8878
+ const manifestPath = join32(tmpDir, "biffo.plugin.json");
8879
+ if (!existsSync30(manifestPath)) {
8812
8880
  throw new Error(
8813
8881
  `Plugin repo ${entry.repo} does not contain a biffo.plugin.json manifest at its root.`
8814
8882
  );
@@ -8836,8 +8904,8 @@ async function runPluginInstall(target, options, deps) {
8836
8904
  `Nothing to install. Pass a registry target (e.g. \`biffo plugin install acme-crm@1.0\`) or a local plugin directory (\`biffo plugin install --local services/acme-crm\`).`
8837
8905
  );
8838
8906
  }
8839
- const servicesDir = join31(options.cwd, "services");
8840
- if (!existsSync29(servicesDir)) {
8907
+ const servicesDir = join32(options.cwd, "services");
8908
+ if (!existsSync30(servicesDir)) {
8841
8909
  throw new Error(
8842
8910
  `${servicesDir} does not exist \u2014 is ${options.cwd} the root of a Biffo project checkout?`
8843
8911
  );
@@ -8855,10 +8923,10 @@ async function runPluginInstall(target, options, deps) {
8855
8923
  }
8856
8924
  const pluginName = entry ? entry.name : source.name;
8857
8925
  const relTargetDir = pluginDir(pluginName, "third-party");
8858
- const targetDir = join31(options.cwd, relTargetDir);
8859
- const modulesDir = join31(options.cwd, "modules", "plugins", pluginName);
8926
+ const targetDir = join32(options.cwd, relTargetDir);
8927
+ const modulesDir = join32(options.cwd, "modules", "plugins", pluginName);
8860
8928
  const inTreeSource = options.local !== void 0 && resolve12(options.local) === resolve12(targetDir);
8861
- if (existsSync29(targetDir) && !inTreeSource) {
8929
+ if (existsSync30(targetDir) && !inTreeSource) {
8862
8930
  throw new Error(
8863
8931
  `Plugin '${pluginName}' is already installed at ${relTargetDir}/. Remove it first, or wait for a future 'biffo plugin upgrade' command.`
8864
8932
  );
@@ -8893,7 +8961,7 @@ async function runPluginInstall(target, options, deps) {
8893
8961
  if (inTreeSource) {
8894
8962
  log.info(`${relTargetDir}/ is already in this checkout \u2014 installing in place.`);
8895
8963
  } else {
8896
- mkdirSync10(targetDir, { recursive: true });
8964
+ mkdirSync11(targetDir, { recursive: true });
8897
8965
  await copyPluginSource(source.sourceDir, targetDir);
8898
8966
  log.success(`Installed plugin source at ${relTargetDir}/`);
8899
8967
  }
@@ -8902,10 +8970,10 @@ async function runPluginInstall(target, options, deps) {
8902
8970
  writePluginProvenance(targetDir, reconcileProvenance(previousProvenance, nextProvenance));
8903
8971
  applyWorkspaceSources(targetDir, options.cwd, relTargetDir);
8904
8972
  const stagePaths = [relTargetDir];
8905
- const tfSourceDir = join31(targetDir, "terraform");
8906
- if (existsSync29(tfSourceDir)) {
8907
- mkdirSync10(modulesDir, { recursive: true });
8908
- cpSync4(tfSourceDir, modulesDir, { recursive: true });
8973
+ const tfSourceDir = join32(targetDir, "terraform");
8974
+ if (existsSync30(tfSourceDir)) {
8975
+ mkdirSync11(modulesDir, { recursive: true });
8976
+ cpSync5(tfSourceDir, modulesDir, { recursive: true });
8909
8977
  stagePaths.push(`modules/plugins/${pluginName}`);
8910
8978
  log.success(`Copied Terraform module to modules/plugins/${pluginName}/`);
8911
8979
  const wiring = syncPluginTerraform(options.cwd);
@@ -8944,6 +9012,10 @@ async function runPluginInstall(target, options, deps) {
8944
9012
  } else {
8945
9013
  log.info(`${pluginName} declares no tables \u2014 nothing to migrate.`);
8946
9014
  }
9015
+ const seedResult = vendorPluginSeed(targetDir, manifest, options.cwd);
9016
+ if (seedResult.vendored) {
9017
+ stagePaths.push(seedResult.stagedPath);
9018
+ }
8947
9019
  const commitMessage = `feat(plugins): install ${pluginName}@${source.version}`;
8948
9020
  await deps.git.add(options.cwd, stagePaths);
8949
9021
  await deps.git.commit(options.cwd, commitMessage);
@@ -8992,13 +9064,18 @@ function printDryRun4(entry, source, relTargetDir, inTreeSource) {
8992
9064
  ` Would generate a migration for ${source.manifest.tables.length} table(s) into services/api/migrations/versions/`
8993
9065
  );
8994
9066
  }
9067
+ if (source && source.manifest.seed) {
9068
+ console.log(
9069
+ ` Would vendor seed DDL into: ${pluginSeedImportDir(name)}/ (baseline_tables: ${source.manifest.seed.baseline_tables.join(", ") || "none declared"})`
9070
+ );
9071
+ }
8995
9072
  console.log(` Would commit: feat(plugins): install ${name}@${version}
8996
9073
  `);
8997
9074
  }
8998
9075
 
8999
9076
  // src/commands/plugin-list.ts
9000
- import { existsSync as existsSync30, readFileSync as readFileSync23 } from "fs";
9001
- import { join as join32, resolve as resolve13 } from "path";
9077
+ import { existsSync as existsSync31, readFileSync as readFileSync23 } from "fs";
9078
+ import { join as join33, resolve as resolve13 } from "path";
9002
9079
  import chalk16 from "chalk";
9003
9080
  import { Command as Command16 } from "commander";
9004
9081
  var pluginListCommand = new Command16("list").description("List plugins installed in this project checkout").option("--cwd <path>", "Project root to scan (defaults to the current directory)").action(async (options) => {
@@ -9011,8 +9088,8 @@ var pluginListCommand = new Command16("list").description("List plugins installe
9011
9088
  }
9012
9089
  });
9013
9090
  async function runPluginList(options) {
9014
- const servicesDir = join32(options.cwd, "services");
9015
- if (!existsSync30(servicesDir)) {
9091
+ const servicesDir = join33(options.cwd, "services");
9092
+ if (!existsSync31(servicesDir)) {
9016
9093
  throw new Error(
9017
9094
  `${servicesDir} does not exist \u2014 is ${options.cwd} the root of a Biffo project checkout?`
9018
9095
  );
@@ -9061,14 +9138,14 @@ import { resolve as resolve14 } from "path";
9061
9138
  import { Command as Command17 } from "commander";
9062
9139
 
9063
9140
  // src/lib/plugin-staleness.ts
9064
- import { existsSync as existsSync31, readFileSync as readFileSync24, readdirSync as readdirSync13, statSync as statSync7 } from "fs";
9065
- import { join as join33, relative as relative4 } from "path";
9141
+ import { existsSync as existsSync32, readFileSync as readFileSync24, readdirSync as readdirSync14, statSync as statSync7 } from "fs";
9142
+ import { join as join34, relative as relative4 } from "path";
9066
9143
  function discoverVendoredPlugins(servicesDir) {
9067
- if (!existsSync31(servicesDir)) return [];
9068
- return readdirSync13(servicesDir, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith("_") && e.name !== "api").map((e) => e.name).filter((name) => existsSync31(join33(servicesDir, name, "biffo.plugin.json"))).sort();
9144
+ if (!existsSync32(servicesDir)) return [];
9145
+ return readdirSync14(servicesDir, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith("_") && e.name !== "api").map((e) => e.name).filter((name) => existsSync32(join34(servicesDir, name, "biffo.plugin.json"))).sort();
9069
9146
  }
9070
9147
  async function checkPluginStaleness(cwd, deps) {
9071
- const servicesDir = join33(cwd, "services");
9148
+ const servicesDir = join34(cwd, "services");
9072
9149
  const names = discoverVendoredPlugins(servicesDir);
9073
9150
  let registryRepoByName = null;
9074
9151
  const resolveRegistryRepo = async (name) => {
@@ -9084,7 +9161,7 @@ async function checkPluginStaleness(cwd, deps) {
9084
9161
  };
9085
9162
  const results = [];
9086
9163
  for (const name of names) {
9087
- results.push(await checkOnePlugin(join33(servicesDir, name), name, resolveRegistryRepo, deps.git));
9164
+ results.push(await checkOnePlugin(join34(servicesDir, name), name, resolveRegistryRepo, deps.git));
9088
9165
  }
9089
9166
  return results;
9090
9167
  }
@@ -9110,7 +9187,7 @@ async function checkOnePlugin(pluginDir2, name, resolveRegistryRepo, git) {
9110
9187
  if (record?.sha && isFetchableUrl(record.origin)) {
9111
9188
  return checkViaProvenance(name, record, record.origin, git);
9112
9189
  }
9113
- const localOrigin = record && !isFetchableUrl(record.origin) && existsSync31(record.origin) ? record.origin : null;
9190
+ const localOrigin = record && !isFetchableUrl(record.origin) && existsSync32(record.origin) ? record.origin : null;
9114
9191
  if (localOrigin) {
9115
9192
  return checkViaContentDiff(name, pluginDir2, localOrigin, { isLocalDir: true }, git);
9116
9193
  }
@@ -9244,8 +9321,8 @@ async function countDifferingFiles(sourceDir, pluginDir2) {
9244
9321
  differing++;
9245
9322
  continue;
9246
9323
  }
9247
- const a = readFileSync24(join33(sourceDir, relPath));
9248
- const b = readFileSync24(join33(pluginDir2, relPath));
9324
+ const a = readFileSync24(join34(sourceDir, relPath));
9325
+ const b = readFileSync24(join34(pluginDir2, relPath));
9249
9326
  if (!a.equals(b)) differing++;
9250
9327
  }
9251
9328
  return differing;
@@ -9260,11 +9337,11 @@ function vendorFileList(dir) {
9260
9337
  return new Set(walkExcluding(dir, dir, LOCAL_COPY_EXCLUDES));
9261
9338
  }
9262
9339
  function walkExcluding(root, dir, excludes) {
9263
- if (!existsSync31(dir)) return [];
9340
+ if (!existsSync32(dir)) return [];
9264
9341
  const out = [];
9265
- for (const entry of readdirSync13(dir)) {
9342
+ for (const entry of readdirSync14(dir)) {
9266
9343
  if (excludes.has(entry) || entry === ".git") continue;
9267
- const full = join33(dir, entry);
9344
+ const full = join34(dir, entry);
9268
9345
  const stat = statSync7(full);
9269
9346
  if (stat.isDirectory()) {
9270
9347
  out.push(...walkExcluding(root, full, excludes));
@@ -9316,8 +9393,8 @@ var pluginStalenessCommand = new Command17("staleness").description(
9316
9393
  });
9317
9394
 
9318
9395
  // src/commands/plugin-sync-migrations.ts
9319
- import { existsSync as existsSync32 } from "fs";
9320
- import { join as join34, relative as relative5, resolve as resolve15 } from "path";
9396
+ import { existsSync as existsSync33 } from "fs";
9397
+ import { join as join35, relative as relative5, resolve as resolve15 } from "path";
9321
9398
  import chalk17 from "chalk";
9322
9399
  import { Command as Command18 } from "commander";
9323
9400
  var pluginSyncMigrationsCommand = new Command18("sync-migrations").description(
@@ -9338,11 +9415,11 @@ var pluginSyncMigrationsCommand = new Command18("sync-migrations").description(
9338
9415
  }
9339
9416
  );
9340
9417
  async function runPluginSyncMigrations(name, options, deps) {
9341
- const servicesDir = join34(options.cwd, "services");
9342
- if (!existsSync32(servicesDir)) {
9418
+ const servicesDir = join35(options.cwd, "services");
9419
+ if (!existsSync33(servicesDir)) {
9343
9420
  throw new Error(`${servicesDir} does not exist \u2014 is ${options.cwd} a Biffo project checkout?`);
9344
9421
  }
9345
- if (name && !existsSync32(join34(servicesDir, name, "biffo.plugin.json"))) {
9422
+ if (name && !existsSync33(join35(servicesDir, name, "biffo.plugin.json"))) {
9346
9423
  throw new Error(`Plugin '${name}' is not installed at services/${name}/.`);
9347
9424
  }
9348
9425
  if (options.dryRun) {
@@ -9378,8 +9455,8 @@ async function runPluginSyncMigrations(name, options, deps) {
9378
9455
  }
9379
9456
 
9380
9457
  // src/commands/plugin-uninstall.ts
9381
- import { existsSync as existsSync33, readFileSync as readFileSync25, rmSync as rmSync8 } from "fs";
9382
- import { join as join35, resolve as resolve16 } from "path";
9458
+ import { existsSync as existsSync34, readFileSync as readFileSync25, rmSync as rmSync9 } from "fs";
9459
+ import { join as join36, resolve as resolve16 } from "path";
9383
9460
  import chalk18 from "chalk";
9384
9461
  import { Command as Command19 } from "commander";
9385
9462
  import inquirer6 from "inquirer";
@@ -9411,16 +9488,16 @@ async function runPluginUninstall(name, options, deps) {
9411
9488
  if (!NAME_PATTERN2.test(name)) {
9412
9489
  throw new Error(`Invalid plugin name '${name}'. Expected a lowercase kebab-case slug.`);
9413
9490
  }
9414
- const servicesDir = join35(options.cwd, "services");
9415
- if (!existsSync33(servicesDir)) {
9491
+ const servicesDir = join36(options.cwd, "services");
9492
+ if (!existsSync34(servicesDir)) {
9416
9493
  throw new Error(
9417
9494
  `${servicesDir} does not exist \u2014 is ${options.cwd} the root of a Biffo project checkout?`
9418
9495
  );
9419
9496
  }
9420
- const targetDir = join35(servicesDir, name);
9421
- if (!existsSync33(targetDir)) {
9422
- const firstParty = join35(servicesDir, FIRST_PARTY_PLUGINS_DIR, name);
9423
- if (existsSync33(firstParty)) {
9497
+ const targetDir = join36(servicesDir, name);
9498
+ if (!existsSync34(targetDir)) {
9499
+ const firstParty = join36(servicesDir, FIRST_PARTY_PLUGINS_DIR, name);
9500
+ if (existsSync34(firstParty)) {
9424
9501
  throw new Error(
9425
9502
  `Plugin '${name}' is a first-party plugin at ${pluginDir(name, "first-party")}/, which is template-owned \u2014 \`biffo core upgrade\` would restore it on the next upgrade. Disable it instead by removing '${name}' from \`enabled_plugins\` in infra/environments/<env>/main.tf and re-applying.`
9426
9503
  );
@@ -9428,9 +9505,9 @@ async function runPluginUninstall(name, options, deps) {
9428
9505
  throw new Error(`Plugin '${name}' is not installed at services/${name}/.`);
9429
9506
  }
9430
9507
  const version = readInstalledVersion(targetDir);
9431
- const modulesDir = join35(options.cwd, "modules", "plugins", name);
9508
+ const modulesDir = join36(options.cwd, "modules", "plugins", name);
9432
9509
  const stagePaths = [`services/${name}`];
9433
- if (existsSync33(modulesDir)) {
9510
+ if (existsSync34(modulesDir)) {
9434
9511
  stagePaths.push(`modules/plugins/${name}`);
9435
9512
  }
9436
9513
  if (options.dryRun) {
@@ -9450,10 +9527,10 @@ async function runPluginUninstall(name, options, deps) {
9450
9527
  `${options.cwd} is not a git repository \u2014 biffo plugin uninstall must be run from a Biffo project checkout.`
9451
9528
  );
9452
9529
  }
9453
- rmSync8(targetDir, { recursive: true, force: true });
9530
+ rmSync9(targetDir, { recursive: true, force: true });
9454
9531
  log.success(`Removed services/${name}/`);
9455
- if (existsSync33(modulesDir)) {
9456
- rmSync8(modulesDir, { recursive: true, force: true });
9532
+ if (existsSync34(modulesDir)) {
9533
+ rmSync9(modulesDir, { recursive: true, force: true });
9457
9534
  log.success(`Removed modules/plugins/${name}/`);
9458
9535
  const wiring = syncPluginTerraform(options.cwd);
9459
9536
  stagePaths.push(...wiring.changedPaths);
@@ -9487,10 +9564,15 @@ async function runPluginUninstall(name, options, deps) {
9487
9564
  "Any tables this plugin created remain in the database, and its migration file at services/api/migrations/versions/ is NOT removed (it is a permanent historical record \u2014 see notes). Dropping tables, if desired, requires a manual Alembic migration written against the Core API."
9488
9565
  );
9489
9566
  }
9567
+ if (existsSync34(join36(options.cwd, pluginSeedImportDir(name)))) {
9568
+ log.warn(
9569
+ `${pluginSeedImportDir(name)}/ (this plugin's vendored baseline-row seed, biffo-template#1554) was NOT removed either, for the same reason \u2014 see notes. Delete it by hand if you are certain the rows it applied should go too, but note nothing drops rows already applied to the database; that still needs a manual migration.`
9570
+ );
9571
+ }
9490
9572
  }
9491
9573
  function readInstalledVersion(targetDir) {
9492
- const manifestPath = join35(targetDir, "biffo.plugin.json");
9493
- if (!existsSync33(manifestPath)) return void 0;
9574
+ const manifestPath = join36(targetDir, "biffo.plugin.json");
9575
+ if (!existsSync34(manifestPath)) return void 0;
9494
9576
  try {
9495
9577
  return validateManifest(JSON.parse(readFileSync25(manifestPath, "utf8"))).version;
9496
9578
  } catch {
@@ -9525,8 +9607,8 @@ function printDryRun5(name, version, stagePaths, keepData) {
9525
9607
  }
9526
9608
 
9527
9609
  // src/commands/plugin-upgrade.ts
9528
- import { cpSync as cpSync5, existsSync as existsSync34, mkdirSync as mkdirSync11, readFileSync as readFileSync26, rmSync as rmSync9 } from "fs";
9529
- import { join as join36, relative as relative6, resolve as resolve17 } from "path";
9610
+ import { cpSync as cpSync6, existsSync as existsSync35, mkdirSync as mkdirSync12, readFileSync as readFileSync26, rmSync as rmSync10 } from "fs";
9611
+ import { join as join37, relative as relative6, resolve as resolve17 } from "path";
9530
9612
  import chalk19 from "chalk";
9531
9613
  import { Command as Command20 } from "commander";
9532
9614
  import inquirer7 from "inquirer";
@@ -9573,8 +9655,8 @@ async function runPluginUpgrade(target, options, deps) {
9573
9655
  `Nothing to upgrade. Pass a registry target (e.g. \`biffo plugin upgrade acme-crm@1.1\`) or a local checkout to refresh from (\`biffo plugin upgrade --local ../acme-crm\`).`
9574
9656
  );
9575
9657
  }
9576
- const servicesDir = join36(options.cwd, "services");
9577
- if (!existsSync34(servicesDir)) {
9658
+ const servicesDir = join37(options.cwd, "services");
9659
+ if (!existsSync35(servicesDir)) {
9578
9660
  throw new Error(
9579
9661
  `${servicesDir} does not exist \u2014 is ${options.cwd} the root of a Biffo project checkout?`
9580
9662
  );
@@ -9583,8 +9665,8 @@ async function runPluginUpgrade(target, options, deps) {
9583
9665
  return runLocalPluginRefresh(options.local, options, deps);
9584
9666
  }
9585
9667
  const { name, minor } = parsePluginTarget(target);
9586
- const targetDir = join36(servicesDir, name);
9587
- if (!existsSync34(targetDir)) {
9668
+ const targetDir = join37(servicesDir, name);
9669
+ if (!existsSync35(targetDir)) {
9588
9670
  throw new Error(
9589
9671
  `Plugin '${name}' is not installed at services/${name}/. Use 'biffo plugin install ${name}@${minor}' instead.`
9590
9672
  );
@@ -9598,7 +9680,7 @@ async function runPluginUpgrade(target, options, deps) {
9598
9680
  `Plugin declares required_core_version '${entry.required_core_version}'. The CLI cannot verify this against your deployment \u2014 the Core API exposes no version endpoint and services/api/pyproject.toml's version is a static placeholder, not a real release marker. Confirm compatibility yourself before deploying.`
9599
9681
  );
9600
9682
  }
9601
- const modulesDir = join36(options.cwd, "modules", "plugins", entry.name);
9683
+ const modulesDir = join37(options.cwd, "modules", "plugins", entry.name);
9602
9684
  if (options.dryRun) {
9603
9685
  printDryRun6(entry, currentVersion);
9604
9686
  return;
@@ -9627,9 +9709,9 @@ async function runPluginUpgrade(target, options, deps) {
9627
9709
  `Manifest valid \u2014 ${manifest.tables.length} table(s), ${manifest.api_routes.length} route(s)`
9628
9710
  );
9629
9711
  const previousProvenance = readProvenance(targetDir);
9630
- rmSync9(targetDir, { recursive: true, force: true });
9631
- mkdirSync11(targetDir, { recursive: true });
9632
- cpSync5(tmpDir, targetDir, { recursive: true });
9712
+ rmSync10(targetDir, { recursive: true, force: true });
9713
+ mkdirSync12(targetDir, { recursive: true });
9714
+ cpSync6(tmpDir, targetDir, { recursive: true });
9633
9715
  log.success(`Upgraded plugin source at services/${entry.name}/`);
9634
9716
  const nextProvenance = resolveRegistryProvenance(
9635
9717
  entry.repo,
@@ -9638,13 +9720,13 @@ async function runPluginUpgrade(target, options, deps) {
9638
9720
  writePluginProvenance(targetDir, reconcileProvenance(previousProvenance, nextProvenance));
9639
9721
  applyWorkspaceSources(targetDir, options.cwd, `services/${entry.name}`);
9640
9722
  const stagePaths = [`services/${entry.name}`];
9641
- if (existsSync34(modulesDir)) {
9642
- rmSync9(modulesDir, { recursive: true, force: true });
9723
+ if (existsSync35(modulesDir)) {
9724
+ rmSync10(modulesDir, { recursive: true, force: true });
9643
9725
  }
9644
- const tfSourceDir = join36(targetDir, "terraform");
9645
- if (existsSync34(tfSourceDir)) {
9646
- mkdirSync11(modulesDir, { recursive: true });
9647
- cpSync5(tfSourceDir, modulesDir, { recursive: true });
9726
+ const tfSourceDir = join37(targetDir, "terraform");
9727
+ if (existsSync35(tfSourceDir)) {
9728
+ mkdirSync12(modulesDir, { recursive: true });
9729
+ cpSync6(tfSourceDir, modulesDir, { recursive: true });
9648
9730
  stagePaths.push(`modules/plugins/${entry.name}`);
9649
9731
  log.success(`Copied Terraform module to modules/plugins/${entry.name}/`);
9650
9732
  }
@@ -9664,6 +9746,10 @@ async function runPluginUpgrade(target, options, deps) {
9664
9746
  );
9665
9747
  }
9666
9748
  }
9749
+ const seedResult = vendorPluginSeed(targetDir, manifest, options.cwd);
9750
+ if (seedResult.vendored) {
9751
+ stagePaths.push(seedResult.stagedPath);
9752
+ }
9667
9753
  const label = currentVersion ? `${entry.name} ${currentVersion} -> ${entry.version}` : `${entry.name} to ${entry.version}`;
9668
9754
  const commitMessage = `feat(plugins): upgrade ${label}`;
9669
9755
  await deps.git.add(options.cwd, stagePaths);
@@ -9682,16 +9768,16 @@ async function runPluginUpgrade(target, options, deps) {
9682
9768
  async function runLocalPluginRefresh(localPath, options, deps) {
9683
9769
  const source = resolveLocalPlugin(localPath);
9684
9770
  log.success(`Resolved ${source.name}@${source.version} from ${source.origin}`);
9685
- const servicesDir = join36(options.cwd, "services");
9686
- const targetDir = join36(servicesDir, source.name);
9687
- if (!existsSync34(targetDir)) {
9771
+ const servicesDir = join37(options.cwd, "services");
9772
+ const targetDir = join37(servicesDir, source.name);
9773
+ if (!existsSync35(targetDir)) {
9688
9774
  throw new Error(
9689
9775
  `Plugin '${source.name}' is not installed at services/${source.name}/. Use 'biffo plugin install --local ${localPath}' instead.`
9690
9776
  );
9691
9777
  }
9692
9778
  const inTreeSource = resolve17(source.sourceDir) === resolve17(targetDir);
9693
9779
  const currentVersion = readInstalledVersion2(targetDir);
9694
- const modulesDir = join36(options.cwd, "modules", "plugins", source.name);
9780
+ const modulesDir = join37(options.cwd, "modules", "plugins", source.name);
9695
9781
  if (options.dryRun) {
9696
9782
  printLocalDryRun(source, currentVersion, inTreeSource);
9697
9783
  return;
@@ -9720,8 +9806,8 @@ async function runLocalPluginRefresh(localPath, options, deps) {
9720
9806
  `services/${source.name}/ is already the local checkout \u2014 nothing to copy; re-syncing its Terraform module and checking for a migration.`
9721
9807
  );
9722
9808
  } else {
9723
- rmSync9(targetDir, { recursive: true, force: true });
9724
- mkdirSync11(targetDir, { recursive: true });
9809
+ rmSync10(targetDir, { recursive: true, force: true });
9810
+ mkdirSync12(targetDir, { recursive: true });
9725
9811
  await copyPluginSource(source.sourceDir, targetDir);
9726
9812
  log.success(`Refreshed plugin source at services/${source.name}/ from ${source.origin}`);
9727
9813
  }
@@ -9729,13 +9815,13 @@ async function runLocalPluginRefresh(localPath, options, deps) {
9729
9815
  writePluginProvenance(targetDir, reconcileProvenance(previousProvenance, nextProvenance));
9730
9816
  applyWorkspaceSources(targetDir, options.cwd, `services/${source.name}`);
9731
9817
  const stagePaths = [`services/${source.name}`];
9732
- if (existsSync34(modulesDir)) {
9733
- rmSync9(modulesDir, { recursive: true, force: true });
9818
+ if (existsSync35(modulesDir)) {
9819
+ rmSync10(modulesDir, { recursive: true, force: true });
9734
9820
  }
9735
- const tfSourceDir = join36(targetDir, "terraform");
9736
- if (existsSync34(tfSourceDir)) {
9737
- mkdirSync11(modulesDir, { recursive: true });
9738
- cpSync5(tfSourceDir, modulesDir, { recursive: true });
9821
+ const tfSourceDir = join37(targetDir, "terraform");
9822
+ if (existsSync35(tfSourceDir)) {
9823
+ mkdirSync12(modulesDir, { recursive: true });
9824
+ cpSync6(tfSourceDir, modulesDir, { recursive: true });
9739
9825
  stagePaths.push(`modules/plugins/${source.name}`);
9740
9826
  log.success(`Refreshed Terraform module at modules/plugins/${source.name}/`);
9741
9827
  }
@@ -9757,6 +9843,10 @@ async function runLocalPluginRefresh(localPath, options, deps) {
9757
9843
  } else {
9758
9844
  log.info(`${source.name} declares no tables \u2014 nothing to migrate.`);
9759
9845
  }
9846
+ const seedResult = vendorPluginSeed(targetDir, manifest, options.cwd);
9847
+ if (seedResult.vendored) {
9848
+ stagePaths.push(seedResult.stagedPath);
9849
+ }
9760
9850
  await deps.git.add(options.cwd, stagePaths);
9761
9851
  if (!await deps.git.hasUncommittedChanges(options.cwd)) {
9762
9852
  log.warn(`services/${source.name}/ already matches ${source.origin} \u2014 nothing to commit.`);
@@ -9776,8 +9866,8 @@ async function runLocalPluginRefresh(localPath, options, deps) {
9776
9866
  }
9777
9867
  }
9778
9868
  function readInstalledVersion2(targetDir) {
9779
- const manifestPath = join36(targetDir, "biffo.plugin.json");
9780
- if (!existsSync34(manifestPath)) return void 0;
9869
+ const manifestPath = join37(targetDir, "biffo.plugin.json");
9870
+ if (!existsSync35(manifestPath)) return void 0;
9781
9871
  try {
9782
9872
  return validateManifest(JSON.parse(readFileSync26(manifestPath, "utf8"))).version;
9783
9873
  } catch {
@@ -9814,6 +9904,11 @@ function printDryRun6(entry, currentVersion) {
9814
9904
  ` Would replace Terraform module at: modules/plugins/${entry.name}/ (if the repo has one)`
9815
9905
  );
9816
9906
  }
9907
+ if (entry.baseline_tables && entry.baseline_tables.length > 0) {
9908
+ console.log(
9909
+ ` Would re-vendor seed DDL into: ${pluginSeedImportDir(entry.name)}/ (baseline_tables: ${entry.baseline_tables.join(", ")})`
9910
+ );
9911
+ }
9817
9912
  console.log(` Would commit: feat(plugins): upgrade ${entry.name} to ${entry.version}
9818
9913
  `);
9819
9914
  }
@@ -9833,6 +9928,11 @@ function printLocalDryRun(source, currentVersion, inTreeSource) {
9833
9928
  ` Would check for a migration for ${source.manifest.tables.length} table(s) (generated for a new table or an added column on an already-migrated table; a removed/retyped/nullability-changed column stops the refresh instead \u2014 #1539)`
9834
9929
  );
9835
9930
  }
9931
+ if (source.manifest.seed) {
9932
+ console.log(
9933
+ ` Would re-vendor seed DDL into: ${pluginSeedImportDir(source.name)}/ (baseline_tables: ${source.manifest.seed.baseline_tables.join(", ") || "none declared"})`
9934
+ );
9935
+ }
9836
9936
  console.log(` Would commit: chore(plugins): refresh ${source.name} from local checkout
9837
9937
  `);
9838
9938
  }
@@ -9852,7 +9952,7 @@ pluginCommand.addCommand(pluginStalenessCommand);
9852
9952
  import { Command as Command23 } from "commander";
9853
9953
 
9854
9954
  // src/commands/sibling-check-identity.ts
9855
- import { existsSync as existsSync35, readFileSync as readFileSync27 } from "fs";
9955
+ import { existsSync as existsSync36, readFileSync as readFileSync27 } from "fs";
9856
9956
  import { resolve as resolve18 } from "path";
9857
9957
  import chalk20 from "chalk";
9858
9958
  import { Command as Command22 } from "commander";
@@ -10066,7 +10166,7 @@ async function resolveConfig4(options) {
10066
10166
  return cfg;
10067
10167
  }
10068
10168
  const localConfigPath = resolve18(process.cwd(), "biffo.config.json");
10069
- if (existsSync35(localConfigPath)) {
10169
+ if (existsSync36(localConfigPath)) {
10070
10170
  const raw = JSON.parse(readFileSync27(localConfigPath, "utf8"));
10071
10171
  const result = BiffoConfigSchema.safeParse(raw);
10072
10172
  if (result.success) return result.data;
@@ -10113,19 +10213,19 @@ siblingCommand.addCommand(siblingCheckIdentityCommand);
10113
10213
  import { Command as Command24 } from "commander";
10114
10214
 
10115
10215
  // src/scripts/check-adr-numbering.ts
10116
- import { existsSync as existsSync37 } from "fs";
10117
- import { join as join38 } from "path";
10216
+ import { existsSync as existsSync38 } from "fs";
10217
+ import { join as join39 } from "path";
10118
10218
  import { execa as execa7 } from "execa";
10119
10219
 
10120
10220
  // src/lib/adr-numbering-guard.ts
10121
- import { existsSync as existsSync36, readdirSync as readdirSync14, readFileSync as readFileSync28 } from "fs";
10122
- import { join as join37 } from "path";
10221
+ import { existsSync as existsSync37, readdirSync as readdirSync15, readFileSync as readFileSync28 } from "fs";
10222
+ import { join as join38 } from "path";
10123
10223
  var ADR_FILENAME = /^(\d{4})-.+\.md$/;
10124
10224
  var ALLOWLIST_FILENAME = ".numbering-allowlist";
10125
10225
  var TEMPLATE_ADR_RESERVED_UPTO = "0099";
10126
10226
  function readAdrNumberingAllowlist(adrDir) {
10127
- const path = join37(adrDir, ALLOWLIST_FILENAME);
10128
- if (!existsSync36(path)) return /* @__PURE__ */ new Set();
10227
+ const path = join38(adrDir, ALLOWLIST_FILENAME);
10228
+ if (!existsSync37(path)) return /* @__PURE__ */ new Set();
10129
10229
  const numbers = /* @__PURE__ */ new Set();
10130
10230
  for (const rawLine of readFileSync28(path, "utf8").split("\n")) {
10131
10231
  const line = rawLine.split("#")[0].trim();
@@ -10135,8 +10235,8 @@ function readAdrNumberingAllowlist(adrDir) {
10135
10235
  }
10136
10236
  function adrNumbersIn(adrDir) {
10137
10237
  const claims = /* @__PURE__ */ new Map();
10138
- if (!existsSync36(adrDir)) return claims;
10139
- for (const entry of readdirSync14(adrDir).sort()) {
10238
+ if (!existsSync37(adrDir)) return claims;
10239
+ for (const entry of readdirSync15(adrDir).sort()) {
10140
10240
  const match = ADR_FILENAME.exec(entry);
10141
10241
  if (!match) continue;
10142
10242
  const number = match[1];
@@ -10190,8 +10290,8 @@ function formatAdrReservedRangeViolations(violations, reservedUpTo = TEMPLATE_AD
10190
10290
  // src/scripts/check-adr-numbering.ts
10191
10291
  async function runAdrNumberingCheck() {
10192
10292
  const root = (await execa7("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
10193
- const adrDir = join38(root, "docs", "ADR");
10194
- if (!existsSync37(adrDir)) {
10293
+ const adrDir = join39(root, "docs", "ADR");
10294
+ if (!existsSync38(adrDir)) {
10195
10295
  console.log("\u2713 ADR numbering guard: no docs/ADR/ directory \u2014 nothing to compare");
10196
10296
  return;
10197
10297
  }
@@ -10489,13 +10589,13 @@ async function runBranchProtectionCheck(explicitRepo, options = {}) {
10489
10589
  }
10490
10590
 
10491
10591
  // src/scripts/check-codeql-suppression.ts
10492
- import { existsSync as existsSync38 } from "fs";
10493
- import { join as join40, relative as relative7 } from "path";
10592
+ import { existsSync as existsSync39 } from "fs";
10593
+ import { join as join41, relative as relative7 } from "path";
10494
10594
  import { execa as execa9 } from "execa";
10495
10595
 
10496
10596
  // src/lib/codeql-suppression-guard.ts
10497
- import { readdirSync as readdirSync15, readFileSync as readFileSync29, statSync as statSync8 } from "fs";
10498
- import { join as join39 } from "path";
10597
+ import { readdirSync as readdirSync16, readFileSync as readFileSync29, statSync as statSync8 } from "fs";
10598
+ import { join as join40 } from "path";
10499
10599
  var SKIP_DIRS = /* @__PURE__ */ new Set([
10500
10600
  ".git",
10501
10601
  ".worktrees",
@@ -10521,12 +10621,12 @@ function walkSourceFiles(root) {
10521
10621
  const walk2 = (dir) => {
10522
10622
  let entries;
10523
10623
  try {
10524
- entries = readdirSync15(dir);
10624
+ entries = readdirSync16(dir);
10525
10625
  } catch {
10526
10626
  return;
10527
10627
  }
10528
10628
  for (const entry of entries) {
10529
- const p = join39(dir, entry);
10629
+ const p = join40(dir, entry);
10530
10630
  let st;
10531
10631
  try {
10532
10632
  st = statSync8(p);
@@ -10563,8 +10663,8 @@ function sweepCodeqlSuppressionComments(root) {
10563
10663
  // src/scripts/check-codeql-suppression.ts
10564
10664
  async function runCodeqlSuppressionCheck() {
10565
10665
  const root = (await execa9("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
10566
- const scanRoot = join40(root, "cli", "src");
10567
- if (!existsSync38(scanRoot)) {
10666
+ const scanRoot = join41(root, "cli", "src");
10667
+ if (!existsSync39(scanRoot)) {
10568
10668
  console.log(
10569
10669
  "\u2014 codeql-suppression guard: skipped \u2014 no cli/src in this repo, so there is no CLI source to scan."
10570
10670
  );
@@ -10591,8 +10691,8 @@ async function runCodeqlSuppressionCheck() {
10591
10691
  import { execa as execa10 } from "execa";
10592
10692
 
10593
10693
  // src/lib/cognito-invite-template-guard.ts
10594
- import { readdirSync as readdirSync16, readFileSync as readFileSync30, statSync as statSync9 } from "fs";
10595
- import { join as join41 } from "path";
10694
+ import { readdirSync as readdirSync17, readFileSync as readFileSync30, statSync as statSync9 } from "fs";
10695
+ import { join as join42 } from "path";
10596
10696
  var REQUIRED_INVITE_MEMBERS = ["email_subject", "email_message", "sms_message"];
10597
10697
  var REQUIRED_INVITE_PLACEHOLDERS = ["{username}", "{####}"];
10598
10698
  var PLACEHOLDER_MEMBERS = ["email_message", "sms_message"];
@@ -10669,13 +10769,13 @@ function findModuleTerraformFiles(repoRoot) {
10669
10769
  const walk2 = (dir, relative10) => {
10670
10770
  let entries;
10671
10771
  try {
10672
- entries = readdirSync16(dir);
10772
+ entries = readdirSync17(dir);
10673
10773
  } catch {
10674
10774
  return;
10675
10775
  }
10676
10776
  for (const entry of entries) {
10677
10777
  if (entry === "node_modules" || entry === ".git" || entry === ".worktrees") continue;
10678
- const full = join41(dir, entry);
10778
+ const full = join42(dir, entry);
10679
10779
  const rel = `${relative10}/${entry}`;
10680
10780
  if (statSync9(full).isDirectory()) {
10681
10781
  walk2(full, rel);
@@ -10684,12 +10784,12 @@ function findModuleTerraformFiles(repoRoot) {
10684
10784
  }
10685
10785
  }
10686
10786
  };
10687
- walk2(join41(repoRoot, "modules"), "modules");
10787
+ walk2(join42(repoRoot, "modules"), "modules");
10688
10788
  return found.sort();
10689
10789
  }
10690
10790
  function checkCognitoInviteTemplates(repoRoot) {
10691
10791
  return findModuleTerraformFiles(repoRoot).flatMap(
10692
- (file) => checkInviteTemplateSource(file, readFileSync30(join41(repoRoot, file), "utf8"))
10792
+ (file) => checkInviteTemplateSource(file, readFileSync30(join42(repoRoot, file), "utf8"))
10693
10793
  );
10694
10794
  }
10695
10795
 
@@ -10717,12 +10817,12 @@ async function runCognitoInviteTemplateCheck() {
10717
10817
  }
10718
10818
 
10719
10819
  // src/scripts/check-core-direct-paths.ts
10720
- import { join as join43 } from "path";
10820
+ import { join as join44 } from "path";
10721
10821
  import { execa as execa11 } from "execa";
10722
10822
 
10723
10823
  // src/lib/core-direct-paths-audit.ts
10724
- import { existsSync as existsSync39, readFileSync as readFileSync31, readdirSync as readdirSync17, statSync as statSync10 } from "fs";
10725
- import { join as join42 } from "path";
10824
+ import { existsSync as existsSync40, readFileSync as readFileSync31, readdirSync as readdirSync18, statSync as statSync10 } from "fs";
10825
+ import { join as join43 } from "path";
10726
10826
  var EXTERNAL_BASE_IDENTIFIERS = ["CORE_API_URL"];
10727
10827
  var API_ROUTE_PREFIX = "/api/v1";
10728
10828
  var TEST_FILE_SUFFIXES = [".test.ts", ".test.tsx", ".spec.ts", ".spec.tsx"];
@@ -10881,12 +10981,12 @@ function walkFiles(root, accept, skipDir) {
10881
10981
  const walk2 = (dir) => {
10882
10982
  let entries;
10883
10983
  try {
10884
- entries = readdirSync17(dir);
10984
+ entries = readdirSync18(dir);
10885
10985
  } catch {
10886
10986
  return;
10887
10987
  }
10888
10988
  for (const entry of entries) {
10889
- const p = join42(dir, entry);
10989
+ const p = join43(dir, entry);
10890
10990
  let st;
10891
10991
  try {
10892
10992
  st = statSync10(p);
@@ -10981,7 +11081,7 @@ function pathMatchesAnyCorePrefix(normalized, corePrefixes, apiRoutePrefix = API
10981
11081
  }
10982
11082
  function resolveSiblingCoreSrc(params) {
10983
11083
  const { estateDir, sibling } = params;
10984
- const configPath = join42(estateDir, sibling, "biffo.sibling.json");
11084
+ const configPath = join43(estateDir, sibling, "biffo.sibling.json");
10985
11085
  let raw;
10986
11086
  try {
10987
11087
  raw = readFileSync31(configPath, "utf8");
@@ -11004,8 +11104,8 @@ function resolveSiblingCoreSrc(params) {
11004
11104
  `cannot resolve ${sibling}'s core: ${configPath} has no non-empty "core_project" field.`
11005
11105
  );
11006
11106
  }
11007
- const coreApiSrcDir = join42(estateDir, coreProject, "services", "api", "src");
11008
- if (!existsSync39(coreApiSrcDir)) {
11107
+ const coreApiSrcDir = join43(estateDir, coreProject, "services", "api", "src");
11108
+ if (!existsSync40(coreApiSrcDir)) {
11009
11109
  throw new Error(
11010
11110
  `cannot resolve ${sibling}'s core: biffo.sibling.json names core_project "${coreProject}", but ${coreApiSrcDir} does not exist -- the instance is missing from this estate checkout, not merely unmatched. Refusing to silently skip ${sibling} and shrink the audit's denominator.`
11011
11111
  );
@@ -11048,7 +11148,7 @@ function auditSiblingCoreDirectPaths(params) {
11048
11148
  async function runCoreDirectPathsCheck(opts = {}) {
11049
11149
  const root = (await execa11("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
11050
11150
  const sibling = opts.sibling ?? "sibling-template (self-check)";
11051
- const frontendSrcDir = opts.frontendSrc ?? join43(root, "_skeletons", "sibling-template", "apps", "frontend", "src");
11151
+ const frontendSrcDir = opts.frontendSrc ?? join44(root, "_skeletons", "sibling-template", "apps", "frontend", "src");
11052
11152
  let coreApiSrcDir;
11053
11153
  let coreProject = null;
11054
11154
  if (opts.coreSrc) {
@@ -11064,7 +11164,7 @@ async function runCoreDirectPathsCheck(opts = {}) {
11064
11164
  coreApiSrcDir = resolution.coreApiSrcDir;
11065
11165
  coreProject = resolution.coreProject;
11066
11166
  } else {
11067
- coreApiSrcDir = join43(root, "services", "api", "src");
11167
+ coreApiSrcDir = join44(root, "services", "api", "src");
11068
11168
  }
11069
11169
  const report = auditSiblingCoreDirectPaths({ sibling, frontendSrcDir, coreApiSrcDir });
11070
11170
  console.log(
@@ -11130,8 +11230,8 @@ async function runOwnershipCheck(argv) {
11130
11230
  const { stdout } = await execa12("git", ["diff", "--cached", "--name-status"], { cwd: root });
11131
11231
  ({ changed: changedFiles, deleted: deletedFiles } = parseNameStatus(stdout));
11132
11232
  if (messageFile) {
11133
- const { readFileSync: readFileSync41, existsSync: existsSync48 } = await import("fs");
11134
- if (existsSync48(messageFile)) commitMessage = readFileSync41(messageFile, "utf8");
11233
+ const { readFileSync: readFileSync41, existsSync: existsSync49 } = await import("fs");
11234
+ if (existsSync49(messageFile)) commitMessage = readFileSync41(messageFile, "utf8");
11135
11235
  }
11136
11236
  } else {
11137
11237
  const base = process.env["GITHUB_BASE_REF"] ?? args[0];
@@ -11235,8 +11335,8 @@ ${BOLD}If the divergence is deliberate${OFF}
11235
11335
  import { execa as execa13 } from "execa";
11236
11336
 
11237
11337
  // src/lib/eventbridge-log-permission-guard.ts
11238
- import { readFileSync as readFileSync32, readdirSync as readdirSync18, statSync as statSync11 } from "fs";
11239
- import { join as join44 } from "path";
11338
+ import { readFileSync as readFileSync32, readdirSync as readdirSync19, statSync as statSync11 } from "fs";
11339
+ import { join as join45 } from "path";
11240
11340
  var SKIP_DIRS2 = /* @__PURE__ */ new Set(["node_modules", ".git", ".terraform", ".worktrees", "dist"]);
11241
11341
  var EVENT_TARGET_TYPE = "aws_cloudwatch_event_target";
11242
11342
  var LOG_RESOURCE_POLICY_TYPE = "aws_cloudwatch_log_resource_policy";
@@ -11308,12 +11408,12 @@ function walkTerraformFiles(root) {
11308
11408
  const walk2 = (dir) => {
11309
11409
  let entries;
11310
11410
  try {
11311
- entries = readdirSync18(dir);
11411
+ entries = readdirSync19(dir);
11312
11412
  } catch {
11313
11413
  return;
11314
11414
  }
11315
11415
  for (const entry of entries) {
11316
- const p = join44(dir, entry);
11416
+ const p = join45(dir, entry);
11317
11417
  let st;
11318
11418
  try {
11319
11419
  st = statSync11(p);
@@ -11450,11 +11550,11 @@ import { execa as execa14 } from "execa";
11450
11550
 
11451
11551
  // src/lib/lambda-output-guard.ts
11452
11552
  import { readFileSync as readFileSync34 } from "fs";
11453
- import { join as join46 } from "path";
11553
+ import { join as join47 } from "path";
11454
11554
 
11455
11555
  // src/lib/terraform-input-guard.ts
11456
- import { readdirSync as readdirSync19, readFileSync as readFileSync33, statSync as statSync12 } from "fs";
11457
- import { join as join45 } from "path";
11556
+ import { readdirSync as readdirSync20, readFileSync as readFileSync33, statSync as statSync12 } from "fs";
11557
+ import { join as join46 } from "path";
11458
11558
  var GUARDED_SUBCOMMANDS = [
11459
11559
  "init",
11460
11560
  "plan",
@@ -11472,13 +11572,13 @@ function findWorkflowFiles(repoRoot) {
11472
11572
  const walk2 = (dir, relative10) => {
11473
11573
  let entries;
11474
11574
  try {
11475
- entries = readdirSync19(dir);
11575
+ entries = readdirSync20(dir);
11476
11576
  } catch {
11477
11577
  return;
11478
11578
  }
11479
11579
  for (const entry of entries) {
11480
11580
  if (entry === "node_modules" || entry === ".git" || entry === ".worktrees") continue;
11481
- const full = join45(dir, entry);
11581
+ const full = join46(dir, entry);
11482
11582
  const rel = relative10 ? `${relative10}/${entry}` : entry;
11483
11583
  if (statSync12(full).isDirectory()) {
11484
11584
  walk2(full, rel);
@@ -11522,7 +11622,7 @@ function checkWorkflowSource(file, rawSource) {
11522
11622
  }
11523
11623
  function checkTerraformInput(repoRoot) {
11524
11624
  return findWorkflowFiles(repoRoot).flatMap(
11525
- (file) => checkWorkflowSource(file, readFileSync33(join45(repoRoot, file), "utf8"))
11625
+ (file) => checkWorkflowSource(file, readFileSync33(join46(repoRoot, file), "utf8"))
11526
11626
  );
11527
11627
  }
11528
11628
 
@@ -11580,7 +11680,7 @@ function checkWorkflowSource2(file, rawSource) {
11580
11680
  }
11581
11681
  function checkLambdaOutput(repoRoot) {
11582
11682
  return findWorkflowFiles(repoRoot).flatMap(
11583
- (file) => checkWorkflowSource2(file, readFileSync34(join46(repoRoot, file), "utf8"))
11683
+ (file) => checkWorkflowSource2(file, readFileSync34(join47(repoRoot, file), "utf8"))
11584
11684
  );
11585
11685
  }
11586
11686
 
@@ -11608,8 +11708,8 @@ async function runLambdaOutputCheck() {
11608
11708
  }
11609
11709
 
11610
11710
  // src/scripts/check-pipe-trap.ts
11611
- import { readFileSync as readFileSync35, readdirSync as readdirSync20 } from "fs";
11612
- import { join as join47, relative as relative8 } from "path";
11711
+ import { readFileSync as readFileSync35, readdirSync as readdirSync21 } from "fs";
11712
+ import { join as join48, relative as relative8 } from "path";
11613
11713
  import { execa as execa15 } from "execa";
11614
11714
 
11615
11715
  // src/lib/pipe-trap-guard.ts
@@ -11706,17 +11806,17 @@ function findPipeTraps(source) {
11706
11806
  function shellFiles(root) {
11707
11807
  const out = [];
11708
11808
  for (const dir of ["scripts", ".githooks"]) {
11709
- const full = join47(root, dir);
11809
+ const full = join48(root, dir);
11710
11810
  let entries;
11711
11811
  try {
11712
- entries = readdirSync20(full, { withFileTypes: true });
11812
+ entries = readdirSync21(full, { withFileTypes: true });
11713
11813
  } catch {
11714
11814
  continue;
11715
11815
  }
11716
11816
  for (const entry of entries) {
11717
11817
  if (!entry.isFile()) continue;
11718
11818
  if (dir === "scripts" && !entry.name.endsWith(".sh")) continue;
11719
- out.push(join47(full, entry.name));
11819
+ out.push(join48(full, entry.name));
11720
11820
  }
11721
11821
  }
11722
11822
  return out;
@@ -11753,7 +11853,7 @@ import { execa as execa16 } from "execa";
11753
11853
 
11754
11854
  // src/lib/plugin-allowlist-convention.ts
11755
11855
  import { readFileSync as readFileSync36 } from "fs";
11756
- import { join as join48 } from "path";
11856
+ import { join as join49 } from "path";
11757
11857
  var COMPUTE_MAIN_TF = "modules/cloud/aws/compute/main.tf";
11758
11858
  var PLUGIN_TEMPLATE_MAIN_TF = "modules/plugins/_template/main.tf";
11759
11859
  var ALLOWLIST_MAIN_TF = "modules/cloud/aws/plugin-allowlist/main.tf";
@@ -11764,7 +11864,7 @@ var PLUGIN = "<plugin>";
11764
11864
  var ACCOUNT = "<account>";
11765
11865
  function read(repoRoot, relative10) {
11766
11866
  try {
11767
- return readFileSync36(join48(repoRoot, relative10), "utf8");
11867
+ return readFileSync36(join49(repoRoot, relative10), "utf8");
11768
11868
  } catch {
11769
11869
  throw new Error(`plugin-allowlist drift guard: cannot read ${relative10}`);
11770
11870
  }
@@ -11885,34 +11985,34 @@ async function runPluginAllowlistConventionCheck() {
11885
11985
  }
11886
11986
 
11887
11987
  // src/scripts/check-plugin-collisions.ts
11888
- import { existsSync as existsSync41 } from "fs";
11889
- import { join as join50 } from "path";
11988
+ import { existsSync as existsSync42 } from "fs";
11989
+ import { join as join51 } from "path";
11890
11990
  import { execa as execa17 } from "execa";
11891
11991
 
11892
11992
  // src/lib/plugin-collision-guard.ts
11893
- import { existsSync as existsSync40, readdirSync as readdirSync21, statSync as statSync13 } from "fs";
11894
- import { join as join49 } from "path";
11993
+ import { existsSync as existsSync41, readdirSync as readdirSync22, statSync as statSync13 } from "fs";
11994
+ import { join as join50 } from "path";
11895
11995
  var PYTEST_SPECIAL = /* @__PURE__ */ new Set(["conftest.py"]);
11896
11996
  var IGNORED_DIRS = /* @__PURE__ */ new Set([".venv", "node_modules", "__pycache__", ".git", "dist", "build"]);
11897
11997
  function subdirectories(dir) {
11898
- if (!existsSync40(dir)) return [];
11899
- return readdirSync21(dir).filter((entry) => {
11998
+ if (!existsSync41(dir)) return [];
11999
+ return readdirSync22(dir).filter((entry) => {
11900
12000
  if (IGNORED_DIRS.has(entry) || entry.startsWith(".")) return false;
11901
12001
  try {
11902
- return statSync13(join49(dir, entry)).isDirectory();
12002
+ return statSync13(join50(dir, entry)).isDirectory();
11903
12003
  } catch {
11904
12004
  return false;
11905
12005
  }
11906
12006
  });
11907
12007
  }
11908
12008
  function regularPackagesOf(pluginDir2) {
11909
- return subdirectories(pluginDir2).filter((name) => existsSync40(join49(pluginDir2, name, "__init__.py"))).sort();
12009
+ return subdirectories(pluginDir2).filter((name) => existsSync41(join50(pluginDir2, name, "__init__.py"))).sort();
11910
12010
  }
11911
12011
  function bareTestModulesOf(pluginDir2) {
11912
- const testsDir = join49(pluginDir2, "tests");
11913
- if (!existsSync40(testsDir)) return [];
11914
- if (existsSync40(join49(testsDir, "__init__.py"))) return [];
11915
- return readdirSync21(testsDir).filter((f) => f.endsWith(".py") && !PYTEST_SPECIAL.has(f)).sort();
12012
+ const testsDir = join50(pluginDir2, "tests");
12013
+ if (!existsSync41(testsDir)) return [];
12014
+ if (existsSync41(join50(testsDir, "__init__.py"))) return [];
12015
+ return readdirSync22(testsDir).filter((f) => f.endsWith(".py") && !PYTEST_SPECIAL.has(f)).sort();
11916
12016
  }
11917
12017
  function findCollisions(servicesDir, pluginDirs) {
11918
12018
  const plugins = (pluginDirs ?? subdirectories(servicesDir)).filter((name) => !name.startsWith("_")).filter((name) => name !== "api").sort();
@@ -11920,7 +12020,7 @@ function findCollisions(servicesDir, pluginDirs) {
11920
12020
  const gather = (kind, namesOf) => {
11921
12021
  const claims = /* @__PURE__ */ new Map();
11922
12022
  for (const plugin of plugins) {
11923
- for (const name of namesOf(join49(servicesDir, plugin))) {
12023
+ for (const name of namesOf(join50(servicesDir, plugin))) {
11924
12024
  claims.set(name, [...claims.get(name) ?? [], plugin]);
11925
12025
  }
11926
12026
  }
@@ -11958,8 +12058,8 @@ function formatCollisions(collisions) {
11958
12058
  // src/scripts/check-plugin-collisions.ts
11959
12059
  async function runPluginCollisionCheck() {
11960
12060
  const root = (await execa17("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
11961
- const servicesDir = join50(root, "services");
11962
- if (!existsSync41(servicesDir)) {
12061
+ const servicesDir = join51(root, "services");
12062
+ if (!existsSync42(servicesDir)) {
11963
12063
  console.log("\u2713 plugin collision guard: no services/ directory \u2014 nothing to compare");
11964
12064
  return;
11965
12065
  }
@@ -11979,8 +12079,8 @@ async function runPluginCollisionCheck() {
11979
12079
  import { execa as execa18 } from "execa";
11980
12080
 
11981
12081
  // src/lib/plugin-terraform-guard.ts
11982
- import { existsSync as existsSync42, readFileSync as readFileSync37, readdirSync as readdirSync22 } from "fs";
11983
- import { dirname as dirname10, join as join51, relative as relative9, sep as sep3 } from "path";
12082
+ import { existsSync as existsSync43, readFileSync as readFileSync37, readdirSync as readdirSync23 } from "fs";
12083
+ import { dirname as dirname10, join as join52, relative as relative9, sep as sep3 } from "path";
11984
12084
  var SKIP_DIRS3 = /* @__PURE__ */ new Set(["node_modules", ".git", ".worktrees", "dist", ".venv", "__pycache__"]);
11985
12085
  var PLUGIN_MANIFEST_FILE2 = "biffo.plugin.json";
11986
12086
  function findPluginManifests(root) {
@@ -11988,16 +12088,16 @@ function findPluginManifests(root) {
11988
12088
  const walk2 = (dir) => {
11989
12089
  let entries;
11990
12090
  try {
11991
- entries = readdirSync22(dir, { withFileTypes: true });
12091
+ entries = readdirSync23(dir, { withFileTypes: true });
11992
12092
  } catch {
11993
12093
  return;
11994
12094
  }
11995
12095
  for (const entry of entries) {
11996
12096
  if (entry.isDirectory()) {
11997
12097
  if (SKIP_DIRS3.has(entry.name)) continue;
11998
- walk2(join51(dir, entry.name));
12098
+ walk2(join52(dir, entry.name));
11999
12099
  } else if (entry.isFile() && entry.name === PLUGIN_MANIFEST_FILE2) {
12000
- found.push(relative9(root, join51(dir, entry.name)).split(sep3).join("/"));
12100
+ found.push(relative9(root, join52(dir, entry.name)).split(sep3).join("/"));
12001
12101
  }
12002
12102
  }
12003
12103
  };
@@ -12022,14 +12122,14 @@ function readSubscriptions(absManifestPath) {
12022
12122
  }
12023
12123
  function checkPluginTerraform(root) {
12024
12124
  const violations = [];
12025
- const coreManifest = existsSync42(join51(root, CORE_MANIFEST_FILE)) ? readCoreManifest(root) : null;
12125
+ const coreManifest = existsSync43(join52(root, CORE_MANIFEST_FILE)) ? readCoreManifest(root) : null;
12026
12126
  for (const manifest of findPluginManifests(root)) {
12027
12127
  if (coreManifest && !isTemplateOwned(manifest, coreManifest)) continue;
12028
- const absManifest = join51(root, manifest);
12128
+ const absManifest = join52(root, manifest);
12029
12129
  const subscriptions = readSubscriptions(absManifest);
12030
12130
  if (subscriptions === null) continue;
12031
12131
  const pluginDir2 = dirname10(absManifest);
12032
- if (existsSync42(join51(pluginDir2, "terraform"))) continue;
12132
+ if (existsSync43(join52(pluginDir2, "terraform"))) continue;
12033
12133
  const relPluginDir = relative9(root, pluginDir2).split(sep3).join("/");
12034
12134
  violations.push({
12035
12135
  manifest,
@@ -12060,13 +12160,13 @@ async function runPluginTerraformCheck() {
12060
12160
  }
12061
12161
 
12062
12162
  // src/scripts/check-plugin-tool-supply.ts
12063
- import { existsSync as existsSync44 } from "fs";
12064
- import { join as join53 } from "path";
12163
+ import { existsSync as existsSync45 } from "fs";
12164
+ import { join as join54 } from "path";
12065
12165
  import { execa as execa19 } from "execa";
12066
12166
 
12067
12167
  // src/lib/plugin-tool-supply-audit.ts
12068
- import { existsSync as existsSync43, readFileSync as readFileSync38, readdirSync as readdirSync23, statSync as statSync14 } from "fs";
12069
- import { join as join52 } from "path";
12168
+ import { existsSync as existsSync44, readFileSync as readFileSync38, readdirSync as readdirSync24, statSync as statSync14 } from "fs";
12169
+ import { join as join53 } from "path";
12070
12170
 
12071
12171
  // src/lib/openrouter-model-snapshot.ts
12072
12172
  var OPENROUTER_MODEL_SNAPSHOT_FETCHED_AT = "2026-08-10T06:39:01Z";
@@ -12477,13 +12577,13 @@ var OPENROUTER_MODEL_IDS = [
12477
12577
  function listDirs(root) {
12478
12578
  let entries;
12479
12579
  try {
12480
- entries = readdirSync23(root);
12580
+ entries = readdirSync24(root);
12481
12581
  } catch {
12482
12582
  return [];
12483
12583
  }
12484
12584
  return entries.filter((e) => {
12485
12585
  try {
12486
- return statSync14(join52(root, e)).isDirectory();
12586
+ return statSync14(join53(root, e)).isDirectory();
12487
12587
  } catch {
12488
12588
  return false;
12489
12589
  }
@@ -12494,12 +12594,12 @@ function walkFiles2(root, accept, skipDir) {
12494
12594
  const walk2 = (dir) => {
12495
12595
  let entries;
12496
12596
  try {
12497
- entries = readdirSync23(dir);
12597
+ entries = readdirSync24(dir);
12498
12598
  } catch {
12499
12599
  return;
12500
12600
  }
12501
12601
  for (const entry of entries) {
12502
- const p = join52(dir, entry);
12602
+ const p = join53(dir, entry);
12503
12603
  let st;
12504
12604
  try {
12505
12605
  st = statSync14(p);
@@ -12525,14 +12625,14 @@ function pluginPythonFiles(pluginDir2) {
12525
12625
  );
12526
12626
  }
12527
12627
  function pluginTerraformFiles(pluginDir2) {
12528
- const tfDir = join52(pluginDir2, "terraform");
12628
+ const tfDir = join53(pluginDir2, "terraform");
12529
12629
  let entries;
12530
12630
  try {
12531
- entries = readdirSync23(tfDir);
12631
+ entries = readdirSync24(tfDir);
12532
12632
  } catch {
12533
12633
  return [];
12534
12634
  }
12535
- return entries.filter((e) => e.endsWith(".tf")).map((e) => join52(tfDir, e)).sort();
12635
+ return entries.filter((e) => e.endsWith(".tf")).map((e) => join53(tfDir, e)).sort();
12536
12636
  }
12537
12637
  function extractManifestTools(manifestText) {
12538
12638
  let parsed;
@@ -12784,8 +12884,8 @@ function isSnapshotStale(fetchedAt, now) {
12784
12884
  function normalizeModelId(id) {
12785
12885
  return id.endsWith(":online") ? id.slice(0, -":online".length) : id;
12786
12886
  }
12787
- var CONFIG_PY_PATH = join52("services", "api", "src", "api", "config.py");
12788
- var ORCHESTRATION_SCHEMA_PATH = join52(
12887
+ var CONFIG_PY_PATH = join53("services", "api", "src", "api", "config.py");
12888
+ var ORCHESTRATION_SCHEMA_PATH = join53(
12789
12889
  "services",
12790
12890
  "api",
12791
12891
  "src",
@@ -12797,10 +12897,10 @@ function auditDeclaredModelIds(repoRoot, options = {}) {
12797
12897
  const knownModelIds = options.knownModelIds ?? OPENROUTER_MODEL_IDS;
12798
12898
  const snapshotFetchedAt = options.snapshotFetchedAt ?? OPENROUTER_MODEL_SNAPSHOT_FETCHED_AT;
12799
12899
  const now = options.now ?? /* @__PURE__ */ new Date();
12800
- const configPath = join52(repoRoot, CONFIG_PY_PATH);
12801
- const orchestrationPath = join52(repoRoot, ORCHESTRATION_SCHEMA_PATH);
12802
- const configMissing = !existsSync43(configPath);
12803
- const orchestrationSchemaMissing = !existsSync43(orchestrationPath);
12900
+ const configPath = join53(repoRoot, CONFIG_PY_PATH);
12901
+ const orchestrationPath = join53(repoRoot, ORCHESTRATION_SCHEMA_PATH);
12902
+ const configMissing = !existsSync44(configPath);
12903
+ const orchestrationSchemaMissing = !existsSync44(orchestrationPath);
12804
12904
  const knownSet = new Set(knownModelIds);
12805
12905
  const snapshotEmpty = knownModelIds.length === 0;
12806
12906
  const snapshotStale = isSnapshotStale(snapshotFetchedAt, now);
@@ -12871,7 +12971,7 @@ function auditDeclaredModelIds(repoRoot, options = {}) {
12871
12971
  function discoverPluginDirs(pluginsRoot) {
12872
12972
  return listDirs(pluginsRoot).filter((name) => {
12873
12973
  try {
12874
- return statSync14(join52(pluginsRoot, name, "biffo.plugin.json")).isFile();
12974
+ return statSync14(join53(pluginsRoot, name, "biffo.plugin.json")).isFile();
12875
12975
  } catch {
12876
12976
  return false;
12877
12977
  }
@@ -12884,8 +12984,8 @@ function auditPluginToolSupply(pluginsRoot) {
12884
12984
  let terraformBlind = false;
12885
12985
  let totalDeclaredTools = 0;
12886
12986
  for (const name of pluginNames) {
12887
- const pluginDir2 = join52(pluginsRoot, name);
12888
- const manifestText = readFileSync38(join52(pluginDir2, "biffo.plugin.json"), "utf8");
12987
+ const pluginDir2 = join53(pluginsRoot, name);
12988
+ const manifestText = readFileSync38(join53(pluginDir2, "biffo.plugin.json"), "utf8");
12889
12989
  const manifest = extractManifestTools(manifestText);
12890
12990
  if (manifest.parseError) {
12891
12991
  findings.push({
@@ -12983,7 +13083,7 @@ function auditPluginToolSupply(pluginsRoot) {
12983
13083
  requiredEnvVars: envResult.envVars,
12984
13084
  missingEnvVars: anyWired ? [] : envResult.envVars,
12985
13085
  status: anyWired ? "ok" : "missing-env",
12986
- detail: anyWired ? `${entry.predicate}() is satisfiable: at least one of ${JSON.stringify(envResult.envVars)} is wired in Terraform` : `${entry.predicate}() reads ${JSON.stringify(envResult.envVars)} \u2014 NONE of these are wired by any environment_variables block under ${join52(pluginDir2, "terraform")}, so this deployment can never supply it`
13086
+ detail: anyWired ? `${entry.predicate}() is satisfiable: at least one of ${JSON.stringify(envResult.envVars)} is wired in Terraform` : `${entry.predicate}() reads ${JSON.stringify(envResult.envVars)} \u2014 NONE of these are wired by any environment_variables block under ${join53(pluginDir2, "terraform")}, so this deployment can never supply it`
12987
13087
  });
12988
13088
  }
12989
13089
  }
@@ -13016,8 +13116,8 @@ function auditPluginToolSupply(pluginsRoot) {
13016
13116
  async function runPluginToolSupplyCheck() {
13017
13117
  const root = (await execa19("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
13018
13118
  let allOk = true;
13019
- const pluginsRoot = join53(root, "services", "_plugins");
13020
- if (!existsSync44(pluginsRoot)) {
13119
+ const pluginsRoot = join54(root, "services", "_plugins");
13120
+ if (!existsSync45(pluginsRoot)) {
13021
13121
  console.log("\u2713 plugin tool-supply guard: no services/_plugins/ \u2014 nothing to audit");
13022
13122
  } else {
13023
13123
  const report = auditPluginToolSupply(pluginsRoot);
@@ -13047,8 +13147,8 @@ async function runPluginToolSupplyCheck() {
13047
13147
  console.log(`\u2713 plugin tool-supply guard: ${report.summary}`);
13048
13148
  }
13049
13149
  }
13050
- const servicesApiRoot = join53(root, "services", "api");
13051
- if (!existsSync44(servicesApiRoot)) {
13150
+ const servicesApiRoot = join54(root, "services", "api");
13151
+ if (!existsSync45(servicesApiRoot)) {
13052
13152
  console.log("\u2713 plugin model-id guard: no services/api/ \u2014 nothing to audit");
13053
13153
  } else {
13054
13154
  const modelReport = auditDeclaredModelIds(root);
@@ -13225,13 +13325,13 @@ async function runReleaseSubjectCheck(argv) {
13225
13325
  }
13226
13326
 
13227
13327
  // src/scripts/check-skeleton-drift.ts
13228
- import { existsSync as existsSync45, readdirSync as readdirSync25 } from "fs";
13229
- import { join as join55 } from "path";
13328
+ import { existsSync as existsSync46, readdirSync as readdirSync26 } from "fs";
13329
+ import { join as join56 } from "path";
13230
13330
  import { execa as execa21 } from "execa";
13231
13331
 
13232
13332
  // src/lib/skeleton-drift-guard.ts
13233
- import { readFileSync as readFileSync39, readdirSync as readdirSync24, statSync as statSync15 } from "fs";
13234
- import { join as join54 } from "path";
13333
+ import { readFileSync as readFileSync39, readdirSync as readdirSync25, statSync as statSync15 } from "fs";
13334
+ import { join as join55 } from "path";
13235
13335
  var isWorkflow = (rel) => rel.startsWith(".github/workflows/") && (rel.endsWith(".yml") || rel.endsWith(".yaml"));
13236
13336
  var isRootLayout = (rel) => rel.endsWith("src/app/layout.tsx");
13237
13337
  var uncommented = (contents) => contents.split("\n").filter((line) => !/^\s*(\/\/|\/\*|\*)/.test(line)).join("\n");
@@ -13289,13 +13389,13 @@ function walk(dir, base = dir) {
13289
13389
  const out = [];
13290
13390
  let entries;
13291
13391
  try {
13292
- entries = readdirSync24(dir);
13392
+ entries = readdirSync25(dir);
13293
13393
  } catch {
13294
13394
  return out;
13295
13395
  }
13296
13396
  for (const entry of entries) {
13297
13397
  if (entry === ".venv" || entry === "node_modules" || entry === ".git") continue;
13298
- const abs = join54(dir, entry);
13398
+ const abs = join55(dir, entry);
13299
13399
  let isDir;
13300
13400
  try {
13301
13401
  isDir = statSync15(abs).isDirectory();
@@ -13317,7 +13417,7 @@ function auditSkeleton(skeletonRoot, name, rules = SKELETON_RULES) {
13317
13417
  if (!rule.appliesTo(rel)) continue;
13318
13418
  let contents;
13319
13419
  try {
13320
- contents = readFileSync39(join54(skeletonRoot, rel), "utf8");
13420
+ contents = readFileSync39(join55(skeletonRoot, rel), "utf8");
13321
13421
  } catch {
13322
13422
  continue;
13323
13423
  }
@@ -13346,23 +13446,23 @@ function formatViolations2(violations) {
13346
13446
 
13347
13447
  // src/scripts/check-skeleton-drift.ts
13348
13448
  function discoverSkeletons(root) {
13349
- const skeletonsDir = join55(root, "_skeletons");
13449
+ const skeletonsDir = join56(root, "_skeletons");
13350
13450
  let entries;
13351
13451
  try {
13352
- entries = readdirSync25(skeletonsDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
13452
+ entries = readdirSync26(skeletonsDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
13353
13453
  } catch {
13354
13454
  return [];
13355
13455
  }
13356
- return entries.filter((name) => existsSync45(join55(skeletonsDir, name, ".github", "workflows", "ci.yml"))).sort();
13456
+ return entries.filter((name) => existsSync46(join56(skeletonsDir, name, ".github", "workflows", "ci.yml"))).sort();
13357
13457
  }
13358
13458
  async function runSkeletonDriftCheck() {
13359
13459
  const root = (await execa21("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
13360
13460
  const skeletons = discoverSkeletons(root);
13361
13461
  let filesConsidered = 0;
13362
13462
  for (const name of skeletons) {
13363
- const skeletonRoot = join55(root, "_skeletons", name);
13463
+ const skeletonRoot = join56(root, "_skeletons", name);
13364
13464
  filesConsidered += findWorkflowFiles(skeletonRoot).length;
13365
- if (existsSync45(join55(skeletonRoot, "apps", "frontend", "src", "app", "layout.tsx"))) {
13465
+ if (existsSync46(join56(skeletonRoot, "apps", "frontend", "src", "app", "layout.tsx"))) {
13366
13466
  filesConsidered += 1;
13367
13467
  }
13368
13468
  }
@@ -13376,7 +13476,7 @@ async function runSkeletonDriftCheck() {
13376
13476
  process.exit(1);
13377
13477
  }
13378
13478
  const violations = skeletons.flatMap(
13379
- (name) => auditSkeleton(join55(root, "_skeletons", name), name)
13479
+ (name) => auditSkeleton(join56(root, "_skeletons", name), name)
13380
13480
  );
13381
13481
  if (violations.length > 0) {
13382
13482
  console.error("\u2717 Skeleton-drift guard: drift found between this repo and its scaffolding\n");
@@ -13514,8 +13614,8 @@ function rawArgsAfter(subcommand) {
13514
13614
  }
13515
13615
 
13516
13616
  // src/commands/doctor.ts
13517
- import { existsSync as existsSync46, readFileSync as readFileSync40 } from "fs";
13518
- import { join as join56, resolve as resolve20 } from "path";
13617
+ import { existsSync as existsSync47, readFileSync as readFileSync40 } from "fs";
13618
+ import { join as join57, resolve as resolve20 } from "path";
13519
13619
  import chalk21 from "chalk";
13520
13620
  import { Command as Command25 } from "commander";
13521
13621
 
@@ -13694,8 +13794,8 @@ async function runDoctor(options, deps = { git: new GitAdapter() }) {
13694
13794
  return runDoctorChecks(facts);
13695
13795
  }
13696
13796
  function readLocalCoreVersion(cwd) {
13697
- const path = join56(cwd, INSTANCE_CORE_FILE);
13698
- if (!existsSync46(path)) return null;
13797
+ const path = join57(cwd, INSTANCE_CORE_FILE);
13798
+ if (!existsSync47(path)) return null;
13699
13799
  try {
13700
13800
  return extractVersionField(readFileSync40(path, "utf8"));
13701
13801
  } catch {
@@ -13717,8 +13817,8 @@ function extractVersionField(contents) {
13717
13817
  return match?.[1] ?? null;
13718
13818
  }
13719
13819
  function readFossil(cwd) {
13720
- const path = join56(cwd, CORE_VERSION_FILE);
13721
- if (!existsSync46(path)) return null;
13820
+ const path = join57(cwd, CORE_VERSION_FILE);
13821
+ if (!existsSync47(path)) return null;
13722
13822
  try {
13723
13823
  const value = readFileSync40(path, "utf8").trim();
13724
13824
  return value === "" ? null : value;
@@ -14169,13 +14269,13 @@ import { fileURLToPath as fileURLToPath6 } from "url";
14169
14269
  import { Command as Command27 } from "commander";
14170
14270
 
14171
14271
  // src/lib/packaged-scripts.ts
14172
- import { existsSync as existsSync47 } from "fs";
14173
- import { dirname as dirname11, join as join57 } from "path";
14272
+ import { existsSync as existsSync48 } from "fs";
14273
+ import { dirname as dirname11, join as join58 } from "path";
14174
14274
  function findPackagedScript(startDir, relativePath) {
14175
14275
  let dir = startDir;
14176
14276
  for (; ; ) {
14177
- const candidate = join57(dir, relativePath);
14178
- if (existsSync47(candidate)) return candidate;
14277
+ const candidate = join58(dir, relativePath);
14278
+ if (existsSync48(candidate)) return candidate;
14179
14279
  const parent = dirname11(dir);
14180
14280
  if (parent === dir) return null;
14181
14281
  dir = parent;