Skip to content

Commit 61c7d8b

Browse files
committed
release: 1.6.13 — audit hotfix on top of 1.6.12
Five findings from the post-1.6.12 cold-pass review, all in the standalone runtime. CLI variant (tdpilot-dpsk4) source untouched; its .tox is rebuilt only to refresh API_VERSION baked into the binary. [P1] Reset no longer races against an in-flight worker. Agent.reset() used to clear _stop_flag unconditionally — if a worker was still running, it kept going on the now-empty history. Post-fix: Agent.reset() clears messages only; new clear_stop() lifts cancellation explicitly; AgentRuntime.reset() reorders to signal stop → cancel pending cook calls → join worker (2s grace) → mutate state → clear_stop(). [P1] Compaction no longer orphans tool_result blocks. The slice point could land inside a tool chain — retained slice starting with user/tool_result whose matching assistant/tool_use was archived. Anthropic-format APIs reject that with a 400. Fix: compact() advances the cut forward past every leading tool_result. Eats into keep_recent — by design, an unsendable history is worse than a slightly smaller one. New helper _starts_with_tool_result. [P2] Stop pulse no longer leaves worker blocked. AgentRuntime.stop() used to set the agent flag and push idle. Workers blocked inside CookThreadDispatcher.__call__ wouldn't see the flag until next API call (or 60s timeout). Fix: stop() now cancels pending cook calls AND joins the worker (2s grace) before pushing idle. [P2] tool_batch sub-calls feed the severity ledger. _record_tool_call now peeks inside tool_batch results. Pre-fix, a batched td_create_node was invisible to the validation hint system. Failed sub-calls are skipped (matches top-level "errors don't count" rule). [P3] README title bumped — H1 was still v1.6.11 because check_versions.py's regex didn't match the en-dash form. Tests: 9 new regression tests pinning each behaviour. - test_agent_reset_does_not_clear_stop_flag - test_runtime_reset_joins_worker_before_clearing_history - test_runtime_stop_cancels_pending_dispatcher_calls - test_record_tool_call_flattens_tool_batch_subcalls - test_validation_hint_fires_for_batched_high_severity - test_compact_returns_synthetic_plus_smaller_recent_when_boundary_repaired - test_compact_advances_past_multiple_tool_results - test_compact_handles_pathological_all_tool_results - test_starts_with_tool_result_helper Pytest 1132 passing (up from 1122). All CI gates clean (check_versions, check_tox_freshness, sync_counts, check_no_personal_paths, ruff). Both .tox rebuilt; the standalone grew to pick up the runtime fixes, the CLI bridge stayed size-stable (only API_VERSION literal changed inside). 12 version files in lockstep at 1.6.13. CHANGELOG entry added.
1 parent dcb3e41 commit 61c7d8b

23 files changed

Lines changed: 598 additions & 37 deletions

