Skip to content

Commit 8a6fca9

Browse files
committed
Merge remote-tracking branch 'origin/main' into chore/clean-todo
# Conflicts: # CHANGELOG.md # tasks/todo.md
2 parents 0f2dd93 + d016f8e commit 8a6fca9

37 files changed

Lines changed: 1554 additions & 7 deletions

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ GitHub Releases page; `0.8.0` is the new starting line.
1818
- **Shell error briefs now show the trailing output of a failed command.** When a `Shell`/`Terminal` command exits non-zero, times out, or is killed by a signal, the collapsed worklog card appended only `Failed with exit code: N`; you had to expand the result to see *why*. The brief now includes the last few non-empty output lines (e.g. the stderr message), rendered as plain text so shell metacharacters (backticks, `#`, `*`) and line breaks are preserved verbatim instead of being reflowed as Markdown.
1919
- **Subagents no longer receive plan-mode workflow reminders.** Plan mode is a session-wide flag shared with subagents (so it persists across resume), but subagent toolsets usually exclude `EnterPlanMode`/`ExitPlanMode`. Injecting the plan-mode reminder into a subagent only invited hallucinated calls to tools it doesn't have; the reminder is now root-only.
2020
- **Terminal no longer risks hanging in raw mode on exit.** The cursor-position probe left `stdin` in cbreak mode and could block in an uninterruptible `os.read()` if cancelled mid-probe (e.g. a race with prompt_toolkit's reader on shutdown). Reads are now non-blocking during the probe and `VMIN`/`VTIME` are restored to canonical defaults, so a hang or crash can't leave the terminal wedged.
21+
- **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.
22+
- **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.
23+
- **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.
24+
- **`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.
25+
- **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.
26+
- **`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.
27+
- **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.
28+
- **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.
2129

2230
## 0.40.1 (2026-06-10)
2331

docs/en/configuration/config-files.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ The configuration file contains the following top-level configuration items:
3737
| `providers` | `table` | API provider configuration |
3838
| `models` | `table` | Model configuration |
3939
| `loop_control` | `table` | Agent loop control parameters |
40+
| `goal` | `table` | Thread-goal (`/goal`) behavior, including auto-continuation |
41+
| `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) |
4042
| `background` | `table` | Background task runtime parameters |
4143
| `services` | `table` | External service configuration (search, fetch) |
4244
| `mcp` | `table` | MCP client configuration |
@@ -72,6 +74,10 @@ max_ralph_iterations = 0
7274
reserved_context_size = 50000
7375
compaction_trigger_ratio = 0.85
7476

77+
[goal]
78+
auto_continue = false
79+
max_continuations = 3
80+
7581
[background]
7682
max_running_tasks = 4
7783
keep_alive_on_exit = false
@@ -162,6 +168,15 @@ capabilities = ["thinking"]
162168
| `reserved_context_size` | `integer` | `50000` | Reserved token count for LLM response generation; auto-compaction triggers when `context_tokens + reserved_context_size >= max_context_size` |
163169
| `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` |
164170

171+
### `goal`
172+
173+
`goal` controls thread-goal (`/goal`) behavior.
174+
175+
| Field | Type | Default | Description |
176+
| --- | --- | --- | --- |
177+
| `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 |
178+
| `max_continuations` | `integer` | `3` | Maximum automatic goal continuations per user submission (1–10); the final continuation carries a wrap-up instruction |
179+
165180
### `background`
166181

167182
`background` controls background task runtime behavior. Background tasks are launched via the `Shell` tool or the `Agent` tool with `run_in_background=true`.

docs/en/reference/slash-commands.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,30 @@ Usage:
276276

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

279+
### `/goal`
280+
281+
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`.
282+
283+
Usage:
284+
285+
- `/goal <objective>`: Set (or replace) the thread goal and start working toward it
286+
- `/goal` or `/goal view`: Show the current goal and its status
287+
- `/goal pause`: Keep the goal but stop pursuing it
288+
- `/goal resume`: Resume a paused, completed, or blocked goal
289+
- `/goal clear`: Remove the goal (also how you confirm completion)
290+
291+
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.
292+
293+
### `/best-practices`
294+
295+
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.
296+
297+
Usage:
298+
299+
- `/best-practices`: Inject the full guidance
300+
- `/best-practices <section>`: Inject a single section, e.g. `/best-practices testing` or `/best-practices debugging`
301+
- Alias: `/bp`
302+
279303
### `/task`
280304

281305
Open the interactive task browser to view, monitor, and manage background tasks.

src/pythinker_code/agents/default/agent.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ agent:
1212
# - "pythinker_code.tools.think:Think"
1313
- "pythinker_code.tools.ask_user:AskUserQuestion"
1414
- "pythinker_code.tools.todo:SetTodoList"
15+
- "pythinker_code.tools.goal:UpdateGoal"
1516
- "pythinker_code.tools.progress:Progress"
1617
- "pythinker_code.tools.suggest:Suggest"
1718
- "pythinker_code.tools.memory:Memory"

src/pythinker_code/agents/default/code_reviewer.yaml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@ agent:
1414
- Prefer no finding over vague speculation. Every finding must cite concrete evidence and a failure mode.
1515
- Treat malformed model output, validation errors, empty diffs, and missing base refs as blockers, not successful reviews.
1616
17+
## Finding Bar
18+
Flag a finding only when ALL of these hold:
19+
- It meaningfully impacts accuracy/correctness, performance, security, or maintainability, and the original author would likely fix it once aware.
20+
- It is discrete and actionable — not a general codebase complaint or several issues bundled together.
21+
- Fixing it does not demand a level of rigor absent from the rest of the codebase.
22+
- It does not rest on unstated assumptions about the author's intent, and is clearly not an intentional change.
23+
- Claimed ripple effects name the provably affected code; speculating that a change "may break something elsewhere" is not a finding.
24+
Do not stop at the first qualifying finding — continue until every qualifying finding is listed. If nothing meets the bar, prefer zero findings.
25+
26+
Comment construction:
27+
- 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.
28+
- Keep each finding to one matter-of-fact paragraph with at most 3 lines of quoted code; no flattery or filler.
29+
1730
## Context Gate
1831
- If `.pythinker/review-guidelines.md` exists, read it before scoring findings.
1932
- 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.
@@ -46,7 +59,7 @@ agent:
4659
4760
## Output Contract
4861
### SUMMARY
49-
One paragraph: command run, number of findings/artifacts, top severity or most important result.
62+
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.
5063
### EVIDENCE
5164
Bullet list of `<file>:<line> [severity] <rule_id> — <title>` for findings, or concise artifact bullets for non-finding commands. Top 10 max.
5265
### CHANGES

src/pythinker_code/agents/default/review.yaml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ agent:
1313
- Prefer no finding over vague speculation. Label residual uncertainty under RISKS.
1414
- Flag only issues introduced or made reachable by the requested diff/files.
1515
16+
## Finding Bar
17+
Flag a finding only when ALL of these hold:
18+
- It meaningfully impacts accuracy/correctness, performance, security, or maintainability, and the original author would likely fix it once aware.
19+
- It is discrete and actionable — not a general codebase complaint or several issues bundled together.
20+
- Fixing it does not demand a level of rigor absent from the rest of the codebase.
21+
- It does not rest on unstated assumptions about the author's intent, and is clearly not an intentional change.
22+
- Claimed ripple effects name the provably affected code; speculating that a change "may break something elsewhere" is not a finding.
23+
Do not stop at the first qualifying finding — continue until every qualifying finding is listed. If nothing meets the bar, prefer zero findings.
24+
25+
Comment construction:
26+
- 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.
27+
- Keep each finding to one matter-of-fact paragraph with at most 3 lines of quoted code; no flattery or filler.
28+
1629
## Context Gate
1730
Evidence gate:
1831
- 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.
@@ -35,7 +48,7 @@ agent:
3548
3649
## Output Contract
3750
### SUMMARY
38-
One paragraph. If there are no MAJOR/BLOCKER issues, say that plainly.
51+
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.
3952
### EVIDENCE
4053
Bullet list. Format review findings as `[SEVERITY] path:line-range — issue; suggested fix`.
4154
### CHANGES

src/pythinker_code/agents/default/system.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ For any non-trivial request, decompose before acting:
168168
- Preview the terrain first: scan the directory structure, file headers, and relevant module boundaries before choosing an implementation path.
169169
- **`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.
170170
- **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.
171+
- **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`.
172+
- **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.
171173
- **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.
172174
- 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.
173175
- 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.

src/pythinker_code/config.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,25 @@ class LLMModel(BaseModel):
361361
"""Human-readable model name (sourced from the provider's models API when available)"""
362362

363363

364+
class GoalConfig(BaseModel):
365+
"""Thread-goal (/goal) behavior."""
366+
367+
auto_continue: bool = Field(
368+
default=False,
369+
description=(
370+
"Automatically continue turns toward the active /goal after the primary "
371+
"turn ends, until the goal is marked complete/blocked, a continuation is "
372+
"rejected, or max_continuations is reached."
373+
),
374+
)
375+
max_continuations: int = Field(
376+
default=3,
377+
ge=1,
378+
le=10,
379+
description="Maximum automatic goal continuations per user submission.",
380+
)
381+
382+
364383
class LoopControl(BaseModel):
365384
"""Agent loop control configuration."""
366385

@@ -782,6 +801,17 @@ class Config(BaseModel):
782801
default_factory=dict, description="List of LLM providers"
783802
)
784803
loop_control: LoopControl = Field(default_factory=LoopControl, description="Agent loop control")
804+
goal: GoalConfig = Field(
805+
default_factory=GoalConfig, description="Thread-goal (/goal) configuration"
806+
)
807+
compact_prompt: str | None = Field(
808+
default=None,
809+
description=(
810+
"Override the built-in compaction summarization prompt. None keeps the "
811+
"default handoff-structured prompt; a per-invocation /compact focus is "
812+
"still appended on top."
813+
),
814+
)
785815
background: BackgroundConfig = Field(
786816
default_factory=BackgroundConfig, description="Background task configuration"
787817
)

src/pythinker_code/prompts/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44

55
INIT = (Path(__file__).parent / "init.md").read_text(encoding="utf-8")
66
COMPACT = (Path(__file__).parent / "compact.md").read_text(encoding="utf-8")
7+
BEST_PRACTICES = (Path(__file__).parent / "best_practices.md").read_text(encoding="utf-8")
8+
GOAL_SET = (Path(__file__).parent / "goal_set.md").read_text(encoding="utf-8")
9+
GOAL_CONTINUATION = (Path(__file__).parent / "goal_continuation.md").read_text(encoding="utf-8")
10+
GOAL_WRAP_UP = (Path(__file__).parent / "goal_wrap_up.md").read_text(encoding="utf-8")

0 commit comments

Comments
 (0)