@biffo/cli 0.317.2 → 0.318.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 +310 -205
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command29 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/core.ts
|
|
7
7
|
import { Command as Command4 } from "commander";
|
|
@@ -1934,7 +1934,7 @@ var GitHubAdapter = class {
|
|
|
1934
1934
|
} catch (err) {
|
|
1935
1935
|
if (err.status !== 404) throw err;
|
|
1936
1936
|
}
|
|
1937
|
-
await new Promise((
|
|
1937
|
+
await new Promise((resolve22) => setTimeout(resolve22, intervalMs));
|
|
1938
1938
|
}
|
|
1939
1939
|
throw new Error(
|
|
1940
1940
|
`Branch "${branch}" not found in ${org}/${repo} after ${timeoutMs / 1e3}s \u2014 GitHub template generation may have stalled. Check the repository and re-run biffo init.`
|
|
@@ -1949,7 +1949,7 @@ var GitHubAdapter = class {
|
|
|
1949
1949
|
} catch (err) {
|
|
1950
1950
|
if (err.status !== 404) throw err;
|
|
1951
1951
|
}
|
|
1952
|
-
await new Promise((
|
|
1952
|
+
await new Promise((resolve22) => setTimeout(resolve22, intervalMs));
|
|
1953
1953
|
}
|
|
1954
1954
|
throw new Error(
|
|
1955
1955
|
`Ref "${ref}" not found in ${org}/${repo} after ${timeoutMs / 1e3}s \u2014 GitHub template generation may have stalled. Check the repository and re-run biffo init.`
|
|
@@ -2183,7 +2183,7 @@ var GitHubAdapter = class {
|
|
|
2183
2183
|
}
|
|
2184
2184
|
if (status !== 404 || Date.now() >= deadline) throw err;
|
|
2185
2185
|
log.info("Branch protection endpoint not yet ready, retrying...");
|
|
2186
|
-
await new Promise((
|
|
2186
|
+
await new Promise((resolve22) => setTimeout(resolve22, protectionIntervalMs));
|
|
2187
2187
|
}
|
|
2188
2188
|
}
|
|
2189
2189
|
}
|
|
@@ -2356,7 +2356,7 @@ var GitHubAdapter = class {
|
|
|
2356
2356
|
}
|
|
2357
2357
|
if (status !== 404 || Date.now() >= deadline) throw err;
|
|
2358
2358
|
log.info("Branch protection endpoint not yet ready, retrying...");
|
|
2359
|
-
await new Promise((
|
|
2359
|
+
await new Promise((resolve22) => setTimeout(resolve22, protectionIntervalMs));
|
|
2360
2360
|
}
|
|
2361
2361
|
}
|
|
2362
2362
|
} catch (err) {
|
|
@@ -2629,7 +2629,7 @@ var GitHubAdapter = class {
|
|
|
2629
2629
|
} catch (err) {
|
|
2630
2630
|
if (err.status !== 404 || Date.now() >= deadline) throw err;
|
|
2631
2631
|
log.info(`Workflow ${workflowId} not yet indexed by GitHub Actions, retrying...`);
|
|
2632
|
-
await new Promise((
|
|
2632
|
+
await new Promise((resolve22) => setTimeout(resolve22, intervalMs));
|
|
2633
2633
|
}
|
|
2634
2634
|
}
|
|
2635
2635
|
}
|
|
@@ -2648,7 +2648,7 @@ var GitHubAdapter = class {
|
|
|
2648
2648
|
} catch (err) {
|
|
2649
2649
|
if (err.status !== 404 || Date.now() >= deadline) throw err;
|
|
2650
2650
|
log.info(`Workflow ${workflowId} not yet indexed by GitHub Actions, retrying...`);
|
|
2651
|
-
await new Promise((
|
|
2651
|
+
await new Promise((resolve22) => setTimeout(resolve22, intervalMs));
|
|
2652
2652
|
}
|
|
2653
2653
|
}
|
|
2654
2654
|
}
|
|
@@ -2672,7 +2672,7 @@ var GitHubAdapter = class {
|
|
|
2672
2672
|
} else {
|
|
2673
2673
|
log.info(" Waiting for run to be queued...");
|
|
2674
2674
|
}
|
|
2675
|
-
await new Promise((
|
|
2675
|
+
await new Promise((resolve22) => setTimeout(resolve22, intervalMs));
|
|
2676
2676
|
}
|
|
2677
2677
|
throw new Error(
|
|
2678
2678
|
`Workflow ${workflowId} did not complete within ${timeoutMs / 1e3 / 60} minutes`
|
|
@@ -5031,7 +5031,7 @@ var AwsAdapter = class {
|
|
|
5031
5031
|
const code = err.Code;
|
|
5032
5032
|
if (code === "OperationAborted" && attempt < maxAttempts) {
|
|
5033
5033
|
log.info(` Waiting for S3 to release "${bucketName}"... (${attempt}/${maxAttempts})`);
|
|
5034
|
-
await new Promise((
|
|
5034
|
+
await new Promise((resolve22) => setTimeout(resolve22, retryDelayMs));
|
|
5035
5035
|
} else if (code === "OperationAborted") {
|
|
5036
5036
|
return false;
|
|
5037
5037
|
} else {
|
|
@@ -8295,7 +8295,7 @@ async function promptForConfig(awsAccountId, awsRegion, awsProfile) {
|
|
|
8295
8295
|
}
|
|
8296
8296
|
|
|
8297
8297
|
// src/commands/plugin.ts
|
|
8298
|
-
import { Command as
|
|
8298
|
+
import { Command as Command22 } from "commander";
|
|
8299
8299
|
|
|
8300
8300
|
// src/commands/plugin-create.ts
|
|
8301
8301
|
import { existsSync as existsSync27, readFileSync as readFileSync20, writeFileSync as writeFileSync9 } from "fs";
|
|
@@ -11233,8 +11233,132 @@ function printLocalDryRun(source, currentVersion, inTreeSource) {
|
|
|
11233
11233
|
`);
|
|
11234
11234
|
}
|
|
11235
11235
|
|
|
11236
|
+
// src/commands/plugin-verify.ts
|
|
11237
|
+
import { dirname as dirname11, resolve as resolve18 } from "path";
|
|
11238
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
11239
|
+
import { Command as Command21 } from "commander";
|
|
11240
|
+
|
|
11241
|
+
// src/lib/plugin-verify/command-runner.ts
|
|
11242
|
+
import { spawnSync } from "child_process";
|
|
11243
|
+
var RealCommandRunner = class {
|
|
11244
|
+
run(cmd, args, opts) {
|
|
11245
|
+
const result = spawnSync(cmd, args, {
|
|
11246
|
+
cwd: opts.cwd,
|
|
11247
|
+
// Progress/errors always go to the terminal so a human watching a local
|
|
11248
|
+
// run (or CI's own log) sees them as they happen; stdout is captured only
|
|
11249
|
+
// when the caller needs the value back (pg-test-db.sh's DSN) — capturing
|
|
11250
|
+
// it unconditionally would silence the conformance checks' own printed
|
|
11251
|
+
// denominators, which are the whole point of this feature (#1363's shape).
|
|
11252
|
+
stdio: ["ignore", opts.captureStdout ? "pipe" : "inherit", "inherit"],
|
|
11253
|
+
encoding: "utf8"
|
|
11254
|
+
});
|
|
11255
|
+
return { status: result.status, stdout: result.stdout ?? "" };
|
|
11256
|
+
}
|
|
11257
|
+
};
|
|
11258
|
+
|
|
11259
|
+
// src/lib/packaged-scripts.ts
|
|
11260
|
+
import { existsSync as existsSync38 } from "fs";
|
|
11261
|
+
import { dirname as dirname10, join as join40 } from "path";
|
|
11262
|
+
function findPackagedScript(startDir, relativePath) {
|
|
11263
|
+
let dir = startDir;
|
|
11264
|
+
for (; ; ) {
|
|
11265
|
+
const candidate = join40(dir, relativePath);
|
|
11266
|
+
if (existsSync38(candidate)) return candidate;
|
|
11267
|
+
const parent = dirname10(dir);
|
|
11268
|
+
if (parent === dir) return null;
|
|
11269
|
+
dir = parent;
|
|
11270
|
+
}
|
|
11271
|
+
}
|
|
11272
|
+
function packagedScriptMissing(relativePath) {
|
|
11273
|
+
return `biffo: cannot find ${relativePath}.
|
|
11274
|
+
It ships with this package via cli/scripts/packaged-root-assets.mjs; if you are running from a checkout, run from inside the template repo. If you are running the published package, this is a packaging bug \u2014 the asset was not copied at prepack.`;
|
|
11275
|
+
}
|
|
11276
|
+
|
|
11277
|
+
// src/lib/plugin-verify/conformance-driver.ts
|
|
11278
|
+
var CONFORMANCE_MODULE = "biffo_plugin_sdk.conformance";
|
|
11279
|
+
function uvRunPython(runner, cwd, args, captureStdout = false) {
|
|
11280
|
+
return runner.run(
|
|
11281
|
+
"uv",
|
|
11282
|
+
["run", "--no-sync", "--directory", cwd, "python", "-m", CONFORMANCE_MODULE, ...args],
|
|
11283
|
+
{ cwd, captureStdout }
|
|
11284
|
+
);
|
|
11285
|
+
}
|
|
11286
|
+
function listChecks(runner, cwd) {
|
|
11287
|
+
const { status } = uvRunPython(runner, cwd, ["list-checks"]);
|
|
11288
|
+
return status ?? 2;
|
|
11289
|
+
}
|
|
11290
|
+
function runChecksOnce(runner, cwd, dsn) {
|
|
11291
|
+
const { status } = uvRunPython(runner, cwd, ["run", "--repo-root", cwd, "--dsn", dsn]);
|
|
11292
|
+
return status ?? 2;
|
|
11293
|
+
}
|
|
11294
|
+
|
|
11295
|
+
// src/lib/plugin-verify/raise-postgres.ts
|
|
11296
|
+
function raisePostgres(runner, script, cwd) {
|
|
11297
|
+
const { status, stdout } = runner.run(script, [], { cwd, captureStdout: true });
|
|
11298
|
+
if (status !== 0) {
|
|
11299
|
+
return { dsn: null, status: status ?? 2 };
|
|
11300
|
+
}
|
|
11301
|
+
const dsn = stdout.trim();
|
|
11302
|
+
if (!dsn) {
|
|
11303
|
+
return { dsn: null, status: 1 };
|
|
11304
|
+
}
|
|
11305
|
+
return { dsn, status: 0 };
|
|
11306
|
+
}
|
|
11307
|
+
|
|
11308
|
+
// src/lib/plugin-verify/run-plugin-verify.ts
|
|
11309
|
+
var PG_TEST_DB_SCRIPT = "scripts/pg-test-db.sh";
|
|
11310
|
+
async function runPluginVerify(options, deps) {
|
|
11311
|
+
if (options.listChecks) {
|
|
11312
|
+
return listChecks(deps.runner, options.cwd);
|
|
11313
|
+
}
|
|
11314
|
+
const script = deps.findScript(PG_TEST_DB_SCRIPT);
|
|
11315
|
+
if (!script) {
|
|
11316
|
+
log.error(packagedScriptMissing(PG_TEST_DB_SCRIPT));
|
|
11317
|
+
return 2;
|
|
11318
|
+
}
|
|
11319
|
+
const raised = raisePostgres(deps.runner, script, options.cwd);
|
|
11320
|
+
if (!raised.dsn) {
|
|
11321
|
+
log.error(
|
|
11322
|
+
`plugin verify: could not provision the local Postgres test database (${PG_TEST_DB_SCRIPT} exited ${raised.status})`
|
|
11323
|
+
);
|
|
11324
|
+
return raised.status;
|
|
11325
|
+
}
|
|
11326
|
+
log.info("plugin verify: pass 1 of 2");
|
|
11327
|
+
const first = runChecksOnce(deps.runner, options.cwd, raised.dsn);
|
|
11328
|
+
if (first !== 0) {
|
|
11329
|
+
log.error("plugin verify: the first run failed -- see the check output above");
|
|
11330
|
+
return first;
|
|
11331
|
+
}
|
|
11332
|
+
log.info("plugin verify: pass 2 of 2 (re-runability against the same database)");
|
|
11333
|
+
const second = runChecksOnce(deps.runner, options.cwd, raised.dsn);
|
|
11334
|
+
if (second !== 0) {
|
|
11335
|
+
log.error(
|
|
11336
|
+
"plugin verify: a second consecutive run against the same database failed -- a check that is not re-runnable fails the job (biffo-template#1924)"
|
|
11337
|
+
);
|
|
11338
|
+
return second;
|
|
11339
|
+
}
|
|
11340
|
+
log.success("plugin verify: green twice against the same database");
|
|
11341
|
+
return 0;
|
|
11342
|
+
}
|
|
11343
|
+
|
|
11344
|
+
// src/commands/plugin-verify.ts
|
|
11345
|
+
var pluginVerifyCommand = new Command21("verify").description(
|
|
11346
|
+
"Real-execution conformance harness for a plugin repo: raises a real Postgres, runs every implemented biffo_plugin_sdk.conformance check twice against it, and exits non-zero on the first failure (biffo-template#1523/#1924)."
|
|
11347
|
+
).option("--cwd <path>", "Plugin repo root to check (defaults to the current directory)").option("--list-checks", "Print every declared #1523 seam and its implemented state, then exit").action(async (options) => {
|
|
11348
|
+
const cwd = options.cwd ? resolve18(options.cwd) : process.cwd();
|
|
11349
|
+
const here = dirname11(fileURLToPath6(import.meta.url));
|
|
11350
|
+
const exitCode = await runPluginVerify(
|
|
11351
|
+
{ cwd, listChecks: options.listChecks ?? false },
|
|
11352
|
+
{
|
|
11353
|
+
runner: new RealCommandRunner(),
|
|
11354
|
+
findScript: (relativePath) => findPackagedScript(here, relativePath)
|
|
11355
|
+
}
|
|
11356
|
+
);
|
|
11357
|
+
process.exit(exitCode);
|
|
11358
|
+
});
|
|
11359
|
+
|
|
11236
11360
|
// src/commands/plugin.ts
|
|
11237
|
-
var pluginCommand = new
|
|
11361
|
+
var pluginCommand = new Command22("plugin").description("Manage Biffo plugins");
|
|
11238
11362
|
pluginCommand.addCommand(pluginCreateCommand);
|
|
11239
11363
|
pluginCommand.addCommand(pluginListCommand);
|
|
11240
11364
|
pluginCommand.addCommand(pluginInstallCommand);
|
|
@@ -11243,15 +11367,16 @@ pluginCommand.addCommand(pluginUpgradeCommand);
|
|
|
11243
11367
|
pluginCommand.addCommand(pluginSyncMigrationsCommand);
|
|
11244
11368
|
pluginCommand.addCommand(pluginInfoCommand);
|
|
11245
11369
|
pluginCommand.addCommand(pluginStalenessCommand);
|
|
11370
|
+
pluginCommand.addCommand(pluginVerifyCommand);
|
|
11246
11371
|
|
|
11247
11372
|
// src/commands/sibling.ts
|
|
11248
|
-
import { Command as
|
|
11373
|
+
import { Command as Command24 } from "commander";
|
|
11249
11374
|
|
|
11250
11375
|
// src/commands/sibling-check-identity.ts
|
|
11251
|
-
import { existsSync as
|
|
11252
|
-
import { resolve as
|
|
11376
|
+
import { existsSync as existsSync39, readFileSync as readFileSync29 } from "fs";
|
|
11377
|
+
import { resolve as resolve19 } from "path";
|
|
11253
11378
|
import chalk20 from "chalk";
|
|
11254
|
-
import { Command as
|
|
11379
|
+
import { Command as Command23 } from "commander";
|
|
11255
11380
|
|
|
11256
11381
|
// src/lib/sibling-identity-check.ts
|
|
11257
11382
|
function checkSiblingIdentity(envs) {
|
|
@@ -11303,7 +11428,7 @@ function checkSiblingIdentity(envs) {
|
|
|
11303
11428
|
// src/commands/sibling-check-identity.ts
|
|
11304
11429
|
var VALID_ENVIRONMENTS2 = ["dev", "staging", "prod"];
|
|
11305
11430
|
var SIBLING_CORE_POOL_VAR = "CORE_COGNITO_USER_POOL_ID";
|
|
11306
|
-
var siblingCheckIdentityCommand = new
|
|
11431
|
+
var siblingCheckIdentityCommand = new Command23("check-identity").description(
|
|
11307
11432
|
"Detect when a core's Cognito pool has drifted from its published identity document or any sibling's baked-in CORE_COGNITO_USER_POOL_ID (#400). Run from the core repo; exits non-zero on drift so a scheduled/CI run goes red."
|
|
11308
11433
|
).option("--env <environment>", "Only check this environment (default: dev, staging, prod)").option("-p, --project <name>", "Project name (overrides biffo.config.json in current directory)").option("-c, --config <path>", "Path to biffo.config.json").action(async (options) => {
|
|
11309
11434
|
if (options.env && !VALID_ENVIRONMENTS2.includes(options.env)) {
|
|
@@ -11442,7 +11567,7 @@ async function fetchPublishedIdentity(portalUrl) {
|
|
|
11442
11567
|
}
|
|
11443
11568
|
async function resolveConfig4(options) {
|
|
11444
11569
|
if (options.config) {
|
|
11445
|
-
const raw = JSON.parse(readFileSync29(
|
|
11570
|
+
const raw = JSON.parse(readFileSync29(resolve19(options.config), "utf8"));
|
|
11446
11571
|
const result = BiffoConfigSchema.safeParse(raw);
|
|
11447
11572
|
if (!result.success) {
|
|
11448
11573
|
log.error(`Invalid config at ${options.config}:`);
|
|
@@ -11461,8 +11586,8 @@ async function resolveConfig4(options) {
|
|
|
11461
11586
|
}
|
|
11462
11587
|
return cfg;
|
|
11463
11588
|
}
|
|
11464
|
-
const localConfigPath =
|
|
11465
|
-
if (
|
|
11589
|
+
const localConfigPath = resolve19(process.cwd(), "biffo.config.json");
|
|
11590
|
+
if (existsSync39(localConfigPath)) {
|
|
11466
11591
|
const raw = JSON.parse(readFileSync29(localConfigPath, "utf8"));
|
|
11467
11592
|
const result = BiffoConfigSchema.safeParse(raw);
|
|
11468
11593
|
if (result.success) return result.data;
|
|
@@ -11499,28 +11624,28 @@ async function resolveConfig4(options) {
|
|
|
11499
11624
|
}
|
|
11500
11625
|
|
|
11501
11626
|
// src/commands/sibling.ts
|
|
11502
|
-
var siblingCommand = new
|
|
11627
|
+
var siblingCommand = new Command24("sibling").description(
|
|
11503
11628
|
"Create and manage sibling apps that share a Biffo core project (ADR-0007)"
|
|
11504
11629
|
);
|
|
11505
11630
|
siblingCommand.addCommand(siblingCreateCommand);
|
|
11506
11631
|
siblingCommand.addCommand(siblingCheckIdentityCommand);
|
|
11507
11632
|
|
|
11508
11633
|
// src/commands/check.ts
|
|
11509
|
-
import { Command as
|
|
11634
|
+
import { Command as Command25 } from "commander";
|
|
11510
11635
|
|
|
11511
11636
|
// src/scripts/check-adr-numbering.ts
|
|
11512
|
-
import { existsSync as
|
|
11513
|
-
import { join as
|
|
11637
|
+
import { existsSync as existsSync41 } from "fs";
|
|
11638
|
+
import { join as join42 } from "path";
|
|
11514
11639
|
|
|
11515
11640
|
// src/lib/adr-numbering-guard.ts
|
|
11516
|
-
import { existsSync as
|
|
11517
|
-
import { join as
|
|
11641
|
+
import { existsSync as existsSync40, readdirSync as readdirSync15, readFileSync as readFileSync30 } from "fs";
|
|
11642
|
+
import { join as join41 } from "path";
|
|
11518
11643
|
var ADR_FILENAME = /^(\d{4})-.+\.md$/;
|
|
11519
11644
|
var ALLOWLIST_FILENAME = ".numbering-allowlist";
|
|
11520
11645
|
var TEMPLATE_ADR_RESERVED_UPTO = "0099";
|
|
11521
11646
|
function readAdrNumberingAllowlist(adrDir) {
|
|
11522
|
-
const path =
|
|
11523
|
-
if (!
|
|
11647
|
+
const path = join41(adrDir, ALLOWLIST_FILENAME);
|
|
11648
|
+
if (!existsSync40(path)) return /* @__PURE__ */ new Set();
|
|
11524
11649
|
const numbers = /* @__PURE__ */ new Set();
|
|
11525
11650
|
for (const rawLine of readFileSync30(path, "utf8").split("\n")) {
|
|
11526
11651
|
const line = rawLine.split("#")[0].trim();
|
|
@@ -11530,7 +11655,7 @@ function readAdrNumberingAllowlist(adrDir) {
|
|
|
11530
11655
|
}
|
|
11531
11656
|
function adrNumbersIn(adrDir) {
|
|
11532
11657
|
const claims = /* @__PURE__ */ new Map();
|
|
11533
|
-
if (!
|
|
11658
|
+
if (!existsSync40(adrDir)) return claims;
|
|
11534
11659
|
for (const entry of readdirSync15(adrDir).sort()) {
|
|
11535
11660
|
const match = ADR_FILENAME.exec(entry);
|
|
11536
11661
|
if (!match) continue;
|
|
@@ -11585,8 +11710,8 @@ function formatAdrReservedRangeViolations(violations, reservedUpTo = TEMPLATE_AD
|
|
|
11585
11710
|
// src/scripts/check-adr-numbering.ts
|
|
11586
11711
|
async function runAdrNumberingCheck() {
|
|
11587
11712
|
const root = (await execa("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
11588
|
-
const adrDir =
|
|
11589
|
-
if (!
|
|
11713
|
+
const adrDir = join42(root, "docs", "ADR");
|
|
11714
|
+
if (!existsSync41(adrDir)) {
|
|
11590
11715
|
console.log("\u2713 ADR numbering guard: no docs/ADR/ directory \u2014 nothing to compare");
|
|
11591
11716
|
return;
|
|
11592
11717
|
}
|
|
@@ -11625,7 +11750,7 @@ Already accepted? List it in docs/ADR/${ALLOWLIST_FILENAME} instead of leaving t
|
|
|
11625
11750
|
|
|
11626
11751
|
// src/lib/api-gateway-integration-guard.ts
|
|
11627
11752
|
import { readFileSync as readFileSync31, readdirSync as readdirSync16, statSync as statSync9 } from "fs";
|
|
11628
|
-
import { join as
|
|
11753
|
+
import { join as join43 } from "path";
|
|
11629
11754
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", ".terraform", ".worktrees", "dist"]);
|
|
11630
11755
|
var MODULE_TYPE = "module";
|
|
11631
11756
|
var INTEGRATION_TYPE = "aws_apigatewayv2_integration";
|
|
@@ -11707,7 +11832,7 @@ function walkTerraformFiles(root) {
|
|
|
11707
11832
|
return;
|
|
11708
11833
|
}
|
|
11709
11834
|
for (const entry of entries) {
|
|
11710
|
-
const p =
|
|
11835
|
+
const p = join43(dir, entry);
|
|
11711
11836
|
let st;
|
|
11712
11837
|
try {
|
|
11713
11838
|
st = statSync9(p);
|
|
@@ -12123,17 +12248,17 @@ async function runBranchProtectionCheck(explicitRepo, options = {}) {
|
|
|
12123
12248
|
}
|
|
12124
12249
|
|
|
12125
12250
|
// src/lib/claim-invocation-parity.ts
|
|
12126
|
-
import { existsSync as
|
|
12127
|
-
import { join as
|
|
12251
|
+
import { existsSync as existsSync42, readFileSync as readFileSync32, readdirSync as readdirSync17 } from "fs";
|
|
12252
|
+
import { join as join44 } from "path";
|
|
12128
12253
|
function distributedAgentsDocs(root) {
|
|
12129
12254
|
const docs = [];
|
|
12130
|
-
const own =
|
|
12131
|
-
if (
|
|
12132
|
-
const skeletons =
|
|
12133
|
-
if (
|
|
12255
|
+
const own = join44(root, "AGENTS.md");
|
|
12256
|
+
if (existsSync42(own)) docs.push({ path: "AGENTS.md", text: readFileSync32(own, "utf8") });
|
|
12257
|
+
const skeletons = join44(root, "_skeletons");
|
|
12258
|
+
if (existsSync42(skeletons)) {
|
|
12134
12259
|
for (const name of readdirSync17(skeletons).sort()) {
|
|
12135
|
-
const abs =
|
|
12136
|
-
if (!
|
|
12260
|
+
const abs = join44(skeletons, name, "AGENTS.md");
|
|
12261
|
+
if (!existsSync42(abs)) continue;
|
|
12137
12262
|
docs.push({ path: `_skeletons/${name}/AGENTS.md`, text: readFileSync32(abs, "utf8") });
|
|
12138
12263
|
}
|
|
12139
12264
|
}
|
|
@@ -12266,12 +12391,12 @@ async function runClaimInvocationCheck() {
|
|
|
12266
12391
|
}
|
|
12267
12392
|
|
|
12268
12393
|
// src/scripts/check-codeql-suppression.ts
|
|
12269
|
-
import { existsSync as
|
|
12270
|
-
import { join as
|
|
12394
|
+
import { existsSync as existsSync43 } from "fs";
|
|
12395
|
+
import { join as join46, relative as relative8 } from "path";
|
|
12271
12396
|
|
|
12272
12397
|
// src/lib/codeql-suppression-guard.ts
|
|
12273
12398
|
import { readdirSync as readdirSync18, readFileSync as readFileSync33, statSync as statSync10 } from "fs";
|
|
12274
|
-
import { join as
|
|
12399
|
+
import { join as join45 } from "path";
|
|
12275
12400
|
var SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
12276
12401
|
".git",
|
|
12277
12402
|
".worktrees",
|
|
@@ -12302,7 +12427,7 @@ function walkSourceFiles(root) {
|
|
|
12302
12427
|
return;
|
|
12303
12428
|
}
|
|
12304
12429
|
for (const entry of entries) {
|
|
12305
|
-
const p =
|
|
12430
|
+
const p = join45(dir, entry);
|
|
12306
12431
|
let st;
|
|
12307
12432
|
try {
|
|
12308
12433
|
st = statSync10(p);
|
|
@@ -12339,8 +12464,8 @@ function sweepCodeqlSuppressionComments(root) {
|
|
|
12339
12464
|
// src/scripts/check-codeql-suppression.ts
|
|
12340
12465
|
async function runCodeqlSuppressionCheck() {
|
|
12341
12466
|
const root = (await execa("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
12342
|
-
const scanRoot =
|
|
12343
|
-
if (!
|
|
12467
|
+
const scanRoot = join46(root, "cli", "src");
|
|
12468
|
+
if (!existsSync43(scanRoot)) {
|
|
12344
12469
|
console.log(
|
|
12345
12470
|
"\u2014 codeql-suppression guard: skipped \u2014 no cli/src in this repo, so there is no CLI source to scan."
|
|
12346
12471
|
);
|
|
@@ -12364,12 +12489,12 @@ async function runCodeqlSuppressionCheck() {
|
|
|
12364
12489
|
}
|
|
12365
12490
|
|
|
12366
12491
|
// src/scripts/check-cognito-invite-template.ts
|
|
12367
|
-
import { existsSync as
|
|
12368
|
-
import { join as
|
|
12492
|
+
import { existsSync as existsSync44 } from "fs";
|
|
12493
|
+
import { join as join48 } from "path";
|
|
12369
12494
|
|
|
12370
12495
|
// src/lib/cognito-invite-template-guard.ts
|
|
12371
12496
|
import { readdirSync as readdirSync19, readFileSync as readFileSync34, statSync as statSync11 } from "fs";
|
|
12372
|
-
import { join as
|
|
12497
|
+
import { join as join47 } from "path";
|
|
12373
12498
|
var REQUIRED_INVITE_MEMBERS = ["email_subject", "email_message", "sms_message"];
|
|
12374
12499
|
var REQUIRED_INVITE_PLACEHOLDERS = ["{username}", "{####}"];
|
|
12375
12500
|
var PLACEHOLDER_MEMBERS = ["email_message", "sms_message"];
|
|
@@ -12453,7 +12578,7 @@ function findModuleTerraformFiles(repoRoot) {
|
|
|
12453
12578
|
for (const entry of entries) {
|
|
12454
12579
|
if (entry === "node_modules" || entry === ".git" || entry === ".worktrees" || entry === ".venv")
|
|
12455
12580
|
continue;
|
|
12456
|
-
const full =
|
|
12581
|
+
const full = join47(dir, entry);
|
|
12457
12582
|
const rel = `${relative11}/${entry}`;
|
|
12458
12583
|
let isDir;
|
|
12459
12584
|
try {
|
|
@@ -12468,12 +12593,12 @@ function findModuleTerraformFiles(repoRoot) {
|
|
|
12468
12593
|
}
|
|
12469
12594
|
}
|
|
12470
12595
|
};
|
|
12471
|
-
walk2(
|
|
12596
|
+
walk2(join47(repoRoot, "modules"), "modules");
|
|
12472
12597
|
return found.sort();
|
|
12473
12598
|
}
|
|
12474
12599
|
function checkCognitoInviteTemplates(repoRoot) {
|
|
12475
12600
|
return findModuleTerraformFiles(repoRoot).flatMap(
|
|
12476
|
-
(file) => checkInviteTemplateSource(file, readFileSync34(
|
|
12601
|
+
(file) => checkInviteTemplateSource(file, readFileSync34(join47(repoRoot, file), "utf8"))
|
|
12477
12602
|
);
|
|
12478
12603
|
}
|
|
12479
12604
|
|
|
@@ -12483,7 +12608,7 @@ async function runCognitoInviteTemplateCheck() {
|
|
|
12483
12608
|
const files = findModuleTerraformFiles(root);
|
|
12484
12609
|
console.log(`audited ${files.length} .tf file(s) under modules/ under ${root}`);
|
|
12485
12610
|
if (files.length === 0) {
|
|
12486
|
-
if (!
|
|
12611
|
+
if (!existsSync44(join48(root, "modules"))) {
|
|
12487
12612
|
console.log(
|
|
12488
12613
|
`\xB7 Cognito invite template guard: not applicable \u2014 no modules/ directory under ${root} \u2014 this is not a template/instance tree (a satellite repo never carries the template-owned Terraform modules). Skipping.`
|
|
12489
12614
|
);
|
|
@@ -12507,11 +12632,11 @@ async function runCognitoInviteTemplateCheck() {
|
|
|
12507
12632
|
}
|
|
12508
12633
|
|
|
12509
12634
|
// src/scripts/check-core-direct-paths.ts
|
|
12510
|
-
import { join as
|
|
12635
|
+
import { join as join50 } from "path";
|
|
12511
12636
|
|
|
12512
12637
|
// src/lib/core-direct-paths-audit.ts
|
|
12513
|
-
import { existsSync as
|
|
12514
|
-
import { join as
|
|
12638
|
+
import { existsSync as existsSync45, readFileSync as readFileSync35, readdirSync as readdirSync20, statSync as statSync12 } from "fs";
|
|
12639
|
+
import { join as join49 } from "path";
|
|
12515
12640
|
var EXTERNAL_BASE_IDENTIFIERS = ["CORE_API_URL"];
|
|
12516
12641
|
var API_ROUTE_PREFIX = "/api/v1";
|
|
12517
12642
|
var TEST_FILE_SUFFIXES = [".test.ts", ".test.tsx", ".spec.ts", ".spec.tsx"];
|
|
@@ -12675,7 +12800,7 @@ function walkFiles(root, accept, skipDir) {
|
|
|
12675
12800
|
return;
|
|
12676
12801
|
}
|
|
12677
12802
|
for (const entry of entries) {
|
|
12678
|
-
const p =
|
|
12803
|
+
const p = join49(dir, entry);
|
|
12679
12804
|
let st;
|
|
12680
12805
|
try {
|
|
12681
12806
|
st = statSync12(p);
|
|
@@ -12770,7 +12895,7 @@ function pathMatchesAnyCorePrefix(normalized, corePrefixes, apiRoutePrefix = API
|
|
|
12770
12895
|
}
|
|
12771
12896
|
function resolveSiblingCoreSrc(params) {
|
|
12772
12897
|
const { estateDir, sibling } = params;
|
|
12773
|
-
const configPath =
|
|
12898
|
+
const configPath = join49(estateDir, sibling, "biffo.sibling.json");
|
|
12774
12899
|
let raw;
|
|
12775
12900
|
try {
|
|
12776
12901
|
raw = readFileSync35(configPath, "utf8");
|
|
@@ -12793,8 +12918,8 @@ function resolveSiblingCoreSrc(params) {
|
|
|
12793
12918
|
`cannot resolve ${sibling}'s core: ${configPath} has no non-empty "core_project" field.`
|
|
12794
12919
|
);
|
|
12795
12920
|
}
|
|
12796
|
-
const coreApiSrcDir =
|
|
12797
|
-
if (!
|
|
12921
|
+
const coreApiSrcDir = join49(estateDir, coreProject, "services", "api", "src");
|
|
12922
|
+
if (!existsSync45(coreApiSrcDir)) {
|
|
12798
12923
|
throw new Error(
|
|
12799
12924
|
`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.`
|
|
12800
12925
|
);
|
|
@@ -12847,7 +12972,7 @@ async function runCoreDirectPathsCheck(opts = {}) {
|
|
|
12847
12972
|
}
|
|
12848
12973
|
}
|
|
12849
12974
|
const sibling = opts.sibling ?? "sibling-template (self-check)";
|
|
12850
|
-
const frontendSrcDir = opts.frontendSrc ??
|
|
12975
|
+
const frontendSrcDir = opts.frontendSrc ?? join50(root, "_skeletons", "sibling-template", "apps", "frontend", "src");
|
|
12851
12976
|
let coreApiSrcDir;
|
|
12852
12977
|
let coreProject = null;
|
|
12853
12978
|
if (opts.coreSrc) {
|
|
@@ -12863,7 +12988,7 @@ async function runCoreDirectPathsCheck(opts = {}) {
|
|
|
12863
12988
|
coreApiSrcDir = resolution.coreApiSrcDir;
|
|
12864
12989
|
coreProject = resolution.coreProject;
|
|
12865
12990
|
} else {
|
|
12866
|
-
coreApiSrcDir =
|
|
12991
|
+
coreApiSrcDir = join50(root, "services", "api", "src");
|
|
12867
12992
|
}
|
|
12868
12993
|
const report = auditSiblingCoreDirectPaths({ sibling, frontendSrcDir, coreApiSrcDir });
|
|
12869
12994
|
console.log(
|
|
@@ -13114,16 +13239,16 @@ ${BOLD}If the divergence is deliberate${OFF}
|
|
|
13114
13239
|
}
|
|
13115
13240
|
|
|
13116
13241
|
// src/scripts/check-distribution-inventory.ts
|
|
13117
|
-
import { existsSync as
|
|
13118
|
-
import { join as
|
|
13242
|
+
import { existsSync as existsSync47 } from "fs";
|
|
13243
|
+
import { join as join52 } from "path";
|
|
13119
13244
|
|
|
13120
13245
|
// src/lib/distribution-inventory.ts
|
|
13121
|
-
import { existsSync as
|
|
13122
|
-
import { join as
|
|
13246
|
+
import { existsSync as existsSync46, readFileSync as readFileSync36 } from "fs";
|
|
13247
|
+
import { join as join51 } from "path";
|
|
13123
13248
|
var INVENTORY_FILENAME = "distribution-inventory.json";
|
|
13124
13249
|
function loadDistributionInventory(root) {
|
|
13125
|
-
const path =
|
|
13126
|
-
if (!
|
|
13250
|
+
const path = join51(root, INVENTORY_FILENAME);
|
|
13251
|
+
if (!existsSync46(path)) {
|
|
13127
13252
|
throw new Error(
|
|
13128
13253
|
`${INVENTORY_FILENAME} not found at ${root} -- expected it beside core-manifest.json`
|
|
13129
13254
|
);
|
|
@@ -13288,7 +13413,7 @@ async function runDistributionInventoryCheck(root) {
|
|
|
13288
13413
|
);
|
|
13289
13414
|
return;
|
|
13290
13415
|
}
|
|
13291
|
-
if (!
|
|
13416
|
+
if (!existsSync47(join52(repoRoot, INVENTORY_FILENAME))) {
|
|
13292
13417
|
console.log(
|
|
13293
13418
|
`\u2713 distribution-inventory: skipped \u2014 no ${INVENTORY_FILENAME} at ${repoRoot}. This is a template-only registry; a checkout that legitimately has none has nothing for this guard to check.`
|
|
13294
13419
|
);
|
|
@@ -13314,7 +13439,7 @@ async function runDistributionInventoryCheck(root) {
|
|
|
13314
13439
|
}
|
|
13315
13440
|
|
|
13316
13441
|
// src/scripts/check-distribution-remote-state.ts
|
|
13317
|
-
import { join as
|
|
13442
|
+
import { join as join53 } from "path";
|
|
13318
13443
|
async function ghExecCommand(file, args) {
|
|
13319
13444
|
const result = await execa(file, args, { reject: false });
|
|
13320
13445
|
return { stdout: String(result.stdout ?? ""), exitCode: result.exitCode ?? null };
|
|
@@ -13329,7 +13454,7 @@ async function runDistributionRemoteStateCheck(root) {
|
|
|
13329
13454
|
}
|
|
13330
13455
|
}
|
|
13331
13456
|
console.log(
|
|
13332
|
-
`distribution-remote-state: examined ${assertions.length} remote content assertion(s) declared across ${inventory.entries.length} inventory entries (${
|
|
13457
|
+
`distribution-remote-state: examined ${assertions.length} remote content assertion(s) declared across ${inventory.entries.length} inventory entries (${join53(repoRoot, "distribution-inventory.json")})`
|
|
13333
13458
|
);
|
|
13334
13459
|
if (assertions.length === 0) {
|
|
13335
13460
|
console.log("\u2713 distribution-remote-state: nothing declared to check");
|
|
@@ -13375,7 +13500,7 @@ ${assertion.ref}`;
|
|
|
13375
13500
|
|
|
13376
13501
|
// src/lib/eventbridge-log-permission-guard.ts
|
|
13377
13502
|
import { readFileSync as readFileSync37, readdirSync as readdirSync21, statSync as statSync13 } from "fs";
|
|
13378
|
-
import { join as
|
|
13503
|
+
import { join as join54 } from "path";
|
|
13379
13504
|
var SKIP_DIRS3 = /* @__PURE__ */ new Set(["node_modules", ".git", ".terraform", ".worktrees", "dist"]);
|
|
13380
13505
|
var EVENT_TARGET_TYPE = "aws_cloudwatch_event_target";
|
|
13381
13506
|
var LOG_RESOURCE_POLICY_TYPE = "aws_cloudwatch_log_resource_policy";
|
|
@@ -13452,7 +13577,7 @@ function walkTerraformFiles2(root) {
|
|
|
13452
13577
|
return;
|
|
13453
13578
|
}
|
|
13454
13579
|
for (const entry of entries) {
|
|
13455
|
-
const p =
|
|
13580
|
+
const p = join54(dir, entry);
|
|
13456
13581
|
let st;
|
|
13457
13582
|
try {
|
|
13458
13583
|
st = statSync13(p);
|
|
@@ -13592,8 +13717,8 @@ async function runEventBridgeLogPermissionCheck() {
|
|
|
13592
13717
|
}
|
|
13593
13718
|
|
|
13594
13719
|
// src/scripts/check-instance-adoption.ts
|
|
13595
|
-
import { existsSync as
|
|
13596
|
-
import { join as
|
|
13720
|
+
import { existsSync as existsSync48 } from "fs";
|
|
13721
|
+
import { join as join55 } from "path";
|
|
13597
13722
|
async function runInstanceAdoptionCheck(opts = {}) {
|
|
13598
13723
|
if (!opts.instanceDir) {
|
|
13599
13724
|
console.error(
|
|
@@ -13601,7 +13726,7 @@ async function runInstanceAdoptionCheck(opts = {}) {
|
|
|
13601
13726
|
);
|
|
13602
13727
|
process.exit(2);
|
|
13603
13728
|
}
|
|
13604
|
-
if (!
|
|
13729
|
+
if (!existsSync48(opts.instanceDir)) {
|
|
13605
13730
|
console.error(
|
|
13606
13731
|
`\u2717 instance-adoption guard: --instance-dir ${opts.instanceDir} does not exist \u2014 cannot tell whether it is adopted, and that is not the same as a clean pass.`
|
|
13607
13732
|
);
|
|
@@ -13609,7 +13734,7 @@ async function runInstanceAdoptionCheck(opts = {}) {
|
|
|
13609
13734
|
}
|
|
13610
13735
|
const root = (await execa("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
13611
13736
|
const theirsDir = opts.theirsDir ?? root;
|
|
13612
|
-
const instanceLabel = opts.instance ??
|
|
13737
|
+
const instanceLabel = opts.instance ?? join55(opts.instanceDir).split("/").filter(Boolean).pop();
|
|
13613
13738
|
const report = checkInstanceAdoption(theirsDir, opts.instanceDir);
|
|
13614
13739
|
console.log(
|
|
13615
13740
|
`examined ${report.examinedInstances} instance (${instanceLabel}) against ${report.registeredPairs} registered pair(s), ${report.applicablePairs} applicable to this instance, against template tree ${theirsDir}`
|
|
@@ -13632,11 +13757,11 @@ async function runInstanceAdoptionCheck(opts = {}) {
|
|
|
13632
13757
|
|
|
13633
13758
|
// src/lib/lambda-output-guard.ts
|
|
13634
13759
|
import { readFileSync as readFileSync39 } from "fs";
|
|
13635
|
-
import { join as
|
|
13760
|
+
import { join as join57 } from "path";
|
|
13636
13761
|
|
|
13637
13762
|
// src/lib/terraform-input-guard.ts
|
|
13638
|
-
import { existsSync as
|
|
13639
|
-
import { join as
|
|
13763
|
+
import { existsSync as existsSync49, readdirSync as readdirSync22, readFileSync as readFileSync38, statSync as statSync14 } from "fs";
|
|
13764
|
+
import { join as join56 } from "path";
|
|
13640
13765
|
var GUARDED_SUBCOMMANDS = [
|
|
13641
13766
|
"init",
|
|
13642
13767
|
"plan",
|
|
@@ -13650,7 +13775,7 @@ function stripComments2(source) {
|
|
|
13650
13775
|
return source.split("\n").map((line) => line.replace(/(^|\s)#.*$/, "$1")).join("\n");
|
|
13651
13776
|
}
|
|
13652
13777
|
function vendoredPluginServiceDirs(repoRoot) {
|
|
13653
|
-
const servicesDir =
|
|
13778
|
+
const servicesDir = join56(repoRoot, "services");
|
|
13654
13779
|
const result = /* @__PURE__ */ new Set();
|
|
13655
13780
|
let entries;
|
|
13656
13781
|
try {
|
|
@@ -13659,9 +13784,9 @@ function vendoredPluginServiceDirs(repoRoot) {
|
|
|
13659
13784
|
return result;
|
|
13660
13785
|
}
|
|
13661
13786
|
for (const entry of entries) {
|
|
13662
|
-
const full =
|
|
13663
|
-
if (!
|
|
13664
|
-
if (
|
|
13787
|
+
const full = join56(servicesDir, entry);
|
|
13788
|
+
if (!existsSync49(full) || !statSync14(full).isDirectory()) continue;
|
|
13789
|
+
if (existsSync49(join56(full, "biffo.plugin.json"))) {
|
|
13665
13790
|
result.add(entry);
|
|
13666
13791
|
}
|
|
13667
13792
|
}
|
|
@@ -13683,7 +13808,7 @@ function findWorkflowFiles(repoRoot) {
|
|
|
13683
13808
|
if (entry === ".github" && relative11.startsWith("services/") && vendoredPluginDirs.has(relative11.slice("services/".length))) {
|
|
13684
13809
|
continue;
|
|
13685
13810
|
}
|
|
13686
|
-
const full =
|
|
13811
|
+
const full = join56(dir, entry);
|
|
13687
13812
|
const rel = relative11 ? `${relative11}/${entry}` : entry;
|
|
13688
13813
|
let isDir;
|
|
13689
13814
|
try {
|
|
@@ -13733,7 +13858,7 @@ function checkWorkflowSource(file, rawSource) {
|
|
|
13733
13858
|
}
|
|
13734
13859
|
function checkTerraformInput(repoRoot) {
|
|
13735
13860
|
return findWorkflowFiles(repoRoot).flatMap(
|
|
13736
|
-
(file) => checkWorkflowSource(file, readFileSync38(
|
|
13861
|
+
(file) => checkWorkflowSource(file, readFileSync38(join56(repoRoot, file), "utf8"))
|
|
13737
13862
|
);
|
|
13738
13863
|
}
|
|
13739
13864
|
|
|
@@ -13791,7 +13916,7 @@ function checkWorkflowSource2(file, rawSource) {
|
|
|
13791
13916
|
}
|
|
13792
13917
|
function checkLambdaOutput(repoRoot) {
|
|
13793
13918
|
return findWorkflowFiles(repoRoot).flatMap(
|
|
13794
|
-
(file) => checkWorkflowSource2(file, readFileSync39(
|
|
13919
|
+
(file) => checkWorkflowSource2(file, readFileSync39(join57(repoRoot, file), "utf8"))
|
|
13795
13920
|
);
|
|
13796
13921
|
}
|
|
13797
13922
|
|
|
@@ -13819,8 +13944,8 @@ async function runLambdaOutputCheck() {
|
|
|
13819
13944
|
}
|
|
13820
13945
|
|
|
13821
13946
|
// src/scripts/check-migration-body-change.ts
|
|
13822
|
-
import { existsSync as
|
|
13823
|
-
import { join as
|
|
13947
|
+
import { existsSync as existsSync50 } from "fs";
|
|
13948
|
+
import { join as join58 } from "path";
|
|
13824
13949
|
|
|
13825
13950
|
// src/lib/migration-body-change-guard.ts
|
|
13826
13951
|
function checkMigrationBodyChangeMarkers(diffs) {
|
|
@@ -13902,7 +14027,7 @@ async function runMigrationBodyChangeCheck(argv) {
|
|
|
13902
14027
|
);
|
|
13903
14028
|
return;
|
|
13904
14029
|
}
|
|
13905
|
-
if (!
|
|
14030
|
+
if (!existsSync50(join58(root, MIGRATIONS_VERSIONS_DIR))) {
|
|
13906
14031
|
console.log(`\u2713 migration body-change guard: no ${MIGRATIONS_VERSIONS_DIR} in this repo.`);
|
|
13907
14032
|
return;
|
|
13908
14033
|
}
|
|
@@ -14008,8 +14133,8 @@ ${BOLD2}What to do${OFF2}
|
|
|
14008
14133
|
}
|
|
14009
14134
|
|
|
14010
14135
|
// src/scripts/check-orphan-ratchet.ts
|
|
14011
|
-
import { existsSync as
|
|
14012
|
-
import { basename as basename3, join as
|
|
14136
|
+
import { existsSync as existsSync51 } from "fs";
|
|
14137
|
+
import { basename as basename3, join as join59 } from "path";
|
|
14013
14138
|
function reportOrphan(entry, manifest) {
|
|
14014
14139
|
console.error(` ${entry.path}`);
|
|
14015
14140
|
const { templateOwnedMatch, nearestUserOwnedEntries } = explainOwnership(entry.path, manifest);
|
|
@@ -14031,7 +14156,7 @@ function reportOrphan(entry, manifest) {
|
|
|
14031
14156
|
}
|
|
14032
14157
|
}
|
|
14033
14158
|
async function runOrphanRatchetCheck(opts = {}) {
|
|
14034
|
-
if (opts.instanceDir !== void 0 && !
|
|
14159
|
+
if (opts.instanceDir !== void 0 && !existsSync51(opts.instanceDir)) {
|
|
14035
14160
|
console.error(
|
|
14036
14161
|
`\u2717 orphan-ratchet guard: --instance-dir ${opts.instanceDir} does not exist \u2014 cannot tell whether it carries unsanctioned files, and that is not the same as a clean pass.`
|
|
14037
14162
|
);
|
|
@@ -14048,7 +14173,7 @@ async function runOrphanRatchetCheck(opts = {}) {
|
|
|
14048
14173
|
"self-check mode: --instance-dir was not given, so it defaulted to --theirs-dir (this repo's own root) alongside --base-dir \u2014 all three trees are the same, so this run can only ever find zero orphans by construction. See this script's doc comment. Pass a real instance tree with --instance-dir for a check that can actually find something. biffo-template#1714."
|
|
14049
14174
|
);
|
|
14050
14175
|
}
|
|
14051
|
-
if (!
|
|
14176
|
+
if (!existsSync51(join59(theirsDir, CORE_MANIFEST_FILE))) {
|
|
14052
14177
|
console.log(
|
|
14053
14178
|
`orphan-ratchet guard (${label}): no ${CORE_MANIFEST_FILE} in ${theirsDir} \u2014 this is not a Biffo template/instance tree (a satellite repo never carries one), so there is no ownership manifest to classify paths against. Not applicable; skipping.`
|
|
14054
14179
|
);
|
|
@@ -14080,7 +14205,7 @@ baseline was ${String(ratchet.baseline)}, now ${String(ratchet.count)}. See biff
|
|
|
14080
14205
|
|
|
14081
14206
|
// src/lib/ownership-header-claim-guard.ts
|
|
14082
14207
|
import { readFileSync as readFileSync40 } from "fs";
|
|
14083
|
-
import { join as
|
|
14208
|
+
import { join as join60 } from "path";
|
|
14084
14209
|
var OWNERSHIP_HEADER_SWEEP_DIRS = [
|
|
14085
14210
|
"scripts",
|
|
14086
14211
|
".githooks",
|
|
@@ -14289,7 +14414,7 @@ function sweepOwnershipHeaderClaims(root, options = {}) {
|
|
|
14289
14414
|
for (const rel of files) {
|
|
14290
14415
|
let content;
|
|
14291
14416
|
try {
|
|
14292
|
-
content = readFileSync40(
|
|
14417
|
+
content = readFileSync40(join60(root, rel), "utf8");
|
|
14293
14418
|
} catch {
|
|
14294
14419
|
continue;
|
|
14295
14420
|
}
|
|
@@ -14365,7 +14490,7 @@ async function runOwnershipHeaderClaimCheck() {
|
|
|
14365
14490
|
|
|
14366
14491
|
// src/scripts/check-pipe-trap.ts
|
|
14367
14492
|
import { readFileSync as readFileSync41, readdirSync as readdirSync23 } from "fs";
|
|
14368
|
-
import { join as
|
|
14493
|
+
import { join as join61, relative as relative9 } from "path";
|
|
14369
14494
|
|
|
14370
14495
|
// src/lib/pipe-trap-guard.ts
|
|
14371
14496
|
var STATUS_BEARING = [
|
|
@@ -14461,7 +14586,7 @@ function findPipeTraps(source) {
|
|
|
14461
14586
|
function shellFiles(root) {
|
|
14462
14587
|
const out = [];
|
|
14463
14588
|
for (const dir of ["scripts", ".githooks"]) {
|
|
14464
|
-
const full =
|
|
14589
|
+
const full = join61(root, dir);
|
|
14465
14590
|
let entries;
|
|
14466
14591
|
try {
|
|
14467
14592
|
entries = readdirSync23(full, { withFileTypes: true });
|
|
@@ -14471,7 +14596,7 @@ function shellFiles(root) {
|
|
|
14471
14596
|
for (const entry of entries) {
|
|
14472
14597
|
if (!entry.isFile()) continue;
|
|
14473
14598
|
if (dir === "scripts" && !entry.name.endsWith(".sh")) continue;
|
|
14474
|
-
out.push(
|
|
14599
|
+
out.push(join61(full, entry.name));
|
|
14475
14600
|
}
|
|
14476
14601
|
}
|
|
14477
14602
|
return out;
|
|
@@ -14505,7 +14630,7 @@ async function runPipeTrapCheck() {
|
|
|
14505
14630
|
|
|
14506
14631
|
// src/lib/plugin-allowlist-convention.ts
|
|
14507
14632
|
import { readFileSync as readFileSync42 } from "fs";
|
|
14508
|
-
import { join as
|
|
14633
|
+
import { join as join62 } from "path";
|
|
14509
14634
|
var COMPUTE_MAIN_TF = "modules/cloud/aws/compute/main.tf";
|
|
14510
14635
|
var PLUGIN_TEMPLATE_MAIN_TF = "modules/plugins/_template/main.tf";
|
|
14511
14636
|
var ALLOWLIST_MAIN_TF = "modules/cloud/aws/plugin-allowlist/main.tf";
|
|
@@ -14516,7 +14641,7 @@ var PLUGIN = "<plugin>";
|
|
|
14516
14641
|
var ACCOUNT = "<account>";
|
|
14517
14642
|
function read(repoRoot, relative11) {
|
|
14518
14643
|
try {
|
|
14519
|
-
return readFileSync42(
|
|
14644
|
+
return readFileSync42(join62(repoRoot, relative11), "utf8");
|
|
14520
14645
|
} catch {
|
|
14521
14646
|
throw new Error(`plugin-allowlist drift guard: cannot read ${relative11}`);
|
|
14522
14647
|
}
|
|
@@ -14525,7 +14650,7 @@ function assignedString(source, name) {
|
|
|
14525
14650
|
const match = new RegExp(`^\\s*${name}\\s*=\\s*"((?:[^"\\\\]|\\\\.)*)"\\s*$`, "m").exec(source);
|
|
14526
14651
|
return match?.[1];
|
|
14527
14652
|
}
|
|
14528
|
-
function
|
|
14653
|
+
function resolve20(expression, bindings) {
|
|
14529
14654
|
let current = expression;
|
|
14530
14655
|
for (let pass = 0; pass < 10; pass += 1) {
|
|
14531
14656
|
const next = current.replace(/\$\{([^}]+)\}/g, (whole, ref) => {
|
|
@@ -14562,13 +14687,13 @@ function composeExpectedRoleName(repoRoot) {
|
|
|
14562
14687
|
"var.project_name": PROJECT,
|
|
14563
14688
|
"var.environment": ENV,
|
|
14564
14689
|
"var.plugin_name": PLUGIN,
|
|
14565
|
-
"var.function_name":
|
|
14690
|
+
"var.function_name": resolve20(pluginFunctionName, {
|
|
14566
14691
|
"var.plugin_name": PLUGIN
|
|
14567
14692
|
})
|
|
14568
14693
|
};
|
|
14569
|
-
bindings["local.name_prefix"] =
|
|
14570
|
-
bindings["local.function_name"] =
|
|
14571
|
-
return
|
|
14694
|
+
bindings["local.name_prefix"] = resolve20(namePrefix, bindings);
|
|
14695
|
+
bindings["local.function_name"] = resolve20(functionName, bindings);
|
|
14696
|
+
return resolve20(roleName, bindings);
|
|
14572
14697
|
}
|
|
14573
14698
|
function readAllowlistGlob(repoRoot) {
|
|
14574
14699
|
const allowlist = read(repoRoot, ALLOWLIST_MAIN_TF);
|
|
@@ -14578,7 +14703,7 @@ function readAllowlistGlob(repoRoot) {
|
|
|
14578
14703
|
`plugin-allowlist drift guard: could not find the "for name in var.enabled_plugins" glob in ${ALLOWLIST_MAIN_TF}.`
|
|
14579
14704
|
);
|
|
14580
14705
|
}
|
|
14581
|
-
return
|
|
14706
|
+
return resolve20(glob, {
|
|
14582
14707
|
"data.aws_caller_identity.current.account_id": ACCOUNT,
|
|
14583
14708
|
"var.project_name": PROJECT,
|
|
14584
14709
|
"var.environment": ENV,
|
|
@@ -14644,32 +14769,32 @@ async function runPluginAllowlistConventionCheck() {
|
|
|
14644
14769
|
}
|
|
14645
14770
|
|
|
14646
14771
|
// src/scripts/check-plugin-collisions.ts
|
|
14647
|
-
import { existsSync as
|
|
14648
|
-
import { join as
|
|
14772
|
+
import { existsSync as existsSync53 } from "fs";
|
|
14773
|
+
import { join as join64 } from "path";
|
|
14649
14774
|
|
|
14650
14775
|
// src/lib/plugin-collision-guard.ts
|
|
14651
|
-
import { existsSync as
|
|
14652
|
-
import { join as
|
|
14776
|
+
import { existsSync as existsSync52, readdirSync as readdirSync24, statSync as statSync15 } from "fs";
|
|
14777
|
+
import { join as join63 } from "path";
|
|
14653
14778
|
var PYTEST_SPECIAL = /* @__PURE__ */ new Set(["conftest.py"]);
|
|
14654
14779
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([".venv", "node_modules", "__pycache__", ".git", "dist", "build"]);
|
|
14655
14780
|
function subdirectories(dir) {
|
|
14656
|
-
if (!
|
|
14781
|
+
if (!existsSync52(dir)) return [];
|
|
14657
14782
|
return readdirSync24(dir).filter((entry) => {
|
|
14658
14783
|
if (IGNORED_DIRS.has(entry) || entry.startsWith(".")) return false;
|
|
14659
14784
|
try {
|
|
14660
|
-
return statSync15(
|
|
14785
|
+
return statSync15(join63(dir, entry)).isDirectory();
|
|
14661
14786
|
} catch {
|
|
14662
14787
|
return false;
|
|
14663
14788
|
}
|
|
14664
14789
|
});
|
|
14665
14790
|
}
|
|
14666
14791
|
function regularPackagesOf(pluginDir2) {
|
|
14667
|
-
return subdirectories(pluginDir2).filter((name) =>
|
|
14792
|
+
return subdirectories(pluginDir2).filter((name) => existsSync52(join63(pluginDir2, name, "__init__.py"))).sort();
|
|
14668
14793
|
}
|
|
14669
14794
|
function bareTestModulesOf(pluginDir2) {
|
|
14670
|
-
const testsDir =
|
|
14671
|
-
if (!
|
|
14672
|
-
if (
|
|
14795
|
+
const testsDir = join63(pluginDir2, "tests");
|
|
14796
|
+
if (!existsSync52(testsDir)) return [];
|
|
14797
|
+
if (existsSync52(join63(testsDir, "__init__.py"))) return [];
|
|
14673
14798
|
return readdirSync24(testsDir).filter((f) => f.endsWith(".py") && !PYTEST_SPECIAL.has(f)).sort();
|
|
14674
14799
|
}
|
|
14675
14800
|
function findCollisions(servicesDir, pluginDirs) {
|
|
@@ -14678,7 +14803,7 @@ function findCollisions(servicesDir, pluginDirs) {
|
|
|
14678
14803
|
const gather = (kind, namesOf) => {
|
|
14679
14804
|
const claims = /* @__PURE__ */ new Map();
|
|
14680
14805
|
for (const plugin of plugins) {
|
|
14681
|
-
for (const name of namesOf(
|
|
14806
|
+
for (const name of namesOf(join63(servicesDir, plugin))) {
|
|
14682
14807
|
claims.set(name, [...claims.get(name) ?? [], plugin]);
|
|
14683
14808
|
}
|
|
14684
14809
|
}
|
|
@@ -14716,8 +14841,8 @@ function formatCollisions(collisions) {
|
|
|
14716
14841
|
// src/scripts/check-plugin-collisions.ts
|
|
14717
14842
|
async function runPluginCollisionCheck() {
|
|
14718
14843
|
const root = (await execa("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
14719
|
-
const servicesDir =
|
|
14720
|
-
if (!
|
|
14844
|
+
const servicesDir = join64(root, "services");
|
|
14845
|
+
if (!existsSync53(servicesDir)) {
|
|
14721
14846
|
console.log("\u2713 plugin collision guard: no services/ directory \u2014 nothing to compare");
|
|
14722
14847
|
return;
|
|
14723
14848
|
}
|
|
@@ -14734,8 +14859,8 @@ async function runPluginCollisionCheck() {
|
|
|
14734
14859
|
}
|
|
14735
14860
|
|
|
14736
14861
|
// src/lib/plugin-terraform-guard.ts
|
|
14737
|
-
import { existsSync as
|
|
14738
|
-
import { dirname as
|
|
14862
|
+
import { existsSync as existsSync54, readFileSync as readFileSync43, readdirSync as readdirSync25 } from "fs";
|
|
14863
|
+
import { dirname as dirname12, join as join65, relative as relative10, sep as sep4 } from "path";
|
|
14739
14864
|
var SKIP_DIRS4 = /* @__PURE__ */ new Set(["node_modules", ".git", ".worktrees", "dist", ".venv", "__pycache__"]);
|
|
14740
14865
|
var PLUGIN_MANIFEST_FILE2 = "biffo.plugin.json";
|
|
14741
14866
|
function findPluginManifests(root) {
|
|
@@ -14750,9 +14875,9 @@ function findPluginManifests(root) {
|
|
|
14750
14875
|
for (const entry of entries) {
|
|
14751
14876
|
if (entry.isDirectory()) {
|
|
14752
14877
|
if (SKIP_DIRS4.has(entry.name)) continue;
|
|
14753
|
-
walk2(
|
|
14878
|
+
walk2(join65(dir, entry.name));
|
|
14754
14879
|
} else if (entry.isFile() && entry.name === PLUGIN_MANIFEST_FILE2) {
|
|
14755
|
-
found.push(relative10(root,
|
|
14880
|
+
found.push(relative10(root, join65(dir, entry.name)).split(sep4).join("/"));
|
|
14756
14881
|
}
|
|
14757
14882
|
}
|
|
14758
14883
|
};
|
|
@@ -14777,14 +14902,14 @@ function readSubscriptions(absManifestPath) {
|
|
|
14777
14902
|
}
|
|
14778
14903
|
function checkPluginTerraform(root) {
|
|
14779
14904
|
const violations = [];
|
|
14780
|
-
const coreManifest =
|
|
14905
|
+
const coreManifest = existsSync54(join65(root, CORE_MANIFEST_FILE)) ? readCoreManifest(root) : null;
|
|
14781
14906
|
for (const manifest of findPluginManifests(root)) {
|
|
14782
14907
|
if (coreManifest && !isTemplateOwned(manifest, coreManifest)) continue;
|
|
14783
|
-
const absManifest =
|
|
14908
|
+
const absManifest = join65(root, manifest);
|
|
14784
14909
|
const subscriptions = readSubscriptions(absManifest);
|
|
14785
14910
|
if (subscriptions === null) continue;
|
|
14786
|
-
const pluginDir2 =
|
|
14787
|
-
if (
|
|
14911
|
+
const pluginDir2 = dirname12(absManifest);
|
|
14912
|
+
if (existsSync54(join65(pluginDir2, "terraform"))) continue;
|
|
14788
14913
|
const relPluginDir = relative10(root, pluginDir2).split(sep4).join("/");
|
|
14789
14914
|
violations.push({
|
|
14790
14915
|
manifest,
|
|
@@ -14815,12 +14940,12 @@ async function runPluginTerraformCheck() {
|
|
|
14815
14940
|
}
|
|
14816
14941
|
|
|
14817
14942
|
// src/scripts/check-plugin-tool-supply.ts
|
|
14818
|
-
import { existsSync as
|
|
14819
|
-
import { join as
|
|
14943
|
+
import { existsSync as existsSync56 } from "fs";
|
|
14944
|
+
import { join as join67 } from "path";
|
|
14820
14945
|
|
|
14821
14946
|
// src/lib/plugin-tool-supply-audit.ts
|
|
14822
|
-
import { existsSync as
|
|
14823
|
-
import { join as
|
|
14947
|
+
import { existsSync as existsSync55, readFileSync as readFileSync44, readdirSync as readdirSync26, statSync as statSync16 } from "fs";
|
|
14948
|
+
import { join as join66 } from "path";
|
|
14824
14949
|
|
|
14825
14950
|
// src/lib/openrouter-model-snapshot.ts
|
|
14826
14951
|
var OPENROUTER_MODEL_SNAPSHOT_FETCHED_AT = "2026-08-10T06:39:01Z";
|
|
@@ -15237,7 +15362,7 @@ function listDirs(root) {
|
|
|
15237
15362
|
}
|
|
15238
15363
|
return entries.filter((e) => {
|
|
15239
15364
|
try {
|
|
15240
|
-
return statSync16(
|
|
15365
|
+
return statSync16(join66(root, e)).isDirectory();
|
|
15241
15366
|
} catch {
|
|
15242
15367
|
return false;
|
|
15243
15368
|
}
|
|
@@ -15253,7 +15378,7 @@ function walkFiles2(root, accept, skipDir) {
|
|
|
15253
15378
|
return;
|
|
15254
15379
|
}
|
|
15255
15380
|
for (const entry of entries) {
|
|
15256
|
-
const p =
|
|
15381
|
+
const p = join66(dir, entry);
|
|
15257
15382
|
let st;
|
|
15258
15383
|
try {
|
|
15259
15384
|
st = statSync16(p);
|
|
@@ -15279,14 +15404,14 @@ function pluginPythonFiles(pluginDir2) {
|
|
|
15279
15404
|
);
|
|
15280
15405
|
}
|
|
15281
15406
|
function pluginTerraformFiles(pluginDir2) {
|
|
15282
|
-
const tfDir =
|
|
15407
|
+
const tfDir = join66(pluginDir2, "terraform");
|
|
15283
15408
|
let entries;
|
|
15284
15409
|
try {
|
|
15285
15410
|
entries = readdirSync26(tfDir);
|
|
15286
15411
|
} catch {
|
|
15287
15412
|
return [];
|
|
15288
15413
|
}
|
|
15289
|
-
return entries.filter((e) => e.endsWith(".tf")).map((e) =>
|
|
15414
|
+
return entries.filter((e) => e.endsWith(".tf")).map((e) => join66(tfDir, e)).sort();
|
|
15290
15415
|
}
|
|
15291
15416
|
function extractManifestTools(manifestText) {
|
|
15292
15417
|
let parsed;
|
|
@@ -15538,8 +15663,8 @@ function isSnapshotStale(fetchedAt, now) {
|
|
|
15538
15663
|
function normalizeModelId(id) {
|
|
15539
15664
|
return id.endsWith(":online") ? id.slice(0, -":online".length) : id;
|
|
15540
15665
|
}
|
|
15541
|
-
var CONFIG_PY_PATH =
|
|
15542
|
-
var ORCHESTRATION_SCHEMA_PATH =
|
|
15666
|
+
var CONFIG_PY_PATH = join66("services", "api", "src", "api", "config.py");
|
|
15667
|
+
var ORCHESTRATION_SCHEMA_PATH = join66(
|
|
15543
15668
|
"services",
|
|
15544
15669
|
"api",
|
|
15545
15670
|
"src",
|
|
@@ -15551,10 +15676,10 @@ function auditDeclaredModelIds(repoRoot, options = {}) {
|
|
|
15551
15676
|
const knownModelIds = options.knownModelIds ?? OPENROUTER_MODEL_IDS;
|
|
15552
15677
|
const snapshotFetchedAt = options.snapshotFetchedAt ?? OPENROUTER_MODEL_SNAPSHOT_FETCHED_AT;
|
|
15553
15678
|
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
15554
|
-
const configPath =
|
|
15555
|
-
const orchestrationPath =
|
|
15556
|
-
const configMissing = !
|
|
15557
|
-
const orchestrationSchemaMissing = !
|
|
15679
|
+
const configPath = join66(repoRoot, CONFIG_PY_PATH);
|
|
15680
|
+
const orchestrationPath = join66(repoRoot, ORCHESTRATION_SCHEMA_PATH);
|
|
15681
|
+
const configMissing = !existsSync55(configPath);
|
|
15682
|
+
const orchestrationSchemaMissing = !existsSync55(orchestrationPath);
|
|
15558
15683
|
const knownSet = new Set(knownModelIds);
|
|
15559
15684
|
const snapshotEmpty = knownModelIds.length === 0;
|
|
15560
15685
|
const snapshotStale = isSnapshotStale(snapshotFetchedAt, now);
|
|
@@ -15625,7 +15750,7 @@ function auditDeclaredModelIds(repoRoot, options = {}) {
|
|
|
15625
15750
|
function discoverPluginDirs(pluginsRoot) {
|
|
15626
15751
|
return listDirs(pluginsRoot).filter((name) => {
|
|
15627
15752
|
try {
|
|
15628
|
-
return statSync16(
|
|
15753
|
+
return statSync16(join66(pluginsRoot, name, "biffo.plugin.json")).isFile();
|
|
15629
15754
|
} catch {
|
|
15630
15755
|
return false;
|
|
15631
15756
|
}
|
|
@@ -15638,8 +15763,8 @@ function auditPluginToolSupply(pluginsRoot) {
|
|
|
15638
15763
|
let terraformBlind = false;
|
|
15639
15764
|
let totalDeclaredTools = 0;
|
|
15640
15765
|
for (const name of pluginNames) {
|
|
15641
|
-
const pluginDir2 =
|
|
15642
|
-
const manifestText = readFileSync44(
|
|
15766
|
+
const pluginDir2 = join66(pluginsRoot, name);
|
|
15767
|
+
const manifestText = readFileSync44(join66(pluginDir2, "biffo.plugin.json"), "utf8");
|
|
15643
15768
|
const manifest = extractManifestTools(manifestText);
|
|
15644
15769
|
if (manifest.parseError) {
|
|
15645
15770
|
findings.push({
|
|
@@ -15737,7 +15862,7 @@ function auditPluginToolSupply(pluginsRoot) {
|
|
|
15737
15862
|
requiredEnvVars: envResult.envVars,
|
|
15738
15863
|
missingEnvVars: anyWired ? [] : envResult.envVars,
|
|
15739
15864
|
status: anyWired ? "ok" : "missing-env",
|
|
15740
|
-
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 ${
|
|
15865
|
+
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 ${join66(pluginDir2, "terraform")}, so this deployment can never supply it`
|
|
15741
15866
|
});
|
|
15742
15867
|
}
|
|
15743
15868
|
}
|
|
@@ -15777,8 +15902,8 @@ async function runPluginToolSupplyCheck() {
|
|
|
15777
15902
|
return;
|
|
15778
15903
|
}
|
|
15779
15904
|
let allOk = true;
|
|
15780
|
-
const pluginsRoot =
|
|
15781
|
-
if (!
|
|
15905
|
+
const pluginsRoot = join67(root, "services", "_plugins");
|
|
15906
|
+
if (!existsSync56(pluginsRoot)) {
|
|
15782
15907
|
console.log("\u2713 plugin tool-supply guard: no services/_plugins/ \u2014 nothing to audit");
|
|
15783
15908
|
} else {
|
|
15784
15909
|
const report = auditPluginToolSupply(pluginsRoot);
|
|
@@ -15808,8 +15933,8 @@ async function runPluginToolSupplyCheck() {
|
|
|
15808
15933
|
console.log(`\u2713 plugin tool-supply guard: ${report.summary}`);
|
|
15809
15934
|
}
|
|
15810
15935
|
}
|
|
15811
|
-
const servicesApiRoot =
|
|
15812
|
-
if (!
|
|
15936
|
+
const servicesApiRoot = join67(root, "services", "api");
|
|
15937
|
+
if (!existsSync56(servicesApiRoot)) {
|
|
15813
15938
|
console.log("\u2713 plugin model-id guard: no services/api/ \u2014 nothing to audit");
|
|
15814
15939
|
} else {
|
|
15815
15940
|
const modelReport = auditDeclaredModelIds(root);
|
|
@@ -16186,12 +16311,12 @@ async function runSharedFileReductionCheck(args) {
|
|
|
16186
16311
|
}
|
|
16187
16312
|
|
|
16188
16313
|
// src/scripts/check-skeleton-drift.ts
|
|
16189
|
-
import { existsSync as
|
|
16190
|
-
import { join as
|
|
16314
|
+
import { existsSync as existsSync57, readdirSync as readdirSync28 } from "fs";
|
|
16315
|
+
import { join as join69 } from "path";
|
|
16191
16316
|
|
|
16192
16317
|
// src/lib/skeleton-drift-guard.ts
|
|
16193
16318
|
import { readFileSync as readFileSync47, readdirSync as readdirSync27, statSync as statSync17 } from "fs";
|
|
16194
|
-
import { join as
|
|
16319
|
+
import { join as join68 } from "path";
|
|
16195
16320
|
var isWorkflow = (rel) => rel.startsWith(".github/workflows/") && (rel.endsWith(".yml") || rel.endsWith(".yaml"));
|
|
16196
16321
|
var isRootLayout = (rel) => rel.endsWith("src/app/layout.tsx");
|
|
16197
16322
|
var uncommented = (contents) => contents.split("\n").filter((line) => !/^\s*(\/\/|\/\*|\*)/.test(line)).join("\n");
|
|
@@ -16255,7 +16380,7 @@ function walk(dir, base = dir) {
|
|
|
16255
16380
|
}
|
|
16256
16381
|
for (const entry of entries) {
|
|
16257
16382
|
if (entry === ".venv" || entry === "node_modules" || entry === ".git") continue;
|
|
16258
|
-
const abs =
|
|
16383
|
+
const abs = join68(dir, entry);
|
|
16259
16384
|
let isDir;
|
|
16260
16385
|
try {
|
|
16261
16386
|
isDir = statSync17(abs).isDirectory();
|
|
@@ -16277,7 +16402,7 @@ function auditSkeleton(skeletonRoot, name, rules = SKELETON_RULES) {
|
|
|
16277
16402
|
if (!rule.appliesTo(rel)) continue;
|
|
16278
16403
|
let contents;
|
|
16279
16404
|
try {
|
|
16280
|
-
contents = readFileSync47(
|
|
16405
|
+
contents = readFileSync47(join68(skeletonRoot, rel), "utf8");
|
|
16281
16406
|
} catch {
|
|
16282
16407
|
continue;
|
|
16283
16408
|
}
|
|
@@ -16306,23 +16431,23 @@ function formatViolations2(violations) {
|
|
|
16306
16431
|
|
|
16307
16432
|
// src/scripts/check-skeleton-drift.ts
|
|
16308
16433
|
function discoverSkeletons(root) {
|
|
16309
|
-
const skeletonsDir =
|
|
16434
|
+
const skeletonsDir = join69(root, "_skeletons");
|
|
16310
16435
|
let entries;
|
|
16311
16436
|
try {
|
|
16312
16437
|
entries = readdirSync28(skeletonsDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
16313
16438
|
} catch {
|
|
16314
16439
|
return [];
|
|
16315
16440
|
}
|
|
16316
|
-
return entries.filter((name) =>
|
|
16441
|
+
return entries.filter((name) => existsSync57(join69(skeletonsDir, name, ".github", "workflows", "ci.yml"))).sort();
|
|
16317
16442
|
}
|
|
16318
16443
|
async function runSkeletonDriftCheck() {
|
|
16319
16444
|
const root = (await execa("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
16320
16445
|
const skeletons = discoverSkeletons(root);
|
|
16321
16446
|
let filesConsidered = 0;
|
|
16322
16447
|
for (const name of skeletons) {
|
|
16323
|
-
const skeletonRoot =
|
|
16448
|
+
const skeletonRoot = join69(root, "_skeletons", name);
|
|
16324
16449
|
filesConsidered += findWorkflowFiles(skeletonRoot).length;
|
|
16325
|
-
if (
|
|
16450
|
+
if (existsSync57(join69(skeletonRoot, "apps", "frontend", "src", "app", "layout.tsx"))) {
|
|
16326
16451
|
filesConsidered += 1;
|
|
16327
16452
|
}
|
|
16328
16453
|
}
|
|
@@ -16330,7 +16455,7 @@ async function runSkeletonDriftCheck() {
|
|
|
16330
16455
|
`audited ${skeletons.length} skeleton(s) (${skeletons.join(", ") || "none"}), ${filesConsidered} file(s) considered, under ${root}/_skeletons`
|
|
16331
16456
|
);
|
|
16332
16457
|
if (skeletons.length === 0) {
|
|
16333
|
-
if (!
|
|
16458
|
+
if (!existsSync57(join69(root, "_skeletons"))) {
|
|
16334
16459
|
console.log(
|
|
16335
16460
|
`\xB7 Skeleton-drift guard: no _skeletons/ directory under ${root} \u2014 this is not a repo that ships scaffolding (a satellite repo never carries one). Not applicable; skipping.`
|
|
16336
16461
|
);
|
|
@@ -16342,7 +16467,7 @@ async function runSkeletonDriftCheck() {
|
|
|
16342
16467
|
process.exit(1);
|
|
16343
16468
|
}
|
|
16344
16469
|
const violations = skeletons.flatMap(
|
|
16345
|
-
(name) => auditSkeleton(
|
|
16470
|
+
(name) => auditSkeleton(join69(root, "_skeletons", name), name)
|
|
16346
16471
|
);
|
|
16347
16472
|
if (violations.length > 0) {
|
|
16348
16473
|
console.error("\u2717 Skeleton-drift guard: drift found between this repo and its scaffolding\n");
|
|
@@ -16377,7 +16502,7 @@ async function runTerraformInputCheck() {
|
|
|
16377
16502
|
}
|
|
16378
16503
|
|
|
16379
16504
|
// src/commands/check.ts
|
|
16380
|
-
var checkCommand = new
|
|
16505
|
+
var checkCommand = new Command25("check").description(
|
|
16381
16506
|
"Repo guards (ownership, ownership-header-claim, release subject, plugin terraform, plugin collisions, eventbridge-log-permissions, plugin-tool-supply, core-direct-paths, instance-adoption, orphan-ratchet, cognito-invite-template, lambda-output, pipe-trap, codeql-suppression, skeleton-drift, terraform-input, plugin-allowlist-convention, migration-body-change, distribution-inventory, distribution-remote-state, api-gateway-integration) run in CI and git hooks, plus out-of-band audits (branch protection, plugin-staleness)"
|
|
16382
16507
|
);
|
|
16383
16508
|
checkCommand.command("ownership").description("Refuse changes to template-owned paths in an instance (#370)").argument("[base]", "Base branch to diff against; defaults to $GITHUB_BASE_REF").option("--staged <messageFile>", "Check staged changes instead of a branch diff (commit hook)").allowExcessArguments(true).action(async () => {
|
|
@@ -16543,10 +16668,10 @@ function rawArgsAfter(subcommand) {
|
|
|
16543
16668
|
}
|
|
16544
16669
|
|
|
16545
16670
|
// src/commands/doctor.ts
|
|
16546
|
-
import { existsSync as
|
|
16547
|
-
import { join as
|
|
16671
|
+
import { existsSync as existsSync58, readFileSync as readFileSync48 } from "fs";
|
|
16672
|
+
import { join as join71, resolve as resolve21 } from "path";
|
|
16548
16673
|
import chalk21 from "chalk";
|
|
16549
|
-
import { Command as
|
|
16674
|
+
import { Command as Command26 } from "commander";
|
|
16550
16675
|
|
|
16551
16676
|
// src/adapters/github-cli/index.ts
|
|
16552
16677
|
var GithubCliAdapter = class {
|
|
@@ -16885,11 +17010,11 @@ async function reapAllBareBranches(cwd, branches, worktrees, currentBranch, deps
|
|
|
16885
17010
|
|
|
16886
17011
|
// src/lib/scratch-clone-scan.ts
|
|
16887
17012
|
import { readdirSync as readdirSync29, statSync as statSync18 } from "fs";
|
|
16888
|
-
import { join as
|
|
17013
|
+
import { join as join70 } from "path";
|
|
16889
17014
|
var INTEGRATION_BRANCH = "dev";
|
|
16890
17015
|
function isPlainCloneDir(path) {
|
|
16891
17016
|
try {
|
|
16892
|
-
return statSync18(
|
|
17017
|
+
return statSync18(join70(path, ".git")).isDirectory();
|
|
16893
17018
|
} catch {
|
|
16894
17019
|
return false;
|
|
16895
17020
|
}
|
|
@@ -16904,7 +17029,7 @@ async function findScratchCloneCandidates(estateRoot, deps) {
|
|
|
16904
17029
|
const names = readdirSync29(estateRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
16905
17030
|
const candidates = [];
|
|
16906
17031
|
for (const name of names) {
|
|
16907
|
-
const path =
|
|
17032
|
+
const path = join70(estateRoot, name);
|
|
16908
17033
|
if (!isPlainCloneDir(path)) continue;
|
|
16909
17034
|
let branch;
|
|
16910
17035
|
try {
|
|
@@ -16953,7 +17078,7 @@ async function classifyScratchClones(candidates, deps) {
|
|
|
16953
17078
|
|
|
16954
17079
|
// src/commands/doctor.ts
|
|
16955
17080
|
var INTEGRATION_BRANCH2 = "dev";
|
|
16956
|
-
var doctorCommand = new
|
|
17081
|
+
var doctorCommand = new Command26("doctor").description(
|
|
16957
17082
|
"Report repo-state conditions that make everything read from this checkout unreliable"
|
|
16958
17083
|
).option("--cwd <path>", "Repo root to inspect (defaults to the current directory)").option("--no-fetch", "Skip the fetch; report against refs as they already are locally").option(
|
|
16959
17084
|
"--fix",
|
|
@@ -16964,10 +17089,10 @@ var doctorCommand = new Command25("doctor").description(
|
|
|
16964
17089
|
).action(
|
|
16965
17090
|
async (options) => {
|
|
16966
17091
|
if (options.scratchClones !== void 0) {
|
|
16967
|
-
await runScratchCloneScan(
|
|
17092
|
+
await runScratchCloneScan(resolve21(options.scratchClones));
|
|
16968
17093
|
return;
|
|
16969
17094
|
}
|
|
16970
|
-
const cwd = options.cwd ?
|
|
17095
|
+
const cwd = options.cwd ? resolve21(options.cwd) : process.cwd();
|
|
16971
17096
|
const git = new GitAdapter();
|
|
16972
17097
|
try {
|
|
16973
17098
|
const facts = await gatherRepoFacts({ cwd, fetch: options.fetch !== false }, { git });
|
|
@@ -17084,8 +17209,8 @@ function printScratchCloneReports(estateRoot, reports) {
|
|
|
17084
17209
|
);
|
|
17085
17210
|
}
|
|
17086
17211
|
function readLocalCoreVersion(cwd) {
|
|
17087
|
-
const path =
|
|
17088
|
-
if (!
|
|
17212
|
+
const path = join71(cwd, INSTANCE_CORE_FILE);
|
|
17213
|
+
if (!existsSync58(path)) return null;
|
|
17089
17214
|
try {
|
|
17090
17215
|
return extractVersionField(readFileSync48(path, "utf8"));
|
|
17091
17216
|
} catch {
|
|
@@ -17107,8 +17232,8 @@ function extractVersionField(contents) {
|
|
|
17107
17232
|
return match?.[1] ?? null;
|
|
17108
17233
|
}
|
|
17109
17234
|
function readFossil(cwd) {
|
|
17110
|
-
const path =
|
|
17111
|
-
if (!
|
|
17235
|
+
const path = join71(cwd, CORE_VERSION_FILE);
|
|
17236
|
+
if (!existsSync58(path)) return null;
|
|
17112
17237
|
try {
|
|
17113
17238
|
const value = readFileSync48(path, "utf8").trim();
|
|
17114
17239
|
return value === "" ? null : value;
|
|
@@ -17231,9 +17356,9 @@ function printBranchReapOutcomes(outcomes) {
|
|
|
17231
17356
|
import { execSync as execSync7 } from "child_process";
|
|
17232
17357
|
import { GetCallerIdentityCommand as GetCallerIdentityCommand3, STSClient as STSClient3 } from "@aws-sdk/client-sts";
|
|
17233
17358
|
import chalk22 from "chalk";
|
|
17234
|
-
import { Command as
|
|
17359
|
+
import { Command as Command27 } from "commander";
|
|
17235
17360
|
import inquirer8 from "inquirer";
|
|
17236
|
-
var teardownCommand = new
|
|
17361
|
+
var teardownCommand = new Command27("teardown").description(
|
|
17237
17362
|
"Destroy all infrastructure then remove the repo, IAM role, and state bucket \u2014 single command"
|
|
17238
17363
|
).option("--project <name>", "Project name to tear down (reads session if omitted)").option("--skip-destroy", "Skip terraform destroy (only use if infrastructure is already gone)").option(
|
|
17239
17364
|
"--confirm <name>",
|
|
@@ -17641,31 +17766,11 @@ function resolveGithubToken4() {
|
|
|
17641
17766
|
}
|
|
17642
17767
|
|
|
17643
17768
|
// src/lib/packaged-script-command.ts
|
|
17644
|
-
import { spawnSync } from "child_process";
|
|
17769
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
17645
17770
|
import { chmodSync as chmodSync2, statSync as statSync19 } from "fs";
|
|
17646
|
-
import { dirname as
|
|
17647
|
-
import { fileURLToPath as
|
|
17648
|
-
import { Command as
|
|
17649
|
-
|
|
17650
|
-
// src/lib/packaged-scripts.ts
|
|
17651
|
-
import { existsSync as existsSync58 } from "fs";
|
|
17652
|
-
import { dirname as dirname11, join as join71 } from "path";
|
|
17653
|
-
function findPackagedScript(startDir, relativePath) {
|
|
17654
|
-
let dir = startDir;
|
|
17655
|
-
for (; ; ) {
|
|
17656
|
-
const candidate = join71(dir, relativePath);
|
|
17657
|
-
if (existsSync58(candidate)) return candidate;
|
|
17658
|
-
const parent = dirname11(dir);
|
|
17659
|
-
if (parent === dir) return null;
|
|
17660
|
-
dir = parent;
|
|
17661
|
-
}
|
|
17662
|
-
}
|
|
17663
|
-
function packagedScriptMissing(relativePath) {
|
|
17664
|
-
return `biffo: cannot find ${relativePath}.
|
|
17665
|
-
It ships with this package via cli/scripts/packaged-root-assets.mjs; if you are running from a checkout, run from inside the template repo. If you are running the published package, this is a packaging bug \u2014 the asset was not copied at prepack.`;
|
|
17666
|
-
}
|
|
17667
|
-
|
|
17668
|
-
// src/lib/packaged-script-command.ts
|
|
17771
|
+
import { dirname as dirname13 } from "path";
|
|
17772
|
+
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
17773
|
+
import { Command as Command28 } from "commander";
|
|
17669
17774
|
function ensureExecutable(script) {
|
|
17670
17775
|
try {
|
|
17671
17776
|
const { mode } = statSync19(script);
|
|
@@ -17675,14 +17780,14 @@ function ensureExecutable(script) {
|
|
|
17675
17780
|
}
|
|
17676
17781
|
function runPackagedScript(script, args, cwd) {
|
|
17677
17782
|
ensureExecutable(script);
|
|
17678
|
-
const result =
|
|
17783
|
+
const result = spawnSync2(script, args, { stdio: "inherit", cwd });
|
|
17679
17784
|
return result.status === null ? 2 : result.status;
|
|
17680
17785
|
}
|
|
17681
17786
|
function packagedScriptCommand(spec) {
|
|
17682
|
-
const command = new
|
|
17787
|
+
const command = new Command28(spec.name).description(spec.description).allowExcessArguments(true).allowUnknownOption(true);
|
|
17683
17788
|
if (spec.argument) command.argument(`<${spec.argument.name}>`, spec.argument.description);
|
|
17684
17789
|
return command.action(() => {
|
|
17685
|
-
const here =
|
|
17790
|
+
const here = dirname13(fileURLToPath7(import.meta.url));
|
|
17686
17791
|
const script = findPackagedScript(here, spec.script);
|
|
17687
17792
|
if (!script) {
|
|
17688
17793
|
process.stderr.write(`${packagedScriptMissing(spec.script)}
|
|
@@ -17768,7 +17873,7 @@ var runnerDropForensicsCommand = packagedScriptCommand({
|
|
|
17768
17873
|
});
|
|
17769
17874
|
|
|
17770
17875
|
// src/index.ts
|
|
17771
|
-
var program = new
|
|
17876
|
+
var program = new Command29();
|
|
17772
17877
|
function cliVersion() {
|
|
17773
17878
|
try {
|
|
17774
17879
|
return getLatestCoreVersion();
|