From 0243732e22a415203d4139170c7609e8194cddba Mon Sep 17 00:00:00 2001 From: BukeLy Date: Wed, 27 May 2026 03:35:12 +0800 Subject: [PATCH] fix(filesystem): clarify agent evidence recovery --- .gitignore | 1 + pageindex/filesystem/agent.py | 16 +++++++++++----- pageindex/filesystem/commands.py | 6 +++++- tests/test_pageindex_structural_read.py | 2 +- tests/test_pifs_agent_stream.py | 8 ++++++++ 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 3702bda..31664a9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ __pycache__ .venv/ logs/ examples/pifs_workspace/ +examples/Benchmark/enterpriseragbenchmark_workspace/ diff --git a/pageindex/filesystem/agent.py b/pageindex/filesystem/agent.py index facaceb..b1f1625 100644 --- a/pageindex/filesystem/agent.py +++ b/pageindex/filesystem/agent.py @@ -60,9 +60,11 @@ commands described in the workspace context. grep -R is lexical evidence search; grep does not support regex alternation such as "a|b"; run multiple grep commands or use search-summary for semantic candidate discovery instead. semantic search commands such as search-summary return candidate documents and -do not guarantee literal text matches. Use search-summary when the user asks for -summary search, semantic search, or vector search and the command is listed as -available. Quote multi-word semantic queries, for example: +do not guarantee literal text matches or final answer evidence. After choosing +a likely search-summary candidate, verify the relevant claim with cat before +answering. Use search-summary when the user asks for summary search, semantic +search, or vector search and the command is listed as available. Quote +multi-word semantic queries, for example: search-summary "Federal Reserve" /documents. Do not write search-summary Federal Reserve /documents. Errors are returned as text prefixed with ERROR. Do not call @@ -70,7 +72,9 @@ commands that are not listed as available. When evidence is required, inspect it with cat or grep before answering. Prefer shell-like target-first cat syntax with stable targets: cat --structure, cat --page 31-59, and cat --node 0009. You may also use file_ref or document_id when a path is -ambiguous. After structure identifies a relevant section node, prefer +ambiguous. Do not reconstruct paths from document titles; use exact targets +returned by PIFS commands and quote paths containing spaces. After structure +identifies a relevant section node, prefer cat --node ; use cat --page when the user asks for page-level evidence, no suitable node exists, or exact page text is needed. cat --structure is paginated; request more with --offset if needed. Page @@ -94,11 +98,13 @@ Tool policy: - Use --where only with metadata fields shown by stat --schema. - grep -R performs lexical evidence search. - grep does not support regex alternation such as "a|b"; run separate grep commands or use search-summary for semantic candidate discovery. -- Semantic search commands are candidate-discovery tools and do not guarantee literal text matches. +- Semantic search commands are candidate-discovery tools and do not guarantee literal text matches or final answer evidence. After selecting a likely search-summary candidate, verify the relevant facts with cat before answering. +- Do not use find | grep as an exhaustive search or as proof that no document exists; find output can be scoped or limited. Use metadata filters, search-summary, grep on a narrowed target, or cat on likely candidates instead. - A single failed grep is not enough evidence to say there is no relevant document. If grep returns no matches for a workspace-topic question, verify with search-summary or another available semantic/vector candidate command, or inspect likely document structure, before answering no-evidence. - If search-summary is available and the user asks for summary search, semantic search, vector search, or "用 summary 搜", use search-summary "" ; quote multi-word queries, for example search-summary "Federal Reserve" /documents; do not translate that request into find --where. - Tool errors are returned as ERROR text; recover by trying an available command. - Use cat or grep to gather evidence before making source-backed claims. +- Do not reconstruct a file path from a title. Use exact paths returned by PIFS commands, or use file_ref/document_id when available; quote paths that contain spaces. - For broad topic, method, or "what solution" questions that are likely about the workspace, search for candidate documents before asking the user to choose a document. - Use stat only for metadata/schema/status questions or to resolve ambiguous target identity. Do not run stat merely to understand what a document says. - Prefer target-first cat syntax with stable targets: cat --structure, cat --page 31-59, cat --node . diff --git a/pageindex/filesystem/commands.py b/pageindex/filesystem/commands.py index 73470a6..2ec5920 100644 --- a/pageindex/filesystem/commands.py +++ b/pageindex/filesystem/commands.py @@ -534,7 +534,11 @@ class PIFSCommandExecutor: "cat accepts one file target. Use target-first syntax: " "cat --structure, " "cat --node 0002 0004, or " - "cat --page 31-33" + "cat --page 31-33. " + f"Unexpected extra argument: {arg!r}. If the target path or title contains " + "spaces, quote the whole target, for example: cat \"/documents/report name.pdf\" " + "--structure. If a title-derived path is ambiguous, use the file_ref or " + "document_id instead." ) i += 1 if structural_mode == "structure": diff --git a/tests/test_pageindex_structural_read.py b/tests/test_pageindex_structural_read.py index a78f1d1..3994aa4 100644 --- a/tests/test_pageindex_structural_read.py +++ b/tests/test_pageindex_structural_read.py @@ -517,7 +517,7 @@ def test_cat_structure_page_node_and_text_outputs_are_hard_limited(): "0006 0007 0008 0009 0010 0011" ) - with pytest.raises(PIFSCommandError, match="cat accepts one file target"): + with pytest.raises(PIFSCommandError, match="quote the whole target"): executor.execute("cat dsid_limited_pdf 0001") text = json.loads(executor.execute("cat dsid_long_text --all")) diff --git a/tests/test_pifs_agent_stream.py b/tests/test_pifs_agent_stream.py index 5dae40b..69f62ed 100644 --- a/tests/test_pifs_agent_stream.py +++ b/tests/test_pifs_agent_stream.py @@ -204,6 +204,8 @@ class PIFSAgentStreamTest(unittest.TestCase): self.assertIn("prefer\ncat --node ", BASH_TOOL_DESCRIPTION) self.assertIn("stop if the evidence is sufficient", AGENT_TOOL_POLICY) self.assertIn("continue with another chunk before answering", BASH_TOOL_DESCRIPTION) + self.assertIn("Do not reconstruct paths from document titles", BASH_TOOL_DESCRIPTION) + self.assertIn("file_ref/document_id", AGENT_TOOL_POLICY) def test_prompt_requires_stat_for_metadata_questions(self): self.assertIn("stat --schema and stat ", AGENT_TOOL_POLICY) @@ -218,6 +220,12 @@ class PIFSAgentStreamTest(unittest.TestCase): self.assertIn('use search-summary "" ', AGENT_TOOL_POLICY) self.assertIn('search-summary "Federal Reserve" /documents', BASH_TOOL_DESCRIPTION) self.assertIn("do not translate that request into find --where", AGENT_TOOL_POLICY) + self.assertIn("verify the relevant facts with cat", AGENT_TOOL_POLICY) + self.assertIn("verify the relevant claim with cat", BASH_TOOL_DESCRIPTION) + + def test_prompt_rejects_find_grep_as_exhaustive_search(self): + self.assertIn("Do not use find | grep as an exhaustive search", AGENT_TOOL_POLICY) + self.assertIn("find output can be scoped or limited", AGENT_TOOL_POLICY) def test_system_prompt_sets_workspace_identity_and_scope(self): self.assertIn("PageIndex FileSystem Demo Agent", AGENT_SYSTEM_PROMPT)