From 7b5e1911f88be05eb5f9ce34453149dddd95ced3 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Fri, 28 Aug 2026 08:58:12 -0700 Subject: [PATCH] =?UTF-8?q?refactor(todo):=20schema=20diet=20=E2=80=94=20i?= =?UTF-8?q?tem=20shape=20and=20merge=20semantics=20taught=20once,=20by=20t?= =?UTF-8?q?he=20param=20schema=20(323=20->=20232=20tok/call,=20-28%)=20(#9?= =?UTF-8?q?7257)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/tools/test_todo_schema_diet.py | 50 ++++++++++++++++++++++++++++ tools/todo_tool.py | 28 ++++++---------- 2 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 tests/tools/test_todo_schema_diet.py diff --git a/tests/tools/test_todo_schema_diet.py b/tests/tools/test_todo_schema_diet.py new file mode 100644 index 0000000000..9c84396a11 --- /dev/null +++ b/tests/tools/test_todo_schema_diet.py @@ -0,0 +1,50 @@ +"""todo schema diet contract (#95681). + +Pins the dedup: item shape and merge semantics are taught ONLY by the +parameter schema (types/enum/required), never re-spelled in the +description — and the load-bearing behavioral teachings survive. +""" +import os +import sys +import unittest + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..")) + +from tools.todo_tool import TODO_SCHEMA + + +class TestTodoSchemaDiet(unittest.TestCase): + def test_description_does_not_respell_param_structure(self): + desc = TODO_SCHEMA["description"] + # The old '{id: string, content: string, status: ...}' spell-out + # and the 'Writing:' merge bullets duplicated the param schema. + self.assertNotIn("{id:", desc) + self.assertNotIn("Writing:", desc) + self.assertNotIn("merge=", desc) + self.assertNotIn("pending|in_progress", desc) + + def test_param_schema_is_the_single_structure_source(self): + item = TODO_SCHEMA["parameters"]["properties"]["todos"]["items"] + self.assertEqual(item["required"], ["id", "content", "status"]) + self.assertEqual( + item["properties"]["status"]["enum"], + ["pending", "in_progress", "completed", "cancelled"], + ) + merge_desc = TODO_SCHEMA["parameters"]["properties"]["merge"]["description"] + self.assertIn("replace the entire list", merge_desc) + self.assertIn("update existing items by id", merge_desc) + + def test_behavioral_teachings_survive(self): + """The parts that fight real model failure modes must not be + dieted away: enumerate-all-N, one in_progress, verified-done, + cancel-and-revise.""" + desc = TODO_SCHEMA["description"] + self.assertIn("enumerate every instance", desc) + self.assertIn("ONE item in_progress", desc) + self.assertIn("verified done", desc) + self.assertIn("cancel it and add a revised item", desc) + self.assertIn("3+ steps", desc) + + +if __name__ == "__main__": + unittest.main() diff --git a/tools/todo_tool.py b/tools/todo_tool.py index cc80fb92fb..8cd74c5f87 100644 --- a/tools/todo_tool.py +++ b/tools/todo_tool.py @@ -293,36 +293,31 @@ def check_todo_requirements() -> bool: TODO_SCHEMA = { "name": "todo", + # Dieted (#95681): the item shape and merge semantics live ONLY in the + # parameter schema below — the description teaches behavior, not + # structure the params already define. "description": ( "Manage your task list for the current session. Use for complex tasks " "with 3+ steps or when the user provides multiple tasks. " "For 'all N items' tasks, enumerate every instance as its own checklist " "item so none are silently dropped. " - "Call with no parameters to read the current list.\n\n" - "Writing:\n" - "- Provide 'todos' array to create/update items\n" - "- merge=false (default): replace the entire list with a fresh plan\n" - "- merge=true: update existing items by id, add any new ones\n\n" - "Each item: {id: string, content: string, " - "status: pending|in_progress|completed|cancelled}\n" - "List order is priority. Only ONE item in_progress at a time.\n" + "Call with no parameters to read the current list.\n" + "List order is priority. Only ONE item in_progress at a time. " "Mark an item completed only after the work is verified done, never " - "based on intent. If something fails, " - "cancel it and add a revised item.\n\n" - "Always returns the full current list." + "based on intent. If something fails, cancel it and add a revised " + "item. Always returns the full current list." ), "parameters": { "type": "object", "properties": { "todos": { "type": "array", - "description": "Task items to write. Omit to read current list.", + "description": "Task items to write.", "items": { "type": "object", "properties": { "id": { - "type": "string", - "description": "Unique item identifier" + "type": "string" }, "content": { "type": "string", @@ -330,8 +325,7 @@ TODO_SCHEMA = { }, "status": { "type": "string", - "enum": ["pending", "in_progress", "completed", "cancelled"], - "description": "Current status" + "enum": ["pending", "in_progress", "completed", "cancelled"] } }, "required": ["id", "content", "status"] @@ -341,7 +335,7 @@ TODO_SCHEMA = { "type": "boolean", "description": ( "true: update existing items by id, add new ones. " - "false (default): replace the entire list." + "false (default): replace the entire list with a fresh plan." ), "default": False }