Emergent:Re/Patches/look-only-pi-turns
From PickiPedia: A knowledge base of bluegrass, old time psychedelic jams, and other public domain music
Jump to navigationJump to search
What it fixes
Look-only Pi turns name only --tools read,grep,find,ls. Pi's --tools with plain names is a strict allowlist that replaces the whole selection, so codemode — the only way MCP tools (default exposure) are reachable — was never activated. A look-only Pi turn could read neither its memory nor the wiki, though the wake footer promises both.
The change
LOOK_ONLY_TOOLSnow namescodemodeplus anmcp__read-only allowlist:- every magenta-memory-v2 tool (
mcp__magenta_memory_v2__*— all 18 are queries, verified againstconversations/mcp/tools.py) - pickipedia's read tools (
mcp__pickipedia__get_*,mcp__pickipedia__search_*) - pickipedia's SMW queries (
mcp__pickipedia__smw_*)
- every magenta-memory-v2 tool (
- The stale comment ("MCP tools stay") is replaced with what's actually true: the allowlist governs which MCP tools codemode may call.
- SMW divergence note: Claude Code's look-only list (
mood_poller.ALLOWED) has no SMW tools at all — so after this fix, Pi look-only turns can SMW-query and Claude Code look-only turns cannot. Read-only, so harmless, but the two harnesses should agree deliberately, not by accident.
Test update
test_pi_harness.py now asserts the new entries instead of the bare read,grep,find,ls.
Full diff (apply from origin/main c0ec1fa)
diff --git a/memory-lane/conversations/tests/test_pi_harness.py b/memory-lane/conversations/tests/test_pi_harness.py
index 3730e02..9ff0dca 100644
--- a/memory-lane/conversations/tests/test_pi_harness.py
+++ b/memory-lane/conversations/tests/test_pi_harness.py
@@ -102,7 +102,10 @@ class CommandTest(TestCase):
self.assertEqual(cmd[:2], ['pi', '--mode'])
self.assertIn('--fork', cmd)
self.assertEqual(cmd[cmd.index('--session-id') + 1], 'new')
- self.assertEqual(cmd[cmd.index('--tools') + 1], 'read,grep,find,ls')
+ tools = cmd[cmd.index('--tools') + 1]
+ for wanted in ('codemode', 'mcp__magenta_memory_v2__*', 'mcp__pickipedia__get_*',
+ 'mcp__pickipedia__search_*', 'mcp__pickipedia__smw_*'):
+ self.assertIn(wanted, tools) # the look-only allowlist: codemode + the MCP read tools
self.assertEqual(cmd[cmd.index('--thinking') + 1], 'xhigh')
self.assertNotIn('--tools', waker.command(None, 'new', 'hi', full=True))
self.assertEqual(cmd[-1], 'hi')
diff --git a/memory-lane/poller/pi_harness.py b/memory-lane/poller/pi_harness.py
index 0b1641c..3c48312 100644
--- a/memory-lane/poller/pi_harness.py
+++ b/memory-lane/poller/pi_harness.py
@@ -39,7 +39,26 @@ logger = logging.getLogger(__name__)
STOP_REASONS = {'stop': 'end_turn', 'length': 'max_tokens', 'toolUse': 'tool_use', 'error': 'error',
'aborted': 'aborted'}
-LOOK_ONLY_TOOLS = 'read,grep,find,ls'
+# What a look-only Pi turn may call. --tools with plain names is a strict
+# allowlist that replaces the whole selection (docs/cli.md), so codemode must
+# be named here: MCP servers use the default 'codemode' exposure (docs/mcp.md),
+# so their tools are reachable only through codemode scripts, and without it a
+# look-only turn has no way to reach its memory or the wiki at all. Once any
+# entry starts with mcp__, --tools filters the MCP tools callable from
+# codemode too (docs/cli.md), so the entries below are the read-only set:
+# every magenta-memory-v2 tool (all queries — no writes; hyphens become
+# underscores in MCP names) and pickipedia's read/SMW tools. A new pickipedia
+# write tool stays blocked by default. Claude Code's look-only list
+# (mood_poller.ALLOWED) deliberately has no SMW tools, so the two harnesses
+# differ here by decision, not by drift: Pi look-only turns can SMW-query,
+# Claude Code look-only turns cannot.
+LOOK_ONLY_TOOLS = (
+ 'read,grep,find,ls,codemode,'
+ 'mcp__magenta_memory_v2__*,'
+ 'mcp__pickipedia__get_*,'
+ 'mcp__pickipedia__search_*,'
+ 'mcp__pickipedia__smw_*'
+)
COMPACT = re.compile(r'/compact\s+(.+)\Z', re.S) # what the runner sends for "/compact re <what to keep>"
EFFORTS = {'max': 'xhigh'} # our effort names that Pi spells differently
# The names the model menu has always offered, as Pi should read them. Left
@@ -497,7 +516,7 @@ class PiWaker:
if effort:
cmd += ['--thinking', EFFORTS.get(effort, effort)]
if not full:
- cmd += ['--tools', LOOK_ONLY_TOOLS] # reading only; MCP tools stay
+ cmd += ['--tools', LOOK_ONLY_TOOLS] # look-only: strict allowlist, including which MCP tools codemode may call
if system: # its instructions (mood_poller.MoodPoller.instructions_for): after Pi's own, never in the session
cmd += ['--append-system-prompt', system]
return cmd + [prompt]