State is stored inbound projectSQLite blackboard, does not depend on conversation context, and does not use the
.pentest/directory. The system automatically injects the "project blackboard index" (onlyfact_key+ summary);if the summary is insufficient, you mustget_project_fact, and it is forbidden to fabricate details from the summary.
Primitives and division of labor (product model)
| Concept | Product placement | Rule |
|---|---|---|
| Fact | project_facts(upsert_project_fact) |
Same fact_key overwrite update; informal vulnerability entry.confidence: confirmed | tentative | deprecated |
| Relation edge | project_fact_edges(upsert's links) |
structured attack graph; finding/chain/exploit/poc mustcarry links |
| Deliverable vulnerability | record_vulnerability |
and Fact may each be recorded once: Fact = reproduction context, vulnerability = formal finding |
| Exploration direction | this round's plan / coordinator delegation / plantask (if enabled) | is nota standalone Intent table; for pending verification directions use confidence=tentative 's note/ or do not persist first, and write after verification |
| Human injection | user message / HITL approval | directly absorbed into decision-making; does not need to be written as a Hint primitive |
Fact vs vulnerability
- Cognition such as environment/target/authentication → write only Fact (
target/auth/infra/business/) - Discovery and exploitation context → Fact(
finding/chain/exploit/poc/) + fill attack chain in body - Deliverable findings →
record_vulnerability(title, severity, type, target, POC, impact, remediation); before recording, you can uselist_vulnerabilitiesto check for duplicates
Mandatory cadence: record while penetration testing
Do not wait until the end of the session to write in batches.
- Each timeconfirmone new piece of cognition (open port/service version, entry path, authentication state or credential characteristics, exploitable point, or attack surface change) → immediately
upsert_project_fact(same key overwrites). - Each timeverifyone reproducible vulnerability (including POC/impact) → immediately
record_vulnerability; it and the fact may each be recorded once. - Before continuing to the next step, prioritize persisting, to avoid losing details during context compression.
- Unbound project: indicates that the blackboard cannot be written; still retain an evidence summary in this round.
- Coordinator: when a subtask returns new cognition/vulnerabilities, the coordinator writes them; do not assume the sub-agent has recorded them.
- When a sub-agent has no tools: at the end of the deliverable, provide "pending persistence" items (recommended
fact_key, summary, body/POC key points), for the coordinator to write immediately.
Tool quick reference
| Tool | Purpose |
|---|---|
upsert_project_fact |
Write/update facts (including body, confidence, links) |
get_project_fact |
Fetch the full body by key (must call when the index is insufficient) |
list_project_facts / search_project_facts |
Search the blackboard |
deprecate_project_fact / restore_project_fact |
False-positive discard / restore |
record_vulnerability |
Deliverable vulnerabilities |
list_vulnerabilities / get_vulnerability |
Deduplication and details |
Prerequisite:The current conversation is already bound to a project(otherwise the tool errors).
Write specification
fact_key / category
- Format: lowercase
category/slug(e.g.target/primary_domain、finding/sqli-login) - Environment:
target|auth|infra|business - Exploitation finding:
finding|chain|exploit|poc(alternatively usenote) - Keep the same
fact_keyfor the same finding, overwrite, do not split into multiple keys causing loss of context
summary / body / confidence
- summary(index uses one line): must contain "what + where + how to trigger/verify", do not write only "SQLi exists"
- body: complete reproducible context (index does not contain body). Discovery/exploitation type must contain: entry → steps → raw request/response or command → phenomenon → evidence →
related_vulnerability_id(if any) - confidence: evidence nails it down →
confirmed; clue only/to be verified →tentative; false positive →deprecate_project_fact(ordeprecated) - When updating, if body is omitted, the existing body in the database is preserved (you may change only the summary)
Relation edges links (required when writing finding/chain/exploit/poc)
- Recommended
from: source fact → currentfact_key - Minimum: finding has at least 1
{from: target/*, type: discovered_on}; attach exploit on finding using{from: exploit/*, type: exploits} - Common type:
discovered_on|depends_on|leads_to|enables|exploits|contains|part_of|supports - Omit links = preserve existing edges; passing links = replaceall incoming edges
Working mode (aligned with this product's orchestration)
No Bootstrap/Reason/Explore disk state machine. Advance according to the current run mode, butthe discipline of reading and writing the blackboard remains unchanged:
| Mode | Blackboard usage |
|---|---|
| Single agent / deep | Work while upsert_project_fact; if reading the index is not enough, get_project_fact |
| plan_execute | write planned step output to the database immediately after gaining cognition; before replanning list/search_project_facts |
| supervisor | the coordinator summarizes subagents' "to be written to the database" and writes it; if a subagent has no tools, it delivers in structured form |
When stuck: switch edge/switch starting point/switch attack domain; use search_project_facts to re-review existing Facts, avoiding repeating dead ends. Negative results must also be written to the database (see the verification iron law skill).
Behavior triggers (discipline)
Must check every step (not checking = violating the verification iron law):
- Identify→search: identify any component/framework/version/middleware → pause exploitation → immediately execute
component-vuln-intelall commands (browser_navigate+terminal curl, do all 7 steps) → use results withtentativeFact or current-round plan tracking → only continue after searching. Saying "no known vulnerabilities" without searching = hallucination;after verificationthenconfirmed/record_vulnerability。 - Rejection→switch path: receiving 403/429/timeout/RST/WAF block/CDN 502/rate limit/empty response → forbidden to retry under the same conditions → immediately switch path sequence: SOCKS5 proxy→change UA→add XFF→change protocol (WS/DNS)→change port→encoding mutation (for complete proxy acquisition/verification see
proxy-tool-bootstrap) → only after all switches still fail write a negative result Fact (confirmed+ body clearly states the conditions tested) and switch surface. - New cognition→lateral: obtaining credentials/domain/IP/path → immediately spray laterally: reuse credentials across all services / scan all ports of new domain / reverse-lookup IP for same site → automatically expand the attack surface without waiting for instructions, and
upsert_project_fact(e.g.auth/cred-*、target/related-*). Having credentials but not spraying = omission.
Violation determination: saying "no known vulnerabilities" without searching = hallucination; giving up after being blocked instead of switching paths = giving up; having credentials but not using them = omission → all violate the iron law of verification.
Evidence / Loot / Changes
| Original "disk" concept | This product's approach |
|---|---|
| evidence/ | Fact body + record_vulnerability proof fields + tool execution records; large files go in the session/project workspace |
| loot/ | Credential characteristics written to auth/ Fact (note desensitization and authorization scope); complete secrets handled according to project policy |
| changelog.md | Write-type changes are ledgered in the reply, and can be note/change-* Recorded by Fact as host/type/location/rollback command |
Connection with the iron law of verification
See pentest-verification: search ≠ vulnerability; do not write without evidence confirmed; vague "possible/suspected" statements are prohibited as conclusions; failed verification writes a negative-result Fact.