@bubblebrain-ai/bubble 0.0.41 → 0.0.42

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/agent.d.ts CHANGED
@@ -227,6 +227,7 @@ export declare class Agent {
227
227
  private getActiveToolEntries;
228
228
  injectSystemReminder(content: string): void;
229
229
  injectModeReminder(): void;
230
+ get role(): "parent" | "subagent";
230
231
  get model(): string;
231
232
  set model(value: string);
232
233
  get providerId(): string;
package/dist/agent.js CHANGED
@@ -428,6 +428,9 @@ export class Agent {
428
428
  }
429
429
  this.injectSystemReminder(reminder);
430
430
  }
431
+ get role() {
432
+ return this.agentRole;
433
+ }
431
434
  get model() {
432
435
  return this._model;
433
436
  }
@@ -4,7 +4,7 @@ import { EvidenceTracker } from "../agent/evidence-tracker.js";
4
4
  import { ExecutionGovernor } from "../agent/execution-governor.js";
5
5
  import { DiscoveryBarrier } from "../agent/discovery-barrier.js";
6
6
  import { arbitrateToolCall } from "../agent/tool-arbiter.js";
7
- import { buildEditRetryEscalationReminder, buildSmallTaskHint, buildWorkflowPhaseReminder, } from "../prompt/reminders.js";
7
+ import { buildCompletionSelfCheckReminder, buildEditRetryEscalationReminder, buildSmallTaskHint, buildWorkflowPhaseReminder, } from "../prompt/reminders.js";
8
8
  import { largeImplementationTaskReminder, orchestrationRequestReminder, reminderForTaskType, userNamedModelReminder } from "../prompt/task-reminders.js";
9
9
  import { formatCoverageSummary, resolveWorkflowPhase } from "./workflow.js";
10
10
  import { resolve as resolvePath } from "node:path";
@@ -220,9 +220,33 @@ export function createDefaultHooks() {
220
220
  }
221
221
  // Verification reminders intentionally removed. See afterToolCall.
222
222
  },
223
- afterTurn() {
223
+ afterTurn(ctx) {
224
224
  // Verification force-continuation removed. The model decides whether
225
225
  // verification is meaningful for the task, per the system prompt.
226
+ //
227
+ // Completion self-check gate: when a run that changed code is about
228
+ // to end (this hook only runs on final, no-tool-call turns), remind
229
+ // the model ONCE to re-read the original request before finishing.
230
+ // Unlike the removed verification gate it never repeats — the model
231
+ // is explicitly told a confirming final answer ends the run — so the
232
+ // "prove it" spiral that killed the old design cannot start.
233
+ if (ctx.state.completionGateFired)
234
+ return;
235
+ if (!ctx.state.codeChanged)
236
+ return;
237
+ // Tools are frozen: the model could not act on anything the check
238
+ // surfaces, so another turn is pure token burn.
239
+ if (ctx.state.forceTextOnlyReason)
240
+ return;
241
+ // Subagents hand off to a parent that does its own closing pass, and
242
+ // worktree profiles explicitly forbid the very actions a completion
243
+ // check would suggest.
244
+ if (ctx.agent.role === "subagent")
245
+ return;
246
+ ctx.state.completionGateFired = true;
247
+ ctx.state.forceContinuationReason = "completion_self_check";
248
+ ctx.queueReminder(buildCompletionSelfCheckReminder());
249
+ traceEvent("completion_gate_fired", { turnCount: ctx.state.turnCount });
226
250
  },
227
251
  },
228
252
  ];
@@ -16,6 +16,8 @@ export interface TurnHookState {
16
16
  forceTextOnlyReason?: string;
17
17
  forceContinuationReason?: string;
18
18
  codeChanged?: boolean;
19
+ /** Completion self-check gate already fired this run (fires at most once). */
20
+ completionGateFired?: boolean;
19
21
  smallTaskHintSent?: boolean;
20
22
  recentEditFailures?: string[];
21
23
  editNoMatchReminderPaths?: string[];
@@ -23,6 +23,7 @@ export declare function buildInvestigationReminder(): string;
23
23
  export declare function buildLoopWarningReminder(reason: string): string;
24
24
  export declare function buildSearchFreezeReminder(reason: string): string;
25
25
  export declare function buildExplorationFreezeReminder(reason: string): string;
26
+ export declare function buildCompletionSelfCheckReminder(): string;
26
27
  export declare function buildToolFreezeReminder(reason: string): string;
27
28
  export declare function buildWorkflowPhaseReminder(input: {
28
29
  phase: "investigate" | "correlate" | "conclude";
@@ -119,6 +119,13 @@ Choose one of:
119
119
  3. If files were already changed, run the narrowest meaningful verification or finish with the result.
120
120
  `);
121
121
  }
122
+ export function buildCompletionSelfCheckReminder() {
123
+ return wrapInSystemReminder(`
124
+ You appear to be finishing. Before giving your final answer, re-read the user's original request in this conversation and check whether any explicit requirement in it remains unfulfilled — including requirements about how the work should be delivered or reported, not only whether the implementation works.
125
+
126
+ If something is missing, complete it now. If everything is done, give your final answer directly — do not repeat this check or re-verify work you have already verified.
127
+ `);
128
+ }
122
129
  export function buildToolFreezeReminder(reason) {
123
130
  return wrapInSystemReminder(`
124
131
  CRITICAL - MAXIMUM STEPS REACHED
@@ -11,6 +11,7 @@ const defaultGuidelines = [
11
11
  "Prefer structured tools (glob, grep, read) over bash for search and inspection. Do not repeat a near-identical search or re-read the same file unless new evidence changes the question.",
12
12
  "If a tool fails, diagnose the error before switching tactics. Do not retry the identical call with identical arguments. After two equivalent failures, switch approach — re-read the file, use a different tool, rewrite the whole file with write, or ask the user.",
13
13
  "Before reporting a task complete, verify it works when verification is meaningful and cheap — run the existing test, execute the script, check the output. If no test exists, the change is purely declarative (static HTML/markdown/config), or running the code is not practical, state that explicitly rather than inventing a verification step. Do not write throwaway validation scripts to prove correctness; if there is no real check to run, report the change and stop.",
14
+ "Before declaring a task complete, re-read the user's original request and verify that every explicit requirement in it — about both the result and the process — has been fulfilled, not only that the implementation works.",
14
15
  ];
15
16
  export function buildRuntimePrompt(options = {}) {
16
17
  const guidelines = dedupe(defaultGuidelines, options.guidelines ?? []);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bubblebrain-ai/bubble",
3
- "version": "0.0.41",
3
+ "version": "0.0.42",
4
4
  "description": "A terminal coding agent",
5
5
  "type": "module",
6
6
  "engines": {