@outfitter/tooling 0.2.1 → 0.2.2

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/cli/index.js CHANGED
@@ -1,23 +1,532 @@
1
1
  #!/usr/bin/env bun
2
- // @bun
3
- import {
4
- runCheck
5
- } from "../shared/@outfitter/tooling-xx1146e3.js";
6
- import {
7
- runInit
8
- } from "../shared/@outfitter/tooling-xaxdr9da.js";
9
- import {
10
- runPrePush
11
- } from "../shared/@outfitter/tooling-qm7jeg0d.js";
12
- import {
13
- runFix
14
- } from "../shared/@outfitter/tooling-s4eqq91d.js";
15
- import {
16
- runUpgradeBun
17
- } from "../shared/@outfitter/tooling-75j500dv.js";
18
2
 
19
- // packages/tooling/src/cli/index.ts
3
+ // src/cli/index.ts
20
4
  import { Command } from "commander";
5
+
6
+ // src/cli/check.ts
7
+ function buildCheckCommand(options) {
8
+ const cmd = ["ultracite", "check"];
9
+ if (options.paths && options.paths.length > 0) {
10
+ cmd.push(...options.paths);
11
+ }
12
+ return cmd;
13
+ }
14
+ async function runCheck(paths = []) {
15
+ const cmd = buildCheckCommand({ paths });
16
+ process.stdout.write(`Running: bun x ${cmd.join(" ")}
17
+ `);
18
+ const proc = Bun.spawn(["bun", "x", ...cmd], {
19
+ stdio: ["inherit", "inherit", "inherit"]
20
+ });
21
+ const exitCode = await proc.exited;
22
+ process.exit(exitCode);
23
+ }
24
+
25
+ // src/cli/fix.ts
26
+ function buildFixCommand(options) {
27
+ const cmd = ["ultracite", "fix"];
28
+ if (options.paths && options.paths.length > 0) {
29
+ cmd.push(...options.paths);
30
+ }
31
+ return cmd;
32
+ }
33
+ async function runFix(paths = []) {
34
+ const cmd = buildFixCommand({ paths });
35
+ process.stdout.write(`Running: bun x ${cmd.join(" ")}
36
+ `);
37
+ const proc = Bun.spawn(["bun", "x", ...cmd], {
38
+ stdio: ["inherit", "inherit", "inherit"]
39
+ });
40
+ const exitCode = await proc.exited;
41
+ process.exit(exitCode);
42
+ }
43
+
44
+ // src/cli/init.ts
45
+ var FRAMEWORK_DETECTORS = {
46
+ react: ["react", "react-dom"],
47
+ next: ["next"],
48
+ vue: ["vue"],
49
+ nuxt: ["nuxt"],
50
+ svelte: ["svelte"],
51
+ angular: ["@angular/core"],
52
+ solid: ["solid-js"],
53
+ astro: ["astro"],
54
+ remix: ["@remix-run/react"],
55
+ qwik: ["@builder.io/qwik"]
56
+ };
57
+ function detectFrameworks(pkg) {
58
+ const allDeps = {
59
+ ...pkg.dependencies,
60
+ ...pkg.devDependencies
61
+ };
62
+ const detected = [];
63
+ for (const [framework, packages] of Object.entries(FRAMEWORK_DETECTORS)) {
64
+ if (packages.some((p) => (p in allDeps))) {
65
+ detected.push(framework);
66
+ }
67
+ }
68
+ if (detected.length === 0) {
69
+ return [];
70
+ }
71
+ return ["--frameworks", ...detected];
72
+ }
73
+ function buildUltraciteCommand(options) {
74
+ const cmd = [
75
+ "ultracite",
76
+ "init",
77
+ "--linter",
78
+ "biome",
79
+ "--pm",
80
+ "bun",
81
+ "--quiet"
82
+ ];
83
+ if (options.frameworks && options.frameworks.length > 0) {
84
+ cmd.push("--frameworks", ...options.frameworks);
85
+ }
86
+ return cmd;
87
+ }
88
+ async function runInit(cwd = process.cwd()) {
89
+ const pkgPath = `${cwd}/package.json`;
90
+ const pkgFile = Bun.file(pkgPath);
91
+ if (!await pkgFile.exists()) {
92
+ process.stderr.write(`No package.json found in current directory
93
+ `);
94
+ process.exit(1);
95
+ }
96
+ const pkg = await pkgFile.json();
97
+ const frameworkFlags = detectFrameworks(pkg);
98
+ const frameworks = frameworkFlags.length > 0 ? frameworkFlags.slice(1) : [];
99
+ const cmd = buildUltraciteCommand({ frameworks });
100
+ process.stdout.write(`Running: bun x ${cmd.join(" ")}
101
+ `);
102
+ const proc = Bun.spawn(["bun", "x", ...cmd], {
103
+ cwd,
104
+ stdio: ["inherit", "inherit", "inherit"]
105
+ });
106
+ const exitCode = await proc.exited;
107
+ process.exit(exitCode);
108
+ }
109
+
110
+ // src/cli/pre-push.ts
111
+ import { existsSync, readFileSync } from "node:fs";
112
+ import { join } from "node:path";
113
+ var COLORS = {
114
+ reset: "\x1B[0m",
115
+ red: "\x1B[31m",
116
+ green: "\x1B[32m",
117
+ yellow: "\x1B[33m",
118
+ blue: "\x1B[34m"
119
+ };
120
+ function log(msg) {
121
+ process.stdout.write(`${msg}
122
+ `);
123
+ }
124
+ function getCurrentBranch() {
125
+ const result = Bun.spawnSync(["git", "rev-parse", "--abbrev-ref", "HEAD"]);
126
+ return result.stdout.toString().trim();
127
+ }
128
+ function runGit(args) {
129
+ try {
130
+ const result = Bun.spawnSync(["git", ...args], { stderr: "ignore" });
131
+ if (result.exitCode !== 0) {
132
+ return { ok: false, lines: [] };
133
+ }
134
+ return {
135
+ ok: true,
136
+ lines: result.stdout.toString().split(`
137
+ `).map((line) => line.trim()).filter(Boolean)
138
+ };
139
+ } catch {
140
+ return { ok: false, lines: [] };
141
+ }
142
+ }
143
+ function isRedPhaseBranch(branch) {
144
+ return branch.endsWith("-tests") || branch.endsWith("/tests") || branch.endsWith("_tests");
145
+ }
146
+ function isScaffoldBranch(branch) {
147
+ return branch.endsWith("-scaffold") || branch.endsWith("/scaffold") || branch.endsWith("_scaffold");
148
+ }
149
+ var TEST_PATH_PATTERNS = [
150
+ /(^|\/)__tests__\//,
151
+ /(^|\/)__snapshots__\//,
152
+ /\.(test|spec)\.[cm]?[jt]sx?$/,
153
+ /\.snap$/,
154
+ /(^|\/)(vitest|jest|bun)\.config\.[cm]?[jt]s$/,
155
+ /(^|\/)tsconfig\.test\.json$/,
156
+ /(^|\/)\.env\.test(\.|$)/
157
+ ];
158
+ function isTestOnlyPath(path) {
159
+ const normalized = path.replaceAll("\\", "/");
160
+ return TEST_PATH_PATTERNS.some((pattern) => pattern.test(normalized));
161
+ }
162
+ function areFilesTestOnly(paths) {
163
+ return paths.length > 0 && paths.every((path) => isTestOnlyPath(path));
164
+ }
165
+ function canBypassRedPhaseByChangedFiles(changedFiles) {
166
+ return changedFiles.deterministic && areFilesTestOnly(changedFiles.files);
167
+ }
168
+ function resolveBaseRef() {
169
+ const candidates = [
170
+ "origin/main",
171
+ "main",
172
+ "origin/trunk",
173
+ "trunk",
174
+ "origin/master",
175
+ "master"
176
+ ];
177
+ for (const candidate of candidates) {
178
+ const resolved = runGit(["rev-parse", "--verify", "--quiet", candidate]);
179
+ if (resolved.ok) {
180
+ return candidate;
181
+ }
182
+ }
183
+ return;
184
+ }
185
+ function changedFilesFromRange(range) {
186
+ const result = runGit(["diff", "--name-only", "--diff-filter=d", range]);
187
+ return {
188
+ ok: result.ok,
189
+ files: result.lines
190
+ };
191
+ }
192
+ function getChangedFilesForPush() {
193
+ const upstream = runGit([
194
+ "rev-parse",
195
+ "--abbrev-ref",
196
+ "--symbolic-full-name",
197
+ "@{upstream}"
198
+ ]);
199
+ if (upstream.ok && upstream.lines[0]) {
200
+ const rangeResult = changedFilesFromRange(`${upstream.lines[0]}...HEAD`);
201
+ if (rangeResult.ok) {
202
+ return {
203
+ files: rangeResult.files,
204
+ deterministic: true,
205
+ source: "upstream"
206
+ };
207
+ }
208
+ }
209
+ const baseRef = resolveBaseRef();
210
+ if (baseRef) {
211
+ const rangeResult = changedFilesFromRange(`${baseRef}...HEAD`);
212
+ if (rangeResult.ok) {
213
+ return {
214
+ files: rangeResult.files,
215
+ deterministic: true,
216
+ source: "baseRef"
217
+ };
218
+ }
219
+ }
220
+ return {
221
+ files: [],
222
+ deterministic: false,
223
+ source: "undetermined"
224
+ };
225
+ }
226
+ function maybeSkipForRedPhase(reason, branch) {
227
+ const changedFiles = getChangedFilesForPush();
228
+ if (!changedFiles.deterministic) {
229
+ log(`${COLORS.yellow}RED-phase bypass denied${COLORS.reset}: could not determine full push diff range`);
230
+ log("Running strict verification.");
231
+ log("");
232
+ return false;
233
+ }
234
+ if (!canBypassRedPhaseByChangedFiles(changedFiles)) {
235
+ log(`${COLORS.yellow}RED-phase bypass denied${COLORS.reset}: changed files are not test-only`);
236
+ if (changedFiles.files.length > 0) {
237
+ log(`Changed files (${changedFiles.source}): ${changedFiles.files.join(", ")}`);
238
+ } else {
239
+ log(`No changed files detected in ${changedFiles.source} range. Running strict verification.`);
240
+ }
241
+ log("");
242
+ return false;
243
+ }
244
+ if (reason === "branch") {
245
+ log(`${COLORS.yellow}TDD RED phase${COLORS.reset} detected: ${COLORS.blue}${branch}${COLORS.reset}`);
246
+ } else {
247
+ log(`${COLORS.yellow}Scaffold branch${COLORS.reset} with RED phase branch in context: ${COLORS.blue}${branch}${COLORS.reset}`);
248
+ }
249
+ log(`${COLORS.yellow}Skipping strict verification${COLORS.reset} - changed files are test-only`);
250
+ log(`Diff source: ${changedFiles.source}`);
251
+ log("");
252
+ log("Remember: GREEN phase (implementation) must make these tests pass!");
253
+ return true;
254
+ }
255
+ function hasRedPhaseBranchInContext(currentBranch) {
256
+ let branches = [];
257
+ try {
258
+ const gtResult = Bun.spawnSync(["gt", "ls"], { stderr: "pipe" });
259
+ if (gtResult.exitCode === 0) {
260
+ branches = gtResult.stdout.toString().split(`
261
+ `).map((line) => line.replace(/^[│├└─◉◯ ]*/g, "").replace(/ \(.*/, "")).filter(Boolean);
262
+ }
263
+ } catch {}
264
+ if (branches.length === 0) {
265
+ const gitResult = Bun.spawnSync([
266
+ "git",
267
+ "branch",
268
+ "--list",
269
+ "cli/*",
270
+ "types/*",
271
+ "contracts/*"
272
+ ]);
273
+ branches = gitResult.stdout.toString().split(`
274
+ `).map((line) => line.replace(/^[* ]+/, "")).filter(Boolean);
275
+ }
276
+ for (const branch of branches) {
277
+ if (branch === currentBranch)
278
+ continue;
279
+ if (isRedPhaseBranch(branch))
280
+ return true;
281
+ }
282
+ return false;
283
+ }
284
+ function createVerificationPlan(scripts) {
285
+ if (scripts["verify:ci"]) {
286
+ return { ok: true, scripts: ["verify:ci"], source: "verify:ci" };
287
+ }
288
+ const requiredScripts = ["typecheck", "build", "test"];
289
+ const missingRequired = requiredScripts.filter((name) => !scripts[name]);
290
+ const checkOrLint = scripts["check"] ? "check" : scripts["lint"] ? "lint" : undefined;
291
+ if (!checkOrLint || missingRequired.length > 0) {
292
+ const missing = checkOrLint ? missingRequired : [...missingRequired, "check|lint"];
293
+ return {
294
+ ok: false,
295
+ error: `Missing required scripts for strict pre-push verification: ${missing.join(", ")}`
296
+ };
297
+ }
298
+ return {
299
+ ok: true,
300
+ scripts: ["typecheck", checkOrLint, "build", "test"],
301
+ source: "fallback"
302
+ };
303
+ }
304
+ function readPackageScripts(cwd = process.cwd()) {
305
+ const packageJsonPath = join(cwd, "package.json");
306
+ if (!existsSync(packageJsonPath)) {
307
+ return {};
308
+ }
309
+ try {
310
+ const parsed = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
311
+ const scripts = parsed.scripts ?? {};
312
+ const normalized = {};
313
+ for (const [name, value] of Object.entries(scripts)) {
314
+ if (typeof value === "string") {
315
+ normalized[name] = value;
316
+ }
317
+ }
318
+ return normalized;
319
+ } catch {
320
+ return {};
321
+ }
322
+ }
323
+ function runScript(scriptName) {
324
+ log("");
325
+ log(`Running: ${COLORS.blue}bun run ${scriptName}${COLORS.reset}`);
326
+ const result = Bun.spawnSync(["bun", "run", scriptName], {
327
+ stdio: ["inherit", "inherit", "inherit"]
328
+ });
329
+ return result.exitCode === 0;
330
+ }
331
+ async function runPrePush(options = {}) {
332
+ log(`${COLORS.blue}Pre-push verify${COLORS.reset} (TDD-aware)`);
333
+ log("");
334
+ const branch = getCurrentBranch();
335
+ if (isRedPhaseBranch(branch)) {
336
+ if (maybeSkipForRedPhase("branch", branch)) {
337
+ process.exit(0);
338
+ }
339
+ }
340
+ if (isScaffoldBranch(branch)) {
341
+ if (hasRedPhaseBranchInContext(branch)) {
342
+ if (maybeSkipForRedPhase("context", branch)) {
343
+ process.exit(0);
344
+ }
345
+ }
346
+ }
347
+ if (options.force) {
348
+ log(`${COLORS.yellow}Force flag set${COLORS.reset} - skipping strict verification`);
349
+ process.exit(0);
350
+ }
351
+ const plan = createVerificationPlan(readPackageScripts());
352
+ if (!plan.ok) {
353
+ log(`${COLORS.red}Strict pre-push verification is not configured${COLORS.reset}`);
354
+ log(plan.error);
355
+ log("");
356
+ log("Add one of:");
357
+ log(" - verify:ci");
358
+ log(" - typecheck + (check or lint) + build + test");
359
+ process.exit(1);
360
+ }
361
+ log(`Running strict verification for branch: ${COLORS.blue}${branch}${COLORS.reset}`);
362
+ if (plan.source === "verify:ci") {
363
+ log("Using `verify:ci` script.");
364
+ } else {
365
+ log(`Using fallback scripts: ${plan.scripts.join(" -> ")}`);
366
+ }
367
+ for (const scriptName of plan.scripts) {
368
+ if (runScript(scriptName)) {
369
+ continue;
370
+ }
371
+ log("");
372
+ log(`${COLORS.red}Verification failed${COLORS.reset} on script: ${scriptName}`);
373
+ log("");
374
+ log("If this is intentional TDD RED phase work, name your branch:");
375
+ log(" - feature-tests");
376
+ log(" - feature/tests");
377
+ log(" - feature_tests");
378
+ process.exit(1);
379
+ }
380
+ log("");
381
+ log(`${COLORS.green}Strict verification passed${COLORS.reset}`);
382
+ process.exit(0);
383
+ }
384
+
385
+ // src/cli/upgrade-bun.ts
386
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "node:fs";
387
+ import { join as join2 } from "node:path";
388
+ var COLORS2 = {
389
+ reset: "\x1B[0m",
390
+ red: "\x1B[31m",
391
+ green: "\x1B[32m",
392
+ yellow: "\x1B[33m",
393
+ blue: "\x1B[34m"
394
+ };
395
+ function log2(msg) {
396
+ process.stdout.write(`${msg}
397
+ `);
398
+ }
399
+ function info(msg) {
400
+ process.stdout.write(`${COLORS2.blue}▸${COLORS2.reset} ${msg}
401
+ `);
402
+ }
403
+ function success(msg) {
404
+ process.stdout.write(`${COLORS2.green}✓${COLORS2.reset} ${msg}
405
+ `);
406
+ }
407
+ function warn(msg) {
408
+ process.stdout.write(`${COLORS2.yellow}!${COLORS2.reset} ${msg}
409
+ `);
410
+ }
411
+ async function fetchLatestVersion() {
412
+ const response = await fetch("https://api.github.com/repos/oven-sh/bun/releases/latest");
413
+ const data = await response.json();
414
+ const match = data.tag_name.match(/bun-v(.+)/);
415
+ if (!match?.[1]) {
416
+ throw new Error(`Could not parse version from tag: ${data.tag_name}`);
417
+ }
418
+ return match[1];
419
+ }
420
+ function findPackageJsonFiles(dir) {
421
+ const results = [];
422
+ const glob = new Bun.Glob("**/package.json");
423
+ for (const path of glob.scanSync({ cwd: dir })) {
424
+ if (!path.includes("node_modules")) {
425
+ results.push(join2(dir, path));
426
+ }
427
+ }
428
+ return results;
429
+ }
430
+ function updateEnginesBun(filePath, version) {
431
+ const content = readFileSync2(filePath, "utf-8");
432
+ const pattern = /"bun":\s*">=[\d.]+"/;
433
+ if (!pattern.test(content)) {
434
+ return false;
435
+ }
436
+ const updated = content.replace(pattern, `"bun": ">=${version}"`);
437
+ if (updated !== content) {
438
+ writeFileSync(filePath, updated);
439
+ return true;
440
+ }
441
+ return false;
442
+ }
443
+ function updateTypesBun(filePath, version) {
444
+ const content = readFileSync2(filePath, "utf-8");
445
+ const pattern = /"@types\/bun":\s*"\^[\d.]+"/;
446
+ if (!pattern.test(content)) {
447
+ return false;
448
+ }
449
+ const updated = content.replace(pattern, `"@types/bun": "^${version}"`);
450
+ if (updated !== content) {
451
+ writeFileSync(filePath, updated);
452
+ return true;
453
+ }
454
+ return false;
455
+ }
456
+ async function runUpgradeBun(targetVersion, options = {}) {
457
+ const cwd = process.cwd();
458
+ const bunVersionFile = join2(cwd, ".bun-version");
459
+ let version = targetVersion;
460
+ if (!version) {
461
+ info("Fetching latest Bun version...");
462
+ version = await fetchLatestVersion();
463
+ log2(`Latest version: ${version}`);
464
+ }
465
+ const currentVersion = existsSync2(bunVersionFile) ? readFileSync2(bunVersionFile, "utf-8").trim() : "unknown";
466
+ log2(`Current version: ${currentVersion}`);
467
+ if (currentVersion === version) {
468
+ success(`Already on version ${version}`);
469
+ return;
470
+ }
471
+ log2("");
472
+ info(`Upgrading Bun: ${currentVersion} → ${version}`);
473
+ log2("");
474
+ writeFileSync(bunVersionFile, `${version}
475
+ `);
476
+ success("Updated .bun-version");
477
+ const packageFiles = findPackageJsonFiles(cwd);
478
+ info("Updating engines.bun...");
479
+ for (const file of packageFiles) {
480
+ if (updateEnginesBun(file, version)) {
481
+ log2(` ${file.replace(`${cwd}/`, "")}`);
482
+ }
483
+ }
484
+ info("Updating @types/bun...");
485
+ for (const file of packageFiles) {
486
+ if (updateTypesBun(file, version)) {
487
+ log2(` ${file.replace(`${cwd}/`, "")}`);
488
+ }
489
+ }
490
+ if (options.install !== false) {
491
+ log2("");
492
+ info(`Installing Bun ${version}...`);
493
+ const installResult = Bun.spawnSync([
494
+ "bash",
495
+ "-c",
496
+ `curl -fsSL https://bun.sh/install | bash -s "bun-v${version}"`
497
+ ]);
498
+ if (installResult.exitCode !== 0) {
499
+ warn("Could not install Bun automatically");
500
+ log2("Install manually: curl -fsSL https://bun.sh/install | bash");
501
+ } else {
502
+ success(`Bun ${version} installed`);
503
+ log2("");
504
+ info("Updating lockfile...");
505
+ const bunInstall = Bun.spawnSync(["bun", "install"], {
506
+ cwd,
507
+ env: {
508
+ ...process.env,
509
+ BUN_INSTALL: `${process.env["HOME"]}/.bun`,
510
+ PATH: `${process.env["HOME"]}/.bun/bin:${process.env["PATH"]}`
511
+ }
512
+ });
513
+ if (bunInstall.exitCode === 0) {
514
+ success("Lockfile updated");
515
+ } else {
516
+ warn("Could not update lockfile - run 'bun install' manually");
517
+ }
518
+ }
519
+ }
520
+ log2("");
521
+ success("Done! Changes ready to commit:");
522
+ log2(" - .bun-version");
523
+ log2(" - package.json files (engines.bun, @types/bun)");
524
+ log2(" - bun.lock");
525
+ log2("");
526
+ log2(`Commit with: git add -A && git commit -m 'chore: upgrade Bun to ${version}'`);
527
+ }
528
+
529
+ // src/cli/index.ts
21
530
  var program = new Command;
22
531
  program.name("tooling").description("Dev tooling configuration management for Outfitter projects").version("0.1.0-rc.1");
23
532
  program.command("init").description("Initialize tooling config in the current project").action(async () => {
@@ -32,7 +541,7 @@ program.command("fix").description("Fix linting issues (wraps ultracite)").argum
32
541
  program.command("upgrade-bun").description("Upgrade Bun version across the project").argument("[version]", "Target version (defaults to latest)").option("--no-install", "Skip installing Bun and updating lockfile").action(async (version, options) => {
33
542
  await runUpgradeBun(version, options);
34
543
  });
35
- program.command("pre-push").description("TDD-aware pre-push test hook").option("-f, --force", "Skip tests entirely").action(async (options) => {
544
+ program.command("pre-push").description("TDD-aware pre-push strict verification hook").option("-f, --force", "Skip strict verification entirely").action(async (options) => {
36
545
  await runPrePush(options);
37
546
  });
38
547
  program.parse();
package/dist/cli/init.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  buildUltraciteCommand,
4
4
  detectFrameworks,
5
5
  runInit
6
- } from "../shared/@outfitter/tooling-xaxdr9da.js";
6
+ } from "../shared/@outfitter/tooling-mxwc1n8w.js";
7
7
  export {
8
8
  runInit,
9
9
  detectFrameworks,
@@ -1,3 +1,36 @@
1
+ /**
2
+ * Check if branch is a TDD RED phase branch
3
+ */
4
+ declare function isRedPhaseBranch(branch: string): boolean;
5
+ /**
6
+ * Check if branch is a scaffold branch
7
+ */
8
+ declare function isScaffoldBranch(branch: string): boolean;
9
+ declare function isTestOnlyPath(path: string): boolean;
10
+ declare function areFilesTestOnly(paths: readonly string[]): boolean;
11
+ interface PushChangedFiles {
12
+ readonly files: readonly string[];
13
+ readonly deterministic: boolean;
14
+ readonly source: "upstream" | "baseRef" | "undetermined";
15
+ }
16
+ declare function canBypassRedPhaseByChangedFiles(changedFiles: PushChangedFiles): boolean;
17
+ type ScriptMap = Readonly<Record<string, string | undefined>>;
18
+ type VerificationPlan = {
19
+ readonly ok: true;
20
+ readonly scripts: readonly string[];
21
+ readonly source: "verify:ci" | "fallback";
22
+ } | {
23
+ readonly ok: false;
24
+ readonly error: string;
25
+ };
26
+ /**
27
+ * Derive strict pre-push verification from package scripts.
28
+ *
29
+ * Priority:
30
+ * 1) `verify:ci`
31
+ * 2) fallback sequence: `typecheck`, `check|lint`, `build`, `test`
32
+ */
33
+ declare function createVerificationPlan(scripts: ScriptMap): VerificationPlan;
1
34
  interface PrePushOptions {
2
35
  force?: boolean;
3
36
  }
@@ -5,4 +38,4 @@ interface PrePushOptions {
5
38
  * Main pre-push command
6
39
  */
7
40
  declare function runPrePush(options?: PrePushOptions): Promise<void>;
8
- export { runPrePush, PrePushOptions };
41
+ export { runPrePush, isTestOnlyPath, isScaffoldBranch, isRedPhaseBranch, createVerificationPlan, canBypassRedPhaseByChangedFiles, areFilesTestOnly, VerificationPlan, PushChangedFiles, PrePushOptions };
@@ -1,7 +1,19 @@
1
1
  // @bun
2
2
  import {
3
+ areFilesTestOnly,
4
+ canBypassRedPhaseByChangedFiles,
5
+ createVerificationPlan,
6
+ isRedPhaseBranch,
7
+ isScaffoldBranch,
8
+ isTestOnlyPath,
3
9
  runPrePush
4
- } from "../shared/@outfitter/tooling-qm7jeg0d.js";
10
+ } from "../shared/@outfitter/tooling-8sd32ts6.js";
5
11
  export {
6
- runPrePush
12
+ runPrePush,
13
+ isTestOnlyPath,
14
+ isScaffoldBranch,
15
+ isRedPhaseBranch,
16
+ createVerificationPlan,
17
+ canBypassRedPhaseByChangedFiles,
18
+ areFilesTestOnly
7
19
  };
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  runUpgradeBun
4
- } from "../shared/@outfitter/tooling-75j500dv.js";
4
+ } from "../shared/@outfitter/tooling-9yzd08v1.js";
5
5
  export {
6
6
  runUpgradeBun
7
7
  };