@biffo/cli 0.267.5 → 0.267.7

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.
Files changed (2) hide show
  1. package/dist/index.js +90 -33
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -10006,7 +10006,7 @@ import { join as join38 } from "path";
10006
10006
  import { execa as execa8 } from "execa";
10007
10007
 
10008
10008
  // src/lib/core-direct-paths-audit.ts
10009
- import { readFileSync as readFileSync28, readdirSync as readdirSync15, statSync as statSync8 } from "fs";
10009
+ import { existsSync as existsSync36, readFileSync as readFileSync28, readdirSync as readdirSync15, statSync as statSync8 } from "fs";
10010
10010
  import { join as join37 } from "path";
10011
10011
  var EXTERNAL_BASE_IDENTIFIERS = ["CORE_API_URL"];
10012
10012
  var API_ROUTE_PREFIX = "/api/v1";
@@ -10264,6 +10264,39 @@ function pathMatchesAnyCorePrefix(normalized, corePrefixes, apiRoutePrefix = API
10264
10264
  }
10265
10265
  return false;
10266
10266
  }
10267
+ function resolveSiblingCoreSrc(params) {
10268
+ const { estateDir, sibling } = params;
10269
+ const configPath = join37(estateDir, sibling, "biffo.sibling.json");
10270
+ let raw;
10271
+ try {
10272
+ raw = readFileSync28(configPath, "utf8");
10273
+ } catch (err) {
10274
+ throw new Error(
10275
+ `cannot resolve ${sibling}'s core: ${configPath} does not exist or is unreadable (${err.message}) -- refusing to guess which core serves this sibling.`
10276
+ );
10277
+ }
10278
+ let parsed;
10279
+ try {
10280
+ parsed = JSON.parse(raw);
10281
+ } catch (err) {
10282
+ throw new Error(
10283
+ `cannot resolve ${sibling}'s core: ${configPath} is not valid JSON (${err.message}).`
10284
+ );
10285
+ }
10286
+ const coreProject = parsed !== null && typeof parsed === "object" && "core_project" in parsed ? parsed.core_project : void 0;
10287
+ if (typeof coreProject !== "string" || coreProject.trim() === "") {
10288
+ throw new Error(
10289
+ `cannot resolve ${sibling}'s core: ${configPath} has no non-empty "core_project" field.`
10290
+ );
10291
+ }
10292
+ const coreApiSrcDir = join37(estateDir, coreProject, "services", "api", "src");
10293
+ if (!existsSync36(coreApiSrcDir)) {
10294
+ throw new Error(
10295
+ `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.`
10296
+ );
10297
+ }
10298
+ return { sibling, coreProject, coreApiSrcDir };
10299
+ }
10267
10300
  function auditSiblingCoreDirectPaths(params) {
10268
10301
  const externalBases = params.externalBases ?? EXTERNAL_BASE_IDENTIFIERS;
10269
10302
  const frontend = auditFrontendExtraction(params.frontendSrcDir, externalBases);
@@ -10301,10 +10334,26 @@ async function runCoreDirectPathsCheck(opts = {}) {
10301
10334
  const root = (await execa8("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
10302
10335
  const sibling = opts.sibling ?? "sibling-template (self-check)";
10303
10336
  const frontendSrcDir = opts.frontendSrc ?? join38(root, "_skeletons", "sibling-template", "apps", "frontend", "src");
10304
- const coreApiSrcDir = opts.coreSrc ?? join38(root, "services", "api", "src");
10337
+ let coreApiSrcDir;
10338
+ let coreProject = null;
10339
+ if (opts.coreSrc) {
10340
+ coreApiSrcDir = opts.coreSrc;
10341
+ } else if (opts.sibling && opts.estate) {
10342
+ let resolution;
10343
+ try {
10344
+ resolution = resolveSiblingCoreSrc({ estateDir: opts.estate, sibling: opts.sibling });
10345
+ } catch (err) {
10346
+ console.error(`\u2717 core-direct-paths guard (${sibling}): ${err.message}`);
10347
+ process.exit(1);
10348
+ }
10349
+ coreApiSrcDir = resolution.coreApiSrcDir;
10350
+ coreProject = resolution.coreProject;
10351
+ } else {
10352
+ coreApiSrcDir = join38(root, "services", "api", "src");
10353
+ }
10305
10354
  const report = auditSiblingCoreDirectPaths({ sibling, frontendSrcDir, coreApiSrcDir });
10306
10355
  console.log(
10307
- `audited ${report.extractedCount} core-direct call site(s) across ${report.frontendFiles} frontend file(s) under ${frontendSrcDir}, against ${report.corePrefixCount} route prefix(es) from ${report.coreFiles} core file(s) under ${coreApiSrcDir}`
10356
+ `audited ${report.extractedCount} core-direct call site(s) across ${report.frontendFiles} frontend file(s) under ${frontendSrcDir}, against ${report.corePrefixCount} route prefix(es) from ${report.coreFiles} core file(s) under ${coreApiSrcDir}` + (coreProject ? ` (core project: ${coreProject})` : "")
10308
10357
  );
10309
10358
  if (!report.ok) {
10310
10359
  console.error(`\u2717 core-direct-paths guard (${sibling}): unmatched or unresolved call site(s)
@@ -10366,8 +10415,8 @@ async function runOwnershipCheck(argv) {
10366
10415
  const { stdout } = await execa9("git", ["diff", "--cached", "--name-status"], { cwd: root });
10367
10416
  ({ changed: changedFiles, deleted: deletedFiles } = parseNameStatus(stdout));
10368
10417
  if (messageFile) {
10369
- const { readFileSync: readFileSync37, existsSync: existsSync44 } = await import("fs");
10370
- if (existsSync44(messageFile)) commitMessage = readFileSync37(messageFile, "utf8");
10418
+ const { readFileSync: readFileSync37, existsSync: existsSync45 } = await import("fs");
10419
+ if (existsSync45(messageFile)) commitMessage = readFileSync37(messageFile, "utf8");
10371
10420
  }
10372
10421
  } else {
10373
10422
  const base = process.env["GITHUB_BASE_REF"] ?? args[0];
@@ -10985,17 +11034,17 @@ async function runPipeTrapCheck() {
10985
11034
  }
10986
11035
 
10987
11036
  // src/scripts/check-plugin-collisions.ts
10988
- import { existsSync as existsSync37 } from "fs";
11037
+ import { existsSync as existsSync38 } from "fs";
10989
11038
  import { join as join44 } from "path";
10990
11039
  import { execa as execa13 } from "execa";
10991
11040
 
10992
11041
  // src/lib/plugin-collision-guard.ts
10993
- import { existsSync as existsSync36, readdirSync as readdirSync19, statSync as statSync11 } from "fs";
11042
+ import { existsSync as existsSync37, readdirSync as readdirSync19, statSync as statSync11 } from "fs";
10994
11043
  import { join as join43 } from "path";
10995
11044
  var PYTEST_SPECIAL = /* @__PURE__ */ new Set(["conftest.py"]);
10996
11045
  var IGNORED_DIRS = /* @__PURE__ */ new Set([".venv", "node_modules", "__pycache__", ".git", "dist", "build"]);
10997
11046
  function subdirectories(dir) {
10998
- if (!existsSync36(dir)) return [];
11047
+ if (!existsSync37(dir)) return [];
10999
11048
  return readdirSync19(dir).filter((entry) => {
11000
11049
  if (IGNORED_DIRS.has(entry) || entry.startsWith(".")) return false;
11001
11050
  try {
@@ -11006,12 +11055,12 @@ function subdirectories(dir) {
11006
11055
  });
11007
11056
  }
11008
11057
  function regularPackagesOf(pluginDir2) {
11009
- return subdirectories(pluginDir2).filter((name) => existsSync36(join43(pluginDir2, name, "__init__.py"))).sort();
11058
+ return subdirectories(pluginDir2).filter((name) => existsSync37(join43(pluginDir2, name, "__init__.py"))).sort();
11010
11059
  }
11011
11060
  function bareTestModulesOf(pluginDir2) {
11012
11061
  const testsDir = join43(pluginDir2, "tests");
11013
- if (!existsSync36(testsDir)) return [];
11014
- if (existsSync36(join43(testsDir, "__init__.py"))) return [];
11062
+ if (!existsSync37(testsDir)) return [];
11063
+ if (existsSync37(join43(testsDir, "__init__.py"))) return [];
11015
11064
  return readdirSync19(testsDir).filter((f) => f.endsWith(".py") && !PYTEST_SPECIAL.has(f)).sort();
11016
11065
  }
11017
11066
  function findCollisions(servicesDir, pluginDirs) {
@@ -11059,7 +11108,7 @@ function formatCollisions(collisions) {
11059
11108
  async function runPluginCollisionCheck() {
11060
11109
  const root = (await execa13("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
11061
11110
  const servicesDir = join44(root, "services");
11062
- if (!existsSync37(servicesDir)) {
11111
+ if (!existsSync38(servicesDir)) {
11063
11112
  console.log("\u2713 plugin collision guard: no services/ directory \u2014 nothing to compare");
11064
11113
  return;
11065
11114
  }
@@ -11079,7 +11128,7 @@ async function runPluginCollisionCheck() {
11079
11128
  import { execa as execa14 } from "execa";
11080
11129
 
11081
11130
  // src/lib/plugin-terraform-guard.ts
11082
- import { existsSync as existsSync38, readFileSync as readFileSync33, readdirSync as readdirSync20 } from "fs";
11131
+ import { existsSync as existsSync39, readFileSync as readFileSync33, readdirSync as readdirSync20 } from "fs";
11083
11132
  import { dirname as dirname9, join as join45, relative as relative7, sep as sep3 } from "path";
11084
11133
  var SKIP_DIRS2 = /* @__PURE__ */ new Set(["node_modules", ".git", ".worktrees", "dist", ".venv", "__pycache__"]);
11085
11134
  var PLUGIN_MANIFEST_FILE2 = "biffo.plugin.json";
@@ -11122,14 +11171,14 @@ function readSubscriptions(absManifestPath) {
11122
11171
  }
11123
11172
  function checkPluginTerraform(root) {
11124
11173
  const violations = [];
11125
- const coreManifest = existsSync38(join45(root, CORE_MANIFEST_FILE)) ? readCoreManifest(root) : null;
11174
+ const coreManifest = existsSync39(join45(root, CORE_MANIFEST_FILE)) ? readCoreManifest(root) : null;
11126
11175
  for (const manifest of findPluginManifests(root)) {
11127
11176
  if (coreManifest && !isTemplateOwned(manifest, coreManifest)) continue;
11128
11177
  const absManifest = join45(root, manifest);
11129
11178
  const subscriptions = readSubscriptions(absManifest);
11130
11179
  if (subscriptions === null) continue;
11131
11180
  const pluginDir2 = dirname9(absManifest);
11132
- if (existsSync38(join45(pluginDir2, "terraform"))) continue;
11181
+ if (existsSync39(join45(pluginDir2, "terraform"))) continue;
11133
11182
  const relPluginDir = relative7(root, pluginDir2).split(sep3).join("/");
11134
11183
  violations.push({
11135
11184
  manifest,
@@ -11160,12 +11209,12 @@ async function runPluginTerraformCheck() {
11160
11209
  }
11161
11210
 
11162
11211
  // src/scripts/check-plugin-tool-supply.ts
11163
- import { existsSync as existsSync40 } from "fs";
11212
+ import { existsSync as existsSync41 } from "fs";
11164
11213
  import { join as join47 } from "path";
11165
11214
  import { execa as execa15 } from "execa";
11166
11215
 
11167
11216
  // src/lib/plugin-tool-supply-audit.ts
11168
- import { existsSync as existsSync39, readFileSync as readFileSync34, readdirSync as readdirSync21, statSync as statSync12 } from "fs";
11217
+ import { existsSync as existsSync40, readFileSync as readFileSync34, readdirSync as readdirSync21, statSync as statSync12 } from "fs";
11169
11218
  import { join as join46 } from "path";
11170
11219
 
11171
11220
  // src/lib/openrouter-model-snapshot.ts
@@ -11899,8 +11948,8 @@ function auditDeclaredModelIds(repoRoot, options = {}) {
11899
11948
  const now = options.now ?? /* @__PURE__ */ new Date();
11900
11949
  const configPath = join46(repoRoot, CONFIG_PY_PATH);
11901
11950
  const orchestrationPath = join46(repoRoot, ORCHESTRATION_SCHEMA_PATH);
11902
- const configMissing = !existsSync39(configPath);
11903
- const orchestrationSchemaMissing = !existsSync39(orchestrationPath);
11951
+ const configMissing = !existsSync40(configPath);
11952
+ const orchestrationSchemaMissing = !existsSync40(orchestrationPath);
11904
11953
  const knownSet = new Set(knownModelIds);
11905
11954
  const snapshotEmpty = knownModelIds.length === 0;
11906
11955
  const snapshotStale = isSnapshotStale(snapshotFetchedAt, now);
@@ -12117,7 +12166,7 @@ async function runPluginToolSupplyCheck() {
12117
12166
  const root = (await execa15("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
12118
12167
  let allOk = true;
12119
12168
  const pluginsRoot = join47(root, "services", "_plugins");
12120
- if (!existsSync40(pluginsRoot)) {
12169
+ if (!existsSync41(pluginsRoot)) {
12121
12170
  console.log("\u2713 plugin tool-supply guard: no services/_plugins/ \u2014 nothing to audit");
12122
12171
  } else {
12123
12172
  const report = auditPluginToolSupply(pluginsRoot);
@@ -12148,7 +12197,7 @@ async function runPluginToolSupplyCheck() {
12148
12197
  }
12149
12198
  }
12150
12199
  const servicesApiRoot = join47(root, "services", "api");
12151
- if (!existsSync40(servicesApiRoot)) {
12200
+ if (!existsSync41(servicesApiRoot)) {
12152
12201
  console.log("\u2713 plugin model-id guard: no services/api/ \u2014 nothing to audit");
12153
12202
  } else {
12154
12203
  const modelReport = auditDeclaredModelIds(root);
@@ -12325,7 +12374,7 @@ async function runReleaseSubjectCheck(argv) {
12325
12374
  }
12326
12375
 
12327
12376
  // src/scripts/check-skeleton-drift.ts
12328
- import { existsSync as existsSync41, readdirSync as readdirSync23 } from "fs";
12377
+ import { existsSync as existsSync42, readdirSync as readdirSync23 } from "fs";
12329
12378
  import { join as join49 } from "path";
12330
12379
  import { execa as execa17 } from "execa";
12331
12380
 
@@ -12453,7 +12502,7 @@ function discoverSkeletons(root) {
12453
12502
  } catch {
12454
12503
  return [];
12455
12504
  }
12456
- return entries.filter((name) => existsSync41(join49(skeletonsDir, name, ".github", "workflows", "ci.yml"))).sort();
12505
+ return entries.filter((name) => existsSync42(join49(skeletonsDir, name, ".github", "workflows", "ci.yml"))).sort();
12457
12506
  }
12458
12507
  async function runSkeletonDriftCheck() {
12459
12508
  const root = (await execa17("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
@@ -12462,7 +12511,7 @@ async function runSkeletonDriftCheck() {
12462
12511
  for (const name of skeletons) {
12463
12512
  const skeletonRoot = join49(root, "_skeletons", name);
12464
12513
  filesConsidered += findWorkflowFiles(skeletonRoot).length;
12465
- if (existsSync41(join49(skeletonRoot, "apps", "frontend", "src", "app", "layout.tsx"))) {
12514
+ if (existsSync42(join49(skeletonRoot, "apps", "frontend", "src", "app", "layout.tsx"))) {
12466
12515
  filesConsidered += 1;
12467
12516
  }
12468
12517
  }
@@ -12543,10 +12592,18 @@ checkCommand.command("plugin-tool-supply").description(
12543
12592
  await runPluginToolSupplyCheck();
12544
12593
  });
12545
12594
  checkCommand.command("core-direct-paths").description(
12546
- "Refuse a frontend's core-direct call site (bypassing its own BFF) naming a route prefix core does not register (#1377). Defaults to a self-check of the sibling skeleton against this repo's own services/api/src; --sibling/--frontend-src/--core-src point it at a real checked-out sibling instead"
12547
- ).option("--sibling <name>", "Label for the report").option("--frontend-src <dir>", "Sibling's frontend source directory to scan").option("--core-src <dir>", "Core API's source directory (ground truth for route prefixes)").action(async (opts) => {
12548
- await runCoreDirectPathsCheck(opts);
12549
- });
12595
+ "Refuse a frontend's core-direct call site (bypassing its own BFF) naming a route prefix core does not register (#1377). Defaults to a self-check of the sibling skeleton against this repo's own services/api/src; --sibling/--frontend-src plus either --estate (resolve the sibling's OWN core from its biffo.sibling.json) or --core-src (an explicit override) point it at a real checked-out sibling instead"
12596
+ ).option("--sibling <name>", "Label for the report").option("--frontend-src <dir>", "Sibling's frontend source directory to scan").option(
12597
+ "--estate <dir>",
12598
+ "Directory holding every cloned repo; resolves --sibling's OWN core from its biffo.sibling.json core_project field (ignored if --core-src is also given)"
12599
+ ).option(
12600
+ "--core-src <dir>",
12601
+ "Core API's source directory (ground truth for route prefixes) \u2014 explicit override, takes precedence over --estate resolution"
12602
+ ).action(
12603
+ async (opts) => {
12604
+ await runCoreDirectPathsCheck(opts);
12605
+ }
12606
+ );
12550
12607
  checkCommand.command("cognito-invite-template").description(
12551
12608
  "Refuse a Cognito invite_message_template missing a required member or placeholder (#356) \u2014 terraform validate is silent on this, so a fresh deploy fails on its first apply"
12552
12609
  ).action(async () => {
@@ -12586,7 +12643,7 @@ function rawArgsAfter(subcommand) {
12586
12643
  }
12587
12644
 
12588
12645
  // src/commands/doctor.ts
12589
- import { existsSync as existsSync42, readFileSync as readFileSync36 } from "fs";
12646
+ import { existsSync as existsSync43, readFileSync as readFileSync36 } from "fs";
12590
12647
  import { join as join50, resolve as resolve18 } from "path";
12591
12648
  import chalk21 from "chalk";
12592
12649
  import { Command as Command24 } from "commander";
@@ -12763,7 +12820,7 @@ async function runDoctor(options, deps = { git: new GitAdapter() }) {
12763
12820
  }
12764
12821
  function readLocalCoreVersion(cwd) {
12765
12822
  const path = join50(cwd, INSTANCE_CORE_FILE);
12766
- if (!existsSync42(path)) return null;
12823
+ if (!existsSync43(path)) return null;
12767
12824
  try {
12768
12825
  return parseCoreRecord(readFileSync36(path, "utf8"));
12769
12826
  } catch {
@@ -12781,7 +12838,7 @@ function parseCoreRecord(contents) {
12781
12838
  }
12782
12839
  function readFossil(cwd) {
12783
12840
  const path = join50(cwd, CORE_VERSION_FILE);
12784
- if (!existsSync42(path)) return null;
12841
+ if (!existsSync43(path)) return null;
12785
12842
  try {
12786
12843
  const value = readFileSync36(path, "utf8").trim();
12787
12844
  return value === "" ? null : value;
@@ -13232,13 +13289,13 @@ import { fileURLToPath as fileURLToPath6 } from "url";
13232
13289
  import { Command as Command26 } from "commander";
13233
13290
 
13234
13291
  // src/lib/packaged-scripts.ts
13235
- import { existsSync as existsSync43 } from "fs";
13292
+ import { existsSync as existsSync44 } from "fs";
13236
13293
  import { dirname as dirname10, join as join51 } from "path";
13237
13294
  function findPackagedScript(startDir, relativePath) {
13238
13295
  let dir = startDir;
13239
13296
  for (; ; ) {
13240
13297
  const candidate = join51(dir, relativePath);
13241
- if (existsSync43(candidate)) return candidate;
13298
+ if (existsSync44(candidate)) return candidate;
13242
13299
  const parent = dirname10(dir);
13243
13300
  if (parent === dir) return null;
13244
13301
  dir = parent;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@biffo/cli",
3
- "version": "0.267.5",
3
+ "version": "0.267.7",
4
4
  "description": "Biffo project scaffolding CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",