← reports

#2680 · Automation safety documentation omits a terminal failure path

Bug Priority: Low Effort: Low documentation · automations open on GitHub 2026-08-29 · base fc94f46

Verdict: REPRODUCED · Root-cause confidence: high

1. TL;DR

The automation safety reference describes retries and the three-failure pause. It does not describe the separate unusable-target path. The code disables all enabled automations for that target thread after the first confirmed terminal result. That path does not use the failure counter or schedule a retry. The incomplete reference can therefore make correct runtime behavior look incorrect.

2. Claims vs findings

ClaimStatusEvidence
The safety reference describes the retry and three-failure path.VerifiedLines 46–49 describe the two delays, the third-failure pause, and counter resets.
The reference does not describe the unusable target-thread path.VerifiedThe focused test failed on the first required phrase in two clean checkouts.
A confirmed terminal target result disables all enabled automations for that thread.VerifiedThe runtime calls a thread-keyed update. The existing behavior test confirms that both target automations become disabled.
The terminal path does not use the failure counter or schedule a retry.VerifiedThe terminal branch closes the run directly. Only the separate failure recorder increments the counter and calculates retry time.

3. Environment

4. Minimal reproduction

  1. Check out the trusted base commit.
  2. Run pnpm install --frozen-lockfile --prefer-offline.
  3. Run pnpm exec turbo run build.
  4. Place the linked test at plugins/automations/src/automation-safety-docs.test.ts.
  5. Run pnpm exec turbo run test --filter=bb-plugin-automations --force -- automation-safety-docs.test.ts.

Expected and actual result:

Expected: The safety reference describes terminal target-thread failures.
Actual:   AssertionError: expected documentation to contain
          "unavailable target thread"
          Test Files  1 failed (1)
          Tests       1 failed (1)

Reproduction test: automation-safety-docs.test.ts

import { readFile } from "node:fs/promises";
import { describe, expect, it } from "vitest";

describe("automation execution safety documentation", () => {
  it("describes terminal target-thread failures", async () => {
    const documentation = await readFile(
      new URL(
        "../skills/automations/references/script-runtime.md",
        import.meta.url,
      ),
      "utf8",
    );

    expect(documentation).toContain("unavailable target thread");
    expect(documentation).toContain("does not retry");
    expect(documentation).toContain("does not use the failure count");
    expect(documentation).toContain(
      "disables every enabled automation that targets the thread",
    );
  });
});

Second clean verification

The same agent used a second clean checkout at the same commit. The agent repeated the frozen install, full Turbo build, and focused test. The second test failed at the same assertion. No report claim needed a correction.

5. Root cause

The reference lists the strike path but no terminal target path. See the execution safety list.

- Failed recurring runs retry after 30 seconds and then 60 seconds. The third
  consecutive failure pauses the automation.
- A successful or skipped run clears the failure count.

The runtime checks whether the target thread can accept work. It closes the run through a separate terminal branch when the check fails. See the target-thread branch.

if (!isThreadReusable(thread)) {
  closeRunForUnusableTargetThread(bb, db, ...);
  return;
}

disableAutomationsForDeletedThread(db, ...);
closeAutomationRun(db, { status: "failed", ... });

The disable update selects all enabled automations with the same target thread. See the thread-keyed update.

UPDATE automations SET
  enabled = 0,
  next_run_at = NULL
WHERE target_thread_id = @threadId AND enabled = 1

The terminal branch does not call the counter-based failure recorder. That recorder alone increments failures and calculates retry time. See the strike implementation.

6. Proposed fix (first principles)

Add one safety-list item for an unavailable target thread. State that the first confirmed terminal result disables every enabled automation for that thread. State that this path does not retry or use the failure counter. Keep runtime behavior unchanged. Add the focused documentation test.

7. Related issues

No linked open pull request or related issue was present during the report.

8. Appendix

The issue data was untrusted. The investigation used it only as claims to test. No linked code, branch, script, attachment, or external issue URL was used.

The first Turbo test in each checkout found a temporary native-module ABI mismatch before Vitest started. The repository repair command restored a private matching binary. The final runs then reached Vitest and produced the same assertion failure.

Commands used:

git fetch origin main
git worktree add --detach <checkout-a> fc94f46c13b89f54e9c8ba53600352df64b81798
git worktree add --detach <checkout-b> fc94f46c13b89f54e9c8ba53600352df64b81798
pnpm install --frozen-lockfile --prefer-offline
pnpm exec turbo run build
pnpm run ensure-native-modules
pnpm exec turbo run test --filter=bb-plugin-automations --force -- automation-safety-docs.test.ts
git log fc94f46c..origin/main --oneline -- plugins/automations/skills/automations/references/script-runtime.md