Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ GitHub Releases page; `0.8.0` is the new starting line.

## Unreleased

- **New `/goal` command: goal-driven execution ported from Codex CLI.** `/goal <objective>` sets a persistent thread goal the agent pursues across turns until it is verifiably complete. The objective is stored in session state (survives restarts and context compaction), kicks off work immediately with a success-criteria derivation prompt, and is re-injected on later turns as a continuation reminder carrying Codex's fidelity rules (no scope-shrinking, no easier-to-test substitutes) and evidence-based completion audit — the agent may only claim completion after proving every requirement against current state, and the user confirms with `/goal clear`. Subcommands: `view`, `pause`, `resume`, `clear`. Objectives are injected as untrusted data (`<objective>` framing), never as higher-priority instructions.
- **New `/best-practices` command (alias `/bp`).** Injects opt-in engineering best-practice guidance distilled from the Codex CLI system prompts — code-change discipline, dirty-worktree safety (never revert changes you didn't make), specific-to-broad testing strategy, todo hygiene, progress-update cadence, debugging methodology, and final-answer style — into the session context without consuming a turn. `/best-practices <section>` injects a single section.
- **SetTodoList nudges the single-`in_progress` discipline.** Todo lists with more than one `in_progress` item now get a corrective notice (ported from Codex's plan-tool contract, softened because parallel-subagent fan-out legitimately tracks one `in_progress` sub-todo per running child), and the system prompt gains matching status-discipline guidance: no single-step lists, no `pending`→`done` jumps, no batch-completing after the fact.
- **`UpdateGoal` tool + opt-in goal auto-continuation: the full "loop until verified".** The agent can now mark the active `/goal` `complete` (only after the evidence-based completion audit) or `blocked` (only after Codex's strict three-strike blocked audit) via the new root-only `UpdateGoal` tool, which stops goal reminders and continuations; `/goal resume` reactivates either state. With `goal.auto_continue = true` (new config table, default off, `max_continuations` 1–10 capped at 3 by default), each user message is followed by automatic continuation turns toward the active goal — carrying the Codex continuation prompt — until the goal is marked, a tool call is rejected, or the cap is reached, with a budget-style wrap-up instruction on the final continuation.
- **Approval-mode-aware validation guidance.** Auto/yolo-mode injections now tell the agent to proactively run tests and lint before finishing (no user present to confirm), while the back-to-interactive reminder defers slow test/lint commands to user confirmation except for test-related tasks — ported from the Codex CLI validation philosophy.
- **`compact_prompt` config override.** A new optional top-level config key replaces the built-in compaction summarization prompt for both manual and automatic compaction; a `/compact` focus argument is still appended on top, and leaving it unset preserves current behavior.
- **Progress-update cadence in the system prompt.** Ported the Codex User Updates spec: short Progress notes on meaningful insights, a goal/constraints/next-steps statement before the first tool call of substantial work, heads-down announcements, and explicit plan-change callouts.
- **Reviewer subagents adopt Codex's review rubric.** The `review` and `code-reviewer` specs gain an explicit finding bar (only discrete, actionable issues the author would fix; rigor matched to the codebase; provable ripple effects; prefer zero findings over speculation), comment-construction rules (severity honesty, trigger conditions, one matter-of-fact paragraph), and an overall-correctness verdict (`patch is correct`/`patch is incorrect`) in the review summary.

## 0.40.1 (2026-06-10)

- **Windows/Linux native installers: web UI no longer 404s on `/`.** The installer CI froze the app without building the gitignored web/vis frontend bundles, so `pythinker web` opened a browser onto `GET /?token=… → 404 Not Found`. Both installer workflows now build the bundles before PyInstaller (matching the PyPI release flow — pip/wheel installs were never affected), every PyInstaller spec refuses to freeze when the bundles are missing, and a build that still lacks them serves an explanatory page on `/` (with the REST API still reachable under `/api`) instead of a bare 404.
Expand Down
15 changes: 15 additions & 0 deletions docs/en/configuration/config-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ The configuration file contains the following top-level configuration items:
| `providers` | `table` | API provider configuration |
| `models` | `table` | Model configuration |
| `loop_control` | `table` | Agent loop control parameters |
| `goal` | `table` | Thread-goal (`/goal`) behavior, including auto-continuation |
| `compact_prompt` | `string \| null` | Override the built-in compaction summarization prompt; `null`/unset keeps the default handoff-structured prompt (a `/compact` focus argument is still appended on top) |
| `background` | `table` | Background task runtime parameters |
| `services` | `table` | External service configuration (search, fetch) |
| `mcp` | `table` | MCP client configuration |
Expand Down Expand Up @@ -72,6 +74,10 @@ max_ralph_iterations = 0
reserved_context_size = 50000
compaction_trigger_ratio = 0.85

[goal]
auto_continue = false
max_continuations = 3

[background]
max_running_tasks = 4
keep_alive_on_exit = false
Expand Down Expand Up @@ -162,6 +168,15 @@ capabilities = ["thinking"]
| `reserved_context_size` | `integer` | `50000` | Reserved token count for LLM response generation; auto-compaction triggers when `context_tokens + reserved_context_size >= max_context_size` |
| `compaction_trigger_ratio` | `float` | `0.85` | Context usage ratio threshold for auto-compaction (0.5–0.99); auto-compaction triggers when `context_tokens >= max_context_size * compaction_trigger_ratio`, whichever condition is met first with `reserved_context_size` |

### `goal`

`goal` controls thread-goal (`/goal`) behavior.

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `auto_continue` | `boolean` | `false` | Automatically continue turns toward the active `/goal` after the primary turn ends, until the goal is marked complete/blocked (via the `UpdateGoal` tool), a continuation is rejected, or the cap is reached |
| `max_continuations` | `integer` | `3` | Maximum automatic goal continuations per user submission (1–10); the final continuation carries a wrap-up instruction |

### `background`

`background` controls background task runtime behavior. Background tasks are launched via the `Shell` tool or the `Agent` tool with `run_in_background=true`.
Expand Down
24 changes: 24 additions & 0 deletions docs/en/reference/slash-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,30 @@ Usage:

When plan mode is enabled, the prompt changes to `📋` and a blue `plan` badge appears in the status bar.

### `/goal`

Set a thread goal the agent pursues across turns until it is verifiably complete. The objective persists in the session, is re-injected as a continuation reminder on later turns, and survives context compaction. The agent derives concrete success criteria up front, refuses to shrink scope to an easier task, and only marks completion through the `UpdateGoal` tool after an evidence-based completion audit (or `blocked` after a strict blocked audit) — you then confirm with `/goal clear` or reactivate with `/goal resume`.

Usage:

- `/goal <objective>`: Set (or replace) the thread goal and start working toward it
- `/goal` or `/goal view`: Show the current goal and its status
- `/goal pause`: Keep the goal but stop pursuing it
- `/goal resume`: Resume a paused, completed, or blocked goal
- `/goal clear`: Remove the goal (also how you confirm completion)

With `goal.auto_continue = true` in the [config](../configuration/config-files.md#goal), the agent automatically starts follow-up turns toward the active goal after each of your messages (up to `goal.max_continuations`), stopping as soon as the goal is marked complete or blocked.

### `/best-practices`

Inject engineering best-practice guidance (code-change discipline, dirty-worktree safety, testing strategy, todo hygiene, progress updates, debugging methodology, final-answer style) into the session context. The guidance applies for the rest of the session without consuming a turn.

Usage:

- `/best-practices`: Inject the full guidance
- `/best-practices <section>`: Inject a single section, e.g. `/best-practices testing` or `/best-practices debugging`
- Alias: `/bp`

### `/task`

Open the interactive task browser to view, monitor, and manage background tasks.
Expand Down
1 change: 1 addition & 0 deletions src/pythinker_code/agents/default/agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ agent:
# - "pythinker_code.tools.think:Think"
- "pythinker_code.tools.ask_user:AskUserQuestion"
- "pythinker_code.tools.todo:SetTodoList"
- "pythinker_code.tools.goal:UpdateGoal"
- "pythinker_code.tools.progress:Progress"
- "pythinker_code.tools.suggest:Suggest"
- "pythinker_code.tools.memory:Memory"
Expand Down
15 changes: 14 additions & 1 deletion src/pythinker_code/agents/default/code_reviewer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ agent:
- Prefer no finding over vague speculation. Every finding must cite concrete evidence and a failure mode.
- Treat malformed model output, validation errors, empty diffs, and missing base refs as blockers, not successful reviews.

## Finding Bar
Flag a finding only when ALL of these hold:
- It meaningfully impacts accuracy/correctness, performance, security, or maintainability, and the original author would likely fix it once aware.
- It is discrete and actionable — not a general codebase complaint or several issues bundled together.
- Fixing it does not demand a level of rigor absent from the rest of the codebase.
- It does not rest on unstated assumptions about the author's intent, and is clearly not an intentional change.
- Claimed ripple effects name the provably affected code; speculating that a change "may break something elsewhere" is not a finding.
Do not stop at the first qualifying finding — continue until every qualifying finding is listed. If nothing meets the bar, prefer zero findings.

Comment construction:
- Each finding states why it is a bug, the exact scenarios/inputs/environments required to trigger it, and the concrete fix; the severity must not overstate the impact and should note when it depends on those conditions.
- Keep each finding to one matter-of-fact paragraph with at most 3 lines of quoted code; no flattery or filler.

## Context Gate
- If `.pythinker/review-guidelines.md` exists, read it before scoring findings.
- Build a review context packet: base ref/diff scope or Reviewflow feature IDs, changed behavior, likely tests, user-visible impact, valid evidence paths, omitted/truncated context, and validation evidence.
Expand Down Expand Up @@ -46,7 +59,7 @@ agent:

## Output Contract
### SUMMARY
One paragraph: command run, number of findings/artifacts, top severity or most important result.
One paragraph: command run, number of findings/artifacts, top severity or most important result. End with an overall-correctness verdict — `patch is correct` or `patch is incorrect` (correct means existing code and tests will not break and the change is free of blocking issues; ignore non-blocking style, formatting, and nits) — plus a 1-3 sentence justification.
### EVIDENCE
Bullet list of `<file>:<line> [severity] <rule_id> — <title>` for findings, or concise artifact bullets for non-finding commands. Top 10 max.
### CHANGES
Expand Down
15 changes: 14 additions & 1 deletion src/pythinker_code/agents/default/review.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ agent:
- Prefer no finding over vague speculation. Label residual uncertainty under RISKS.
- Flag only issues introduced or made reachable by the requested diff/files.

## Finding Bar
Flag a finding only when ALL of these hold:
- It meaningfully impacts accuracy/correctness, performance, security, or maintainability, and the original author would likely fix it once aware.
- It is discrete and actionable — not a general codebase complaint or several issues bundled together.
- Fixing it does not demand a level of rigor absent from the rest of the codebase.
- It does not rest on unstated assumptions about the author's intent, and is clearly not an intentional change.
- Claimed ripple effects name the provably affected code; speculating that a change "may break something elsewhere" is not a finding.
Do not stop at the first qualifying finding — continue until every qualifying finding is listed. If nothing meets the bar, prefer zero findings.

Comment construction:
- Each finding states why it is a bug, the exact scenarios/inputs/environments required to trigger it, and the concrete fix; the severity must not overstate the impact and should note when it depends on those conditions.
- Keep each finding to one matter-of-fact paragraph with at most 3 lines of quoted code; no flattery or filler.

## Context Gate
Evidence gate:
- Do not score or report a finding until you have read the relevant diff/file and at least one supporting caller, test, config, or sibling pattern when applicable.
Expand All @@ -35,7 +48,7 @@ agent:

## Output Contract
### SUMMARY
One paragraph. If there are no MAJOR/BLOCKER issues, say that plainly.
One paragraph. If there are no MAJOR/BLOCKER issues, say that plainly. End with an overall-correctness verdict — `patch is correct` or `patch is incorrect` (correct means existing code and tests will not break and the change is free of blocking issues; ignore non-blocking style, formatting, and nits) — plus a 1-3 sentence justification.
### EVIDENCE
Bullet list. Format review findings as `[SEVERITY] path:line-range — issue; suggested fix`.
### CHANGES
Expand Down
2 changes: 2 additions & 0 deletions src/pythinker_code/agents/default/system.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ For any non-trivial request, decompose before acting:
- Preview the terrain first: scan the directory structure, file headers, and relevant module boundaries before choosing an implementation path.
- **`SetTodoList` marks the start of execution, not planning.** Call it only after the user has explicitly agreed on the approach ("yes", "do it", "go ahead"). Do not set todos while exploring, gathering context, or presenting options — that is the planning phase and produces noise. Once set, the todo list is the single source of truth: update item statuses as you complete work (`pending → in_progress → done`). Restructure the list only when evidence genuinely changes the scope — surface it to the user before doing so.
- **Granular todos, not umbrella todos.** Each todo must name a single concrete deliverable a human can recognize as "this part is done." Avoid umbrella titles like "Determine X" or "Investigate Y" that cover hours of parallel work — they freeze the progress UI while real work happens underneath. If a single todo would stay `in_progress` for more than ~3 minutes, it is too coarse: split it before launching work.
- **Status discipline.** Do not make single-step todo lists or pad simple work with filler steps. Never jump an item from `pending` to `done` — set it `in_progress` first, keeping at most one item `in_progress` at a time for your own sequential work (parallel-subagent fan-out is the exception: one `in_progress` sub-todo per running child, per the rule below) — and never batch-complete multiple items after the fact. End the turn with every item `done` or explicitly `cancelled`.
- **Progress cadence.** Post a short Progress note (1-2 sentences) when you uncover a meaningful insight or change direction — notes replace, not duplicate, narration in your final text. Before the first tool call of substantial work, state the goal, constraints, and next steps. Announce longer heads-down stretches and summarize what you learned when you resume; call out plan changes explicitly in the next update.
- **One todo per dispatched child.** When you launch `RunAgents` with N children, the visible todo list MUST contain one in_progress sub-todo per child (or per independent objective the batch covers) **before** the batch starts. Update each sub-todo to `done` as that child returns — do not wait for the whole batch to finish to flip a single umbrella todo. Same rule applies to multiple parallel `Agent` calls in the same turn.
- Split broad work into independent chunks; use parallel tool calls or focused subagents for chunks that do not depend on each other. Scale the number of agents to the task's independent subparts — a single lookup needs none, a small comparison 2-4 — and prefer the fewest that cover the work; over-provisioning burns the multi-agent token premium.
- For large codebase scans, start with indexes/graphs and targeted searches; avoid one vague repo-wide subagent prompt. If using background agents for thorough exploration, set a realistic explicit timeout and keep scopes narrow. If agents time out, do not repeat the same broad launch; summarize partial evidence, run targeted direct scans, and resume or relaunch narrower agents only when useful.
Expand Down
30 changes: 30 additions & 0 deletions src/pythinker_code/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,25 @@ class LLMModel(BaseModel):
"""Human-readable model name (sourced from the provider's models API when available)"""


class GoalConfig(BaseModel):
"""Thread-goal (/goal) behavior."""

auto_continue: bool = Field(
default=False,
description=(
"Automatically continue turns toward the active /goal after the primary "
"turn ends, until the goal is marked complete/blocked, a continuation is "
"rejected, or max_continuations is reached."
),
)
max_continuations: int = Field(
default=3,
ge=1,
le=10,
description="Maximum automatic goal continuations per user submission.",
)


class LoopControl(BaseModel):
"""Agent loop control configuration."""

Expand Down Expand Up @@ -782,6 +801,17 @@ class Config(BaseModel):
default_factory=dict, description="List of LLM providers"
)
loop_control: LoopControl = Field(default_factory=LoopControl, description="Agent loop control")
goal: GoalConfig = Field(
default_factory=GoalConfig, description="Thread-goal (/goal) configuration"
)
compact_prompt: str | None = Field(
default=None,
description=(
"Override the built-in compaction summarization prompt. None keeps the "
"default handoff-structured prompt; a per-invocation /compact focus is "
"still appended on top."
),
)
background: BackgroundConfig = Field(
default_factory=BackgroundConfig, description="Background task configuration"
)
Expand Down
4 changes: 4 additions & 0 deletions src/pythinker_code/prompts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@

INIT = (Path(__file__).parent / "init.md").read_text(encoding="utf-8")
COMPACT = (Path(__file__).parent / "compact.md").read_text(encoding="utf-8")
BEST_PRACTICES = (Path(__file__).parent / "best_practices.md").read_text(encoding="utf-8")
GOAL_SET = (Path(__file__).parent / "goal_set.md").read_text(encoding="utf-8")
GOAL_CONTINUATION = (Path(__file__).parent / "goal_continuation.md").read_text(encoding="utf-8")
GOAL_WRAP_UP = (Path(__file__).parent / "goal_wrap_up.md").read_text(encoding="utf-8")
Loading
Loading