@kungfu-tech/buildchain 3.0.4-alpha.1 → 3.0.4-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/AGENTS.md +14 -5
  2. package/README.md +18 -0
  3. package/bin/buildchain.mjs +136 -73
  4. package/bin/internal/trust-release-cli.mjs +15 -537
  5. package/bin/internal/trust-release-command-handlers.mjs +14 -0
  6. package/bin/internal/trust-release-inspection-handlers.mjs +175 -0
  7. package/bin/internal/trust-release-release-handlers.mjs +317 -0
  8. package/bin/internal/trust-release-verification-handlers.mjs +306 -0
  9. package/dist/site/buildchain-contract.json +35 -24
  10. package/dist/site/buildchain-site.json +1474 -61
  11. package/dist/site/capability-registry.json +8 -5
  12. package/dist/site/cli-registry.json +1869 -0
  13. package/dist/site/controller-registry.json +16 -3
  14. package/dist/site/kfd-claims.json +84 -10
  15. package/dist/site/kfd-upstream-aggregate.json +1 -1
  16. package/dist/site/manual-registry.json +49 -6
  17. package/dist/site/node-api-registry.json +17802 -11
  18. package/dist/site/page-registry.json +1441 -59
  19. package/dist/site/public-surface-audit.json +2863 -358
  20. package/dist/site/publication-registry.json +4 -4
  21. package/dist/site/release-model.json +7 -0
  22. package/dist/site/site-manifest.json +34 -10
  23. package/dist/site/workflow-registry.json +13 -5
  24. package/docs/MAP.md +21 -6
  25. package/docs/cli-reference.md +1936 -0
  26. package/docs/cli.md +15 -1
  27. package/docs/getting-started.md +167 -0
  28. package/docs/install.md +7 -8
  29. package/docs/node-api-reference.md +1952 -0
  30. package/docs/release-propagation.md +166 -8
  31. package/docs/site-bundle-contract.md +10 -4
  32. package/docs/versioning.md +5 -4
  33. package/package.json +8 -5
  34. package/packages/core/buildchain-agent-manuals.js +37 -0
  35. package/packages/core/buildchain-kfd-claims.js +4 -37
  36. package/packages/core/controller-evidence.js +8 -1
  37. package/packages/core/index.js +1 -13
  38. package/packages/core/paper-agent-entry.js +14 -11
  39. package/packages/core/paper-fleet.js +34 -7
  40. package/packages/core/paper-npm-bootstrap.js +492 -0
  41. package/packages/core/paper-repository.js +1 -0
  42. package/packages/core/paper.js +346 -671
  43. package/packages/core/public-surface-cli.js +12 -1
  44. package/packages/core/publication-package.js +7 -0
  45. package/packages/core/release-passport.js +67 -71
  46. package/packages/core/release-propagation-common.js +64 -0
  47. package/packages/core/release-propagation-execution-profile.js +59 -0
  48. package/packages/core/release-propagation-release.js +196 -0
  49. package/packages/core/release-propagation-stage-evidence.js +364 -0
  50. package/packages/core/release-propagation-work-capture.js +64 -0
  51. package/packages/core/release-propagation-work-constants.js +34 -0
  52. package/packages/core/release-propagation-work-control.js +203 -0
  53. package/packages/core/release-propagation-work-transitions.js +145 -0
  54. package/packages/core/release-propagation-work.js +517 -0
  55. package/packages/core/release-propagation.js +34 -158
  56. package/scripts/aws-windows-jit-controller-core.mjs +269 -0
  57. package/scripts/aws-windows-jit-controller.mjs +502 -0
  58. package/scripts/check-internal-architecture.mjs +178 -52
  59. package/scripts/check-inventory.mjs +2 -2
  60. package/scripts/check-maintainability.mjs +76 -17
  61. package/scripts/generate-public-reference.mjs +68 -0
  62. package/scripts/generate-site-bundle.mjs +35 -41
  63. package/scripts/maintainability-metrics.mjs +24 -4
  64. package/scripts/paper-work-fleet-cli.mjs +22 -3
  65. package/scripts/public-reference.mjs +557 -0
  66. package/scripts/release-propagation.mjs +126 -0
  67. package/scripts/resolve-artifact-transfer-mode.mjs +117 -0
  68. package/scripts/site-reference-registry.mjs +174 -0
  69. package/scripts/verify-golden-path.mjs +169 -0
  70. package/scripts/web-surface-core.mjs +46 -207
  71. package/scripts/web-surface-routing.mjs +286 -0
