mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-12 23:12:23 -06:00
docs(tools): apply review round-1 findings (cwd notes)
- docs/tools.md: sync the tool-JSON metadata-keys table to _META_KEYS — it had drifted to 3 of 8 keys (coordinator, interactive, kind_variants were already missing; cwd_note/workspace_note are new). - tests: cover the third note-rebuild trigger (_drop_mcp_surface) with a count==1 assertion on both lanes, and pin the deliberately uniform workspace_note wording across the fs tools so a one-file reword cannot drift the copies apart.
This commit is contained in:
+12
-6
@@ -28,13 +28,19 @@ schema plus turnstone-specific metadata keys:
|
||||
}
|
||||
```
|
||||
|
||||
**Metadata keys** (stripped before sending the schema to the model):
|
||||
**Metadata keys** (stripped before sending the schema to the model; the full
|
||||
set lives in `_META_KEYS` in `turnstone/core/tools.py`):
|
||||
|
||||
| Key | Type | Meaning |
|
||||
|----------------|------|---------|
|
||||
| `task_agent` | bool | Tool is available to task sub-agents. |
|
||||
| `auto_approve` | bool | Tool runs without user confirmation (read-only, safe operations). |
|
||||
| `primary_key` | str | When the model sends a bare string instead of JSON args, map it to this parameter name. |
|
||||
| Key | Type | Meaning |
|
||||
|------------------|------|---------|
|
||||
| `task_agent` | bool | Tool is available to task sub-agents. |
|
||||
| `coordinator` | bool | Tool is available to coordinator sessions. Without `interactive: true` alongside it, this reads as coord-only and the tool is stripped from interactive sessions. |
|
||||
| `interactive` | bool | Opt a `coordinator: true` tool back into interactive sessions (dual-kind tools like `memory`). |
|
||||
| `auto_approve` | bool | Tool runs without user confirmation (read-only, safe operations). |
|
||||
| `primary_key` | str | When the model sends a bare string instead of JSON args, map it to this parameter name. |
|
||||
| `kind_variants` | dict | Per-kind description / parameter-schema overlays so each session kind sees only the surface it can use (see `memory.json`). |
|
||||
| `cwd_note` | str | Sentence appended to the description at session build time with `{working_dir}` substituted — declare on tools whose semantics depend on the process working directory (see `bash.json`, `apply_cwd_context`). |
|
||||
| `workspace_note` | str | Companion sentence naming the operator-configured workspace directory, `{workspace_dir}` substituted; dropped when no workspace is configured. |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -123,6 +123,14 @@ class TestNoteMetadataInvariants:
|
||||
assert "cwd_note" not in t["function"]
|
||||
assert "workspace_note" not in t["function"]
|
||||
|
||||
def test_workspace_note_wording_uniform(self):
|
||||
# The workspace fact is one node-level value, so its sentence is
|
||||
# deliberately identical across the fs tools (unlike cwd_note, whose
|
||||
# prose is per-tool). Guards a one-file reword from drifting the
|
||||
# copies apart, independent of the exact wording.
|
||||
notes = {_META[name]["workspace_note"] for name in _FS_TOOLS}
|
||||
assert len(notes) == 1, notes
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ChatSession build sites
|
||||
@@ -208,3 +216,16 @@ class TestSessionCwdNotes:
|
||||
session._on_mcp_tools_changed()
|
||||
assert _desc(session._tools, "bash").count(f"Commands run in {os.getcwd()}") == 1
|
||||
assert _desc(session._task_tools, "bash").count(f"Commands run in {os.getcwd()}") == 1
|
||||
|
||||
def test_mcp_drop_surface_keeps_single_note(self, tmp_db):
|
||||
# The MCP-disconnect rebuild (_drop_mcp_surface, reached via resume()
|
||||
# adopting an MCP-off persona) is the third rebuild trigger — the note
|
||||
# must survive it, exactly once, on both lanes.
|
||||
mock_mcp = MagicMock()
|
||||
mock_mcp.get_tools.return_value = []
|
||||
with patch("turnstone.core.session.get_workspace_dir", return_value=None):
|
||||
session = _make_session(mcp_client=mock_mcp)
|
||||
session._drop_mcp_surface()
|
||||
assert session._mcp_client is None
|
||||
assert _desc(session._tools, "bash").count(f"Commands run in {os.getcwd()}") == 1
|
||||
assert _desc(session._task_tools, "bash").count(f"Commands run in {os.getcwd()}") == 1
|
||||
|
||||
Reference in New Issue
Block a user