docs: PicoClaw fact-check tool order before a factual reply (#22)
Tests / Test (push) Failing after 5s
Tests / Release (semver) (push) Skipped

search then get then audit. throttled is not absence. 2dph is the
gate, not the agent loop.
This commit is contained in:
2026-08-13 21:36:31 +01:00
committed by GitHub
co-authored by GitHub
parent 6b680bdb90
commit e5a982e99a
4 changed files with 39 additions and 1 deletions
+3
View File
@@ -15,6 +15,9 @@ Read first: [PLAN](PLAN.md) → [docs](docs/).
- `info` root = descriptive/narrative leafs, searchable, never asserted as fact. - `info` root = descriptive/narrative leafs, searchable, never asserted as fact.
- Search is deduction: `facts``info``web-search` (second independent - Search is deduction: `facts``info``web-search` (second independent
source). An answer is `confirmed` only if it comes off the facts root. source). An answer is `confirmed` only if it comes off the facts root.
- Fact-check every *claim* (facts → info → live → web), not every edit or
syntax tweak. PicoClaw: `search` then `get` then `audit` before a factual
reply (`skills/picoclaw/SKILL.md`). `throttled` is not a negative finding.
## Hard rules ## Hard rules
+1 -1
View File
@@ -51,7 +51,7 @@ detective method: **a fact needs ≥2 independent sources or it is
2dph/ 2dph/
PLAN.md / AGENTS.md PLAN.md / AGENTS.md
docs/ published docs (this conversation → docs/ as md) docs/ published docs (this conversation → docs/ as md)
skills/ in-project skills (web-search, postgres, brain, diataxis-docs) skills/ in-project skills (web-search, postgres, brain, picoclaw, diataxis-docs)
bin/ bin/
facts/extract.go audit.go crm.go # D14 shebang; Python implementation facts/extract.go audit.go crm.go # D14 shebang; Python implementation
kb/index Python write path (called by bin/brain/index.go) kb/index Python write path (called by bin/brain/index.go)
+10
View File
@@ -37,3 +37,13 @@ class SkillsTest(unittest.TestCase):
self.assertIn("tools.md", skill) self.assertIn("tools.md", skill)
for name in ("search", "get", "stats", "audit"): for name in ("search", "get", "stats", "audit"):
self.assertIn(f"`{name}`", tools) self.assertIn(f"`{name}`", tools)
def test_picoclaw_lists_tool_order(self) -> None:
skill = (ROOT / "skills" / "picoclaw" / "SKILL.md").read_text()
agents = (ROOT / "AGENTS.md").read_text()
self.assertIn("**`search`**", skill)
self.assertIn("**`get`**", skill)
self.assertIn("**`audit`**", skill)
self.assertIn("throttled", skill.lower())
self.assertIn("not a negative finding", agents)
self.assertIn("Fact-check every", agents)
+25
View File
@@ -0,0 +1,25 @@
---
name: picoclaw
description: >-
2dph is the memory/fact gate, not the agent loop. Use when wiring PicoClaw
or any MCP client: call brain search/get/audit before a factual reply.
throttled is not a negative finding.
---
# PicoClaw — fact-check before assert
PicoClaw (or any agent) speaks MCP at `POST /mcp` on `bin/brain/serve.go`.
2dph does not run the agent loop. Compose profile for a live agent is issue #9.
## Tool order (before a factual reply)
1. **`search`** — facts root first, then info. The `web` block is a second
source when there is no facts hit. Status `throttled` / `skipped` /
`refused` is **not** evidence of absence.
2. **`get`** — full leaf body only when a hit `id` is needed.
3. **`audit`** — if recall or confidence looks wrong.
Then answer. Confirmed only from facts (≥2 independent sources). Anything
else is `(not confirmed)`. Missing graph ≠ “does not exist”.
Generated tool list: [../brain/tools.md](../brain/tools.md).