@botbuddy/cli 1.5.2 → 1.5.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbuddy/cli",
3
- "version": "1.5.2",
3
+ "version": "1.5.4",
4
4
  "description": "BotBuddy — Swarm coordination CLI for multi-agent workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +1 @@
1
- {"schema_version":1,"source_version":"1.5.1","source_identity":"0f390ab84c23f56dcae6e8cc1331fb2fa8533ae2f026f396f8adb76d9485b2d8"}
1
+ {"schema_version":1,"source_version":"1.5.1","source_identity":"56890dbd45a92364dc2a57ed8f09710d3e3d53c5af8999680ef1d19552e19c94"}
@@ -556,6 +556,7 @@ export function evaluatePressure({
556
556
  }) {
557
557
  const current = Number(bridgeNetworks) + (2 * Number(attachedEndpoints));
558
558
  const projected = current + 1 + (2 * Number(projectedEndpoints));
559
+ const status = projected >= fail ? "fail" : projected >= warn ? "warn" : "ok";
559
560
  return {
560
561
  metric: "conservative_network_pressure_units",
561
562
  formula: "bridge_networks + (2 * attached_endpoints)",
@@ -564,7 +565,18 @@ export function evaluatePressure({
564
565
  projected_endpoints: Number(projectedEndpoints),
565
566
  warn_pressure: Number(warn),
566
567
  fail_pressure: Number(fail),
567
- status: projected >= fail ? "fail" : projected >= warn ? "warn" : "ok",
568
+ status,
569
+ // BOT-1412: a host-wide interface-pressure refusal is not a per-stack
570
+ // `supabase_local` lock wait. Emit the relay's capacity condition in the
571
+ // machine receipt so callers park on the global policy and receive the
572
+ // eventual capacity signal, rather than retrying Docker locally.
573
+ ...(status === "fail" ? {
574
+ wait: {
575
+ kind: "global_capacity",
576
+ condition: "capacity:policy=host_docker_pressure_v1,slots>=1",
577
+ command: "bb-wait 'capacity:policy=host_docker_pressure_v1,slots>=1'",
578
+ },
579
+ } : {}),
568
580
  note: "Conservative pressure proxy; OrbStack does not expose a kernel interface ceiling through the Docker API.",
569
581
  };
570
582
  }
package/src/wait-core.mjs CHANGED
@@ -217,6 +217,17 @@ const VALIDATORS = {
217
217
  if (!String(p.sha).trim()) throw new Error("ci sha must be non-empty");
218
218
  return { repo, scope: "sha", sha: String(p.sha).trim(), pr: p.pr != null ? String(p.pr).trim() : null };
219
219
  },
220
+ "staging-green"(p) {
221
+ const repo = p.repo != null ? String(p.repo).trim() : null;
222
+ if (!repo || !/^[^/\s]+\/[^/\s]+$/.test(repo)) {
223
+ throw new Error("staging-green needs repo=<owner/repo>");
224
+ }
225
+ const extras = Object.keys(p).filter((key) => key !== "repo");
226
+ if (extras.length > 0) {
227
+ throw new Error("staging-green accepts only repo=<owner/repo>");
228
+ }
229
+ return { repo };
230
+ },
220
231
  // BOT-1247 — unblocked: wake when a ticket's LAST open blocker clears (its
221
232
  // open-blocker count transitions >0 → 0). Level-triggered: a ticket already
222
233
  // unblocked (or never blocked) at registration is granted immediately with
@@ -643,6 +654,18 @@ function conditionMatchesSignal(condition, signal, waitSessionId) {
643
654
  return signal.subject_key === `${params.repo}#${params.pr}` ||
644
655
  (signal.payload?.pr_number != null && String(signal.payload.pr_number) === params.pr);
645
656
  }
657
+ case "staging-green": {
658
+ if (signal.signal_type !== "staging_gate" || signal.subject_key !== params.repo) return false;
659
+ const payload = signal.payload ?? {};
660
+ // A staging_gate signal is also used for manual overrides and red/freeze
661
+ // transitions. This public condition is deliberately narrower: only the
662
+ // webhook's evidenced, automatic recovery may wake a delivery session.
663
+ return (payload.reason === "green_recovery" || payload.reason === "already_green") &&
664
+ payload.source === "automatic_workflow_recovery" &&
665
+ payload.verified === true &&
666
+ payload.gate_open === false &&
667
+ payload.operational_status === "healthy";
668
+ }
646
669
  case "unblocked": {
647
670
  // Wakes on the ticket_unblocked spine signal for this ticket (the server emits both
648
671
  // the genuine >0→0 transition and the level-triggered `already_unblocked` echo).
package/src/wait.mjs CHANGED
@@ -78,6 +78,9 @@ CONDITIONS (TYPE:key=val,key=val — repeat for several; --any wakes on the fir
78
78
  a PR's CI reaching a terminal conclusion (owner-scoped);
79
79
  GitHub Actions or an external check_suite provider.
80
80
  A repo with no CI feed is rejected (no_signal_source).
81
+ staging-green:repo=<owner/repo> verified automatic recovery of an enabled staging gate.
82
+ Wakes only after a complete non-vacuous workflow success;
83
+ manual resolutions, overrides, skipped, and neutral runs do not match.
81
84
  event:type=<signal_type>[,subject=<key>]
82
85
  raw signal-spine match (escape hatch)
83
86
 
@@ -211,6 +214,7 @@ async function registerWait(opts, conditions, deadlineIso) {
211
214
  "wait_tenant_unresolved",
212
215
  "wait_cross_tenant",
213
216
  "wait_tenant_mismatch",
217
+ "staging_repository_unconfigured",
214
218
  // BOT-1259: a `linear` condition set spanning multiple workspaces can't bind one
215
219
  // tenant; the server rejects it (register one wait per workspace) — a hard stop, not
216
220
  // a transient error, so don't fall back to an untracked live-only wait.