Skip to content

release(v1.6.16): agent observability + state_cache bake fix#2

Merged
dreamrec merged 3 commits into
mainfrom
claude/gracious-moser-65a76d
May 18, 2026
Merged

release(v1.6.16): agent observability + state_cache bake fix#2
dreamrec merged 3 commits into
mainfrom
claude/gracious-moser-65a76d

Conversation

@dreamrec
Copy link
Copy Markdown
Owner

Summary

  • Agent observability: every dispatched MCP tool response now carries a _read_journal hint (call_count, result_unchanged, first_seen_at, last_seen_at) so Claude can see across MCP request boundaries which reads have moved.
  • Activity log: 200-entry server-side ring buffer + new td_get_activity_log MCP tool + in-TD activity_log Table DAT mirror for wiring agent activity into visuals.
  • td_self_update: new MCP tool that hits GitHub releases API, optionally writes the latest .tox to all three install paths with md5 sync reporting — closes the seven-layer staleness saga.
  • Latent bug fixed: state_cache.py source was never baked into its textDAT since v1.6.7 — silently broke the state_cache writer. Now properly threaded through _populate_component.
  • Dual-writer separation: _record_request_safe now has independent try blocks for state_cache + activity_log, plus me.parent() for resilience across TD module-load contexts.
  • Tool count 104 → 106. Version cascade 1.6.15 → 1.6.16 (all 7 fields synced).

Verification

  • ✅ 970 pytest pass (incl. 71 new tests across 4 new test files)
  • ✅ 29-check live audit against running TouchDesigner (scripts/audit_v1_6_16_live.py)
  • check_versions, check_tox_freshness, smoke_mcp_registry, check_no_personal_paths all green
  • .tox rebuilt inside TD; activity_log mirror + state_cache writer verified live with real MCP traffic
  • ✅ npm publish workflow already passed for tag v1.6.16

Test plan

  • Unit tests: read_journal (18), activity_log (14), self_updater (21), _forward integration (4)
  • Live audit script exercises all v1.6.16 surfaces end-to-end against running TD
  • Concurrent 10-parallel-call test confirms no race conditions in journal/log
  • Ring-buffer trim verified at MAX_ENTRIES=200 (220 fakes → 201 rows, oldest evicted)
  • Error path (TD 404) recorded in activity_log; error responses skip _read_journal (by design)

🤖 Generated with Claude Code

dreamrec and others added 3 commits May 18, 2026 21:56
… td_self_update + state_cache bake fix

- Added: `_read_journal` response hint on every dispatched MCP tool
  (`src/td_mcp/read_journal.py`, wired in `_forward()`). Each response
  carries {call_count, first_seen_at, last_seen_at, result_unchanged}
  keyed by (tool_name, args_fingerprint). Claude can see across MCP
  request boundaries which reads have moved and which haven't.
- Added: 200-entry server-side activity_log ring buffer + new
  `td_get_activity_log` MCP tool (`src/td_mcp/activity_log.py`,
  `src/td_mcp/registry/tools_meta.py`).
- Added: in-TD `activity_log` Table DAT mirror at /local/mcp_server/
  activity_log — rolling 200-row window so users can wire agent
  activity into their visual patch. `td_component/event_emitter.py`
  gains `append_activity_row`; `mcp_webserver_callbacks.py`
  `_record_request_safe` appends on every HTTP request.
- Added: `td_self_update` MCP tool + `td_mcp/self_updater.py`. Hits
  GitHub releases API, compares semver, optionally writes the latest
  .tox to all three install paths (repo, plugin cache, ~/.tdpilot/)
  with md5 sync reporting. Closes the seven-layer staleness saga.
  Pure stdlib so it also runs inside TD's Python via Textport.
- Fixed: `td_component/state_cache.py` source was never baked into
  the textDAT — listed in `_TOX_SOURCE_FILES` since v1.6.7 for hash
  tracking, but `_populate_component` callers never passed
  `state_cache_code`. The DAT shipped empty, `.module` raised
  tdError, and hasattr propagated through (only catches AttributeError),
  killing the state_cache writer. Latent for 9 releases. Fixed in
  `td_component/build_export_mcp_tox.py:build_and_export`.
