Skip to content

Commit 3b6cf52

Browse files
Merge pull request #409 from corbitsdev/remove-goal-subsystem
Remove the goal subsystem
2 parents 21ae5a4 + 3df306c commit 3b6cf52

52 files changed

Lines changed: 160 additions & 3387 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/ARCHITECTURE.md

Lines changed: 16 additions & 6 deletions
Large diffs are not rendered by default.

docs/PRODUCT.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ $ corbits exec "Add JWT auth to the API"
4848
$ corbits run "Add JWT auth to the API"
4949
```
5050

51-
Same directors, tools, permissions, MCP, plugins, and hooks as the TUI — without the OpenTUI shell. The exec bootstrap is a deliberate fork of the TUI path (not a shared factory yet); see `docs/ARCHITECTURE.md` “Exec Runner” for intentional deltas (no workflow controller or goal governor; single primary send; non-interactive permission gate). Compaction continuation matches TUI so long runs do not stall after compact. Streams assistant text to stdout for scripts and CI. Non-interactive by default: actions that need operator approval are denied unless `--dangerously-skip-permissions` is set (or auto mode covers them). `ask_operator` reads a single line from stdin when available.
51+
Same directors, tools, permissions, MCP, plugins, and hooks as the TUI — without the OpenTUI shell. The exec bootstrap is a deliberate fork of the TUI path (not a shared factory yet); see `docs/ARCHITECTURE.md` “Exec Runner” for intentional deltas (no workflow controller; single primary send; non-interactive permission gate). Compaction continuation matches TUI so long runs do not stall after compact. Streams assistant text to stdout for scripts and CI. Non-interactive by default: actions that need operator approval are denied unless `--dangerously-skip-permissions` is set (or auto mode covers them). `ask_operator` reads a single line from stdin when available.
5252

5353
Local multi-model capability checks use this path (`bun run eval:capability`); see `evals/capability/README.md`.
5454

@@ -76,14 +76,12 @@ Continues from the last saved state in the working directory.
7676

7777
## Slash Commands (TUI)
7878

79-
The TUI has an extensible slash-command framework. Built-ins include `/help` (shortcut + command overlay), `/model` (open the agent configuration surface — connect providers with **c** / **Ctrl+A**, pick models, tiers, and profiles), `/settings`, `/permissions`, `/plugins`, `/clear`, `/new`, `/mcp`, and `/goal` (session goal: expand a brief into an acceptance checklist and auto-continue until every criterion is done — see `/goal [turns] <brief>`, `/goal pause|resume|clear|status`, optional `--tokens N` / `--replace`), plus a `/<name>` command per available workflow. Plugins can register additional commands.
79+
The TUI has an extensible slash-command framework. Built-ins include `/help` (shortcut + command overlay), `/model` (open the agent configuration surface — connect providers with **c** / **Ctrl+A**, pick models, tiers, and profiles), `/settings`, `/permissions`, `/plugins`, `/clear`, `/new`, and `/mcp`, plus a `/<name>` command per available workflow. Plugins can register additional commands.
8080

8181
Providers are **models-first**: there is no standalone `/login` command. `/model` opens on a **model list** (Recent, Favorites, then providers) so you pick a model without drilling provider first. **Alt+A** (or **c**) opens Connect; **Alt+F** toggles favorite on the highlighted model; **a** opens the advanced provider drill-down (edit/delete/tiers). Connect lists first-class providers (OpenAI dual-path ChatGPT OAuth or API key, xAI, OpenCode Zen, Anthropic, Google, OpenCode Go, Z.AI Coding Plan, Custom). OAuth providers open their existing browser login; API-key providers show an **auth-only** form (key + fixed catalog base URL), validate, and persist pre-seeded models for immediate selection. OpenCode Go routes each model by its protocol metadata (chat completions, OpenAI responses, or Anthropic messages) and can show subscription usage in the status bar when active (rolling 5h / weekly / monthly windows when the usage API responds; omitted on auth or network failure). When Go returns a quota or rate-limit error — including some HTTP 400 responses that carry limit payloads — Corbits classifies them so quota aborts cleanly and short provider rate limits remain retryable. On a free-tier or subscription quota hit, wait for the window to reset or use OpenCode Zen free models.
8282

8383
`/model` opens a dedicated full-screen modal — the single place agent configuration lives. The default view is models-first (Recent / Favorites / Providers); connect, tiers, and profiles remain reachable from the same surface. A switch applies to the running session immediately (no restart), and can be saved as this project's default (written to the per-repo selection file). Recent and favorite model pairs are stored in global settings (no credentials).
8484

85-
`/goal <brief>` arms a session-scoped goal governor. The operator brief is **not** the completion condition: the agent must clarify success (via `ask_operator` when vague) and expand it into a multi-item **acceptance** checklist with `manage_goal` *before* substantial work. Work steps go in `manage_tasks` (shown as **Work** while a goal is active) — separate from acceptance. Lifecycle phases surface in the UI: **planning** (define Acceptance) → **implementing** (Work primary; Acceptance compact; `doing` on a criterion stays here) → **reviewing** (starts when any criterion is `done` or `blocked`) → **completed** (all non-cancelled criteria done; auto-achieves). After each clean yield the agent is re-inferred until every acceptance criterion is done, a finite turn/token budget soft-stops, or the operator pauses/clears. **Default turn budget is unlimited** (`0`); an optional leading integer caps continues (`/goal 40 ship the feature`). Resume restores a prior goal as **paused** (never silently re-armed); unlimited goals stay unlimited on resume, finite ones get headroom. While a goal is **active**, permission prompts that still need a human answer auto-skip after ~15s with a note back to the agent (human may be away — continue another way); the operator can still approve/deny earlier. Pair with auto mode and/or `--dangerously-skip-permissions` for longer unattended runs. Goal mode does not shrink tools, skills, slash commands, sub-agents, or MCP.
86-
8785
## Lifecycle Hooks
8886

8987
Config-driven `postTurn` and `postRun` hooks (TypeScript or shell) run automatically, discovered from `.corbits/hooks` (per-repo) and `~/.corbits/hooks` (global). `postTurn` receives aggregated turn context (tool calls, results, token usage, duration); `postRun` receives a run summary. The TUI hook panel lists discovered hooks and lets the user enable/disable them. See `docs/HOOKS.md`.

docs/TUI.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ palette," a plain question — never the word "overlay."
1717

1818
There is no titlebar, no status strip, and no key-hint row as permanent
1919
chrome. The prompt box is the only permanent chrome in the shell: it is
20-
anchored at the bottom in every state, and everything else — goal/task/agents
20+
anchored at the bottom in every state, and everything else — task/agents
2121
strips, notices, banners, the overlay host — is optional and collapses to
2222
zero rows when it has nothing to say (`src/tui-opentui/geometry/zones.ts`).
2323
The transcript is residual: whatever rows remain after chrome and any open
@@ -32,7 +32,7 @@ terminal with nothing optional showing, the transcript floor is 12 rows
3232
proposed 8 rows (`OVERLAY_TRANSCRIPT_FLOOR`) so the log stays glanceable
3333
underneath a permission prompt. When space is scarce, collapse follows a
3434
fixed order — transient banners first, then settings/plugin notices, then
35-
goal/task/agents strips, then progress, then the prompt itself shrinks one
35+
task/agents strips, then progress, then the prompt itself shrinks one
3636
row at a time down to its 3-row base — never the transcript
3737
(`COLLAPSE_ORDER` in `zones.ts`).
3838

@@ -134,7 +134,7 @@ agent, with `agentId` as a tiebreak for a simultaneous fan-out.
134134

135135
Under space pressure, the zone shrinks one row at a time toward 1 rather
136136
than collapsing straight to 0 (`COLLAPSE_ORDER` treats it like `progress`,
137-
not like the single-row `goal`/`task` strips) — a 1-row panel still carries
137+
not like the single-row `task` strip) — a 1-row panel still carries
138138
the stalest agent plus its `+N more` trailer, so it stays meaningful all
139139
the way down. Only once every other collapsible zone ahead of it in
140140
`COLLAPSE_ORDER` and the panel itself are exhausted does it reach 0, the

src/agent/director.ts

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ import { type } from "arktype";
2020
import { applyManageTasks, hasActiveTasks, parseManageTasksArgs, type Task } from "./tasks.js";
2121
import { createCorbitsRetryPolicy } from "./retry-policy.js";
2222
import { isInternalRecoveryAbortRaw } from "../inference-abort.js";
23-
import type { GoalGovernor } from "./goal.js";
24-
import { evidenceFromTurns } from "./goal-evaluator.js";
2523
import { LOG_NAMESPACE_ROOT } from "../branding.js";
2624
import { resolveModelFamilyPolicy, type ModelFamilyPolicy } from "./model-family-policy.js";
2725
import { PRESENT_VIEW_PRIMITIVES_GUIDANCE } from "./tool-schema-normalize.js";
@@ -67,8 +65,8 @@ function inferWithNudge(
6765
// Assumes a bare wait always means the turn is over. That holds for every
6866
// current wait path: DefaultDirector in conversational mode (the only mode
6967
// ChatDirector uses) yields a bare wait only on an empty model turn, and its
70-
// halt path already carries a reply; the compaction, workflow, open-task, and
71-
// goal rewrites either keep those terminals or replace them with an infer.
68+
// halt path already carries a reply; the compaction, workflow, and open-task
69+
// rewrites either keep those terminals or replace them with an infer.
7270
// A future wait that pauses mid-turn while expecting more work must not be
7371
// settled here.
7472
function ensureCycleSettlesWithReply(
@@ -363,7 +361,6 @@ class ChatDirectorImpl extends DefaultDirector {
363361
private lastTaskSummary: string | undefined;
364362
private startedAt = Date.now();
365363
private readonly compaction: CompactionGovernor;
366-
private goal: GoalGovernor | undefined;
367364
private readonly modelFamilyPolicy: ModelFamilyPolicy;
368365
// Consecutive assistant turns that contain tool calls and no text. Reset on
369366
// any turn with text and on every fresh user message — a weak model that
@@ -393,14 +390,6 @@ class ChatDirectorImpl extends DefaultDirector {
393390
this.workflowCoordinator = coordinator;
394391
}
395392

396-
setGoalGovernor(goal: GoalGovernor | undefined): void {
397-
this.goal = goal;
398-
}
399-
400-
getGoalGovernor(): GoalGovernor | undefined {
401-
return this.goal;
402-
}
403-
404393
updateToolDefinitions(toolDefinitions: ToolDefinition[]): void {
405394
this._toolDefinitions = toolDefinitions;
406395
}
@@ -629,16 +618,6 @@ class ChatDirectorImpl extends DefaultDirector {
629618
this.pendingToolOnlyNudge = true;
630619
}
631620

632-
// Attribute main-loop tokens to an active goal for soft token budgets.
633-
if (this.goal !== undefined) {
634-
const u = event.usage;
635-
if (u !== undefined) {
636-
const n =
637-
(typeof u.input === "number" ? u.input : 0) +
638-
(typeof u.output === "number" ? u.output : 0);
639-
if (n > 0) this.goal.noteMainTokens(n);
640-
}
641-
}
642621
if (this.workflowCoordinator?.isActive()) {
643622
if (hasToolCalls) {
644623
this.workflowIdleTurns = 0;
@@ -723,7 +702,7 @@ class ChatDirectorImpl extends DefaultDirector {
723702
const compacted = this.compaction.interceptActions(event, baseActions, capabilities);
724703
if (compacted !== null) return compacted;
725704

726-
// Loop protection takes precedence over workflow/open-task/goal
705+
// Loop protection takes precedence over workflow/open-task
727706
// continuation nudges below: those exist to keep a session moving,
728707
// which is exactly the behavior the pause is guarding against. A tool
729708
// call turn (like the one that triggered this) must still execute
@@ -789,17 +768,6 @@ class ChatDirectorImpl extends DefaultDirector {
789768
}
790769
}
791770

792-
// Goal continue-rule runs last among terminal rewrites so open-task and
793-
// workflow nudges keep precedence. Only fires when we would otherwise yield.
794-
if (this.goal !== undefined) {
795-
const goalRewrite = await this.goal.interceptTerminal(baseActions, capabilities, {
796-
atWorkflowGate,
797-
lastTurnHadContent: this.lastInferenceTurnHadContent,
798-
evidence: evidenceFromTurns(state.turns ?? []),
799-
});
800-
if (goalRewrite !== null) return goalRewrite;
801-
}
802-
803771
return base;
804772
}
805773
}
@@ -839,8 +807,6 @@ export function hydrateTasksFromTurns(turns: ConversationTurn[]): Task[] {
839807
export interface ChatDirector extends ReactorDirector {
840808
updateToolDefinitions(toolDefinitions: ToolDefinition[]): void;
841809
setWorkflowCoordinator(coordinator: WorkflowCoordinator | undefined): void;
842-
setGoalGovernor(goal: GoalGovernor | undefined): void;
843-
getGoalGovernor(): GoalGovernor | undefined;
844810
getTasks(): Task[];
845811
restoreTasks(tasks: Task[]): void;
846812
getContextEstimate(): { tokens: number; isEstimate: boolean };

src/agent/goal-evaluator.test.ts

Lines changed: 0 additions & 124 deletions
This file was deleted.

0 commit comments

Comments
 (0)