.claude-plugin/marketplace.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
{
1111
"name": "tdpilot-dpsk4",
1212
"description": "AI copilot for TouchDesigner with live MCP control (DeepSeek v4 optimized) \u2014 103 tools, focus + locations, hint injection, component notes, POPx inspection, knowledge corpus, project lifecycle, custom parameter authoring, snapshots, undo-block safety, and typed patch sessions. Works with Claude Desktop, Claude Code (DeepSeek v4 backend), and any MCP-compatible client.",
13-
"version": "1.6.12",
13+
"version": "1.6.13",
1414
"author": {
1515
"name": "silviu"
1616
},

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tdpilot-dpsk4",
3-
"version": "1.6.12",
3+
"version": "1.6.13",
44
"description": "TDPilot DPSK4 \u2014 AI copilot for TouchDesigner (DeepSeek v4 optimized). 103 MCP tools for live node graph control, parameter management, diagnostics, safety, streaming, knowledge corpus, focus + locations, hint injection, component notes, technique memory, and typed patch sessions.",
55
"author": {
66
"name": "silviu"

CHANGELOG.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,94 @@
11
# Changelog
22

3+
## 1.6.13 - 2026-05-07
4+
5+
**Audit hotfix.** Five findings from the post-1.6.12 cold-pass review,
6+
all on the standalone runtime. CLI variant (`tdpilot-dpsk4`) is
7+
untouched at the source level; this release rebuilds its .tox solely
8+
to refresh `API_VERSION` baked into the binary.
9+
10+
### [P1] Reset no longer races against an in-flight worker
11+
12+
`Agent.reset()` used to clear `_stop_flag` unconditionally. If a
13+
worker thread was still running a turn, the freshly-cleared flag let
14+
it keep going on a now-empty history — appending stale tool_result
15+
blocks and potentially making a fresh API call against the cleared
16+
session.
17+
18+
Post-fix:
19+
- `Agent.reset()` clears `messages` only. Stop flag stays set.
20+
- New `Agent.clear_stop()` lifts cancellation explicitly — only
21+
safe to call after the previous worker has been joined.
22+
- `AgentRuntime.reset()` reorders: signal stop → cancel pending
23+
cook calls → join the worker (2s grace) → THEN mutate state →
24+
finally `clear_stop()`.
25+
26+
### [P1] Compaction no longer orphans tool_result blocks
27+
28+
The compactor's slice point could land inside a tool chain — the
29+
retained slice would start with a user `tool_result` block whose
30+
matching assistant `tool_use` was archived. Anthropic-format APIs
31+
reject that with `messages.0: tool_result block without matching
32+
tool_use`, so long sessions could 400 exactly when compaction was
33+
supposed to save them.
34+
35+
Post-fix: `compact()` advances the cut forward past every leading
36+
`tool_result` so the retained slice starts on a clean boundary. The
37+
retained slice may end up smaller than `keep_recent` — by design;
38+
an unsendable history is worse than a slightly smaller one. New
39+
helper `_starts_with_tool_result(message)` makes the predicate
40+
testable.
41+
42+
### [P2] Stop pulse no longer leaves worker blocked
43+
44+
`AgentRuntime.stop()` used to set the agent stop flag and push idle.
45+
But if the worker was blocked inside `CookThreadDispatcher.__call__`
46+
waiting for a pump, it wouldn't see the flag until the next API call
47+
(or the 60s timeout). The UI reported idle while `start_turn()`
48+
still refused new work because the old thread was alive.
49+
50+
Post-fix: `stop()` cancels pending cook calls (waking any blocked
51+
worker immediately) AND waits up to 2s for the worker to actually
52+
exit before pushing idle.
53+
54+
### [P2] `tool_batch` sub-calls feed into the severity ledger
55+
56+
The validation-hint system (Phase 1.3) tracked `_turn_tool_calls`
57+
based on the top-level tool name the agent invoked. When the agent
58+
called `tool_batch`, the tracker only saw `tool_batch` (severity=low)
59+
— sub-calls like `td_create_node` or `td_exec_python` hidden inside
60+
the batch escaped the high-severity hint system entirely.
61+
62+
Post-fix: `_record_tool_call` now peeks inside `tool_batch` results
63+
and feeds each successful sub-call's name into the ledger. Failed
64+
sub-calls are skipped (mirrors the top-level "errors don't count"
65+
rule). A batched `td_create_node` without a follow-up validator now
66+
fires the same `EV_HINT` a non-batched call would.
67+
68+
### [P3] README title bumped to 1.6.13
69+
70+
The 1.6.12 release left the H1 in `README.md` reading
71+
`# TDPilot — DeepSeek v4 · v1.6.11``check_versions.py` doesn't
72+
match that pattern, so it slipped past the lockstep enforcer.
73+
74+
### Tests
75+
76+
9 new regression tests covering reset/stop/compaction/severity:
77+
- `test_agent_reset_does_not_clear_stop_flag`
78+
- `test_runtime_reset_joins_worker_before_clearing_history`
79+
- `test_runtime_stop_cancels_pending_dispatcher_calls`
80+
- `test_record_tool_call_flattens_tool_batch_subcalls`
81+
- `test_validation_hint_fires_for_batched_high_severity`
82+
- `test_compact_returns_synthetic_plus_smaller_recent_when_boundary_repaired`
83+
- `test_compact_advances_past_multiple_tool_results`
84+
- `test_compact_handles_pathological_all_tool_results`
85+
- `test_starts_with_tool_result_helper`
86+
87+
Pytest 1132 passing (up from 1122). Lints + format + version drift +
88+
sync_counts + personal-path checks all clean.
89+
90+
---
91+
392
## 1.6.12 - 2026-05-07
493

594
**Standalone runtime overhaul.** The "agent with a big prompt → small runtime

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝
88
```
99

10-
# TDPilot — DeepSeek v4 · v1.6.11
10+
# TDPilot — DeepSeek v4 · v1.6.13
1111

1212
[![CI](https://github.com/dreamrec/TDPilot_deepseekv4/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/dreamrec/TDPilot_deepseekv4/actions/workflows/ci.yml)
1313
[![npm](https://img.shields.io/npm/v/tdpilot-dpsk4?label=npm)](https://www.npmjs.com/package/tdpilot-dpsk4)

docs/MANUAL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# TDPilot v1.6.12 Manual
1+
# TDPilot v1.6.13 Manual
22

33
The full reference. Read the [README](../README.md) first if you haven't installed yet — this manual assumes you've got either the standalone .tox or the Claude Code plugin running.
44

mcp/manifest.json

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,25 @@
22
"schema_version": 1,
33
"name": "TDPilot DPSK4",
44
"slug": "tdpilot-dpsk4",
5-
"version": "1.6.12",
5+
"version": "1.6.13",
66
"repository": "https://github.com/dreamrec/TDPilot_deepseekv4",
77
"description": "MCP server for TouchDesigner (DeepSeek v4 optimized) with live graph control, diagnostics, safety, streaming, knowledge corpus, technique memory, and typed patch sessions.",
88
"entrypoints": {
99
"npm": {
1010
"command": "npx",
11-
"args": ["-y", "tdpilot-dpsk4"]
11+
"args": [
12+
"-y",
13+
"tdpilot-dpsk4"
14+
]
1215
},
1316
"python": {
1417
"command": "uv",
15-
"args": ["run", "--directory", "<repo-path>", "tdpilot-dpsk4"]
18+
"args": [
19+
"run",
20+
"--directory",
21+
"<repo-path>",
22+
"tdpilot-dpsk4"
23+
]
1624
}
1725
},
1826
"defaults": {

npm/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# TDPilot v1.6.12
1+
# TDPilot v1.6.13
22

33
[![CI](https://github.com/dreamrec/TDPilot_deepseekv4/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/dreamrec/TDPilot_deepseekv4/actions/workflows/ci.yml)
44
[![npm](https://img.shields.io/npm/v/tdpilot-dpsk4?label=npm)](https://www.npmjs.com/package/tdpilot-dpsk4)

npm/package.json

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
{
22
"name": "tdpilot-dpsk4",
3-
"version": "1.6.12",
4-
"description": "AI copilot for TouchDesigner with live MCP control (DeepSeek v4 optimized) — 103 tools, focus + locations, hint injection, component notes, POPx inspection, knowledge corpus, project lifecycle control, technique memory, typed patch sessions.",
5-
"keywords": ["touchdesigner", "mcp", "ai", "model-context-protocol", "creative-coding", "deepseek"],
3+
"version": "1.6.13",
4+
"description": "AI copilot for TouchDesigner with live MCP control (DeepSeek v4 optimized) \u2014 103 tools, focus + locations, hint injection, component notes, POPx inspection, knowledge corpus, project lifecycle control, technique memory, typed patch sessions.",
5+
"keywords": [
6+
"touchdesigner",
7+
"mcp",
8+
"ai",
9+
"model-context-protocol",
10+
"creative-coding",
11+
"deepseek"
12+
],
613
"author": "dreamrec",
714
"license": "MIT",
815
"repository": {
@@ -16,7 +23,13 @@
1623
"bin": {
1724
"tdpilot-dpsk4": "./run.js"
1825
},
19-
"files": ["run.js", "install.js", "plugin.js", "brains.js", "README.md"],
26+
"files": [
27+
"run.js",
28+
"install.js",
29+
"plugin.js",
30+
"brains.js",
31+
"README.md"
32+
],
2033
"engines": {
2134
"node": ">=16"
2235
}

plugin_README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# TDPilot v1.6.12 — TouchDesigner AI Assistant Plugin
1+
# TDPilot v1.6.13 — TouchDesigner AI Assistant Plugin
22

33
This plugin installs the **DPSK4 (Claude Code CLI) variant** of TDPilot.
44
Two variants ship in the same repo:
@@ -12,7 +12,7 @@ For the standalone .tox path, see the [main README](https://github.com/dreamrec/
1212

1313
---
1414

15-
TDPilot v1.6.12 provides 103 MCP tools for live control of TouchDesigner projects from Claude Code, optimized for DeepSeek v4. The bundled `.tox` includes a one-button installer (drag-drop into TD, click "Bootstrap All", done) — no manual setup script.
15+
TDPilot v1.6.13 provides 103 MCP tools for live control of TouchDesigner projects from Claude Code, optimized for DeepSeek v4. The bundled `.tox` includes a one-button installer (drag-drop into TD, click "Bootstrap All", done) — no manual setup script.
1616

1717
## Components
1818

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "tdpilot-dpsk4"
3-
version = "1.6.12"
3+
version = "1.6.13"
44
description = "MCP server for live control of TouchDesigner — create, inspect, connect, and manipulate nodes via AI agents"
55
readme = "README.md"
66
license = "MIT"

0 commit comments

Comments
 (0)