diff --git a/CHANGELOG.md b/CHANGELOG.md index 32b66796..1212aa0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,52 +15,24 @@ GitHub Releases page; `0.8.0` is the new starting line. ## Unreleased -- **A streaming `/statusline command` can no longer wedge the refresh loop.** Killing a status command that streams endless output left its stdout pipe flow-control-paused on a full buffer; asyncio resolves `wait()` only once every pipe reaches EOF, so the reap could deadlock the refresh task forever (frozen footer) — or, in the milder path, burn the full command timeout per refresh and render nothing. The runner now drains the pipe after kill so the child is always reaped, and a command that produced output but won't exit within the timeout renders its first line instead of failing closed. -- **Inline `/command` references are no longer silently dropped.** Slash commands only execute when a message starts with `/`; a `/best-practices` or `/skill:` referenced mid-message used to reach the model as plain text and routinely got ignored. A new dynamic injection now flags such references once per user message (known commands, aliases, and `skill:*` names — path-like tokens such as `/usr/local` or `tests/clear` are not confused for commands) and instructs the model to load the referenced skill, apply the equivalent guidance, or tell the user how to actually invoke the command; the base prompt carries the matching standing rule. -- **Capped file reads now say exactly how to continue.** When `ReadFile` stops at the line or byte cap, the result message names the remaining line count and the precise `line_offset` to resume from (`Partial read: 206 lines remain; continue with line_offset=1001.`), the tool description tells the model a below-total read is partial, and the base prompt requires finishing partial reads of spec/skill/checklist files before implementing against them — closing the failure mode where an agent reads the first 1,000 lines of a spec and ships against a fraction of it. -- **User-designated spec files get artifact-scoped authority.** File contents arrive wrapped as untrusted data ("never instructions to follow"), which also discounted the very skill or spec the user explicitly asked to apply. The base prompt now distinguishes the two: a file the user directs you to apply defines requirements for the deliverable — implemented faithfully, mandatory checks included — while its authority still never extends to the agent itself (embedded directives to run commands, switch tasks, or exfiltrate stay inert). -- **Definition of Done walks the task's own checklist.** Work performed under a skill, spec, or plan with mandatory rules now exits through a new checklist item: every rule checked against the artifact (mechanically where possible), each compliance claim naming the check that actually ran, and anything the environment cannot execute or render reported as unverified instead of implied to work. -- **`` arrival is no longer mistaken for user activity.** Models repeatedly misread injected reminders as "the user sent a new message." The base prompt now states they are injected machinery: their arrival never means the user replied, changed the request, or ended the turn. -- **Agent specs now tell the truth about their runtime permissions.** The hardened permission profiles block network tools (`SearchWeb`/`FetchURL`) for review/verify/read-only subagents and all MCP/external tools for every non-implementation profile — but most subagent specs still instructed live docs/advisory lookups through exactly those tools, wasting steps on denied calls and silently disabling the mandated checks. The reviewer-class specs (`review`, `code-reviewer`, `security-reviewer`, `debugger`, `judge`, `explore`) are rewritten offline-honest: never assert third-party "deprecated/removed/wrong API" claims from training memory, verify what the repository itself proves (installed dependency source, manifest/lockfile pins, call sites), and return everything else under RISKS as structured `needs verification — : ` items; dead tool entries are removed from their specs so the parent sees an accurate toolset. `plan` and `scout` keep first-class web research and route it through `SearchWeb`/`FetchURL`. -- **`scout` regains its mission: it was accidentally offline.** The external-docs researcher was missing from the subagent profile map, defaulting to the offline `read_only` profile — which hid and denied the web tools its entire spec is built on. It now maps to the read-only-plus-network `ask` profile and is the designated delegate for verifying the `needs verification` claims offline reviewers return. -- **Review fan-out & finding-verification discipline in the base prompt.** The orchestrator now: decomposes large diffs (above ~1,500 changed lines or ~25 files, one reviewer per subsystem with explicit file lists, deduped on synthesis); adversarially verifies every finding against the cited lines before reporting (non-reproducing findings are dropped or listed as rejected — never retained at a laundered lower severity); re-anchors exact `path:line` references and re-derives severity counts itself instead of transcribing child tallies; and resolves reviewers' needs-verification third-party claims — and only those — against live docs, directly or via `scout`, with query hygiene enforced at the layer that actually has network access. -- **Workspace-jail shell denials now name the jail.** The escape denial tells the agent the actual workspace root it must stay within, so a blocked reviewer corrects the path instead of retrying blind variations; reviewer specs also gain explicit command-timeout discipline (narrow scope on timeout, never re-run bigger). -- **Workspace jail closes the expansion/glob/cwd bypass family.** Read-style commands under restricted profiles can no longer smuggle paths past the boundary check: path arguments containing unexpanded `$` variables are rejected outright (shlex strips quotes, so a runtime expansion is indistinguishable from a quoted literal — regex and program arguments are unaffected because pattern extractors never treat them as paths); glob arguments are validated by their literal prefix instead of being skipped (`rg x /etc/*` and `ls ../*` are denied, `rg x src/**/*.py` stays allowed, and glob-then-`..` traversal like `src/*/../..` is rejected); and `cd`/`pushd` moves are tracked across command segments so `cd .. && rg x .` is judged against the directory the shell will actually be in (`popd`, `cd -`, bare `cd`, and `(`/`{` command grouping are rejected as untrackable). ReadFile parity for absolute file reads is preserved (`cat /etc/hosts` and `cat /etc/*` stay legal). -- **Statusline execution knobs are user-scope-only.** A repo-controlled project config could flip `tui.statusline.enabled` plus `segments=["command"]` to trigger the user's pre-configured external status command and observe its output. `enabled`, `segments`, and `command_timeout_ms` now join `command` in the scope locks (cosmetic fields like `style`/`bar_width` stay project-configurable), and `command_timeout_ms` gains a 60s upper bound so a runaway value cannot park a subprocess for days. -- **Secret env scrub covers more credential shapes.** Bare `PRIVATE_KEY`/`JWT`/`COOKIE`/`BEARER` and the `_JWT`/`_COOKIE`/`_BEARER` suffixes are now scrubbed from restricted-profile subprocess environments; cookie-adjacent non-credentials (`COOKIE_JAR_PATH`) survive. -- **Restricted-profile retry cap is whitespace-insensitive.** The two-failures hard stop now keys on the whitespace-normalized command string, so trailing-space padding can no longer mint a fresh counter and bypass the cap; semantically different commands stay distinct. -- **TaskOutput steers to notification-driven waiting.** A timed-out blocking wait now leads with "return control and rely on the completion notification" (retrying with a longer timeout is the explicit exception); consecutive blocking timeouts escalate to a firm STOP-waiting hint with a per-task streak; and a timed-out blocking attempt no longer resets the non-blocking "STOP polling" escalation — interleaving one blocking call between polls used to absolve the streak indefinitely. -- **Review-scope measurement and judge-gate reinforcement in the base prompt.** Review fan-out scope is measured against the merge base (committed plus worktree changes), not the uncommitted-only diff stat that made a ~140-file branch review look like 17 files; the dual-destination rule now names severity-scored findings reports as judge-gate triggers and forbids silently re-grading a child reviewer's severities during synthesis. -- **No more transient red `` flash while tool calls stream.** While a tool call's arguments stream in, the partial-JSON repair turns a key-without-value into `null`, and card renderers (shell, agent, edit, write, ...) treated "key present, non-string value" as invalid for a frame or two. While args are incomplete, `None`-valued keys are now dropped before rendering so every card shows its pending state; finished calls with genuinely invalid args still show ``. -- **Flicker-free streaming on terminals with synchronized output.** Every redraw frame — renderer updates and scrollback prints alike — is now bracketed in DEC mode 2026 synchronized-update marks so supporting terminals paint atomically instead of mid-frame. Capability-gated (off for `TERM=dumb`; kill switch `PYTHINKER_NO_SYNC_OUTPUT=1`) and harmlessly ignored by terminals without support. -- **Parallel subagents get distinctive instance codenames.** Children launched via `RunAgents` whose name merely echoes their type (the common `code-reviewer:code-reviewer` degenerate case), or that duplicate a sibling's name, are now assigned a generated `adjective-noun` codename (`amber-falcon`, `tidal-wren`, ...) unique within the batch. The codename flows through the result tree, TaskList, TaskOutput, and completion notifications (as `codename (type)` when the caller gave no title), so simultaneous same-type agents are finally distinguishable; caller-chosen distinct names and titles pass through untouched. -- **Background agent task ids are codenames too.** A background agent task was previously handled by an opaque random id (`agent-kzsr0h9a`) — the one token that stays visible in `TaskOutput`/`TaskStop` headers, the task list, and notifications, which made single background launches indistinguishable at a glance even after the codename work. Generated agent task ids now use the same codename vocabulary (`agent-tidal-wren`), unique against every id already in the session's task store; bash task ids keep the opaque random suffix. -- **Slash commands ghost-complete inline; Tab accepts.** Typing a root `/comm…` token now renders the remainder of the best-matching command as dim ghost text after the cursor (mode-aware, same command set as the completion menu); Tab — or the standard right-arrow/ctrl-e suggestion keys — completes it in place without submitting. The existing completion menu, Enter-to-run, and Escape-to-discard behaviors are unchanged. -- **Workspace jail for read-style shell commands in restricted profiles.** Read-only/plan/review/verify permission profiles now apply the same boundary the first-class file tools enforce to raw shell path arguments: discovery/search commands (`find `, `rg`/`grep` paths, `ls`/`du`/`tree`, `git -C`/`--git-dir`/`--work-tree`, generic `--directory`/`--project`) are denied when a path argument resolves outside the workspace and approved additional directories (symlinks and `~` are resolved first), while file-read commands (`cat`/`head`/`tail`/`sed`/...) keep ReadFile parity — absolute paths outside the workspace stay readable, relative `..` escapes are denied. Closes the gap where `find .. -name AGENTS.md` from a review subagent passed every gate; foreground and background shell share the same decision path, and every denial is an explicit error naming the offending argument. -- **Review/read-only subagents are offline by default, enforced — not prompted.** `PermissionProfile` gains an explicit `allow_network` field: review/verify/read-only profiles deny the first-class network tools (`SearchWeb`/`FetchURL`) at execution time (in addition to hiding them from the model), and the existing invariant that a root `yolo` flag never broadens a subagent's hard profile is now locked by tests. Plan/ask modes keep network access for interactive research. -- **Secret env scrubbing for restricted-profile shell.** Shell subprocesses spawned under profiles without shell-mutation rights (review/verify/read-only/plan subagents) no longer inherit credential-looking environment variables (`*_API_KEY`, `*_TOKEN`, `*_SECRET*`, `*_PASSWORD`, `AWS_*`, `GOOGLE_APPLICATION_*`, ...). Those profiles already block network access; inherited secrets were pure downside. Applies to foreground and background shell (the background task spec persists only a boolean, never the environment). -- **Retry-loop hard stop for restricted profiles.** Under review/read-only profiles, a verbatim shell command that has already failed twice is denied outright with guidance to change approach or report the blocker, instead of letting an agent flag-thrash the same failing invocation across steps. Implementation profiles are unaffected (re-running a failing test command while iterating stays legal). -- **Review diff base fallback is now loud.** `pythinker review`/`secscan` recorded only the *chosen* base ref, hiding the silent `origin/main` → `main`/`master` fallback. `ResolvedDiff` and `RunMeta` now carry `requested_base_ref` and `fallback_reason`; JSON output includes both, the pretty renderer prints a fallback warning, and PR-artifact metadata exposes them — so every report states exactly which base was reviewed and whether it was the one asked for. -- **Subagent todo lists are normalized to a single `in_progress` item.** A subagent is one sequential worker: extra `in_progress` items are demoted to pending (first wins, order preserved) with a corrective note in the tool output. The root list keeps the parallel-batch allowance (one `in_progress` sub-todo per running child). -- **Tool-call rows in the TUI are monotonic.** A finished row ignores late/duplicated wire events: a replayed `ToolResult` can no longer flip a failed row to successful (retries are separate rows), and a stray `ToolExecutionStarted`/output chunk after completion no longer restyles or mutates a committed row. -- **Statusline v2: full visual redesign of the shell footer.** The footer now renders colored segments separated by `│`/`·`, with a smooth gradient context bar (`ctx 36k/200k ████▌░░░░░ 18%`, green→gold→orange→red by fill, blinking `⚠ CTX LOW` past 90%), a working spinner, live `in N out M t/s` token speed, session cost (`$1.84`, or `$spent/$budget` once `/statusline budget` is set), a thinking-effort badge, git `+added/-removed` diff counts, session elapsed time, and a clock. Segments are fail-closed — each renders only when its data source has real data for the active provider/model, so the same default config is correct on Anthropic, OpenAI-compatible, and local Ollama/MLX setups (no `$0.00`, no empty bars). Everything is tunable via `/statusline`: `segments ` (bare `segments` now lists every available segment with its zone and on/off state), `style fancy|plain`, `bar-width <4-20>`, `budget `, plus the existing `on|off` and external `command`; all settings persist under `[tui.statusline]`. ASCII-only terminals degrade glyphs automatically, and narrow widths drop low-priority segments (speed, diff, cost, effort) instead of truncating the essentials. Disabling customization (`/statusline off`) reproduces the plain pre-v2 footer. -- **Foreground `RunAgents` batches now run children concurrently.** Previously only background batches parallelized; foreground children executed one at a time. Children now overlap (bounded by `background.max_running_tasks` so a large batch cannot fork-bomb the session), results keep request order, and a crashing child reports its own error entry instead of aborting its siblings. -- **`RunAgents` rolls up child RISKS/BLOCKERS.** Foreground batch results now end with `batch_risks:`/`batch_blockers:` blocks that deduplicate findings raised by multiple children and attribute each finding to its reporters, so the orchestrating agent sees cross-child issues without re-parsing every report body. -- **New `/statusline` command: customizable status line.** The footer under the prompt is now configurable: pick which segments show (`cwd`, `git`, `flags`, `context`, `tokens`, `model`) with `/statusline segments `, toggle customization with `/statusline on|off`, and optionally surface your own info with `/statusline command ` — an external command whose first stdout line is rendered in the footer (refreshed on a cadence, run without a shell, killed on timeout, and failing closed so a broken command never breaks the footer). Settings persist under `[tui.statusline]`; defaults reproduce the previous footer exactly. -- **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. -- **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. -- **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. -- **New `/goal` command: goal-driven execution ported from Codex CLI.** `/goal ` 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 (`` 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, and extends them with generalized sections on scoping and assumptions, subagent orchestration (scoped prompts, single blocking waits, verify findings against real code), security and secrets, and verification before done. `/best-practices
` injects a single section, and the working-spinner tips now advertise the command. -- **Best-practices guidance is now a default, not just an opt-in.** The default system prompt ships a condensed always-on best-practices profile — smallest-complete-change ownership, environment detection from artifacts, blast-radius mapping, never-invent-APIs with dependency-name verification, dirty-worktree and git safety, honest testing (no verification gaming, deterministic tests), debugging method, migration/concurrency conformance, secrets and boundary parameterization, idempotent operations with a three-failures escalation rule, and answer-shape guidance — inherited by the root agent and every subagent role. The full `/best-practices` profile is expanded to match, gaining five new sections (operating principles, context gathering, design and implementation, version control, agent operational discipline) and sharper rules throughout. -- **New `/learn` command: session lesson extraction.** Reviews the session for user corrections, non-obvious error resolutions, and hard-won conventions, distills each into a trigger rule ("when X, do Y"), and persists it via the Memory tool to per-project memory (consolidating near-duplicates instead of stacking them). `/learn ` steers extraction; an empty result is explicitly valid. This makes the working-spinner tip about `/learn` real. -- **TaskOutput escalates its hint on repeated non-blocking polls.** Polling a still-running task without `block=true` more than once now returns a firm "non-blocking poll #N … STOP polling" hint instead of the gentle default, steering the agent toward one blocking wait or the completion notification. The counter resets after any blocking attempt or once the task reaches a terminal state. -- **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. +## 0.41.0 (2026-06-11) + +- **New `/goal` command — goal-driven execution that loops until verified.** `/goal ` sets a persistent thread goal the agent pursues across turns, restarts, and context compaction until it is verifiably complete. It kicks off immediately with a success-criteria derivation prompt and is re-injected each turn with fidelity rules (no scope-shrinking, no easier-to-test substitutes) and an evidence-based completion audit — completion may only be claimed after every requirement is proven against current state. The new root-only `UpdateGoal` tool marks the goal `complete` (after that audit) or `blocked` (after a strict three-strike audit) and stops the reminders; opt-in `goal.auto_continue` (new config table, default off, `max_continuations` 1–10, capped at 3) drives automatic continuation turns toward the goal until it is marked, a tool call is rejected, or the cap is reached, with a wrap-up instruction on the final continuation. Subcommands: `view`, `pause`, `resume`, `clear`. Objectives are injected as untrusted data, never as higher-priority instructions. +- **New `/best-practices` command (alias `/bp`) and an always-on default profile.** `/best-practices` injects opt-in engineering guidance — code-change discipline, dirty-worktree safety, specific-to-broad testing, todo hygiene, progress cadence, debugging method, subagent orchestration, secrets handling, and verification-before-done — into the session without consuming a turn (`/best-practices
` injects a single section). A condensed version of this guidance now ships always-on in the default system prompt — smallest-complete-change ownership, environment detection from artifacts, blast-radius mapping, never-invent-APIs with dependency-name verification, git safety, honest deterministic testing, and a three-failures escalation rule — inherited by the root agent and every subagent role. +- **New `/learn` command — session lesson extraction.** Reviews the session for user corrections, non-obvious error resolutions, and hard-won conventions, distills each into a trigger rule ("when X, do Y"), and persists it to per-project memory (consolidating near-duplicates instead of stacking them). `/learn ` steers extraction; an empty result is explicitly valid. +- **Statusline v2 — a full redesign of the shell footer, plus the new `/statusline` command.** The footer renders colored segments separated by `│`/`·`: a smooth gradient context bar (`ctx 36k/200k ████▌░░░░░ 18%`, green→gold→orange→red by fill, blinking `⚠ CTX LOW` past 90%), a working spinner, live token speed (`in N out M t/s`), session cost (`$1.84`, or `$spent/$budget` once a budget is set), a thinking-effort badge, git `+added/-removed` diff counts, session elapsed time, and a clock. Segments are fail-closed — each renders only when its data source has real data for the active provider/model — so the same default config is correct on Anthropic, OpenAI-compatible, and local Ollama/MLX setups. Everything is tunable via `/statusline` (`segments`, `style fancy|plain`, `bar-width`, `budget`, `on|off`, external `command`) and persists under `[tui.statusline]`; ASCII-only terminals degrade glyphs automatically, narrow widths drop low-priority segments, and `/statusline off` reproduces the plain pre-v2 footer. A streaming external `command` can no longer wedge the refresh loop — the runner drains and reaps the child after kill, and renders its first line on timeout instead of failing closed. +- **Parallel subagents and background tasks get distinctive codenames.** Children launched via `RunAgents` whose name merely echoes their type (the common `code-reviewer:code-reviewer` case), or duplicates a sibling's, are assigned a generated `adjective-noun` codename unique within the batch, flowing through the result tree, TaskList, TaskOutput, and completion notifications. Background agent task ids use the same vocabulary (`agent-tidal-wren`) instead of an opaque random suffix, so simultaneous same-type agents are finally distinguishable at a glance. +- **Foreground `RunAgents` batches run concurrently and roll up child findings.** Foreground children now overlap (bounded by `background.max_running_tasks` so a large batch cannot fork-bomb the session) instead of executing one at a time, keep request order, and a crashing child reports its own error entry instead of aborting its siblings. Batch results end with deduplicated `batch_risks:`/`batch_blockers:` blocks that attribute each finding to its reporters. +- **Subagent and todo-list discipline tightened.** Subagent todo lists are normalized to a single `in_progress` item (extras demoted to pending, first wins, order preserved); `SetTodoList` nudges the same single-`in_progress` discipline at the root (with the parallel-batch allowance) and the system prompt gains matching status guidance — no single-step lists, no `pending`→`done` jumps, no batch-completing after the fact. `TaskOutput` steers toward notification-driven waiting and escalates its hint on repeated non-blocking polls; subagents no longer receive plan-mode workflow reminders for tools they don't have. +- **Review pipeline hardened for large diffs and finding fidelity.** The orchestrator decomposes large diffs (one reviewer per subsystem with explicit file lists, deduped on synthesis), adversarially verifies every finding against the cited lines before reporting (non-reproducing findings are dropped, never laundered to a lower severity), re-anchors `path:line` references, and measures review scope against the merge base rather than the uncommitted-only diff. Reviewer specs gain an explicit finding bar, comment-construction rules, and an overall-correctness verdict. Agent specs now tell the truth about their runtime permissions — offline reviewers return third-party claims as structured `needs verification` items rather than asserting them, and `scout`, accidentally defaulted offline, is restored to its network-enabled profile as the designated verifier of those claims. `pythinker review`/`secscan` now surface the previously silent base-ref fallback (`requested_base_ref`/`fallback_reason`) in JSON output, the pretty renderer, and PR-artifact metadata. +- **Workspace jail extended to raw shell commands under restricted profiles.** Read-only/plan/review/verify profiles now apply the file-tool boundary to shell path arguments: discovery/search commands (`find`, `rg`/`grep`, `ls`/`du`/`tree`, `git -C`/`--git-dir`/`--work-tree`) are denied when a path resolves outside the workspace, while file-read commands keep ReadFile parity (absolute outside-workspace reads stay legal, relative `..` escapes are denied). The jail closes the expansion/glob/cwd bypass family — path arguments with unexpanded `$` variables are rejected, glob arguments are validated by their literal prefix, and `cd`/`pushd` moves are tracked across command segments so a later command is judged against the directory the shell will actually be in. Every denial names the offending argument and the workspace root the agent must stay within. +- **Restricted-profile subagents are offline and secret-scrubbed by default.** `PermissionProfile` gains an explicit `allow_network` field: review/verify/read-only profiles deny the network tools (`SearchWeb`/`FetchURL`) at execution time as well as hiding them, with the invariant that a root `yolo` flag never broadens a subagent's hard profile now locked by tests. Their shell subprocesses no longer inherit credential-looking environment variables (`*_API_KEY`, `*_TOKEN`, `*_SECRET*`, `*_PASSWORD`, `AWS_*`, plus bare `PRIVATE_KEY`/`JWT`/`COOKIE`/`BEARER` and their suffixes), and a verbatim command that has already failed twice (whitespace-normalized, so trailing-space padding can't mint a fresh counter) is denied outright with guidance to change approach. +- **Statusline execution knobs are user-scope-only.** `enabled`, `segments`, and `command_timeout_ms` join `command` in the configuration scope locks, so a repo-controlled project config can no longer trigger or observe the user's external status command; `command_timeout_ms` also gains a 60s upper bound. Cosmetic fields (`style`, `bar_width`) stay project-configurable. +- **Base-prompt fidelity improvements.** Inline `/command` references mid-message are flagged once per user message instead of silently reaching the model as plain text; capped file reads name the remaining line count and the exact `line_offset` to resume from, and the prompt requires finishing partial reads of spec/skill/checklist files before implementing against them; user-designated spec files get artifact-scoped authority (requirements to implement faithfully, while embedded directives to run commands or switch tasks stay inert); a Definition-of-Done item walks the task's own checklist, reporting anything unverifiable instead of implying it works; `` arrival is no longer mistaken for user activity; and approval-mode-aware validation guidance plus a progress-update cadence were added. +- **TUI polish.** No more transient red `` flash while tool-call arguments stream (incomplete `None`-valued keys are dropped before rendering); flicker-free streaming on terminals with synchronized output (DEC mode 2026, capability-gated, `PYTHINKER_NO_SYNC_OUTPUT=1` kill switch); slash commands ghost-complete inline with Tab to accept; finished tool-call rows are monotonic (a late or duplicated wire event can't flip a failed row to successful); shell error briefs show the trailing output of a failed command as plain text; and the cursor-position probe can no longer leave the terminal wedged in raw mode on exit. - **`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. + +Upgrade with `pythinker update`, `pip install --upgrade pythinker-code==0.41.0`, or use the native installer for your platform from the [Releases page](https://github.com/Pythoughts-labs/pythinker-code/releases/latest). ## 0.40.1 (2026-06-10) diff --git a/README.md b/README.md index 06d6b958..0e4ff8b9 100644 --- a/README.md +++ b/README.md @@ -50,12 +50,14 @@ It speaks the [**Agent Client Protocol (ACP)**](https://github.com/agentclientpr --- -## 🆕 What's New in 0.40.1 +## 🆕 What's New in 0.41.0 -- **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 503 page instead of a bare 404. -- **Startup banner renders on legacy Windows consoles.** `pythinker web` / `pythinker vis` now honor the existing ASCII-glyph detection with width-preserving fallbacks and degrade per line instead of crashing when the output stream rejects Unicode (e.g. PowerShell with cp1252). +- **Goal-driven execution: new `/goal`, `/best-practices`, and `/learn` commands.** `/goal ` sets a persistent thread goal the agent pursues across turns, restarts, and compaction until it is verifiably complete — with an evidence-based completion audit, a root-only `UpdateGoal` tool to mark it `complete`/`blocked`, and opt-in `goal.auto_continue` to loop automatically toward it. `/best-practices` (alias `/bp`) injects engineering-discipline guidance now also shipped always-on in the default prompt, and `/learn` distills session lessons into per-project memory. +- **Statusline v2: a full redesign of the shell footer.** Colored segments with a gradient context bar, working spinner, live token speed, session cost/budget, thinking-effort badge, git diff counts, elapsed time, and a clock — all fail-closed and tunable via the new `/statusline` command (persisted under `[tui.statusline]`), with ASCII fallback and narrow-width graceful degradation. +- **Agentic orchestration hardening.** Parallel subagents and background tasks get distinctive codenames, foreground `RunAgents` batches run concurrently and roll up child RISKS/BLOCKERS, the review pipeline decomposes large diffs and adversarially verifies every finding, and restricted-profile subagents are now offline, secret-scrubbed, and workspace-jailed by default — enforced at execution time, not just prompted. +- **TUI polish.** Flicker-free streaming on synchronized-output terminals, inline ghost-completion for slash commands, monotonic tool-call rows, shell error briefs that surface the failing command's output, and no more transient `` flashes or raw-mode hangs on exit. -Upgrade with `pythinker update`, `pip install --upgrade pythinker-code==0.40.1`, or use the native installer for your platform from the [Releases page](https://github.com/Pythoughts-labs/pythinker-code/releases/latest). +Upgrade with `pythinker update`, `pip install --upgrade pythinker-code==0.41.0`, or use the native installer for your platform from the [Releases page](https://github.com/Pythoughts-labs/pythinker-code/releases/latest). --- @@ -145,7 +147,7 @@ matches your OS — no Python, Node, or `uv` prerequisite. | Platform | Recommended install | Artifact source | |---|---|---| -| **🪟 Windows** | `irm https://pythinker.com/install.ps1 \| iex` | `PythinkerSetup-0.40.1.exe` from [Releases](https://github.com/Pythoughts-labs/pythinker-code/releases/latest) | +| **🪟 Windows** | `irm https://pythinker.com/install.ps1 \| iex` | `PythinkerSetup-0.41.0.exe` from [Releases](https://github.com/Pythoughts-labs/pythinker-code/releases/latest) | | **macOS / Linux** | `curl -fsSL https://pythinker.com/install.sh \| bash` | native tarball from [Releases](https://github.com/Pythoughts-labs/pythinker-code/releases/latest) | | **macOS — Homebrew** | `brew install Pythoughts-labs/pythinker/pythinker-code` | auto-published Homebrew tap | | **🐳 Docker** | `docker run --rm -it ghcr.io/pythoughts-labs/pythinker-code` | GHCR multi-arch image | @@ -173,7 +175,7 @@ pythinker # start the interactive TUI ### 🪟 Windows — native installer -`PythinkerSetup-0.40.1.exe` is a signed* Inno Setup wizard. Installs per-user +`PythinkerSetup-0.41.0.exe` is a signed* Inno Setup wizard. Installs per-user into `%LOCALAPPDATA%\Programs\Pythinker`, registers `pythinker` on your user PATH (`HKCU\Environment`), broadcasts `WM_SETTINGCHANGE` so new shells see the change. **No UAC prompt.** @@ -184,13 +186,13 @@ irm https://pythinker.com/install.ps1 | iex # Or manually download the installer + checksum from the Releases page, # verify with Get-FileHash, then run: -.\PythinkerSetup-0.40.1.exe +.\PythinkerSetup-0.41.0.exe # Open a fresh PowerShell pythinker --version ``` -**Per-machine install** (IT-managed boxes): `.\PythinkerSetup-0.40.1.exe /ALLUSERS` +**Per-machine install** (IT-managed boxes): `.\PythinkerSetup-0.41.0.exe /ALLUSERS` installs to `%ProgramFiles%\Pythinker` and writes PATH to HKLM (requires admin). **Upgrade:** `pythinker update` from inside the running app — it downloads @@ -241,26 +243,26 @@ attached to every GitHub Release. ```sh # Debian / Ubuntu (x86_64) -sudo dpkg -i pythinker-code_0.40.1_amd64.deb +sudo dpkg -i pythinker-code_0.41.0_amd64.deb sudo apt-get install -f # only if dpkg reports missing deps # Debian / Ubuntu (ARM64) -sudo dpkg -i pythinker-code_0.40.1_arm64.deb +sudo dpkg -i pythinker-code_0.41.0_arm64.deb # Fedora / RHEL / openSUSE (x86_64) -curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.40.1/pythinker-code-0.40.1.x86_64.rpm -curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.40.1/pythinker-code-0.40.1.x86_64.rpm.sha256 -sha256sum -c pythinker-code-0.40.1.x86_64.rpm.sha256 +curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.41.0/pythinker-code-0.41.0.x86_64.rpm +curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.41.0/pythinker-code-0.41.0.x86_64.rpm.sha256 +sha256sum -c pythinker-code-0.41.0.x86_64.rpm.sha256 # Fedora / RHEL: -sudo dnf install ./pythinker-code-0.40.1.x86_64.rpm +sudo dnf install ./pythinker-code-0.41.0.x86_64.rpm # openSUSE: -sudo zypper install ./pythinker-code-0.40.1.x86_64.rpm +sudo zypper install ./pythinker-code-0.41.0.x86_64.rpm # Fedora / RHEL (aarch64) -curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.40.1/pythinker-code-0.40.1.aarch64.rpm -curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.40.1/pythinker-code-0.40.1.aarch64.rpm.sha256 -sha256sum -c pythinker-code-0.40.1.aarch64.rpm.sha256 -sudo dnf install ./pythinker-code-0.40.1.aarch64.rpm +curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.41.0/pythinker-code-0.41.0.aarch64.rpm +curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.41.0/pythinker-code-0.41.0.aarch64.rpm.sha256 +sha256sum -c pythinker-code-0.41.0.aarch64.rpm.sha256 +sudo dnf install ./pythinker-code-0.41.0.aarch64.rpm ``` Both packages drop a small `/usr/bin/pythinker` launcher that execs the real @@ -269,8 +271,8 @@ binary under `/usr/lib/pythinker/`, so your `$PATH` stays tidy. **Verify before install:** ```sh -sha256sum -c pythinker-code_0.40.1_amd64.deb.sha256 # Debian/Ubuntu -sha256sum -c pythinker-code-0.40.1.x86_64.rpm.sha256 # Fedora/RHEL +sha256sum -c pythinker-code_0.41.0_amd64.deb.sha256 # Debian/Ubuntu +sha256sum -c pythinker-code-0.41.0.x86_64.rpm.sha256 # Fedora/RHEL ``` **Upgrade:** download the new `.deb`/`.rpm` from Releases and `dpkg -i` / diff --git a/docs/en/guides/getting-started.md b/docs/en/guides/getting-started.md index b036d3fb..26818c5f 100644 --- a/docs/en/guides/getting-started.md +++ b/docs/en/guides/getting-started.md @@ -31,7 +31,7 @@ Run the native installation script to complete the installation. The canonical e curl -fsSL https://pythinker.com/install.sh | bash # Pin a specific version -curl -fsSL https://pythinker.com/install.sh | bash -s -- --version 0.40.1 +curl -fsSL https://pythinker.com/install.sh | bash -s -- --version 0.41.0 # Custom prefix (defaults to $HOME/.local) curl -fsSL https://pythinker.com/install.sh | bash -s -- --prefix /opt/pythinker @@ -44,7 +44,7 @@ On Windows, run the PowerShell bootstrap. It downloads the native installer, ver irm https://pythinker.com/install.ps1 | iex ``` -You can also download `PythinkerSetup-0.40.1.exe` manually from the [latest release](https://github.com/Pythoughts-labs/pythinker-code/releases/latest). +You can also download `PythinkerSetup-0.41.0.exe` manually from the [latest release](https://github.com/Pythoughts-labs/pythinker-code/releases/latest). Verify the installation: diff --git a/docs/en/release-notes/breaking-changes.md b/docs/en/release-notes/breaking-changes.md index be7b407f..22bf6251 100644 --- a/docs/en/release-notes/breaking-changes.md +++ b/docs/en/release-notes/breaking-changes.md @@ -4,6 +4,10 @@ This page documents breaking changes in Pythinker Code releases and provides mig ## Unreleased +## 0.41.0 (2026-06-11) + +No breaking changes. This release is compatible with 0.40.1 user configuration, native installs, and session data. + ## 0.40.1 (2026-06-10) No breaking changes. This release is compatible with 0.40.0 user configuration, native installs, and session data. diff --git a/docs/en/release-notes/changelog.md b/docs/en/release-notes/changelog.md index c2372109..4e1f61f0 100644 --- a/docs/en/release-notes/changelog.md +++ b/docs/en/release-notes/changelog.md @@ -17,33 +17,24 @@ GitHub Releases page; `0.8.0` is the new starting line. ## Unreleased -- **Parallel subagents get distinctive instance codenames.** Children launched via `RunAgents` whose name merely echoes their type (the common `code-reviewer:code-reviewer` degenerate case), or that duplicate a sibling's name, are now assigned a generated `adjective-noun` codename (`amber-falcon`, `tidal-wren`, ...) unique within the batch. The codename flows through the result tree, TaskList, TaskOutput, and completion notifications (as `codename (type)` when the caller gave no title), so simultaneous same-type agents are finally distinguishable; caller-chosen distinct names and titles pass through untouched. -- **Slash commands ghost-complete inline; Tab accepts.** Typing a root `/comm…` token now renders the remainder of the best-matching command as dim ghost text after the cursor (mode-aware, same command set as the completion menu); Tab — or the standard right-arrow/ctrl-e suggestion keys — completes it in place without submitting. The existing completion menu, Enter-to-run, and Escape-to-discard behaviors are unchanged. -- **Workspace jail for read-style shell commands in restricted profiles.** Read-only/plan/review/verify permission profiles now apply the same boundary the first-class file tools enforce to raw shell path arguments: discovery/search commands (`find `, `rg`/`grep` paths, `ls`/`du`/`tree`, `git -C`/`--git-dir`/`--work-tree`, generic `--directory`/`--project`) are denied when a path argument resolves outside the workspace and approved additional directories (symlinks and `~` are resolved first), while file-read commands (`cat`/`head`/`tail`/`sed`/...) keep ReadFile parity — absolute paths outside the workspace stay readable, relative `..` escapes are denied. Closes the gap where `find .. -name AGENTS.md` from a review subagent passed every gate; foreground and background shell share the same decision path, and every denial is an explicit error naming the offending argument. -- **Review/read-only subagents are offline by default, enforced — not prompted.** `PermissionProfile` gains an explicit `allow_network` field: review/verify/read-only profiles deny the first-class network tools (`SearchWeb`/`FetchURL`) at execution time (in addition to hiding them from the model), and the existing invariant that a root `yolo` flag never broadens a subagent's hard profile is now locked by tests. Plan/ask modes keep network access for interactive research. -- **Secret env scrubbing for restricted-profile shell.** Shell subprocesses spawned under profiles without shell-mutation rights (review/verify/read-only/plan subagents) no longer inherit credential-looking environment variables (`*_API_KEY`, `*_TOKEN`, `*_SECRET*`, `*_PASSWORD`, `AWS_*`, `GOOGLE_APPLICATION_*`, ...). Those profiles already block network access; inherited secrets were pure downside. Applies to foreground and background shell (the background task spec persists only a boolean, never the environment). -- **Retry-loop hard stop for restricted profiles.** Under review/read-only profiles, a verbatim shell command that has already failed twice is denied outright with guidance to change approach or report the blocker, instead of letting an agent flag-thrash the same failing invocation across steps. Implementation profiles are unaffected (re-running a failing test command while iterating stays legal). -- **Review diff base fallback is now loud.** `pythinker review`/`secscan` recorded only the *chosen* base ref, hiding the silent `origin/main` → `main`/`master` fallback. `ResolvedDiff` and `RunMeta` now carry `requested_base_ref` and `fallback_reason`; JSON output includes both, the pretty renderer prints a fallback warning, and PR-artifact metadata exposes them — so every report states exactly which base was reviewed and whether it was the one asked for. -- **Subagent todo lists are normalized to a single `in_progress` item.** A subagent is one sequential worker: extra `in_progress` items are demoted to pending (first wins, order preserved) with a corrective note in the tool output. The root list keeps the parallel-batch allowance (one `in_progress` sub-todo per running child). -- **Tool-call rows in the TUI are monotonic.** A finished row ignores late/duplicated wire events: a replayed `ToolResult` can no longer flip a failed row to successful (retries are separate rows), and a stray `ToolExecutionStarted`/output chunk after completion no longer restyles or mutates a committed row. -- **Statusline v2: full visual redesign of the shell footer.** The footer now renders colored segments separated by `│`/`·`, with a smooth gradient context bar (`ctx 36k/200k ████▌░░░░░ 18%`, green→gold→orange→red by fill, blinking `⚠ CTX LOW` past 90%), a working spinner, live `in N out M t/s` token speed, session cost (`$1.84`, or `$spent/$budget` once `/statusline budget` is set), a thinking-effort badge, git `+added/-removed` diff counts, session elapsed time, and a clock. Segments are fail-closed — each renders only when its data source has real data for the active provider/model, so the same default config is correct on Anthropic, OpenAI-compatible, and local Ollama/MLX setups (no `$0.00`, no empty bars). Everything is tunable via `/statusline`: `segments ` (bare `segments` now lists every available segment with its zone and on/off state), `style fancy|plain`, `bar-width <4-20>`, `budget `, plus the existing `on|off` and external `command`; all settings persist under `[tui.statusline]`. ASCII-only terminals degrade glyphs automatically, and narrow widths drop low-priority segments (speed, diff, cost, effort) instead of truncating the essentials. Disabling customization (`/statusline off`) reproduces the plain pre-v2 footer. -- **Foreground `RunAgents` batches now run children concurrently.** Previously only background batches parallelized; foreground children executed one at a time. Children now overlap (bounded by `background.max_running_tasks` so a large batch cannot fork-bomb the session), results keep request order, and a crashing child reports its own error entry instead of aborting its siblings. -- **`RunAgents` rolls up child RISKS/BLOCKERS.** Foreground batch results now end with `batch_risks:`/`batch_blockers:` blocks that deduplicate findings raised by multiple children and attribute each finding to its reporters, so the orchestrating agent sees cross-child issues without re-parsing every report body. -- **New `/statusline` command: customizable status line.** The footer under the prompt is now configurable: pick which segments show (`cwd`, `git`, `flags`, `context`, `tokens`, `model`) with `/statusline segments `, toggle customization with `/statusline on|off`, and optionally surface your own info with `/statusline command ` — an external command whose first stdout line is rendered in the footer (refreshed on a cadence, run without a shell, killed on timeout, and failing closed so a broken command never breaks the footer). Settings persist under `[tui.statusline]`; defaults reproduce the previous footer exactly. -- **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. -- **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. -- **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. -- **New `/goal` command: goal-driven execution ported from Codex CLI.** `/goal ` 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 (`` 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, and extends them with generalized sections on scoping and assumptions, subagent orchestration (scoped prompts, single blocking waits, verify findings against real code), security and secrets, and verification before done. `/best-practices
` injects a single section, and the working-spinner tips now advertise the command. -- **Best-practices guidance is now a default, not just an opt-in.** The default system prompt ships a condensed always-on best-practices profile — smallest-complete-change ownership, environment detection from artifacts, blast-radius mapping, never-invent-APIs with dependency-name verification, dirty-worktree and git safety, honest testing (no verification gaming, deterministic tests), debugging method, migration/concurrency conformance, secrets and boundary parameterization, idempotent operations with a three-failures escalation rule, and answer-shape guidance — inherited by the root agent and every subagent role. The full `/best-practices` profile is expanded to match, gaining five new sections (operating principles, context gathering, design and implementation, version control, agent operational discipline) and sharper rules throughout. -- **New `/learn` command: session lesson extraction.** Reviews the session for user corrections, non-obvious error resolutions, and hard-won conventions, distills each into a trigger rule ("when X, do Y"), and persists it via the Memory tool to per-project memory (consolidating near-duplicates instead of stacking them). `/learn ` steers extraction; an empty result is explicitly valid. This makes the working-spinner tip about `/learn` real. -- **TaskOutput escalates its hint on repeated non-blocking polls.** Polling a still-running task without `block=true` more than once now returns a firm "non-blocking poll #N … STOP polling" hint instead of the gentle default, steering the agent toward one blocking wait or the completion notification. The counter resets after any blocking attempt or once the task reaches a terminal state. -- **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. +## 0.41.0 (2026-06-11) + +- **New `/goal` command — goal-driven execution that loops until verified.** `/goal ` sets a persistent thread goal the agent pursues across turns, restarts, and context compaction until it is verifiably complete. It kicks off immediately with a success-criteria derivation prompt and is re-injected each turn with fidelity rules (no scope-shrinking, no easier-to-test substitutes) and an evidence-based completion audit — completion may only be claimed after every requirement is proven against current state. The new root-only `UpdateGoal` tool marks the goal `complete` (after that audit) or `blocked` (after a strict three-strike audit) and stops the reminders; opt-in `goal.auto_continue` (new config table, default off, `max_continuations` 1–10, capped at 3) drives automatic continuation turns toward the goal until it is marked, a tool call is rejected, or the cap is reached, with a wrap-up instruction on the final continuation. Subcommands: `view`, `pause`, `resume`, `clear`. Objectives are injected as untrusted data, never as higher-priority instructions. +- **New `/best-practices` command (alias `/bp`) and an always-on default profile.** `/best-practices` injects opt-in engineering guidance — code-change discipline, dirty-worktree safety, specific-to-broad testing, todo hygiene, progress cadence, debugging method, subagent orchestration, secrets handling, and verification-before-done — into the session without consuming a turn (`/best-practices
` injects a single section). A condensed version of this guidance now ships always-on in the default system prompt — smallest-complete-change ownership, environment detection from artifacts, blast-radius mapping, never-invent-APIs with dependency-name verification, git safety, honest deterministic testing, and a three-failures escalation rule — inherited by the root agent and every subagent role. +- **New `/learn` command — session lesson extraction.** Reviews the session for user corrections, non-obvious error resolutions, and hard-won conventions, distills each into a trigger rule ("when X, do Y"), and persists it to per-project memory (consolidating near-duplicates instead of stacking them). `/learn ` steers extraction; an empty result is explicitly valid. +- **Statusline v2 — a full redesign of the shell footer, plus the new `/statusline` command.** The footer renders colored segments separated by `│`/`·`: a smooth gradient context bar (`ctx 36k/200k ████▌░░░░░ 18%`, green→gold→orange→red by fill, blinking `⚠ CTX LOW` past 90%), a working spinner, live token speed (`in N out M t/s`), session cost (`$1.84`, or `$spent/$budget` once a budget is set), a thinking-effort badge, git `+added/-removed` diff counts, session elapsed time, and a clock. Segments are fail-closed — each renders only when its data source has real data for the active provider/model — so the same default config is correct on Anthropic, OpenAI-compatible, and local Ollama/MLX setups. Everything is tunable via `/statusline` (`segments`, `style fancy|plain`, `bar-width`, `budget`, `on|off`, external `command`) and persists under `[tui.statusline]`; ASCII-only terminals degrade glyphs automatically, narrow widths drop low-priority segments, and `/statusline off` reproduces the plain pre-v2 footer. A streaming external `command` can no longer wedge the refresh loop — the runner drains and reaps the child after kill, and renders its first line on timeout instead of failing closed. +- **Parallel subagents and background tasks get distinctive codenames.** Children launched via `RunAgents` whose name merely echoes their type (the common `code-reviewer:code-reviewer` case), or duplicates a sibling's, are assigned a generated `adjective-noun` codename unique within the batch, flowing through the result tree, TaskList, TaskOutput, and completion notifications. Background agent task ids use the same vocabulary (`agent-tidal-wren`) instead of an opaque random suffix, so simultaneous same-type agents are finally distinguishable at a glance. +- **Foreground `RunAgents` batches run concurrently and roll up child findings.** Foreground children now overlap (bounded by `background.max_running_tasks` so a large batch cannot fork-bomb the session) instead of executing one at a time, keep request order, and a crashing child reports its own error entry instead of aborting its siblings. Batch results end with deduplicated `batch_risks:`/`batch_blockers:` blocks that attribute each finding to its reporters. +- **Subagent and todo-list discipline tightened.** Subagent todo lists are normalized to a single `in_progress` item (extras demoted to pending, first wins, order preserved); `SetTodoList` nudges the same single-`in_progress` discipline at the root (with the parallel-batch allowance) and the system prompt gains matching status guidance — no single-step lists, no `pending`→`done` jumps, no batch-completing after the fact. `TaskOutput` steers toward notification-driven waiting and escalates its hint on repeated non-blocking polls; subagents no longer receive plan-mode workflow reminders for tools they don't have. +- **Review pipeline hardened for large diffs and finding fidelity.** The orchestrator decomposes large diffs (one reviewer per subsystem with explicit file lists, deduped on synthesis), adversarially verifies every finding against the cited lines before reporting (non-reproducing findings are dropped, never laundered to a lower severity), re-anchors `path:line` references, and measures review scope against the merge base rather than the uncommitted-only diff. Reviewer specs gain an explicit finding bar, comment-construction rules, and an overall-correctness verdict. Agent specs now tell the truth about their runtime permissions — offline reviewers return third-party claims as structured `needs verification` items rather than asserting them, and `scout`, accidentally defaulted offline, is restored to its network-enabled profile as the designated verifier of those claims. `pythinker review`/`secscan` now surface the previously silent base-ref fallback (`requested_base_ref`/`fallback_reason`) in JSON output, the pretty renderer, and PR-artifact metadata. +- **Workspace jail extended to raw shell commands under restricted profiles.** Read-only/plan/review/verify profiles now apply the file-tool boundary to shell path arguments: discovery/search commands (`find`, `rg`/`grep`, `ls`/`du`/`tree`, `git -C`/`--git-dir`/`--work-tree`) are denied when a path resolves outside the workspace, while file-read commands keep ReadFile parity (absolute outside-workspace reads stay legal, relative `..` escapes are denied). The jail closes the expansion/glob/cwd bypass family — path arguments with unexpanded `$` variables are rejected, glob arguments are validated by their literal prefix, and `cd`/`pushd` moves are tracked across command segments so a later command is judged against the directory the shell will actually be in. Every denial names the offending argument and the workspace root the agent must stay within. +- **Restricted-profile subagents are offline and secret-scrubbed by default.** `PermissionProfile` gains an explicit `allow_network` field: review/verify/read-only profiles deny the network tools (`SearchWeb`/`FetchURL`) at execution time as well as hiding them, with the invariant that a root `yolo` flag never broadens a subagent's hard profile now locked by tests. Their shell subprocesses no longer inherit credential-looking environment variables (`*_API_KEY`, `*_TOKEN`, `*_SECRET*`, `*_PASSWORD`, `AWS_*`, plus bare `PRIVATE_KEY`/`JWT`/`COOKIE`/`BEARER` and their suffixes), and a verbatim command that has already failed twice (whitespace-normalized, so trailing-space padding can't mint a fresh counter) is denied outright with guidance to change approach. +- **Statusline execution knobs are user-scope-only.** `enabled`, `segments`, and `command_timeout_ms` join `command` in the configuration scope locks, so a repo-controlled project config can no longer trigger or observe the user's external status command; `command_timeout_ms` also gains a 60s upper bound. Cosmetic fields (`style`, `bar_width`) stay project-configurable. +- **Base-prompt fidelity improvements.** Inline `/command` references mid-message are flagged once per user message instead of silently reaching the model as plain text; capped file reads name the remaining line count and the exact `line_offset` to resume from, and the prompt requires finishing partial reads of spec/skill/checklist files before implementing against them; user-designated spec files get artifact-scoped authority (requirements to implement faithfully, while embedded directives to run commands or switch tasks stay inert); a Definition-of-Done item walks the task's own checklist, reporting anything unverifiable instead of implying it works; `` arrival is no longer mistaken for user activity; and approval-mode-aware validation guidance plus a progress-update cadence were added. +- **TUI polish.** No more transient red `` flash while tool-call arguments stream (incomplete `None`-valued keys are dropped before rendering); flicker-free streaming on terminals with synchronized output (DEC mode 2026, capability-gated, `PYTHINKER_NO_SYNC_OUTPUT=1` kill switch); slash commands ghost-complete inline with Tab to accept; finished tool-call rows are monotonic (a late or duplicated wire event can't flip a failed row to successful); shell error briefs show the trailing output of a failed command as plain text; and the cursor-position probe can no longer leave the terminal wedged in raw mode on exit. - **`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. + +Upgrade with `pythinker update`, `pip install --upgrade pythinker-code==0.41.0`, or use the native installer for your platform from the [Releases page](https://github.com/Pythoughts-labs/pythinker-code/releases/latest). ## 0.40.1 (2026-06-10) diff --git a/packages/linux-installer/README.md b/packages/linux-installer/README.md index 50fdce13..26e41843 100644 --- a/packages/linux-installer/README.md +++ b/packages/linux-installer/README.md @@ -8,19 +8,19 @@ End-user install from the current GitHub Release: ```sh # Debian / Ubuntu -curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.40.1/pythinker-code_0.40.1_amd64.deb -curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.40.1/pythinker-code_0.40.1_amd64.deb.sha256 -sha256sum -c pythinker-code_0.40.1_amd64.deb.sha256 -sudo dpkg -i pythinker-code_0.40.1_amd64.deb +curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.41.0/pythinker-code_0.41.0_amd64.deb +curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.41.0/pythinker-code_0.41.0_amd64.deb.sha256 +sha256sum -c pythinker-code_0.41.0_amd64.deb.sha256 +sudo dpkg -i pythinker-code_0.41.0_amd64.deb sudo apt-get install -f # only needed if dependencies fail to resolve # Fedora / RHEL / openSUSE -curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.40.1/pythinker-code-0.40.1.x86_64.rpm -curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.40.1/pythinker-code-0.40.1.x86_64.rpm.sha256 -sha256sum -c pythinker-code-0.40.1.x86_64.rpm.sha256 -sudo dnf install ./pythinker-code-0.40.1.x86_64.rpm +curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.41.0/pythinker-code-0.41.0.x86_64.rpm +curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.41.0/pythinker-code-0.41.0.x86_64.rpm.sha256 +sha256sum -c pythinker-code-0.41.0.x86_64.rpm.sha256 +sudo dnf install ./pythinker-code-0.41.0.x86_64.rpm # or, on openSUSE: -sudo zypper install ./pythinker-code-0.40.1.x86_64.rpm +sudo zypper install ./pythinker-code-0.41.0.x86_64.rpm ``` The package drops a single executable at `/usr/bin/pythinker` and a license @@ -36,17 +36,17 @@ file at `/usr/share/doc/pythinker-code/LICENSE`. ## Build ```sh -bash packages/linux-installer/build.sh 0.40.1 +bash packages/linux-installer/build.sh 0.41.0 ``` Outputs to `dist/`: -- `pythinker-code_0.40.1_amd64.deb` -- `pythinker-code-0.40.1.x86_64.rpm` +- `pythinker-code_0.41.0_amd64.deb` +- `pythinker-code-0.41.0.x86_64.rpm` The portable tarball used by `scripts/install-native.sh` is published by the existing `release-pythinker-cli.yml` workflow under the cargo-dist -target-triple naming (e.g. `pythinker-0.40.1-x86_64-unknown-linux-gnu.tar.gz`). +target-triple naming (e.g. `pythinker-0.41.0-x86_64-unknown-linux-gnu.tar.gz`). ## CI diff --git a/pyproject.toml b/pyproject.toml index ba47d09e..62014a21 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "pythinker-code" -version = "0.40.1" +version = "0.41.0" description = "Pythinker — an agentic CLI developed by Pythoughts-labs." readme = "README.md" requires-python = ">=3.12" diff --git a/uv.lock b/uv.lock index 589373cf..97e2e303 100644 --- a/uv.lock +++ b/uv.lock @@ -2515,7 +2515,7 @@ wheels = [ [[package]] name = "pythinker-code" -version = "0.40.1" +version = "0.41.0" source = { editable = "." } dependencies = [ { name = "agent-client-protocol" },