package/AGENTS.md CHANGED
@@ -6,9 +6,14 @@ restating them.
6
6
 
7
7
  ## Are you using Buildchain, or building it?
8
8
 
9
- - **Using Buildchain** - initialize a repository, call a reusable workflow, run
10
- a release dry-run, or inspect the release model: start at the documentation
11
- map, [`docs/MAP.md`](docs/MAP.md).
9
+ - **Adopting Buildchain for the first time** - follow the 15-30 minute
10
+ [`Golden Path`](docs/getting-started.md).
11
+ - **Looking up a CLI command** - use the generated
12
+ [`CLI Reference`](docs/cli-reference.md).
13
+ - **Writing Node build automation** - use the generated
14
+ [`Node API Reference`](docs/node-api-reference.md).
15
+ - **Exploring advanced workflows, release governance, or product
16
+ capabilities** - start at the [`Documentation Map`](docs/MAP.md).
12
17
  - **Building or contributing to this repo** - read the rest of this file, then
13
18
  [`CONTRIBUTING.md`](CONTRIBUTING.md).
14
19
 
@@ -74,8 +79,9 @@ pnpm install --frozen-lockfile
74
79
  pnpm run check
75
80
  ```
76
81
 
77
- `pnpm run check` validates inventory data, lints root workflows, runs unit tests,
78
- and rebuilds every action bundle.
82
+ `pnpm run check` validates inventory data, generated public references and site
83
+ bundle drift, lints root workflows, runs unit tests, and rebuilds every action
84
+ bundle.
79
85
 
80
86
  Before broad maintenance or consolidation work, read the current engineering
81
87
  handoff in
@@ -109,6 +115,9 @@ handoff in
109
115
  - Do not build or document official release integrations that bypass provider
110
116
  protections, hide credential boundaries, or forge release evidence.
111
117
  - Keep generated action bundles in sync with source changes.
118
+ - When public documentation, CLI usage authority, or package exports change,
119
+ follow the [Site Bundle Contract generation steps](docs/site-bundle-contract.md#generation)
120
+ and commit the updated generated references and `dist/site/` facts.
112
121
  - Keep documentation in sync with behavior, especially release governance and
113
122
  reusable workflow contracts.
114
123
  - [`docs/MAP.md`](docs/MAP.md) and [`CONTRIBUTING.md`](CONTRIBUTING.md) are the
package/README.md CHANGED
@@ -25,6 +25,20 @@ its existing CI.
25
25
 
26
26
  The same mechanism releases Buildchain itself.
27
27
 
28
+ ## Choose Your Path
29
+
30
+ | You are... | Start here | You will get... |
31
+ | --- | --- | --- |
32
+ | adopting Buildchain for the first time | [Golden Path](docs/getting-started.md) | an exact install, project declaration, validated config, reusable workflow, release dry-run, and Passport inspection |
33
+ | looking up a CLI command | [Generated CLI Reference](docs/cli-reference.md) | governed syntax, options, aliases, and side-effect-free help paths |
34
+ | writing JavaScript automation | [Generated Node API Reference](docs/node-api-reference.md) | every public subpath and symbol with source-derived signatures and behavior boundaries |
35
+ | operating an advanced build or release | [Documentation Map](docs/MAP.md) | capability-, intent-, and maturity-based navigation to normative contracts |
36
+
37
+ The Golden Path is the beginner lane. Advanced workflow, signing, publishing,
38
+ and governance manuals remain separate so a first-time consumer does not need
39
+ to understand the entire release control plane before reaching a valid local
40
+ configuration.
41
+
28
42
  ## Where Buildchain sits in the Agent Supply Chain
29
43
 
30
44
  Buildchain binds a product's declarations to the exact source cut, build,
@@ -48,6 +62,10 @@ or protocol evidence through the repository issue tracker.
48
62
 
49
63
  ## Install and Verify
50
64
 
65
+ New repository adopters should follow the [15–30 minute Golden Path](docs/getting-started.md).
66
+ The commands below are the shorter verification-only route for an existing
67
+ consumer.
68
+
51
69
  For v3, use the published npm package and verify the release passport before
52
70
  trusting release evidence:
53
71
 
@@ -14,6 +14,7 @@ import { runPublicationPackageCli } from "../scripts/publication-package.mjs";
14
14
  import { runPublicationReproducibilityCli } from "../scripts/publication-reproducibility.mjs";
15
15
  import { runPaperCli } from "../scripts/paper.mjs";
16
16
  import { BUILDCHAIN_USAGE } from "../scripts/buildchain-cli-help.mjs";
17
+ import { formatCliHelp } from "../scripts/public-reference.mjs";
17
18
  import { validateBuildchainConfig } from "../packages/core/buildchain-config.js";
18
19
  import { detectPackageManager } from "../packages/core/package-manager.js";
19
20
  import {
@@ -102,10 +103,7 @@ import {
102
103
  TRUST_RELEASE_COMMANDS,
103
104
  dispatchTrustReleaseCommand,
104
105
  } from "./internal/trust-release-cli.mjs";
105
- import {
106
- BUILDCHAIN_COMMAND_REGISTRY,
107
- dispatchRegisteredCommand,
108
- } from "./internal/command-registry.mjs";
106
+ import { dispatchRegisteredCommand } from "./internal/command-registry.mjs";
109
107
 
110
108
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
111
109
  const embeddedPackageVersion = process.env.BUILDCHAIN_EMBEDDED_PACKAGE_VERSION || "";
@@ -1226,18 +1224,19 @@ async function runProcessTreeSample(sampleArgs = []) {
1226
1224
  return report;
1227
1225
  }
1228
1226
 
1229
- async function runRegisteredCommand(command, args) {
1230
- if (!command || command === "-h" || command === "--help" || command === "help") {
1231
- process.stdout.write(BUILDCHAIN_USAGE);
1227
+ async function handleHelpCommand(args) {
1228
+ process.stdout.write(formatCliHelp({ usageText: BUILDCHAIN_USAGE, pathParts: args }));
1232
1229
  return;
1233
- }
1234
1230
 
1235
- if (command === "version" || command === "--version" || command === "-v") {
1231
+ }
1232
+
1233
+ async function handleVersionCommand(args) {
1236
1234
  process.stdout.write(`${packageVersion()}\n`);
1237
1235
  return;
1238
- }
1239
1236
 
1240
- if (command === "layout") {
1237
+ }
1238
+
1239
+ async function handleLayoutCommand(args) {
1241
1240
  const result = createBuildchainLayoutDiscovery({
1242
1241
  cwd: readFlag(args, "cwd", process.cwd()),
1243
1242
  buildchainVersion: packageVersion(),
@@ -1251,9 +1250,10 @@ async function runRegisteredCommand(command, args) {
1251
1250
  process.stdout.write(`- Shifu jurisdiction: ${result.shifu.jurisdiction.field}=${result.shifu.jurisdiction.value}\n`);
1252
1251
  }
1253
1252
  return;
1254
- }
1255
1253
 
1256
- if (command === "portable-cache") {
1254
+ }
1255
+
1256
+ async function handlePortableCacheCommand(args) {
1257
1257
  const [subcommand = "", ...cacheArgs] = args;
1258
1258
  if (subcommand === "plan") {
1259
1259
  const manifestValue = readFlag(cacheArgs, "manifest", "");
@@ -1296,9 +1296,10 @@ async function runRegisteredCommand(command, args) {
1296
1296
  return;
1297
1297
  }
1298
1298
  throw new Error("usage: buildchain portable-cache <plan|receipt> ...");
1299
- }
1300
1299
 
1301
- if (command === "candidate") {
1300
+ }
1301
+
1302
+ async function handleCandidateCommand(args) {
1302
1303
  const [subcommand = "", ...candidateArgs] = args;
1303
1304
  if (subcommand !== "timeline") {
1304
1305
  throw new Error("usage: buildchain candidate timeline --input <file-or-json>");
@@ -1318,9 +1319,10 @@ async function runRegisteredCommand(command, args) {
1318
1319
  process.stdout.write(`wrote: ${output}\n`);
1319
1320
  }
1320
1321
  return;
1321
- }
1322
1322
 
1323
- if (command === "init") {
1323
+ }
1324
+
1325
+ async function handleInitCommand(args) {
1324
1326
  const result = initBuildchainRepo({
1325
1327
  cwd: readFlag(args, "cwd", process.cwd()),
1326
1328
  type: readFlag(args, "type", "package"),
@@ -1331,9 +1333,10 @@ async function runRegisteredCommand(command, args) {
1331
1333
  });
1332
1334
  printJson(result);
1333
1335
  return;
1334
- }
1335
1336
 
1336
- if (command === "validate") {
1337
+ }
1338
+
1339
+ async function handleValidateCommand(args) {
1337
1340
  const lifecycleStages = readFlag(args, "require-lifecycle-stages", "")
1338
1341
  .split(",")
1339
1342
  .map((entry) => entry.trim())
@@ -1343,9 +1346,10 @@ async function runRegisteredCommand(command, args) {
1343
1346
  requireLifecycleStages: lifecycleStages,
1344
1347
  }));
1345
1348
  return;
1346
- }
1347
1349
 
1348
- if (command === "doctor") {
1350
+ }
1351
+
1352
+ async function handleDoctorCommand(args) {
1349
1353
  const result = runDoctor({
1350
1354
  cwd: readFlag(args, "cwd", process.cwd()),
1351
1355
  requirePublishSourceLock: readBooleanFlag(args, "require-publish-source-lock"),
@@ -1359,18 +1363,20 @@ async function runRegisteredCommand(command, args) {
1359
1363
  }
1360
1364
  }
1361
1365
  return;
1362
- }
1363
1366
 
1364
- if (command === "dev") {
1367
+ }
1368
+
1369
+ async function handleDevCommand(args) {
1365
1370
  const [subcommand = "", ...devArgs] = args;
1366
1371
  if (subcommand !== "merge-queue") {
1367
1372
  throw new Error("usage: buildchain dev merge-queue --repository <owner/repo> --branch <dev/vN/vN.M> [--from-config | --workflow <path>...]");
1368
1373
  }
1369
1374
  runScript("dev-merge-queue.mjs", devArgs);
1370
1375
  return;
1371
- }
1372
1376
 
1373
- if (command === "log") {
1377
+ }
1378
+
1379
+ async function handleLogCommand(args) {
1374
1380
  const [levelOrSubcommand = "info", ...logArgs] = args;
1375
1381
  if (levelOrSubcommand === "summary") {
1376
1382
  const logPath = defaultCliLogPath(logArgs);
@@ -1407,9 +1413,10 @@ async function runRegisteredCommand(command, args) {
1407
1413
  printJson(event);
1408
1414
  }
1409
1415
  return;
1410
- }
1411
1416
 
1412
- if (command === "diagnostics") {
1417
+ }
1418
+
1419
+ async function handleDiagnosticsCommand(args) {
1413
1420
  const [subcommand = "", ...diagnosticsArgs] = args;
1414
1421
  if (subcommand !== "summary") {
1415
1422
  throw new Error("usage: buildchain diagnostics summary <diagnostics.json>...");
@@ -1438,28 +1445,32 @@ async function runRegisteredCommand(command, args) {
1438
1445
  }
1439
1446
  }
1440
1447
  return;
1441
- }
1442
1448
 
1443
- if (command === "facts") {
1449
+ }
1450
+
1451
+ async function handleFactsCommand(args) {
1444
1452
  await runBuildFactsCli(args);
1445
1453
  return;
1446
- }
1447
1454
 
1448
- if (command === "kfd") {
1455
+ }
1456
+
1457
+ async function handleKfdCommand(args) {
1449
1458
  await runKfdCli(args);
1450
1459
  return;
1451
- }
1452
1460
 
1453
- if (command === "sample") {
1461
+ }
1462
+
1463
+ async function handleSampleCommand(args) {
1454
1464
  const [subcommand = "", ...sampleArgs] = args;
1455
1465
  if (subcommand !== "process-tree") {
1456
1466
  throw new Error("usage: buildchain sample process-tree -- <command> [args...]");
1457
1467
  }
1458
1468
  await runProcessTreeSample(sampleArgs);
1459
1469
  return;
1460
- }
1461
1470
 
1462
- if (command === "mark") {
1471
+ }
1472
+
1473
+ async function handleMarkCommand(args) {
1463
1474
  const eventName = readFlag(args, "event", "");
1464
1475
  if (!eventName) {
1465
1476
  throw new Error("buildchain mark requires --event <name>");
@@ -1473,9 +1484,10 @@ async function runRegisteredCommand(command, args) {
1473
1484
  printJson(event);
1474
1485
  }
1475
1486
  return;
1476
- }
1477
1487
 
1478
- if (command === "span") {
1488
+ }
1489
+
1490
+ async function handleSpanCommand(args) {
1479
1491
  const separator = args.indexOf("--");
1480
1492
  const spanArgs = separator === -1 ? args : args.slice(0, separator);
1481
1493
  const commandArgs = separator === -1 ? [] : args.slice(separator + 1);
@@ -1517,9 +1529,10 @@ async function runRegisteredCommand(command, args) {
1517
1529
  attributes: readAttributes(spanArgs),
1518
1530
  });
1519
1531
  return;
1520
- }
1521
1532
 
1522
- if (command === "lifecycle") {
1533
+ }
1534
+
1535
+ async function handleLifecycleCommand(args) {
1523
1536
  const [subcommand, stageName = "", ...lifecycleArgs] = args;
1524
1537
  if (subcommand !== "run" || !stageName) {
1525
1538
  throw new Error("usage: buildchain lifecycle run <stage>");
@@ -1540,9 +1553,10 @@ async function runRegisteredCommand(command, args) {
1540
1553
  });
1541
1554
  printJson(manifest);
1542
1555
  return;
1543
- }
1544
1556
 
1545
- if (command === "npm") {
1557
+ }
1558
+
1559
+ async function handleNpmCommand(args) {
1546
1560
  const [subcommand = "", ...npmArgs] = args;
1547
1561
  if (subcommand !== "dry-run") {
1548
1562
  throw new Error("usage: buildchain npm dry-run");
@@ -1561,24 +1575,28 @@ async function runRegisteredCommand(command, args) {
1561
1575
  process.stdout.write(`pack entries: ${result.pack.entryCount}\n`);
1562
1576
  }
1563
1577
  return;
1564
- }
1565
1578
 
1566
- if (TRUST_RELEASE_COMMANDS.has(command)) {
1579
+ }
1580
+
1581
+ async function handleTrustReleaseCommand(args, { command }) {
1567
1582
  await dispatchTrustReleaseCommand({ command, args, runScript, packageVersion });
1568
1583
  return;
1569
- }
1570
1584
 
1571
- if (command === "web-surface") {
1585
+ }
1586
+
1587
+ async function handleWebSurfaceCommand(args) {
1572
1588
  runScript("web-surface.mjs", args);
1573
1589
  return;
1574
- }
1575
1590
 
1576
- if (command === "infra-contract") {
1591
+ }
1592
+
1593
+ async function handleInfraContractCommand(args) {
1577
1594
  runScript("infra-contract.mjs", args);
1578
1595
  return;
1579
- }
1580
1596
 
1581
- if (command === "publication-artifact" || command === "publication") {
1597
+ }
1598
+
1599
+ async function handlePublicationArtifactCommand(args) {
1582
1600
  if (args[0] === "npm-package" || args[0] === "package") {
1583
1601
  runPublicationPackageCli(args.slice(1));
1584
1602
  return;
@@ -1589,9 +1607,10 @@ async function runRegisteredCommand(command, args) {
1589
1607
  }
1590
1608
  runPublicationArtifactCli(args);
1591
1609
  return;
1592
- }
1593
1610
 
1594
- if (command === "paper") {
1611
+ }
1612
+
1613
+ async function handlePaperCommand(args) {
1595
1614
  await runPaperCli(args, {
1596
1615
  buildchainRoot: root,
1597
1616
  buildchainVersion: packageVersion(),
@@ -1600,39 +1619,46 @@ async function runRegisteredCommand(command, args) {
1600
1619
  process.env.BUILDCHAIN_RUNTIME_SHA || embeddedSourceSha || "",
1601
1620
  });
1602
1621
  return;
1603
- }
1604
1622
 
1605
- if (command === "release-propagation") {
1623
+ }
1624
+
1625
+ async function handleReleasePropagationCommand(args) {
1606
1626
  runReleasePropagationCli(args);
1607
1627
  return;
1608
- }
1609
1628
 
1610
- if (command === "release-governance") {
1629
+ }
1630
+
1631
+ async function handleReleaseGovernanceCommand(args) {
1611
1632
  await runReleaseGovernanceCli(args);
1612
1633
  return;
1613
- }
1614
1634
 
1615
- if (command === "github-governance") {
1635
+ }
1636
+
1637
+ async function handleGitHubGovernanceCommand(args) {
1616
1638
  runScript("reconcile-github-governance.mjs", args);
1617
1639
  return;
1618
- }
1619
1640
 
1620
- if (command === "badges") {
1641
+ }
1642
+
1643
+ async function handleBadgesCommand(args) {
1621
1644
  await runReadmeBadgesCli(args);
1622
1645
  return;
1623
- }
1624
1646
 
1625
- if (command === "homebrew") {
1647
+ }
1648
+
1649
+ async function handleHomebrewCommand(args) {
1626
1650
  await runHomebrewCli(args);
1627
1651
  return;
1628
- }
1629
1652
 
1630
- if (command === "build-contract") {
1653
+ }
1654
+
1655
+ async function handleBuildContractCommand(args) {
1631
1656
  runScript("resolve-build-contract.mjs", args);
1632
1657
  return;
1633
- }
1634
1658
 
1635
- if (command === "publish-source") {
1659
+ }
1660
+
1661
+ async function handlePublishSourceCommand(args) {
1636
1662
  const [mode = "lock", ...publishArgs] = args;
1637
1663
  if (mode === "lock" || mode === "manifest") {
1638
1664
  runScript("resolve-publish-source.mjs", ["--mode", mode, ...publishArgs]);
@@ -1665,19 +1691,56 @@ async function runRegisteredCommand(command, args) {
1665
1691
  return;
1666
1692
  }
1667
1693
  throw new Error(`unsupported publish-source command: ${mode}`);
1668
- }
1669
1694
 
1670
- throw new Error(`unsupported buildchain command: ${command}`);
1671
1695
  }
1672
1696
 
1673
- const BUILDCHAIN_COMMAND_HANDLERS = Object.freeze(Object.fromEntries(
1674
- BUILDCHAIN_COMMAND_REGISTRY.map((entry) => [
1675
- entry.id,
1676
- (args) => runRegisteredCommand(entry.id, args),
1677
- ]),
1678
- ));
1697
+ const BUILDCHAIN_COMMAND_HANDLERS = Object.freeze({
1698
+ "help": handleHelpCommand,
1699
+ "version": handleVersionCommand,
1700
+ "layout": handleLayoutCommand,
1701
+ "portable-cache": handlePortableCacheCommand,
1702
+ "candidate": handleCandidateCommand,
1703
+ "init": handleInitCommand,
1704
+ "validate": handleValidateCommand,
1705
+ "doctor": handleDoctorCommand,
1706
+ "dev": handleDevCommand,
1707
+ "log": handleLogCommand,
1708
+ "diagnostics": handleDiagnosticsCommand,
1709
+ "facts": handleFactsCommand,
1710
+ "kfd": handleKfdCommand,
1711
+ "sample": handleSampleCommand,
1712
+ "mark": handleMarkCommand,
1713
+ "span": handleSpanCommand,
1714
+ "lifecycle": handleLifecycleCommand,
1715
+ "npm": handleNpmCommand,
1716
+ ...Object.fromEntries(
1717
+ [...TRUST_RELEASE_COMMANDS].map((command) => [
1718
+ command,
1719
+ (args) => handleTrustReleaseCommand(args, { command }),
1720
+ ]),
1721
+ ),
1722
+ "web-surface": handleWebSurfaceCommand,
1723
+ "infra-contract": handleInfraContractCommand,
1724
+ "publication-artifact": handlePublicationArtifactCommand,
1725
+ "paper": handlePaperCommand,
1726
+ "release-propagation": handleReleasePropagationCommand,
1727
+ "release-governance": handleReleaseGovernanceCommand,
1728
+ "github-governance": handleGitHubGovernanceCommand,
1729
+ "badges": handleBadgesCommand,
1730
+ "homebrew": handleHomebrewCommand,
1731
+ "build-contract": handleBuildContractCommand,
1732
+ "publish-source": handlePublishSourceCommand,
1733
+ });
1679
1734
 
1680
1735
  async function main(argv = process.argv.slice(2)) {
1736
+ const helpIndex = argv.findIndex((entry) => entry === "--help" || entry === "-h");
1737
+ if (helpIndex >= 0) {
1738
+ process.stdout.write(formatCliHelp({
1739
+ usageText: BUILDCHAIN_USAGE,
1740
+ pathParts: argv.slice(0, helpIndex),
1741
+ }));
1742
+ return;
1743
+ }
1681
1744
  const [command = "help", ...args] = argv;
1682
1745
  return dispatchRegisteredCommand({
1683
1746
  command,