- Fixed: `_record_request_safe` dual-writer separation — state_cache
  and activity_log writers now in independent try blocks. A
  state_cache compile error can no longer take down the activity_log
  mirror. Also switched `parent()` to `me.parent()` (instance method,
  always defined) to be resilient across TD module-load contexts.
- Bumped: tool count 104 → 106 (EXPECTED_MIN_TOOL_COUNT). Updated
  README, npm/README, plugin_README, docs/{API_REFERENCE,USER_GUIDE,
  GETTING_STARTED,MANUAL}, skills/{tdpilot-core,tdpilot-production},
  marketplace+plugin descriptions, npm description, mcp/manifest.json,
  td_component/renderer.py, CHANGELOG.
- Bumped: version 1.6.15 → 1.6.16 across all 7 fields (pyproject,
  __init__, .claude-plugin/plugin.json, marketplace.json, npm/package,
  mcp/manifest, API_VERSION in mcp_webserver_callbacks.py).
- Added: `scripts/audit_v1_6_16_live.py` — end-to-end live audit
  script that exercises all v1.6.16 surfaces against a running TD
  (29 checks, all PASS). Joins patch_session_smoke.py + full_td_mcp_e2e.py
  as a permanent regression tool in scripts/.

Verification: 970 pytest pass, 29-check live audit pass, check_versions
+ check_tox_freshness + smoke_mcp_registry all green. .tox rebuilt via
Textport (hash 796a3d488aa48052..., 18:34 UTC).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three trivial auto-fixes flagged by CI lint on the v1.6.16 release commit:

- F541 in scripts/audit_v1_6_16_live.py: drop extraneous `f` prefix
  on f-string with no placeholder.
- UP035 in src/td_mcp/self_updater.py: import `Callable` from
  `collections.abc` instead of `typing` (PEP 585 deprecation).
- I001 in tests/test_self_updater.py: import-block ordering.

All other CI jobs on v1.6.16 already pass (test 3.11, test 3.12, npm
publish, install parse-checks macos+windows, Build & upload release
assets v1.6.16 with tdpilot.plugin + tdpilot.mcpb attached).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI lint step runs BOTH `ruff check` and `ruff format --check`. The
previous fix only ran `ruff check --fix`, missing two files the
formatter wanted to reflow:

- scripts/audit_v1_6_16_live.py
- tests/test_read_journal.py

No behavior change — pure whitespace/style. 970 tests still pass;
`ruff check` + `ruff format --check` both clean locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dreamrec dreamrec merged commit 898e028 into main May 18, 2026
5 checks passed
@dreamrec dreamrec deleted the claude/gracious-moser-65a76d branch May 18, 2026 19:13
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 23294bd75d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

try:
from td_mcp import self_updater

result = self_updater.run(check_only=check_only)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Run self-update I/O off the async request thread

td_self_update is declared async but calls self_updater.run() synchronously, and that function performs blocking network (urllib) and filesystem writes. In practice this can block the MCP server’s event loop for up to the HTTP timeout (30s+) during an update/check, stalling unrelated tool calls in the same process. Wrapping the call in asyncio.to_thread(...) (or making the updater async) avoids request-wide head-of-line blocking.

Useful? React with 👍 / 👎.

Comment on lines +61 to +63
text = json.dumps(value, default=str, separators=(",", ":"))
except Exception:
text = repr(value)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid serializing full payloads for truncated summaries

The summary path serializes the entire result with json.dumps(...) and only then truncates to 120 chars. Since _forward now logs every tool result, large responses (for example image/base64-heavy or large graph payloads) incur an extra full serialization/allocation per call, which can add significant latency and memory pressure under load. The summary should be size-bounded before full serialization or use a cheap structural preview.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant