@biffo/cli 0.303.2 → 0.303.3
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 +164 -111
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11122,8 +11122,15 @@ async function runApiGatewayIntegrationCheck() {
|
|
|
11122
11122
|
try {
|
|
11123
11123
|
report = auditApiGatewayIntegrations(root);
|
|
11124
11124
|
} catch (err) {
|
|
11125
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
11126
|
+
if (message.includes("no .tf files found under")) {
|
|
11127
|
+
console.log(
|
|
11128
|
+
`\xB7 API Gateway integration-qualifier guard: not applicable \u2014 ${message} This repo carries no Terraform at all, which is expected for a non-instance satellite. Skipping.`
|
|
11129
|
+
);
|
|
11130
|
+
return;
|
|
11131
|
+
}
|
|
11125
11132
|
console.error("\u2717 API Gateway integration-qualifier guard: could not run\n");
|
|
11126
|
-
console.error(
|
|
11133
|
+
console.error(message);
|
|
11127
11134
|
process.exit(1);
|
|
11128
11135
|
}
|
|
11129
11136
|
console.log(`scanned ${report.filesScanned} .tf file(s) under ${root}`);
|
|
@@ -11653,6 +11660,10 @@ async function runCodeqlSuppressionCheck() {
|
|
|
11653
11660
|
console.log("\u2713 codeql-suppression guard: no dead `codeql[...]` suppression comment found");
|
|
11654
11661
|
}
|
|
11655
11662
|
|
|
11663
|
+
// src/scripts/check-cognito-invite-template.ts
|
|
11664
|
+
import { existsSync as existsSync42 } from "fs";
|
|
11665
|
+
import { join as join46 } from "path";
|
|
11666
|
+
|
|
11656
11667
|
// src/lib/cognito-invite-template-guard.ts
|
|
11657
11668
|
import { readdirSync as readdirSync19, readFileSync as readFileSync33, statSync as statSync11 } from "fs";
|
|
11658
11669
|
import { join as join45 } from "path";
|
|
@@ -11769,6 +11780,12 @@ async function runCognitoInviteTemplateCheck() {
|
|
|
11769
11780
|
const files = findModuleTerraformFiles(root);
|
|
11770
11781
|
console.log(`audited ${files.length} .tf file(s) under modules/ under ${root}`);
|
|
11771
11782
|
if (files.length === 0) {
|
|
11783
|
+
if (!existsSync42(join46(root, "modules"))) {
|
|
11784
|
+
console.log(
|
|
11785
|
+
`\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.`
|
|
11786
|
+
);
|
|
11787
|
+
return;
|
|
11788
|
+
}
|
|
11772
11789
|
console.error(
|
|
11773
11790
|
"\u2717 Cognito invite template guard: found 0 .tf files under modules/ \u2014 this looks like a broken scan, not a clean repo. Refusing to report success over zero input."
|
|
11774
11791
|
);
|
|
@@ -11787,11 +11804,11 @@ async function runCognitoInviteTemplateCheck() {
|
|
|
11787
11804
|
}
|
|
11788
11805
|
|
|
11789
11806
|
// src/scripts/check-core-direct-paths.ts
|
|
11790
|
-
import { join as
|
|
11807
|
+
import { join as join48 } from "path";
|
|
11791
11808
|
|
|
11792
11809
|
// src/lib/core-direct-paths-audit.ts
|
|
11793
|
-
import { existsSync as
|
|
11794
|
-
import { join as
|
|
11810
|
+
import { existsSync as existsSync43, readFileSync as readFileSync34, readdirSync as readdirSync20, statSync as statSync12 } from "fs";
|
|
11811
|
+
import { join as join47 } from "path";
|
|
11795
11812
|
var EXTERNAL_BASE_IDENTIFIERS = ["CORE_API_URL"];
|
|
11796
11813
|
var API_ROUTE_PREFIX = "/api/v1";
|
|
11797
11814
|
var TEST_FILE_SUFFIXES = [".test.ts", ".test.tsx", ".spec.ts", ".spec.tsx"];
|
|
@@ -11955,7 +11972,7 @@ function walkFiles(root, accept, skipDir) {
|
|
|
11955
11972
|
return;
|
|
11956
11973
|
}
|
|
11957
11974
|
for (const entry of entries) {
|
|
11958
|
-
const p =
|
|
11975
|
+
const p = join47(dir, entry);
|
|
11959
11976
|
let st;
|
|
11960
11977
|
try {
|
|
11961
11978
|
st = statSync12(p);
|
|
@@ -12050,7 +12067,7 @@ function pathMatchesAnyCorePrefix(normalized, corePrefixes, apiRoutePrefix = API
|
|
|
12050
12067
|
}
|
|
12051
12068
|
function resolveSiblingCoreSrc(params) {
|
|
12052
12069
|
const { estateDir, sibling } = params;
|
|
12053
|
-
const configPath =
|
|
12070
|
+
const configPath = join47(estateDir, sibling, "biffo.sibling.json");
|
|
12054
12071
|
let raw;
|
|
12055
12072
|
try {
|
|
12056
12073
|
raw = readFileSync34(configPath, "utf8");
|
|
@@ -12073,8 +12090,8 @@ function resolveSiblingCoreSrc(params) {
|
|
|
12073
12090
|
`cannot resolve ${sibling}'s core: ${configPath} has no non-empty "core_project" field.`
|
|
12074
12091
|
);
|
|
12075
12092
|
}
|
|
12076
|
-
const coreApiSrcDir =
|
|
12077
|
-
if (!
|
|
12093
|
+
const coreApiSrcDir = join47(estateDir, coreProject, "services", "api", "src");
|
|
12094
|
+
if (!existsSync43(coreApiSrcDir)) {
|
|
12078
12095
|
throw new Error(
|
|
12079
12096
|
`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.`
|
|
12080
12097
|
);
|
|
@@ -12117,7 +12134,7 @@ function auditSiblingCoreDirectPaths(params) {
|
|
|
12117
12134
|
async function runCoreDirectPathsCheck(opts = {}) {
|
|
12118
12135
|
const root = (await execa("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
12119
12136
|
const sibling = opts.sibling ?? "sibling-template (self-check)";
|
|
12120
|
-
const frontendSrcDir = opts.frontendSrc ??
|
|
12137
|
+
const frontendSrcDir = opts.frontendSrc ?? join48(root, "_skeletons", "sibling-template", "apps", "frontend", "src");
|
|
12121
12138
|
let coreApiSrcDir;
|
|
12122
12139
|
let coreProject = null;
|
|
12123
12140
|
if (opts.coreSrc) {
|
|
@@ -12133,7 +12150,7 @@ async function runCoreDirectPathsCheck(opts = {}) {
|
|
|
12133
12150
|
coreApiSrcDir = resolution.coreApiSrcDir;
|
|
12134
12151
|
coreProject = resolution.coreProject;
|
|
12135
12152
|
} else {
|
|
12136
|
-
coreApiSrcDir =
|
|
12153
|
+
coreApiSrcDir = join48(root, "services", "api", "src");
|
|
12137
12154
|
}
|
|
12138
12155
|
const report = auditSiblingCoreDirectPaths({ sibling, frontendSrcDir, coreApiSrcDir });
|
|
12139
12156
|
console.log(
|
|
@@ -12198,8 +12215,8 @@ async function runOwnershipCheck(argv) {
|
|
|
12198
12215
|
const { stdout } = await execa("git", ["diff", "--cached", "--name-status"], { cwd: root });
|
|
12199
12216
|
({ changed: changedFiles, deleted: deletedFiles } = parseNameStatus(stdout));
|
|
12200
12217
|
if (messageFile) {
|
|
12201
|
-
const { readFileSync: readFileSync47, existsSync:
|
|
12202
|
-
if (
|
|
12218
|
+
const { readFileSync: readFileSync47, existsSync: existsSync59 } = await import("fs");
|
|
12219
|
+
if (existsSync59(messageFile)) commitMessage = readFileSync47(messageFile, "utf8");
|
|
12203
12220
|
}
|
|
12204
12221
|
} else {
|
|
12205
12222
|
const base = process.env["GITHUB_BASE_REF"] ?? args[0];
|
|
@@ -12300,16 +12317,16 @@ ${BOLD}If the divergence is deliberate${OFF}
|
|
|
12300
12317
|
}
|
|
12301
12318
|
|
|
12302
12319
|
// src/scripts/check-distribution-inventory.ts
|
|
12303
|
-
import { existsSync as
|
|
12304
|
-
import { join as
|
|
12320
|
+
import { existsSync as existsSync45 } from "fs";
|
|
12321
|
+
import { join as join50 } from "path";
|
|
12305
12322
|
|
|
12306
12323
|
// src/lib/distribution-inventory.ts
|
|
12307
|
-
import { existsSync as
|
|
12308
|
-
import { join as
|
|
12324
|
+
import { existsSync as existsSync44, readFileSync as readFileSync35 } from "fs";
|
|
12325
|
+
import { join as join49 } from "path";
|
|
12309
12326
|
var INVENTORY_FILENAME = "distribution-inventory.json";
|
|
12310
12327
|
function loadDistributionInventory(root) {
|
|
12311
|
-
const path =
|
|
12312
|
-
if (!
|
|
12328
|
+
const path = join49(root, INVENTORY_FILENAME);
|
|
12329
|
+
if (!existsSync44(path)) {
|
|
12313
12330
|
throw new Error(
|
|
12314
12331
|
`${INVENTORY_FILENAME} not found at ${root} -- expected it beside core-manifest.json`
|
|
12315
12332
|
);
|
|
@@ -12474,7 +12491,7 @@ async function runDistributionInventoryCheck(root) {
|
|
|
12474
12491
|
);
|
|
12475
12492
|
return;
|
|
12476
12493
|
}
|
|
12477
|
-
if (!
|
|
12494
|
+
if (!existsSync45(join50(repoRoot, INVENTORY_FILENAME))) {
|
|
12478
12495
|
console.log(
|
|
12479
12496
|
`\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.`
|
|
12480
12497
|
);
|
|
@@ -12500,7 +12517,7 @@ async function runDistributionInventoryCheck(root) {
|
|
|
12500
12517
|
}
|
|
12501
12518
|
|
|
12502
12519
|
// src/scripts/check-distribution-remote-state.ts
|
|
12503
|
-
import { join as
|
|
12520
|
+
import { join as join51 } from "path";
|
|
12504
12521
|
async function ghExecCommand(file, args) {
|
|
12505
12522
|
const result = await execa(file, args, { reject: false });
|
|
12506
12523
|
return { stdout: String(result.stdout ?? ""), exitCode: result.exitCode ?? null };
|
|
@@ -12515,7 +12532,7 @@ async function runDistributionRemoteStateCheck(root) {
|
|
|
12515
12532
|
}
|
|
12516
12533
|
}
|
|
12517
12534
|
console.log(
|
|
12518
|
-
`distribution-remote-state: examined ${assertions.length} remote content assertion(s) declared across ${inventory.entries.length} inventory entries (${
|
|
12535
|
+
`distribution-remote-state: examined ${assertions.length} remote content assertion(s) declared across ${inventory.entries.length} inventory entries (${join51(repoRoot, "distribution-inventory.json")})`
|
|
12519
12536
|
);
|
|
12520
12537
|
if (assertions.length === 0) {
|
|
12521
12538
|
console.log("\u2713 distribution-remote-state: nothing declared to check");
|
|
@@ -12561,7 +12578,7 @@ ${assertion.ref}`;
|
|
|
12561
12578
|
|
|
12562
12579
|
// src/lib/eventbridge-log-permission-guard.ts
|
|
12563
12580
|
import { readFileSync as readFileSync36, readdirSync as readdirSync21, statSync as statSync13 } from "fs";
|
|
12564
|
-
import { join as
|
|
12581
|
+
import { join as join52 } from "path";
|
|
12565
12582
|
var SKIP_DIRS3 = /* @__PURE__ */ new Set(["node_modules", ".git", ".terraform", ".worktrees", "dist"]);
|
|
12566
12583
|
var EVENT_TARGET_TYPE = "aws_cloudwatch_event_target";
|
|
12567
12584
|
var LOG_RESOURCE_POLICY_TYPE = "aws_cloudwatch_log_resource_policy";
|
|
@@ -12638,7 +12655,7 @@ function walkTerraformFiles2(root) {
|
|
|
12638
12655
|
return;
|
|
12639
12656
|
}
|
|
12640
12657
|
for (const entry of entries) {
|
|
12641
|
-
const p =
|
|
12658
|
+
const p = join52(dir, entry);
|
|
12642
12659
|
let st;
|
|
12643
12660
|
try {
|
|
12644
12661
|
st = statSync13(p);
|
|
@@ -12739,8 +12756,15 @@ async function runEventBridgeLogPermissionCheck() {
|
|
|
12739
12756
|
try {
|
|
12740
12757
|
report = auditEventBridgeLogPermissions(root);
|
|
12741
12758
|
} catch (err) {
|
|
12759
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
12760
|
+
if (message.includes("no .tf files found under")) {
|
|
12761
|
+
console.log(
|
|
12762
|
+
`\xB7 EventBridge log permission guard: not applicable \u2014 ${message} This repo carries no Terraform at all, which is expected for a non-instance satellite. Skipping.`
|
|
12763
|
+
);
|
|
12764
|
+
return;
|
|
12765
|
+
}
|
|
12742
12766
|
console.error("\u2717 EventBridge log permission guard: could not run\n");
|
|
12743
|
-
console.error(
|
|
12767
|
+
console.error(message);
|
|
12744
12768
|
process.exit(1);
|
|
12745
12769
|
}
|
|
12746
12770
|
console.log(`audited ${report.filesScanned} .tf file(s) under ${root}`);
|
|
@@ -12771,8 +12795,8 @@ async function runEventBridgeLogPermissionCheck() {
|
|
|
12771
12795
|
}
|
|
12772
12796
|
|
|
12773
12797
|
// src/scripts/check-instance-adoption.ts
|
|
12774
|
-
import { existsSync as
|
|
12775
|
-
import { join as
|
|
12798
|
+
import { existsSync as existsSync46 } from "fs";
|
|
12799
|
+
import { join as join53 } from "path";
|
|
12776
12800
|
async function runInstanceAdoptionCheck(opts = {}) {
|
|
12777
12801
|
if (!opts.instanceDir) {
|
|
12778
12802
|
console.error(
|
|
@@ -12780,7 +12804,7 @@ async function runInstanceAdoptionCheck(opts = {}) {
|
|
|
12780
12804
|
);
|
|
12781
12805
|
process.exit(2);
|
|
12782
12806
|
}
|
|
12783
|
-
if (!
|
|
12807
|
+
if (!existsSync46(opts.instanceDir)) {
|
|
12784
12808
|
console.error(
|
|
12785
12809
|
`\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.`
|
|
12786
12810
|
);
|
|
@@ -12788,7 +12812,7 @@ async function runInstanceAdoptionCheck(opts = {}) {
|
|
|
12788
12812
|
}
|
|
12789
12813
|
const root = (await execa("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
12790
12814
|
const theirsDir = opts.theirsDir ?? root;
|
|
12791
|
-
const instanceLabel = opts.instance ??
|
|
12815
|
+
const instanceLabel = opts.instance ?? join53(opts.instanceDir).split("/").filter(Boolean).pop();
|
|
12792
12816
|
const report = checkInstanceAdoption(theirsDir, opts.instanceDir);
|
|
12793
12817
|
console.log(
|
|
12794
12818
|
`examined ${report.examinedInstances} instance (${instanceLabel}) against ${report.registeredPairs} registered pair(s), ${report.applicablePairs} applicable to this instance, against template tree ${theirsDir}`
|
|
@@ -12811,11 +12835,11 @@ async function runInstanceAdoptionCheck(opts = {}) {
|
|
|
12811
12835
|
|
|
12812
12836
|
// src/lib/lambda-output-guard.ts
|
|
12813
12837
|
import { readFileSync as readFileSync38 } from "fs";
|
|
12814
|
-
import { join as
|
|
12838
|
+
import { join as join55 } from "path";
|
|
12815
12839
|
|
|
12816
12840
|
// src/lib/terraform-input-guard.ts
|
|
12817
|
-
import { existsSync as
|
|
12818
|
-
import { join as
|
|
12841
|
+
import { existsSync as existsSync47, readdirSync as readdirSync22, readFileSync as readFileSync37, statSync as statSync14 } from "fs";
|
|
12842
|
+
import { join as join54 } from "path";
|
|
12819
12843
|
var GUARDED_SUBCOMMANDS = [
|
|
12820
12844
|
"init",
|
|
12821
12845
|
"plan",
|
|
@@ -12829,7 +12853,7 @@ function stripComments2(source) {
|
|
|
12829
12853
|
return source.split("\n").map((line) => line.replace(/(^|\s)#.*$/, "$1")).join("\n");
|
|
12830
12854
|
}
|
|
12831
12855
|
function vendoredPluginServiceDirs(repoRoot) {
|
|
12832
|
-
const servicesDir =
|
|
12856
|
+
const servicesDir = join54(repoRoot, "services");
|
|
12833
12857
|
const result = /* @__PURE__ */ new Set();
|
|
12834
12858
|
let entries;
|
|
12835
12859
|
try {
|
|
@@ -12838,9 +12862,9 @@ function vendoredPluginServiceDirs(repoRoot) {
|
|
|
12838
12862
|
return result;
|
|
12839
12863
|
}
|
|
12840
12864
|
for (const entry of entries) {
|
|
12841
|
-
const full =
|
|
12842
|
-
if (!
|
|
12843
|
-
if (
|
|
12865
|
+
const full = join54(servicesDir, entry);
|
|
12866
|
+
if (!existsSync47(full) || !statSync14(full).isDirectory()) continue;
|
|
12867
|
+
if (existsSync47(join54(full, "biffo.plugin.json"))) {
|
|
12844
12868
|
result.add(entry);
|
|
12845
12869
|
}
|
|
12846
12870
|
}
|
|
@@ -12862,7 +12886,7 @@ function findWorkflowFiles(repoRoot) {
|
|
|
12862
12886
|
if (entry === ".github" && relative11.startsWith("services/") && vendoredPluginDirs.has(relative11.slice("services/".length))) {
|
|
12863
12887
|
continue;
|
|
12864
12888
|
}
|
|
12865
|
-
const full =
|
|
12889
|
+
const full = join54(dir, entry);
|
|
12866
12890
|
const rel = relative11 ? `${relative11}/${entry}` : entry;
|
|
12867
12891
|
let isDir;
|
|
12868
12892
|
try {
|
|
@@ -12912,7 +12936,7 @@ function checkWorkflowSource(file, rawSource) {
|
|
|
12912
12936
|
}
|
|
12913
12937
|
function checkTerraformInput(repoRoot) {
|
|
12914
12938
|
return findWorkflowFiles(repoRoot).flatMap(
|
|
12915
|
-
(file) => checkWorkflowSource(file, readFileSync37(
|
|
12939
|
+
(file) => checkWorkflowSource(file, readFileSync37(join54(repoRoot, file), "utf8"))
|
|
12916
12940
|
);
|
|
12917
12941
|
}
|
|
12918
12942
|
|
|
@@ -12970,7 +12994,7 @@ function checkWorkflowSource2(file, rawSource) {
|
|
|
12970
12994
|
}
|
|
12971
12995
|
function checkLambdaOutput(repoRoot) {
|
|
12972
12996
|
return findWorkflowFiles(repoRoot).flatMap(
|
|
12973
|
-
(file) => checkWorkflowSource2(file, readFileSync38(
|
|
12997
|
+
(file) => checkWorkflowSource2(file, readFileSync38(join55(repoRoot, file), "utf8"))
|
|
12974
12998
|
);
|
|
12975
12999
|
}
|
|
12976
13000
|
|
|
@@ -12998,8 +13022,8 @@ async function runLambdaOutputCheck() {
|
|
|
12998
13022
|
}
|
|
12999
13023
|
|
|
13000
13024
|
// src/scripts/check-migration-body-change.ts
|
|
13001
|
-
import { existsSync as
|
|
13002
|
-
import { join as
|
|
13025
|
+
import { existsSync as existsSync48 } from "fs";
|
|
13026
|
+
import { join as join56 } from "path";
|
|
13003
13027
|
|
|
13004
13028
|
// src/lib/migration-body-change-guard.ts
|
|
13005
13029
|
function checkMigrationBodyChangeMarkers(diffs) {
|
|
@@ -13065,7 +13089,7 @@ async function runMigrationBodyChangeCheck(argv) {
|
|
|
13065
13089
|
);
|
|
13066
13090
|
return;
|
|
13067
13091
|
}
|
|
13068
|
-
if (!
|
|
13092
|
+
if (!existsSync48(join56(root, MIGRATIONS_VERSIONS_DIR))) {
|
|
13069
13093
|
console.log(`\u2713 migration body-change guard: no ${MIGRATIONS_VERSIONS_DIR} in this repo.`);
|
|
13070
13094
|
return;
|
|
13071
13095
|
}
|
|
@@ -13167,8 +13191,8 @@ ${BOLD2}What to do${OFF2}
|
|
|
13167
13191
|
}
|
|
13168
13192
|
|
|
13169
13193
|
// src/scripts/check-orphan-ratchet.ts
|
|
13170
|
-
import { existsSync as
|
|
13171
|
-
import { basename as basename3 } from "path";
|
|
13194
|
+
import { existsSync as existsSync49 } from "fs";
|
|
13195
|
+
import { basename as basename3, join as join57 } from "path";
|
|
13172
13196
|
function reportOrphan(entry, manifest) {
|
|
13173
13197
|
console.error(` ${entry.path}`);
|
|
13174
13198
|
const { templateOwnedMatch, nearestUserOwnedEntries } = explainOwnership(entry.path, manifest);
|
|
@@ -13190,7 +13214,7 @@ function reportOrphan(entry, manifest) {
|
|
|
13190
13214
|
}
|
|
13191
13215
|
}
|
|
13192
13216
|
async function runOrphanRatchetCheck(opts = {}) {
|
|
13193
|
-
if (opts.instanceDir !== void 0 && !
|
|
13217
|
+
if (opts.instanceDir !== void 0 && !existsSync49(opts.instanceDir)) {
|
|
13194
13218
|
console.error(
|
|
13195
13219
|
`\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.`
|
|
13196
13220
|
);
|
|
@@ -13207,6 +13231,12 @@ async function runOrphanRatchetCheck(opts = {}) {
|
|
|
13207
13231
|
"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."
|
|
13208
13232
|
);
|
|
13209
13233
|
}
|
|
13234
|
+
if (!existsSync49(join57(theirsDir, CORE_MANIFEST_FILE))) {
|
|
13235
|
+
console.log(
|
|
13236
|
+
`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.`
|
|
13237
|
+
);
|
|
13238
|
+
return;
|
|
13239
|
+
}
|
|
13210
13240
|
const manifest = readCoreManifest(theirsDir);
|
|
13211
13241
|
const plan = await planCoreUpgrade({ baseDir, oursDir: instanceDir, theirsDir, manifest });
|
|
13212
13242
|
const baseline = readOrphanBaseline(instanceDir);
|
|
@@ -13233,7 +13263,7 @@ baseline was ${String(ratchet.baseline)}, now ${String(ratchet.count)}. See biff
|
|
|
13233
13263
|
|
|
13234
13264
|
// src/scripts/check-pipe-trap.ts
|
|
13235
13265
|
import { readFileSync as readFileSync39, readdirSync as readdirSync23 } from "fs";
|
|
13236
|
-
import { join as
|
|
13266
|
+
import { join as join58, relative as relative9 } from "path";
|
|
13237
13267
|
|
|
13238
13268
|
// src/lib/pipe-trap-guard.ts
|
|
13239
13269
|
var STATUS_BEARING = [
|
|
@@ -13329,7 +13359,7 @@ function findPipeTraps(source) {
|
|
|
13329
13359
|
function shellFiles(root) {
|
|
13330
13360
|
const out = [];
|
|
13331
13361
|
for (const dir of ["scripts", ".githooks"]) {
|
|
13332
|
-
const full =
|
|
13362
|
+
const full = join58(root, dir);
|
|
13333
13363
|
let entries;
|
|
13334
13364
|
try {
|
|
13335
13365
|
entries = readdirSync23(full, { withFileTypes: true });
|
|
@@ -13339,7 +13369,7 @@ function shellFiles(root) {
|
|
|
13339
13369
|
for (const entry of entries) {
|
|
13340
13370
|
if (!entry.isFile()) continue;
|
|
13341
13371
|
if (dir === "scripts" && !entry.name.endsWith(".sh")) continue;
|
|
13342
|
-
out.push(
|
|
13372
|
+
out.push(join58(full, entry.name));
|
|
13343
13373
|
}
|
|
13344
13374
|
}
|
|
13345
13375
|
return out;
|
|
@@ -13371,9 +13401,13 @@ async function runPipeTrapCheck() {
|
|
|
13371
13401
|
console.log(`\u2713 Pipe-trap guard: no status-bearing command is piped away`);
|
|
13372
13402
|
}
|
|
13373
13403
|
|
|
13404
|
+
// src/scripts/check-plugin-allowlist-convention.ts
|
|
13405
|
+
import { existsSync as existsSync50 } from "fs";
|
|
13406
|
+
import { join as join60 } from "path";
|
|
13407
|
+
|
|
13374
13408
|
// src/lib/plugin-allowlist-convention.ts
|
|
13375
13409
|
import { readFileSync as readFileSync40 } from "fs";
|
|
13376
|
-
import { join as
|
|
13410
|
+
import { join as join59 } from "path";
|
|
13377
13411
|
var COMPUTE_MAIN_TF = "modules/cloud/aws/compute/main.tf";
|
|
13378
13412
|
var PLUGIN_TEMPLATE_MAIN_TF = "modules/plugins/_template/main.tf";
|
|
13379
13413
|
var ALLOWLIST_MAIN_TF = "modules/cloud/aws/plugin-allowlist/main.tf";
|
|
@@ -13384,7 +13418,7 @@ var PLUGIN = "<plugin>";
|
|
|
13384
13418
|
var ACCOUNT = "<account>";
|
|
13385
13419
|
function read(repoRoot, relative11) {
|
|
13386
13420
|
try {
|
|
13387
|
-
return readFileSync40(
|
|
13421
|
+
return readFileSync40(join59(repoRoot, relative11), "utf8");
|
|
13388
13422
|
} catch {
|
|
13389
13423
|
throw new Error(`plugin-allowlist drift guard: cannot read ${relative11}`);
|
|
13390
13424
|
}
|
|
@@ -13479,8 +13513,21 @@ Plugins would be rejected by require_service_principal (ADR-0009). Fix the glob,
|
|
|
13479
13513
|
}
|
|
13480
13514
|
|
|
13481
13515
|
// src/scripts/check-plugin-allowlist-convention.ts
|
|
13516
|
+
var REQUIRED_SOURCES = [
|
|
13517
|
+
COMPUTE_MAIN_TF,
|
|
13518
|
+
PLUGIN_TEMPLATE_MAIN_TF,
|
|
13519
|
+
ALLOWLIST_MAIN_TF,
|
|
13520
|
+
ALLOWLIST_VARIABLES_TF
|
|
13521
|
+
];
|
|
13482
13522
|
async function runPluginAllowlistConventionCheck() {
|
|
13483
13523
|
const root = (await execa("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
13524
|
+
const missing = REQUIRED_SOURCES.filter((relative11) => !existsSync50(join60(root, relative11)));
|
|
13525
|
+
if (missing.length === REQUIRED_SOURCES.length) {
|
|
13526
|
+
console.log(
|
|
13527
|
+
`\xB7 Plugin-allowlist convention guard: not applicable \u2014 ${missing.join(", ")} not found under ${root}. This is not a template/instance tree (a satellite repo never carries the plugin-allowlist Terraform modules). Skipping.`
|
|
13528
|
+
);
|
|
13529
|
+
return;
|
|
13530
|
+
}
|
|
13484
13531
|
let violations;
|
|
13485
13532
|
try {
|
|
13486
13533
|
violations = checkAllowlistConvention(root);
|
|
@@ -13505,32 +13552,32 @@ async function runPluginAllowlistConventionCheck() {
|
|
|
13505
13552
|
}
|
|
13506
13553
|
|
|
13507
13554
|
// src/scripts/check-plugin-collisions.ts
|
|
13508
|
-
import { existsSync as
|
|
13509
|
-
import { join as
|
|
13555
|
+
import { existsSync as existsSync52 } from "fs";
|
|
13556
|
+
import { join as join62 } from "path";
|
|
13510
13557
|
|
|
13511
13558
|
// src/lib/plugin-collision-guard.ts
|
|
13512
|
-
import { existsSync as
|
|
13513
|
-
import { join as
|
|
13559
|
+
import { existsSync as existsSync51, readdirSync as readdirSync24, statSync as statSync15 } from "fs";
|
|
13560
|
+
import { join as join61 } from "path";
|
|
13514
13561
|
var PYTEST_SPECIAL = /* @__PURE__ */ new Set(["conftest.py"]);
|
|
13515
13562
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([".venv", "node_modules", "__pycache__", ".git", "dist", "build"]);
|
|
13516
13563
|
function subdirectories(dir) {
|
|
13517
|
-
if (!
|
|
13564
|
+
if (!existsSync51(dir)) return [];
|
|
13518
13565
|
return readdirSync24(dir).filter((entry) => {
|
|
13519
13566
|
if (IGNORED_DIRS.has(entry) || entry.startsWith(".")) return false;
|
|
13520
13567
|
try {
|
|
13521
|
-
return statSync15(
|
|
13568
|
+
return statSync15(join61(dir, entry)).isDirectory();
|
|
13522
13569
|
} catch {
|
|
13523
13570
|
return false;
|
|
13524
13571
|
}
|
|
13525
13572
|
});
|
|
13526
13573
|
}
|
|
13527
13574
|
function regularPackagesOf(pluginDir2) {
|
|
13528
|
-
return subdirectories(pluginDir2).filter((name) =>
|
|
13575
|
+
return subdirectories(pluginDir2).filter((name) => existsSync51(join61(pluginDir2, name, "__init__.py"))).sort();
|
|
13529
13576
|
}
|
|
13530
13577
|
function bareTestModulesOf(pluginDir2) {
|
|
13531
|
-
const testsDir =
|
|
13532
|
-
if (!
|
|
13533
|
-
if (
|
|
13578
|
+
const testsDir = join61(pluginDir2, "tests");
|
|
13579
|
+
if (!existsSync51(testsDir)) return [];
|
|
13580
|
+
if (existsSync51(join61(testsDir, "__init__.py"))) return [];
|
|
13534
13581
|
return readdirSync24(testsDir).filter((f) => f.endsWith(".py") && !PYTEST_SPECIAL.has(f)).sort();
|
|
13535
13582
|
}
|
|
13536
13583
|
function findCollisions(servicesDir, pluginDirs) {
|
|
@@ -13539,7 +13586,7 @@ function findCollisions(servicesDir, pluginDirs) {
|
|
|
13539
13586
|
const gather = (kind, namesOf) => {
|
|
13540
13587
|
const claims = /* @__PURE__ */ new Map();
|
|
13541
13588
|
for (const plugin of plugins) {
|
|
13542
|
-
for (const name of namesOf(
|
|
13589
|
+
for (const name of namesOf(join61(servicesDir, plugin))) {
|
|
13543
13590
|
claims.set(name, [...claims.get(name) ?? [], plugin]);
|
|
13544
13591
|
}
|
|
13545
13592
|
}
|
|
@@ -13577,8 +13624,8 @@ function formatCollisions(collisions) {
|
|
|
13577
13624
|
// src/scripts/check-plugin-collisions.ts
|
|
13578
13625
|
async function runPluginCollisionCheck() {
|
|
13579
13626
|
const root = (await execa("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
13580
|
-
const servicesDir =
|
|
13581
|
-
if (!
|
|
13627
|
+
const servicesDir = join62(root, "services");
|
|
13628
|
+
if (!existsSync52(servicesDir)) {
|
|
13582
13629
|
console.log("\u2713 plugin collision guard: no services/ directory \u2014 nothing to compare");
|
|
13583
13630
|
return;
|
|
13584
13631
|
}
|
|
@@ -13595,8 +13642,8 @@ async function runPluginCollisionCheck() {
|
|
|
13595
13642
|
}
|
|
13596
13643
|
|
|
13597
13644
|
// src/lib/plugin-terraform-guard.ts
|
|
13598
|
-
import { existsSync as
|
|
13599
|
-
import { dirname as dirname10, join as
|
|
13645
|
+
import { existsSync as existsSync53, readFileSync as readFileSync41, readdirSync as readdirSync25 } from "fs";
|
|
13646
|
+
import { dirname as dirname10, join as join63, relative as relative10, sep as sep4 } from "path";
|
|
13600
13647
|
var SKIP_DIRS4 = /* @__PURE__ */ new Set(["node_modules", ".git", ".worktrees", "dist", ".venv", "__pycache__"]);
|
|
13601
13648
|
var PLUGIN_MANIFEST_FILE2 = "biffo.plugin.json";
|
|
13602
13649
|
function findPluginManifests(root) {
|
|
@@ -13611,9 +13658,9 @@ function findPluginManifests(root) {
|
|
|
13611
13658
|
for (const entry of entries) {
|
|
13612
13659
|
if (entry.isDirectory()) {
|
|
13613
13660
|
if (SKIP_DIRS4.has(entry.name)) continue;
|
|
13614
|
-
walk2(
|
|
13661
|
+
walk2(join63(dir, entry.name));
|
|
13615
13662
|
} else if (entry.isFile() && entry.name === PLUGIN_MANIFEST_FILE2) {
|
|
13616
|
-
found.push(relative10(root,
|
|
13663
|
+
found.push(relative10(root, join63(dir, entry.name)).split(sep4).join("/"));
|
|
13617
13664
|
}
|
|
13618
13665
|
}
|
|
13619
13666
|
};
|
|
@@ -13638,14 +13685,14 @@ function readSubscriptions(absManifestPath) {
|
|
|
13638
13685
|
}
|
|
13639
13686
|
function checkPluginTerraform(root) {
|
|
13640
13687
|
const violations = [];
|
|
13641
|
-
const coreManifest =
|
|
13688
|
+
const coreManifest = existsSync53(join63(root, CORE_MANIFEST_FILE)) ? readCoreManifest(root) : null;
|
|
13642
13689
|
for (const manifest of findPluginManifests(root)) {
|
|
13643
13690
|
if (coreManifest && !isTemplateOwned(manifest, coreManifest)) continue;
|
|
13644
|
-
const absManifest =
|
|
13691
|
+
const absManifest = join63(root, manifest);
|
|
13645
13692
|
const subscriptions = readSubscriptions(absManifest);
|
|
13646
13693
|
if (subscriptions === null) continue;
|
|
13647
13694
|
const pluginDir2 = dirname10(absManifest);
|
|
13648
|
-
if (
|
|
13695
|
+
if (existsSync53(join63(pluginDir2, "terraform"))) continue;
|
|
13649
13696
|
const relPluginDir = relative10(root, pluginDir2).split(sep4).join("/");
|
|
13650
13697
|
violations.push({
|
|
13651
13698
|
manifest,
|
|
@@ -13676,12 +13723,12 @@ async function runPluginTerraformCheck() {
|
|
|
13676
13723
|
}
|
|
13677
13724
|
|
|
13678
13725
|
// src/scripts/check-plugin-tool-supply.ts
|
|
13679
|
-
import { existsSync as
|
|
13680
|
-
import { join as
|
|
13726
|
+
import { existsSync as existsSync55 } from "fs";
|
|
13727
|
+
import { join as join65 } from "path";
|
|
13681
13728
|
|
|
13682
13729
|
// src/lib/plugin-tool-supply-audit.ts
|
|
13683
|
-
import { existsSync as
|
|
13684
|
-
import { join as
|
|
13730
|
+
import { existsSync as existsSync54, readFileSync as readFileSync42, readdirSync as readdirSync26, statSync as statSync16 } from "fs";
|
|
13731
|
+
import { join as join64 } from "path";
|
|
13685
13732
|
|
|
13686
13733
|
// src/lib/openrouter-model-snapshot.ts
|
|
13687
13734
|
var OPENROUTER_MODEL_SNAPSHOT_FETCHED_AT = "2026-08-10T06:39:01Z";
|
|
@@ -14098,7 +14145,7 @@ function listDirs(root) {
|
|
|
14098
14145
|
}
|
|
14099
14146
|
return entries.filter((e) => {
|
|
14100
14147
|
try {
|
|
14101
|
-
return statSync16(
|
|
14148
|
+
return statSync16(join64(root, e)).isDirectory();
|
|
14102
14149
|
} catch {
|
|
14103
14150
|
return false;
|
|
14104
14151
|
}
|
|
@@ -14114,7 +14161,7 @@ function walkFiles2(root, accept, skipDir) {
|
|
|
14114
14161
|
return;
|
|
14115
14162
|
}
|
|
14116
14163
|
for (const entry of entries) {
|
|
14117
|
-
const p =
|
|
14164
|
+
const p = join64(dir, entry);
|
|
14118
14165
|
let st;
|
|
14119
14166
|
try {
|
|
14120
14167
|
st = statSync16(p);
|
|
@@ -14140,14 +14187,14 @@ function pluginPythonFiles(pluginDir2) {
|
|
|
14140
14187
|
);
|
|
14141
14188
|
}
|
|
14142
14189
|
function pluginTerraformFiles(pluginDir2) {
|
|
14143
|
-
const tfDir =
|
|
14190
|
+
const tfDir = join64(pluginDir2, "terraform");
|
|
14144
14191
|
let entries;
|
|
14145
14192
|
try {
|
|
14146
14193
|
entries = readdirSync26(tfDir);
|
|
14147
14194
|
} catch {
|
|
14148
14195
|
return [];
|
|
14149
14196
|
}
|
|
14150
|
-
return entries.filter((e) => e.endsWith(".tf")).map((e) =>
|
|
14197
|
+
return entries.filter((e) => e.endsWith(".tf")).map((e) => join64(tfDir, e)).sort();
|
|
14151
14198
|
}
|
|
14152
14199
|
function extractManifestTools(manifestText) {
|
|
14153
14200
|
let parsed;
|
|
@@ -14399,8 +14446,8 @@ function isSnapshotStale(fetchedAt, now) {
|
|
|
14399
14446
|
function normalizeModelId(id) {
|
|
14400
14447
|
return id.endsWith(":online") ? id.slice(0, -":online".length) : id;
|
|
14401
14448
|
}
|
|
14402
|
-
var CONFIG_PY_PATH =
|
|
14403
|
-
var ORCHESTRATION_SCHEMA_PATH =
|
|
14449
|
+
var CONFIG_PY_PATH = join64("services", "api", "src", "api", "config.py");
|
|
14450
|
+
var ORCHESTRATION_SCHEMA_PATH = join64(
|
|
14404
14451
|
"services",
|
|
14405
14452
|
"api",
|
|
14406
14453
|
"src",
|
|
@@ -14412,10 +14459,10 @@ function auditDeclaredModelIds(repoRoot, options = {}) {
|
|
|
14412
14459
|
const knownModelIds = options.knownModelIds ?? OPENROUTER_MODEL_IDS;
|
|
14413
14460
|
const snapshotFetchedAt = options.snapshotFetchedAt ?? OPENROUTER_MODEL_SNAPSHOT_FETCHED_AT;
|
|
14414
14461
|
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
14415
|
-
const configPath =
|
|
14416
|
-
const orchestrationPath =
|
|
14417
|
-
const configMissing = !
|
|
14418
|
-
const orchestrationSchemaMissing = !
|
|
14462
|
+
const configPath = join64(repoRoot, CONFIG_PY_PATH);
|
|
14463
|
+
const orchestrationPath = join64(repoRoot, ORCHESTRATION_SCHEMA_PATH);
|
|
14464
|
+
const configMissing = !existsSync54(configPath);
|
|
14465
|
+
const orchestrationSchemaMissing = !existsSync54(orchestrationPath);
|
|
14419
14466
|
const knownSet = new Set(knownModelIds);
|
|
14420
14467
|
const snapshotEmpty = knownModelIds.length === 0;
|
|
14421
14468
|
const snapshotStale = isSnapshotStale(snapshotFetchedAt, now);
|
|
@@ -14486,7 +14533,7 @@ function auditDeclaredModelIds(repoRoot, options = {}) {
|
|
|
14486
14533
|
function discoverPluginDirs(pluginsRoot) {
|
|
14487
14534
|
return listDirs(pluginsRoot).filter((name) => {
|
|
14488
14535
|
try {
|
|
14489
|
-
return statSync16(
|
|
14536
|
+
return statSync16(join64(pluginsRoot, name, "biffo.plugin.json")).isFile();
|
|
14490
14537
|
} catch {
|
|
14491
14538
|
return false;
|
|
14492
14539
|
}
|
|
@@ -14499,8 +14546,8 @@ function auditPluginToolSupply(pluginsRoot) {
|
|
|
14499
14546
|
let terraformBlind = false;
|
|
14500
14547
|
let totalDeclaredTools = 0;
|
|
14501
14548
|
for (const name of pluginNames) {
|
|
14502
|
-
const pluginDir2 =
|
|
14503
|
-
const manifestText = readFileSync42(
|
|
14549
|
+
const pluginDir2 = join64(pluginsRoot, name);
|
|
14550
|
+
const manifestText = readFileSync42(join64(pluginDir2, "biffo.plugin.json"), "utf8");
|
|
14504
14551
|
const manifest = extractManifestTools(manifestText);
|
|
14505
14552
|
if (manifest.parseError) {
|
|
14506
14553
|
findings.push({
|
|
@@ -14598,7 +14645,7 @@ function auditPluginToolSupply(pluginsRoot) {
|
|
|
14598
14645
|
requiredEnvVars: envResult.envVars,
|
|
14599
14646
|
missingEnvVars: anyWired ? [] : envResult.envVars,
|
|
14600
14647
|
status: anyWired ? "ok" : "missing-env",
|
|
14601
|
-
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 ${
|
|
14648
|
+
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 ${join64(pluginDir2, "terraform")}, so this deployment can never supply it`
|
|
14602
14649
|
});
|
|
14603
14650
|
}
|
|
14604
14651
|
}
|
|
@@ -14631,8 +14678,8 @@ function auditPluginToolSupply(pluginsRoot) {
|
|
|
14631
14678
|
async function runPluginToolSupplyCheck() {
|
|
14632
14679
|
const root = (await execa("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
14633
14680
|
let allOk = true;
|
|
14634
|
-
const pluginsRoot =
|
|
14635
|
-
if (!
|
|
14681
|
+
const pluginsRoot = join65(root, "services", "_plugins");
|
|
14682
|
+
if (!existsSync55(pluginsRoot)) {
|
|
14636
14683
|
console.log("\u2713 plugin tool-supply guard: no services/_plugins/ \u2014 nothing to audit");
|
|
14637
14684
|
} else {
|
|
14638
14685
|
const report = auditPluginToolSupply(pluginsRoot);
|
|
@@ -14662,8 +14709,8 @@ async function runPluginToolSupplyCheck() {
|
|
|
14662
14709
|
console.log(`\u2713 plugin tool-supply guard: ${report.summary}`);
|
|
14663
14710
|
}
|
|
14664
14711
|
}
|
|
14665
|
-
const servicesApiRoot =
|
|
14666
|
-
if (!
|
|
14712
|
+
const servicesApiRoot = join65(root, "services", "api");
|
|
14713
|
+
if (!existsSync55(servicesApiRoot)) {
|
|
14667
14714
|
console.log("\u2713 plugin model-id guard: no services/api/ \u2014 nothing to audit");
|
|
14668
14715
|
} else {
|
|
14669
14716
|
const modelReport = auditDeclaredModelIds(root);
|
|
@@ -15040,12 +15087,12 @@ async function runSharedFileReductionCheck(args) {
|
|
|
15040
15087
|
}
|
|
15041
15088
|
|
|
15042
15089
|
// src/scripts/check-skeleton-drift.ts
|
|
15043
|
-
import { existsSync as
|
|
15044
|
-
import { join as
|
|
15090
|
+
import { existsSync as existsSync56, readdirSync as readdirSync28 } from "fs";
|
|
15091
|
+
import { join as join67 } from "path";
|
|
15045
15092
|
|
|
15046
15093
|
// src/lib/skeleton-drift-guard.ts
|
|
15047
15094
|
import { readFileSync as readFileSync45, readdirSync as readdirSync27, statSync as statSync17 } from "fs";
|
|
15048
|
-
import { join as
|
|
15095
|
+
import { join as join66 } from "path";
|
|
15049
15096
|
var isWorkflow = (rel) => rel.startsWith(".github/workflows/") && (rel.endsWith(".yml") || rel.endsWith(".yaml"));
|
|
15050
15097
|
var isRootLayout = (rel) => rel.endsWith("src/app/layout.tsx");
|
|
15051
15098
|
var uncommented = (contents) => contents.split("\n").filter((line) => !/^\s*(\/\/|\/\*|\*)/.test(line)).join("\n");
|
|
@@ -15109,7 +15156,7 @@ function walk(dir, base = dir) {
|
|
|
15109
15156
|
}
|
|
15110
15157
|
for (const entry of entries) {
|
|
15111
15158
|
if (entry === ".venv" || entry === "node_modules" || entry === ".git") continue;
|
|
15112
|
-
const abs =
|
|
15159
|
+
const abs = join66(dir, entry);
|
|
15113
15160
|
let isDir;
|
|
15114
15161
|
try {
|
|
15115
15162
|
isDir = statSync17(abs).isDirectory();
|
|
@@ -15131,7 +15178,7 @@ function auditSkeleton(skeletonRoot, name, rules = SKELETON_RULES) {
|
|
|
15131
15178
|
if (!rule.appliesTo(rel)) continue;
|
|
15132
15179
|
let contents;
|
|
15133
15180
|
try {
|
|
15134
|
-
contents = readFileSync45(
|
|
15181
|
+
contents = readFileSync45(join66(skeletonRoot, rel), "utf8");
|
|
15135
15182
|
} catch {
|
|
15136
15183
|
continue;
|
|
15137
15184
|
}
|
|
@@ -15160,23 +15207,23 @@ function formatViolations2(violations) {
|
|
|
15160
15207
|
|
|
15161
15208
|
// src/scripts/check-skeleton-drift.ts
|
|
15162
15209
|
function discoverSkeletons(root) {
|
|
15163
|
-
const skeletonsDir =
|
|
15210
|
+
const skeletonsDir = join67(root, "_skeletons");
|
|
15164
15211
|
let entries;
|
|
15165
15212
|
try {
|
|
15166
15213
|
entries = readdirSync28(skeletonsDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
15167
15214
|
} catch {
|
|
15168
15215
|
return [];
|
|
15169
15216
|
}
|
|
15170
|
-
return entries.filter((name) =>
|
|
15217
|
+
return entries.filter((name) => existsSync56(join67(skeletonsDir, name, ".github", "workflows", "ci.yml"))).sort();
|
|
15171
15218
|
}
|
|
15172
15219
|
async function runSkeletonDriftCheck() {
|
|
15173
15220
|
const root = (await execa("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
15174
15221
|
const skeletons = discoverSkeletons(root);
|
|
15175
15222
|
let filesConsidered = 0;
|
|
15176
15223
|
for (const name of skeletons) {
|
|
15177
|
-
const skeletonRoot =
|
|
15224
|
+
const skeletonRoot = join67(root, "_skeletons", name);
|
|
15178
15225
|
filesConsidered += findWorkflowFiles(skeletonRoot).length;
|
|
15179
|
-
if (
|
|
15226
|
+
if (existsSync56(join67(skeletonRoot, "apps", "frontend", "src", "app", "layout.tsx"))) {
|
|
15180
15227
|
filesConsidered += 1;
|
|
15181
15228
|
}
|
|
15182
15229
|
}
|
|
@@ -15184,13 +15231,19 @@ async function runSkeletonDriftCheck() {
|
|
|
15184
15231
|
`audited ${skeletons.length} skeleton(s) (${skeletons.join(", ") || "none"}), ${filesConsidered} file(s) considered, under ${root}/_skeletons`
|
|
15185
15232
|
);
|
|
15186
15233
|
if (skeletons.length === 0) {
|
|
15234
|
+
if (!existsSync56(join67(root, "_skeletons"))) {
|
|
15235
|
+
console.log(
|
|
15236
|
+
`\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.`
|
|
15237
|
+
);
|
|
15238
|
+
return;
|
|
15239
|
+
}
|
|
15187
15240
|
console.error(
|
|
15188
15241
|
"\u2717 Skeleton-drift guard: found 0 repo skeletons under _skeletons/ \u2014 this looks like a broken scan, not a repo with no scaffolding. Refusing to report success over zero input."
|
|
15189
15242
|
);
|
|
15190
15243
|
process.exit(1);
|
|
15191
15244
|
}
|
|
15192
15245
|
const violations = skeletons.flatMap(
|
|
15193
|
-
(name) => auditSkeleton(
|
|
15246
|
+
(name) => auditSkeleton(join67(root, "_skeletons", name), name)
|
|
15194
15247
|
);
|
|
15195
15248
|
if (violations.length > 0) {
|
|
15196
15249
|
console.error("\u2717 Skeleton-drift guard: drift found between this repo and its scaffolding\n");
|
|
@@ -15386,8 +15439,8 @@ function rawArgsAfter(subcommand) {
|
|
|
15386
15439
|
}
|
|
15387
15440
|
|
|
15388
15441
|
// src/commands/doctor.ts
|
|
15389
|
-
import { existsSync as
|
|
15390
|
-
import { join as
|
|
15442
|
+
import { existsSync as existsSync57, readFileSync as readFileSync46 } from "fs";
|
|
15443
|
+
import { join as join68, resolve as resolve20 } from "path";
|
|
15391
15444
|
import chalk21 from "chalk";
|
|
15392
15445
|
import { Command as Command25 } from "commander";
|
|
15393
15446
|
|
|
@@ -15782,8 +15835,8 @@ async function runDoctorFixBranches(cwd, facts, deps = { git: new GitAdapter(),
|
|
|
15782
15835
|
return reapAllBareBranches(cwd, facts.branches, facts.worktrees, facts.currentBranch, deps);
|
|
15783
15836
|
}
|
|
15784
15837
|
function readLocalCoreVersion(cwd) {
|
|
15785
|
-
const path =
|
|
15786
|
-
if (!
|
|
15838
|
+
const path = join68(cwd, INSTANCE_CORE_FILE);
|
|
15839
|
+
if (!existsSync57(path)) return null;
|
|
15787
15840
|
try {
|
|
15788
15841
|
return extractVersionField(readFileSync46(path, "utf8"));
|
|
15789
15842
|
} catch {
|
|
@@ -15805,8 +15858,8 @@ function extractVersionField(contents) {
|
|
|
15805
15858
|
return match?.[1] ?? null;
|
|
15806
15859
|
}
|
|
15807
15860
|
function readFossil(cwd) {
|
|
15808
|
-
const path =
|
|
15809
|
-
if (!
|
|
15861
|
+
const path = join68(cwd, CORE_VERSION_FILE);
|
|
15862
|
+
if (!existsSync57(path)) return null;
|
|
15810
15863
|
try {
|
|
15811
15864
|
const value = readFileSync46(path, "utf8").trim();
|
|
15812
15865
|
return value === "" ? null : value;
|
|
@@ -16337,13 +16390,13 @@ import { fileURLToPath as fileURLToPath6 } from "url";
|
|
|
16337
16390
|
import { Command as Command27 } from "commander";
|
|
16338
16391
|
|
|
16339
16392
|
// src/lib/packaged-scripts.ts
|
|
16340
|
-
import { existsSync as
|
|
16341
|
-
import { dirname as dirname11, join as
|
|
16393
|
+
import { existsSync as existsSync58 } from "fs";
|
|
16394
|
+
import { dirname as dirname11, join as join69 } from "path";
|
|
16342
16395
|
function findPackagedScript(startDir, relativePath) {
|
|
16343
16396
|
let dir = startDir;
|
|
16344
16397
|
for (; ; ) {
|
|
16345
|
-
const candidate =
|
|
16346
|
-
if (
|
|
16398
|
+
const candidate = join69(dir, relativePath);
|
|
16399
|
+
if (existsSync58(candidate)) return candidate;
|
|
16347
16400
|
const parent = dirname11(dir);
|
|
16348
16401
|
if (parent === dir) return null;
|
|
16349
16402
|
dir = parent;
|