@biffo/cli 0.282.0 → 0.283.1
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 +56 -29
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7744,6 +7744,10 @@ var UserIngressSchema = z7.object({
|
|
|
7744
7744
|
required_group: z7.string().min(1, NON_EMPTY_GROUP),
|
|
7745
7745
|
app: z7.string().regex(APP_REF, "must be an ASGI app reference '<module>:<attr>', e.g. 'ideation.app:app'")
|
|
7746
7746
|
}).strict();
|
|
7747
|
+
var AdminIngressSchema = z7.object({
|
|
7748
|
+
required_group: z7.string().min(1, NON_EMPTY_GROUP),
|
|
7749
|
+
app: z7.string().regex(APP_REF, "must be an ASGI app reference '<module>:<attr>', e.g. 'ideation.admin:app'")
|
|
7750
|
+
}).strict();
|
|
7747
7751
|
var UserFrontendSchema = z7.object({
|
|
7748
7752
|
dir: z7.string().regex(
|
|
7749
7753
|
REL_DIR,
|
|
@@ -7788,9 +7792,10 @@ var PluginManifestSchema = z7.object({
|
|
|
7788
7792
|
// schema is the registry's, and this consumer only needs to count them.
|
|
7789
7793
|
event_subscriptions: z7.array(z7.object({ source: z7.string(), detail_type: z7.string() }).passthrough()).default([]),
|
|
7790
7794
|
required_core_version: z7.string().default(">=0.0.0"),
|
|
7791
|
-
// ADR-0018 user-facing surfaces. Optional: a plugin
|
|
7792
|
-
// ordinary (data/event/CRUD) plugin.
|
|
7795
|
+
// ADR-0018/0021 user-facing and admin-facing surfaces. Optional: a plugin
|
|
7796
|
+
// without them is an ordinary (data/event/CRUD) plugin.
|
|
7793
7797
|
user_ingress: UserIngressSchema.optional(),
|
|
7798
|
+
admin_ingress: AdminIngressSchema.optional(),
|
|
7794
7799
|
user_frontend: UserFrontendSchema.optional(),
|
|
7795
7800
|
// Tools the plugin's runtime exposes to an agentic worker (ADR-0014 §7,
|
|
7796
7801
|
// #569). Default empty — an ordinary plugin declares none. Parsing this
|
|
@@ -11230,8 +11235,8 @@ async function runOwnershipCheck(argv) {
|
|
|
11230
11235
|
const { stdout } = await execa12("git", ["diff", "--cached", "--name-status"], { cwd: root });
|
|
11231
11236
|
({ changed: changedFiles, deleted: deletedFiles } = parseNameStatus(stdout));
|
|
11232
11237
|
if (messageFile) {
|
|
11233
|
-
const { readFileSync: readFileSync41, existsSync:
|
|
11234
|
-
if (
|
|
11238
|
+
const { readFileSync: readFileSync41, existsSync: existsSync50 } = await import("fs");
|
|
11239
|
+
if (existsSync50(messageFile)) commitMessage = readFileSync41(messageFile, "utf8");
|
|
11235
11240
|
}
|
|
11236
11241
|
} else {
|
|
11237
11242
|
const base = process.env["GITHUB_BASE_REF"] ?? args[0];
|
|
@@ -11553,7 +11558,7 @@ import { readFileSync as readFileSync34 } from "fs";
|
|
|
11553
11558
|
import { join as join47 } from "path";
|
|
11554
11559
|
|
|
11555
11560
|
// src/lib/terraform-input-guard.ts
|
|
11556
|
-
import { readdirSync as readdirSync20, readFileSync as readFileSync33, statSync as statSync12 } from "fs";
|
|
11561
|
+
import { existsSync as existsSync41, readdirSync as readdirSync20, readFileSync as readFileSync33, statSync as statSync12 } from "fs";
|
|
11557
11562
|
import { join as join46 } from "path";
|
|
11558
11563
|
var GUARDED_SUBCOMMANDS = [
|
|
11559
11564
|
"init",
|
|
@@ -11567,8 +11572,27 @@ var IGNORED_SUBCOMMANDS = ["output", "state", "fmt", "validate", "version", "wor
|
|
|
11567
11572
|
function stripComments2(source) {
|
|
11568
11573
|
return source.split("\n").map((line) => line.replace(/(^|\s)#.*$/, "$1")).join("\n");
|
|
11569
11574
|
}
|
|
11575
|
+
function vendoredPluginServiceDirs(repoRoot) {
|
|
11576
|
+
const servicesDir = join46(repoRoot, "services");
|
|
11577
|
+
const result = /* @__PURE__ */ new Set();
|
|
11578
|
+
let entries;
|
|
11579
|
+
try {
|
|
11580
|
+
entries = readdirSync20(servicesDir);
|
|
11581
|
+
} catch {
|
|
11582
|
+
return result;
|
|
11583
|
+
}
|
|
11584
|
+
for (const entry of entries) {
|
|
11585
|
+
const full = join46(servicesDir, entry);
|
|
11586
|
+
if (!existsSync41(full) || !statSync12(full).isDirectory()) continue;
|
|
11587
|
+
if (existsSync41(join46(full, "biffo.plugin.json"))) {
|
|
11588
|
+
result.add(entry);
|
|
11589
|
+
}
|
|
11590
|
+
}
|
|
11591
|
+
return result;
|
|
11592
|
+
}
|
|
11570
11593
|
function findWorkflowFiles(repoRoot) {
|
|
11571
11594
|
const found = [];
|
|
11595
|
+
const vendoredPluginDirs = vendoredPluginServiceDirs(repoRoot);
|
|
11572
11596
|
const walk2 = (dir, relative10) => {
|
|
11573
11597
|
let entries;
|
|
11574
11598
|
try {
|
|
@@ -11578,6 +11602,9 @@ function findWorkflowFiles(repoRoot) {
|
|
|
11578
11602
|
}
|
|
11579
11603
|
for (const entry of entries) {
|
|
11580
11604
|
if (entry === "node_modules" || entry === ".git" || entry === ".worktrees") continue;
|
|
11605
|
+
if (entry === ".github" && relative10.startsWith("services/") && vendoredPluginDirs.has(relative10.slice("services/".length))) {
|
|
11606
|
+
continue;
|
|
11607
|
+
}
|
|
11581
11608
|
const full = join46(dir, entry);
|
|
11582
11609
|
const rel = relative10 ? `${relative10}/${entry}` : entry;
|
|
11583
11610
|
if (statSync12(full).isDirectory()) {
|
|
@@ -11985,17 +12012,17 @@ async function runPluginAllowlistConventionCheck() {
|
|
|
11985
12012
|
}
|
|
11986
12013
|
|
|
11987
12014
|
// src/scripts/check-plugin-collisions.ts
|
|
11988
|
-
import { existsSync as
|
|
12015
|
+
import { existsSync as existsSync43 } from "fs";
|
|
11989
12016
|
import { join as join51 } from "path";
|
|
11990
12017
|
import { execa as execa17 } from "execa";
|
|
11991
12018
|
|
|
11992
12019
|
// src/lib/plugin-collision-guard.ts
|
|
11993
|
-
import { existsSync as
|
|
12020
|
+
import { existsSync as existsSync42, readdirSync as readdirSync22, statSync as statSync13 } from "fs";
|
|
11994
12021
|
import { join as join50 } from "path";
|
|
11995
12022
|
var PYTEST_SPECIAL = /* @__PURE__ */ new Set(["conftest.py"]);
|
|
11996
12023
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([".venv", "node_modules", "__pycache__", ".git", "dist", "build"]);
|
|
11997
12024
|
function subdirectories(dir) {
|
|
11998
|
-
if (!
|
|
12025
|
+
if (!existsSync42(dir)) return [];
|
|
11999
12026
|
return readdirSync22(dir).filter((entry) => {
|
|
12000
12027
|
if (IGNORED_DIRS.has(entry) || entry.startsWith(".")) return false;
|
|
12001
12028
|
try {
|
|
@@ -12006,12 +12033,12 @@ function subdirectories(dir) {
|
|
|
12006
12033
|
});
|
|
12007
12034
|
}
|
|
12008
12035
|
function regularPackagesOf(pluginDir2) {
|
|
12009
|
-
return subdirectories(pluginDir2).filter((name) =>
|
|
12036
|
+
return subdirectories(pluginDir2).filter((name) => existsSync42(join50(pluginDir2, name, "__init__.py"))).sort();
|
|
12010
12037
|
}
|
|
12011
12038
|
function bareTestModulesOf(pluginDir2) {
|
|
12012
12039
|
const testsDir = join50(pluginDir2, "tests");
|
|
12013
|
-
if (!
|
|
12014
|
-
if (
|
|
12040
|
+
if (!existsSync42(testsDir)) return [];
|
|
12041
|
+
if (existsSync42(join50(testsDir, "__init__.py"))) return [];
|
|
12015
12042
|
return readdirSync22(testsDir).filter((f) => f.endsWith(".py") && !PYTEST_SPECIAL.has(f)).sort();
|
|
12016
12043
|
}
|
|
12017
12044
|
function findCollisions(servicesDir, pluginDirs) {
|
|
@@ -12059,7 +12086,7 @@ function formatCollisions(collisions) {
|
|
|
12059
12086
|
async function runPluginCollisionCheck() {
|
|
12060
12087
|
const root = (await execa17("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
12061
12088
|
const servicesDir = join51(root, "services");
|
|
12062
|
-
if (!
|
|
12089
|
+
if (!existsSync43(servicesDir)) {
|
|
12063
12090
|
console.log("\u2713 plugin collision guard: no services/ directory \u2014 nothing to compare");
|
|
12064
12091
|
return;
|
|
12065
12092
|
}
|
|
@@ -12079,7 +12106,7 @@ async function runPluginCollisionCheck() {
|
|
|
12079
12106
|
import { execa as execa18 } from "execa";
|
|
12080
12107
|
|
|
12081
12108
|
// src/lib/plugin-terraform-guard.ts
|
|
12082
|
-
import { existsSync as
|
|
12109
|
+
import { existsSync as existsSync44, readFileSync as readFileSync37, readdirSync as readdirSync23 } from "fs";
|
|
12083
12110
|
import { dirname as dirname10, join as join52, relative as relative9, sep as sep3 } from "path";
|
|
12084
12111
|
var SKIP_DIRS3 = /* @__PURE__ */ new Set(["node_modules", ".git", ".worktrees", "dist", ".venv", "__pycache__"]);
|
|
12085
12112
|
var PLUGIN_MANIFEST_FILE2 = "biffo.plugin.json";
|
|
@@ -12122,14 +12149,14 @@ function readSubscriptions(absManifestPath) {
|
|
|
12122
12149
|
}
|
|
12123
12150
|
function checkPluginTerraform(root) {
|
|
12124
12151
|
const violations = [];
|
|
12125
|
-
const coreManifest =
|
|
12152
|
+
const coreManifest = existsSync44(join52(root, CORE_MANIFEST_FILE)) ? readCoreManifest(root) : null;
|
|
12126
12153
|
for (const manifest of findPluginManifests(root)) {
|
|
12127
12154
|
if (coreManifest && !isTemplateOwned(manifest, coreManifest)) continue;
|
|
12128
12155
|
const absManifest = join52(root, manifest);
|
|
12129
12156
|
const subscriptions = readSubscriptions(absManifest);
|
|
12130
12157
|
if (subscriptions === null) continue;
|
|
12131
12158
|
const pluginDir2 = dirname10(absManifest);
|
|
12132
|
-
if (
|
|
12159
|
+
if (existsSync44(join52(pluginDir2, "terraform"))) continue;
|
|
12133
12160
|
const relPluginDir = relative9(root, pluginDir2).split(sep3).join("/");
|
|
12134
12161
|
violations.push({
|
|
12135
12162
|
manifest,
|
|
@@ -12160,12 +12187,12 @@ async function runPluginTerraformCheck() {
|
|
|
12160
12187
|
}
|
|
12161
12188
|
|
|
12162
12189
|
// src/scripts/check-plugin-tool-supply.ts
|
|
12163
|
-
import { existsSync as
|
|
12190
|
+
import { existsSync as existsSync46 } from "fs";
|
|
12164
12191
|
import { join as join54 } from "path";
|
|
12165
12192
|
import { execa as execa19 } from "execa";
|
|
12166
12193
|
|
|
12167
12194
|
// src/lib/plugin-tool-supply-audit.ts
|
|
12168
|
-
import { existsSync as
|
|
12195
|
+
import { existsSync as existsSync45, readFileSync as readFileSync38, readdirSync as readdirSync24, statSync as statSync14 } from "fs";
|
|
12169
12196
|
import { join as join53 } from "path";
|
|
12170
12197
|
|
|
12171
12198
|
// src/lib/openrouter-model-snapshot.ts
|
|
@@ -12899,8 +12926,8 @@ function auditDeclaredModelIds(repoRoot, options = {}) {
|
|
|
12899
12926
|
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
12900
12927
|
const configPath = join53(repoRoot, CONFIG_PY_PATH);
|
|
12901
12928
|
const orchestrationPath = join53(repoRoot, ORCHESTRATION_SCHEMA_PATH);
|
|
12902
|
-
const configMissing = !
|
|
12903
|
-
const orchestrationSchemaMissing = !
|
|
12929
|
+
const configMissing = !existsSync45(configPath);
|
|
12930
|
+
const orchestrationSchemaMissing = !existsSync45(orchestrationPath);
|
|
12904
12931
|
const knownSet = new Set(knownModelIds);
|
|
12905
12932
|
const snapshotEmpty = knownModelIds.length === 0;
|
|
12906
12933
|
const snapshotStale = isSnapshotStale(snapshotFetchedAt, now);
|
|
@@ -13117,7 +13144,7 @@ async function runPluginToolSupplyCheck() {
|
|
|
13117
13144
|
const root = (await execa19("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
13118
13145
|
let allOk = true;
|
|
13119
13146
|
const pluginsRoot = join54(root, "services", "_plugins");
|
|
13120
|
-
if (!
|
|
13147
|
+
if (!existsSync46(pluginsRoot)) {
|
|
13121
13148
|
console.log("\u2713 plugin tool-supply guard: no services/_plugins/ \u2014 nothing to audit");
|
|
13122
13149
|
} else {
|
|
13123
13150
|
const report = auditPluginToolSupply(pluginsRoot);
|
|
@@ -13148,7 +13175,7 @@ async function runPluginToolSupplyCheck() {
|
|
|
13148
13175
|
}
|
|
13149
13176
|
}
|
|
13150
13177
|
const servicesApiRoot = join54(root, "services", "api");
|
|
13151
|
-
if (!
|
|
13178
|
+
if (!existsSync46(servicesApiRoot)) {
|
|
13152
13179
|
console.log("\u2713 plugin model-id guard: no services/api/ \u2014 nothing to audit");
|
|
13153
13180
|
} else {
|
|
13154
13181
|
const modelReport = auditDeclaredModelIds(root);
|
|
@@ -13325,7 +13352,7 @@ async function runReleaseSubjectCheck(argv) {
|
|
|
13325
13352
|
}
|
|
13326
13353
|
|
|
13327
13354
|
// src/scripts/check-skeleton-drift.ts
|
|
13328
|
-
import { existsSync as
|
|
13355
|
+
import { existsSync as existsSync47, readdirSync as readdirSync26 } from "fs";
|
|
13329
13356
|
import { join as join56 } from "path";
|
|
13330
13357
|
import { execa as execa21 } from "execa";
|
|
13331
13358
|
|
|
@@ -13453,7 +13480,7 @@ function discoverSkeletons(root) {
|
|
|
13453
13480
|
} catch {
|
|
13454
13481
|
return [];
|
|
13455
13482
|
}
|
|
13456
|
-
return entries.filter((name) =>
|
|
13483
|
+
return entries.filter((name) => existsSync47(join56(skeletonsDir, name, ".github", "workflows", "ci.yml"))).sort();
|
|
13457
13484
|
}
|
|
13458
13485
|
async function runSkeletonDriftCheck() {
|
|
13459
13486
|
const root = (await execa21("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
@@ -13462,7 +13489,7 @@ async function runSkeletonDriftCheck() {
|
|
|
13462
13489
|
for (const name of skeletons) {
|
|
13463
13490
|
const skeletonRoot = join56(root, "_skeletons", name);
|
|
13464
13491
|
filesConsidered += findWorkflowFiles(skeletonRoot).length;
|
|
13465
|
-
if (
|
|
13492
|
+
if (existsSync47(join56(skeletonRoot, "apps", "frontend", "src", "app", "layout.tsx"))) {
|
|
13466
13493
|
filesConsidered += 1;
|
|
13467
13494
|
}
|
|
13468
13495
|
}
|
|
@@ -13614,7 +13641,7 @@ function rawArgsAfter(subcommand) {
|
|
|
13614
13641
|
}
|
|
13615
13642
|
|
|
13616
13643
|
// src/commands/doctor.ts
|
|
13617
|
-
import { existsSync as
|
|
13644
|
+
import { existsSync as existsSync48, readFileSync as readFileSync40 } from "fs";
|
|
13618
13645
|
import { join as join57, resolve as resolve20 } from "path";
|
|
13619
13646
|
import chalk21 from "chalk";
|
|
13620
13647
|
import { Command as Command25 } from "commander";
|
|
@@ -13795,7 +13822,7 @@ async function runDoctor(options, deps = { git: new GitAdapter() }) {
|
|
|
13795
13822
|
}
|
|
13796
13823
|
function readLocalCoreVersion(cwd) {
|
|
13797
13824
|
const path = join57(cwd, INSTANCE_CORE_FILE);
|
|
13798
|
-
if (!
|
|
13825
|
+
if (!existsSync48(path)) return null;
|
|
13799
13826
|
try {
|
|
13800
13827
|
return extractVersionField(readFileSync40(path, "utf8"));
|
|
13801
13828
|
} catch {
|
|
@@ -13818,7 +13845,7 @@ function extractVersionField(contents) {
|
|
|
13818
13845
|
}
|
|
13819
13846
|
function readFossil(cwd) {
|
|
13820
13847
|
const path = join57(cwd, CORE_VERSION_FILE);
|
|
13821
|
-
if (!
|
|
13848
|
+
if (!existsSync48(path)) return null;
|
|
13822
13849
|
try {
|
|
13823
13850
|
const value = readFileSync40(path, "utf8").trim();
|
|
13824
13851
|
return value === "" ? null : value;
|
|
@@ -14269,13 +14296,13 @@ import { fileURLToPath as fileURLToPath6 } from "url";
|
|
|
14269
14296
|
import { Command as Command27 } from "commander";
|
|
14270
14297
|
|
|
14271
14298
|
// src/lib/packaged-scripts.ts
|
|
14272
|
-
import { existsSync as
|
|
14299
|
+
import { existsSync as existsSync49 } from "fs";
|
|
14273
14300
|
import { dirname as dirname11, join as join58 } from "path";
|
|
14274
14301
|
function findPackagedScript(startDir, relativePath) {
|
|
14275
14302
|
let dir = startDir;
|
|
14276
14303
|
for (; ; ) {
|
|
14277
14304
|
const candidate = join58(dir, relativePath);
|
|
14278
|
-
if (
|
|
14305
|
+
if (existsSync49(candidate)) return candidate;
|
|
14279
14306
|
const parent = dirname11(dir);
|
|
14280
14307
|
if (parent === dir) return null;
|
|
14281
14308
|
dir = parent;
|