Repository navigation
v1.13.7
Changes
Left to their own devices, small models will happily play Qxh9. This PR gives any model a harness for chess, Connect Four and Othello where illegal moves can't happen, with dials for how much help it gets. It also lets scripts and other agents hand work to the companion's coding-agent queue without their own API keys, and keeps long agent runs from drowning in oversized tool results and tool schemas.
Highlights
- Any model can play chess, Connect Four or Othello and only ever play legal moves: it picks from a menu, a bad answer is sent back with the reason, and a move it never gets right is played for it and counted.
- A help level runs from "every legal move" up to "only the engine's best move", and concept switches (forks, pins, double threats, corners ...) decide which ideas a model is told about, so a bot can know forks but not skewers.
- Connect Four and Othello come with built-in engines, so every level works with nothing to install; chess uses Stockfish for the engine levels.
- Full games between models, engines and random players, and chess puzzle runs that measure whether teaching a concept helps a model.
prompture delegate "..."hands a task to Claude Code or Codex through the companion, which starts itself if needed;delegate-status,delegate-answeranddelegate-resumefollow up, and exit codes tell scripts how the run ended.- Agents keep large tool results instead of cutting them off: the model gets a preview and reads the rest on demand, and very large tool sets are searched and loaded as needed instead of all being sent every turn.
- Deep agents now pick when to summarise from the model's context window, and the summary keeps user instructions, findings and the current step in fixed sections.
Technical changes
Game harnesses (prompture.games)
games/base.py:GameHarnessoffers candidate moves, puts their names in the reply schema as anenum(enforced natively by drivers with schema support, such as Ollama'sformat), validates replies throughGame.parse_move, retries with the rejection reason, and falls back to the engine's best or a random move withMoveDecision.rescued=True. Usage is summed across attempts.level(0-5) controls which moves are offered (all, tagged, blunders removed by ablunder_dropin winning chances, engine top-N unranked, top-N ranked with scores, best only);conceptsfilters which motif tags are attached. Engine levels useGame.default_engine()when no engine is passed.- A failed model call (timeout, backend down) is recorded as a failed attempt instead of raising, so a match survives a flaky backend and the rescue shows up in the report.
GameandEngineprotocols, plusMotif,Score,Candidate,Attempt,MoveDecisionandcheck_concepts, are the extension points for new games.games/match.py:play_match(game, players, state=None, max_moves=400)returns aMatchResultwith the winner, moves, per-side rescues and afinishedflag;EnginePlayerandRandomPlayerimplement the samechoose(state)interface as a harness.games/connect4.py:Connect4Board(flat cells, play/undo,winning_cells,immediate_wins), tags forwin,block,threat,double-threat,safetyandcenter, a prompt with a grid plus per-column stacks, andConnect4Engine, a centre-first alpha-beta search over open-line windows (default depth 6) with "wins in N" / "loses in N" labels.games/othello.py:OthelloBoardwith flips and forced passes (PASS), tags forcorner,x-square,edge,mobilityandsafety(newly conceded corners), andOthelloEngine, alpha-beta on a positional weight table plus mobility (default depth 4).games/chess/motifs.py:describe_movetags facts (capture, check, promotion, castling) and concepts (mate,back-rank-mate,fork,pinincluding capturing a pinned piece,skewer,discovered-attack,hanging-piece,safety), using one-move static checks; a piece lost on the spot cannot fork, pin or skewer, and pawn pins and pawn discoveries are not reported.games/chess/harness.py:ChessGame(SAN names, SAN/UCI parsing, FEN plus piece lists in the prompt),ChessEnginewrapping a UCI engine path orSimpleEngineinto Lichess winning-chance scores, andChessHarnessas aGameHarnesssubclass.games/chess/puzzles.py:load_puzzles,play_puzzleandrun_puzzlesread Lichess-format packs (opponent's move first, any mate accepted on the last move) into aPuzzleReportwith solve rate and rescues.- New
chessextra (chess>=1.10), included inall;prompture.games.chessraises a clear install hint without it.
Task delegation (prompture/cli/delegate_cmd.py)
delegate,delegate-answer,delegate-resumeanddelegate-statusdrive the companion's automation queue over its loopback API with the bearer token from~/.prompture/companion.json, through a stdliburllibclient.- The client refuses any companion URL that is not
127.0.0.1orlocalhost, so the bearer token never leaves the machine, matching the hook client. - A missing companion is started detached (
DETACHED_PROCESSon Windows, a new session elsewhere), then the command waits for its state file to answer. - Step logs stream to stdout by polling; exit codes are
0finished,1failed,3waiting for an answer,4stopped or detached.--json,--no-wait,--timeout,--agent,--modeland--cost-capare supported. - Registered through
_COMMAND_MODULESincli.py; documented in the README.
Tool-context management (prompture/agents/tool_context.py)
ToolResultPolicyandshape_tool_resultsmove results overper_call_tokens(default 4000), or the largest results of a round overbatch_tokens(default 12000), into anArtifactStore, leaving a head/tail preview and anartifact://handle;read_tool_result(handle, query, offset)is registered only once something is stored. Error results are cut, never offloaded;offload=Falserestores plain truncation.ToolLoadersendssearch_tools/load_toolsinstead of the full schemas when they would exceed ~8k tokens (defer_tools="auto"), keeps loaded tools for the rest of the conversation, and always sendspreload_tools.repair_tool_pairsgives every assistant tool call a result (a placeholder for interrupted calls) and drops orphaned results, so trimmed or interrupted histories are not rejected by providers.ConversationandAsyncConversationgain this throughToolContextMixin;AgentandAsyncAgentaccepttool_result_policy,defer_toolsandpreload_toolsand pass them through.ArtifactStoregainstext(handle, scope=...), a scope-checked text read, andclear(scope=...).create_deep_agentand its async twin default tosummarize_at_tokens="auto", which resolves viaresolve_summarize_thresholdto the smallest of 80k, 75% of the model's context window, and the window minus the output reservation (frommax_output_optionor the model's limit), with a 2k floor and a fallback to 80k for unknown models.SUMMARIZER_SYSTEM_PROMPTrewritten into fixed sections (task, user messages, findings, actions, errors, open items, current step) that keep exact values andartifact://handles.