pwn 0.5.679 → 0.5.682
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/documentation/AI-Integration.md +1 -1
- data/documentation/Agent-Tool-Registry.md +1 -1
- data/documentation/Configuration.md +3 -6
- data/documentation/How-PWN-Works.md +2 -2
- data/documentation/Reinforcement-Learning.md +1 -1
- data/documentation/diagrams/dot/task-summarizer.dot +3 -3
- data/documentation/pwn-ai-Agent.md +16 -35
- data/lib/pwn/ai/agent/loop.rb +272 -196
- data/lib/pwn/ai/agent/mistakes.rb +17 -0
- data/lib/pwn/ai/agent/policy.rb +55 -5
- data/lib/pwn/ai/agent/prompt_builder.rb +38 -12
- data/lib/pwn/ai/agent/registry.rb +17 -9
- data/lib/pwn/ai/agent/task_summarizer.rb +374 -503
- data/lib/pwn/ai/anthropic.rb +1 -0
- data/lib/pwn/ai/gemini.rb +1 -0
- data/lib/pwn/ai/grok.rb +1 -0
- data/lib/pwn/ai/ollama.rb +1 -0
- data/lib/pwn/ai/open_ai.rb +1 -0
- data/lib/pwn/ai/open_web_ui.rb +1 -0
- data/lib/pwn/config.rb +1 -1
- data/lib/pwn/cron.rb +1 -1
- data/lib/pwn/plugins/repl.rb +0 -6
- data/lib/pwn/plugins/tty_spinner.rb +7 -11
- data/lib/pwn/version.rb +1 -1
- data/spec/integration/prompt_builder_spec.rb +6 -4
- data/spec/lib/pwn/ai/agent/loop_spec.rb +251 -33
- data/spec/lib/pwn/ai/agent/mistakes_spec.rb +14 -0
- data/spec/lib/pwn/ai/agent/policy_spec.rb +52 -1
- data/spec/lib/pwn/ai/agent/prompt_builder_spec.rb +4 -9
- data/spec/lib/pwn/ai/agent/registry_spec.rb +22 -2
- data/spec/lib/pwn/ai/agent/signal_hygiene_spec.rb +4 -5
- data/spec/lib/pwn/ai/agent/task_summarizer_spec.rb +321 -90
- data/spec/lib/pwn/plugins/tty_spinner_spec.rb +0 -48
- data/third_party/pwn_rdoc.jsonl +24 -9
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f46629cb3abad0974a4fe9bd5d2936bb42c90e304986261cf0106775ffb8de9
|
|
4
|
+
data.tar.gz: 56fc226ba599b541c47e66c38f7e3a6d142c019442a00707db8f9d8d12caee74
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aadc0dad32c3ac362ee269637c0308a1f89e400c311dd5b69d9a7c2e944cc57698799c85b97c51ea3024207f18703b32735faacf394a7d2e3f91e6945efb724e
|
|
7
|
+
data.tar.gz: 748bedcea767a060882928c3697cc96a3ffa5f316cbca209d7e4dc870bcbaef6737ebb582d86b76dcd9c5f6624cd46c6d646b94dec8f0dbcd20af9a1cc0bbdf9
|
|
@@ -48,7 +48,7 @@ The harness adapts to the *class* of engine, not the model name:
|
|
|
48
48
|
| **MEMORY ranking** | relevance-ranked when a local Ollama `embed_model` is reachable, else newest-first | relevance-ranked via `PWN::MemoryIndex` (`~/.pwn/memory.idx`) |
|
|
49
49
|
| **Tool schemas shipped** | all toolsets | `CORE_TOOLS` + top-K keyword matches when `ai.agent.tool_router` is on (default on). Ties also honor `tool_preference`. |
|
|
50
50
|
| **Pre-pass** | none | `plan_first` numbered tool plan before first dispatch |
|
|
51
|
-
| **Intent route** | always | `request_intent`
|
|
51
|
+
| **Intent route** | always | `request_intent` only (greeting / howto / recall cheap paths). There is no request type. Every other turn gets a TaskSummarizer compass and CORE_TOOLS. |
|
|
52
52
|
| **Few-shot** | none | `Learning.exemplars_for(request)` splices a prior successful trace |
|
|
53
53
|
| **Dispatch parsing** | strict | tolerant - Levenshtein tool-name repair + JSON5-ish arg cleanup, each repair fingerprinted into `Mistakes` |
|
|
54
54
|
| **Post-answer** | `auto_introspect` (deferred by default) | `auto_introspect` **+** `fact_check_local_final` (auto `extro_verify` on CVE/version-shaped claims). Deferred after the reply; specs/cron stay inline. |
|
|
@@ -80,7 +80,7 @@ When keyword fit and other rank scores tie, the registry prefers this
|
|
|
80
80
|
default order:
|
|
81
81
|
|
|
82
82
|
```text
|
|
83
|
-
memory_recall ·
|
|
83
|
+
memory_recall · pwn_eval · shell
|
|
84
84
|
mistakes_record · mistakes_resolve · learning_note_outcome · memory_remember
|
|
85
85
|
```
|
|
86
86
|
|
|
@@ -123,8 +123,7 @@ ai:
|
|
|
123
123
|
task_summary_every: 5 # When task_summary_verbose: emit Progress every N completed tools.
|
|
124
124
|
task_summary_interval_s: 8.0 # When verbose: also emit when this many seconds elapsed.
|
|
125
125
|
task_summary_verbose: false # Mid-flight Progress/Finished lines (default: only plan + about_to).
|
|
126
|
-
task_summary_llm: true # LLM tangible-task decompose
|
|
127
|
-
request_kind_llm: ~ # LLM request_kind classifier (statement|question|autonomous_goal). nil = follow task_summary_llm.
|
|
126
|
+
task_summary_llm: true # LLM tangible-task decompose (default on). false = offline fallback.
|
|
128
127
|
max_depth: 3 # Recursion guard: how many levels deep agent_ask/agent_debate sub-agents may spawn sub-agents.
|
|
129
128
|
auto_introspect: true # Run Learning.auto_introspect (outcome logging + lesson mining) after every final answer.
|
|
130
129
|
auto_extrospect: true # Ambient baseline after every final answer (host/repo/env ONLY - never launches burpsuite/zaproxy/msf/gqrx). Sense tools stay on-demand.
|
|
@@ -136,7 +135,6 @@ ai:
|
|
|
136
135
|
tool_router: ~ # Dynamic tool-set slimming. nil = auto (true for ollama / openwebui).
|
|
137
136
|
tool_preference: # Operator-tunable tool order. Rank bonus + Policy suggested-action list.
|
|
138
137
|
- memory_recall
|
|
139
|
-
- sessions_view
|
|
140
138
|
- pwn_eval
|
|
141
139
|
- shell
|
|
142
140
|
- mistakes_record
|
|
@@ -308,8 +306,7 @@ PWN::Config.refresh_env
|
|
|
308
306
|
| `ai.agent.task_summary_every` | Integer | `5` | `TaskSummarizer.every_n` | Verbose progress cadence (tools). |
|
|
309
307
|
| `ai.agent.task_summary_interval_s` | Float | `8.0` | `TaskSummarizer.interval_s` | Verbose progress cadence (seconds). |
|
|
310
308
|
| `ai.agent.task_summary_verbose` | Boolean | `false` | `TaskSummarizer.verbose?` | Emit mid-flight `Progress:` / `Finished:` lines; default keeps only plan + about_to. |
|
|
311
|
-
| `ai.agent.task_summary_llm` | Boolean \| `nil` | `nil` (on) | `TaskSummarizer.llm_plan_enabled?` | LLM tangible-task decomposition
|
|
312
|
-
| `ai.agent.request_kind_llm` | Boolean \| `nil` | `nil` (follow `task_summary_llm`) | `TaskSummarizer.llm_kind_enabled?` / `request_kind` | LLM classifier for `statement` \| `question` \| `autonomous_goal`. Cheap intents and host-evidence heuristics still win first; `false` is heuristic-only. |
|
|
309
|
+
| `ai.agent.task_summary_llm` | Boolean \| `nil` | `nil` (on) | `TaskSummarizer.llm_plan_enabled?` | LLM tangible-task decomposition. `false` forces offline generic fallback (tests / air-gap). |
|
|
313
310
|
| `ai.agent.max_depth` | Integer | `3` | `PWN::AI::Agent::Swarm` | Recursion guard for `agent_ask` / `agent_debate` sub-agents spawning sub-agents. |
|
|
314
311
|
| `ai.agent.auto_introspect` | Boolean | `true` | `PWN::AI::Agent::Learning.auto_introspect` | Run outcome logging + lesson mining after every final answer. Toggle live via `learning_auto_introspect_toggle`. |
|
|
315
312
|
| `ai.agent.auto_extrospect` | Boolean | `true` | `PWN::AI::Agent::Extrospection.auto_extrospect` | Ambient baseline after every final answer (`AUTO_SECTIONS` = host/repo/env only; never spawns GUI/JVM tools). Sense tools (`intel`/`verify`/`watch`/`rf_tune`/`observe`) stay on-demand. Toggle live via `extro_auto_toggle`. |
|
|
@@ -318,7 +315,7 @@ PWN::Config.refresh_env
|
|
|
318
315
|
| `ai.agent.shell_bash` | Boolean | `false` | `PWN::AI::Agent::ToolGuard.shell_bash?` | When true, `shell` runs via `bash -lc` so bash-only syntax is allowed. Default is POSIX `/bin/sh` and bashisms are rejected with a rewrite hint. |
|
|
319
316
|
| `ai.agent.plan_first` | Boolean \| `nil` | `nil` (auto: `true` when `ai.active` is `ollama` or `openwebui`) | `PWN::AI::Agent::Loop.plan_first` | Plan-then-act pre-pass: the model must emit a numbered tool plan (as an assistant message) *before* it may dispatch anything. Cheap chain-of-thought scaffolding for local models. |
|
|
320
317
|
| `ai.agent.tool_router` | Boolean \| `nil` | `nil` (auto: `true` for `ollama` / `openwebui`) | `PWN::AI::Agent::Registry.definitions` | Dynamic tool-set slimming: expose only `Registry::CORE_TOOLS` + the top-K keyword-relevant schemas for *this* request. Ties break on historical `Metrics` success rate, then `ai.agent.tool_preference`. |
|
|
321
|
-
| `ai.agent.tool_preference` | Array\<String\> | `memory_recall`, `
|
|
318
|
+
| `ai.agent.tool_preference` | Array\<String\> | `memory_recall`, `pwn_eval`, `shell`, `mistakes_record`, `mistakes_resolve`, `learning_note_outcome`, `memory_remember` | `PWN::AI::Agent::Registry.preference_order` / `.rank` / `.apply_preference`, `Policy` | Operator-tunable tool order. Keyword fit stays primary; act/recon kinds lead with `shell`/`pwn_eval`. Explicit empty list disables preference. |
|
|
322
319
|
| `ai.agent.defer_introspect` | Boolean | `true` | `PWN::AI::Agent::TurnFinalizer` | Run `Learning.auto_introspect` on a background thread after the user-visible reply. Specs and cron stay inline. |
|
|
323
320
|
| `ai.agent.prompt_cache` | Boolean | `true` | `PWN::AI::Agent::PromptCache` | Engine-native prefix cache. Anthropic uses `cache_control`; OpenAI uses `prompt_cache_key`; Grok uses `x-grok-conv-id`; Gemini splits `systemInstruction`. Ollama and Open WebUI have no native prefix-cache field. |
|
|
324
321
|
| `ai.agent.local_introspect` | Symbol | `failure_only` | `PWN::AI::Agent::Learning.auto_introspect` | End-of-turn introspect policy for local engines: `always` · `failure_only` · `every_n` (with `introspect_every_n`). |
|
|
@@ -28,8 +28,8 @@ hardware).
|
|
|
28
28
|
| Module | Role |
|
|
29
29
|
|---|---|
|
|
30
30
|
| `Loop` | plan → **TaskSummarizer** briefs → dispatch tool_calls → observe → repeat until final answer; tightens runway when recent turns exhausted the budget |
|
|
31
|
-
| **`TaskSummarizer`** | Executive UX:
|
|
32
|
-
| `Registry` | JSON-Schema function definitions grouped into 13 **toolsets** · **85 tools** · `
|
|
31
|
+
| **`TaskSummarizer`** | Executive UX: every request gets an English task compass (`emit_plan!` · `about_to` as `task k/n`) — no statement/question/goal type |
|
|
32
|
+
| `Registry` | JSON-Schema function definitions grouped into 13 **toolsets** · **85 tools** · `CORE_TOOLS` default pool · kind-aware `tool_preference` |
|
|
33
33
|
| `Dispatch` / `Result` | execute a tool, capture stdout/value/error/duration |
|
|
34
34
|
| `PromptBuilder` | inject MEMORY / SKILLS / LEARNING / **KNOWN MISTAKES + FIXES** / METRICS / **POLICY** / EXTROSPECTION / RECENT TURNS |
|
|
35
35
|
| `Metrics` · `Learning` · `Reflect` · **`Policy`** | **introspection** - how well am I doing? (Policy is live Q / REINFORCE, advisory rank only) |
|
|
@@ -169,7 +169,7 @@ This table is the live control list. Track the outcomes, not source comments.
|
|
|
169
169
|
:max_iters: 75 # hard cap; budget pressure may lower effective value
|
|
170
170
|
:defer_introspect: true # post-answer Learning after the user-visible reply
|
|
171
171
|
:prompt_cache: true # engine-native prefix cache (not ollama / openwebui)
|
|
172
|
-
:tool_preference: [memory_recall,
|
|
172
|
+
:tool_preference: [memory_recall, pwn_eval, shell, mistakes_record, mistakes_resolve, learning_note_outcome, memory_remember]
|
|
173
173
|
```
|
|
174
174
|
|
|
175
175
|
## Cron self-improvement
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
digraph "PWN_TaskSummarizer" {
|
|
2
2
|
graph [
|
|
3
|
-
label=<<B>PWN::AI::Agent::TaskSummarizer -
|
|
3
|
+
label=<<B>PWN::AI::Agent::TaskSummarizer - executive briefs</B><BR/><FONT POINT-SIZE="11" COLOR="#94a3b8">every request → emit_plan! → about_to → tools (no request type)</FONT>>,
|
|
4
4
|
labelloc=t, fontsize=20, fontname="Helvetica",
|
|
5
5
|
rankdir=TB, splines=spline, nodesep=0.55, ranksep=0.9,
|
|
6
6
|
bgcolor="#0f172a", fontcolor="#e2e8f0", pad=0.6, newrank=true, compound=true
|
|
@@ -11,8 +11,8 @@ digraph "PWN_TaskSummarizer" {
|
|
|
11
11
|
fontcolor="#cbd5e1", penwidth=1.3, arrowsize=0.8];
|
|
12
12
|
|
|
13
13
|
User [label="User request", fillcolor="#7dd3fc"];
|
|
14
|
-
Loop [label="Loop.run\nts_state = TaskSummarizer.fresh\
|
|
15
|
-
Kind [label="
|
|
14
|
+
Loop [label="Loop.run\nts_state = TaskSummarizer.fresh\nrequest_intent only", fillcolor="#c4b5fd"];
|
|
15
|
+
Kind [label="no request type\nevery turn is a goal", fillcolor="#fcd34d", penwidth=2];
|
|
16
16
|
{rank=same; User; Loop; Kind}
|
|
17
17
|
|
|
18
18
|
subgraph cluster_nogoal {
|
|
@@ -126,19 +126,11 @@ full `Loop.run` under a persona overlay) that share a JSONL bus. See
|
|
|
126
126
|
## Task summaries (long autonomous turns)
|
|
127
127
|
|
|
128
128
|
`PWN::AI::Agent::TaskSummarizer` keeps the TUI readable during multi-step work.
|
|
129
|
-
|
|
130
|
-
heuristics / `request_intent`):
|
|
131
|
-
|
|
132
|
-
| Kind | Example | Task breakdown |
|
|
133
|
-
|---|---|---|
|
|
134
|
-
| `statement` | "FYI the build is green." | None - brief ack only |
|
|
135
|
-
| `question` | "what is the default GQRX port?" / "how to ...?" | None - concise answer only |
|
|
136
|
-
| `autonomous_goal` | "refactor Loop.run and run rubocop" / "what is my hostname?" | **Required** ordered work units (each may use one or more tools) |
|
|
129
|
+
There is no request type. Every request gets an English task compass.
|
|
137
130
|
|
|
138
131
|
| Surface | When | Content |
|
|
139
132
|
|---|---|---|
|
|
140
|
-
| `
|
|
141
|
-
| `emit_plan!` | Autonomous goals only | **Full** goal + ordered plain-English tangible tasks (each may need many tools) |
|
|
133
|
+
| `emit_plan!` | User submit | **Full** goal + ordered plain-English tangible tasks (each may need many tools) |
|
|
142
134
|
| `about_to` | Before each tool batch | **Primary:** `task k/n: <english>` - **secondary:** `via shell×2 (search)` (not raw argv) |
|
|
143
135
|
| `plan_context` / `active_task_prompt` | Into Loop messages | Same English tasks steer tool choice (not TUI-only) |
|
|
144
136
|
| `record!` | After each tool | Advances `plan_idx`; emits English advancement brief when the index moves; verbose progress only if `task_summary_verbose` |
|
|
@@ -163,8 +155,7 @@ task_summary: true # master switch (default on)
|
|
|
163
155
|
task_summary_every: 5 # verbose progress every N tools
|
|
164
156
|
task_summary_interval_s: 8.0 # or every N seconds (verbose)
|
|
165
157
|
task_summary_verbose: false # mid-flight Progress: lines
|
|
166
|
-
task_summary_llm: true # LLM task decompose
|
|
167
|
-
request_kind_llm: null # null = follow task_summary_llm; false = heuristic-only
|
|
158
|
+
task_summary_llm: true # LLM task decompose (default on)
|
|
168
159
|
max_iters: 75 # budget pressure may lower the effective cap (stricter on local engines)
|
|
169
160
|
```
|
|
170
161
|
|
|
@@ -206,7 +197,7 @@ max_iters: 75 # budget pressure may lower the effective cap (s
|
|
|
206
197
|
| `reward_llm_timeout` | `12` | seconds for the cheap ORM chat (clamped 2..30) |
|
|
207
198
|
| `verify_as_reward` | `nil` (auto) | browser-grounded claim sample policy |
|
|
208
199
|
| `local_introspect` | `:failure_only` | ollama / openwebui end-of-turn introspect policy |
|
|
209
|
-
| `tool_preference` |
|
|
200
|
+
| `tool_preference` | CORE_TOOLS list (act leads with shell) | Rank bonus + Policy suggested-action order |
|
|
210
201
|
| `defer_introspect` | `true` | Post-answer Learning on a background thread |
|
|
211
202
|
| `prompt_cache` | `true` | Engine-native prefix cache (not Ollama / Open WebUI) |
|
|
212
203
|
|
|
@@ -219,28 +210,18 @@ Full detail: [Reinforcement Learning](Reinforcement-Learning.md).
|
|
|
219
210
|
|
|
220
211
|
[← Home](Home.md)
|
|
221
212
|
|
|
222
|
-
## Intent routing
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
| Intent | Kind | Example | Behavior |
|
|
235
|
-
|--------|------|---------|----------|
|
|
236
|
-
| How-to | question | "how to do a ping sweep of a subnet using hping3?" | Short explanation with example commands only. No tools and no multi-step plan. |
|
|
237
|
-
| Question | question | "what is the default GQRX remote-control port?" | Concise answer. No multi-step task breakdown. |
|
|
238
|
-
| Host evidence | autonomous_goal | "what is my hostname?" / "excellent - what is my hostname?" | Needs a live local lookup (hostname, cwd, whoami, IP, ...). Treated as a goal so tools run; not text-only Q&A. |
|
|
239
|
-
| Greeting | statement | "Howdy, it's cloudy." / "hi" | Fixed short ack that the system is ready. No tools, no LLM, and no weather echo such as "noted, cloudy out there." |
|
|
240
|
-
| Statement | statement | "FYI the build is green." | Brief note. No multi-step task plan. |
|
|
241
|
-
| Recall | question | "what did I just say?" / "how did you respond?" | Cheap prior-turn answer from the session transcript. No plan_first and no multi-tool archaeology. |
|
|
242
|
-
| Live recon | autonomous_goal | "using hping3 what live hosts can you find in this subnet?" | Needs clear in-scope / authorized engagement wording, or set `ai.agent.recon_authorized=true`. Otherwise the agent refuses and points you at the how-to form. |
|
|
243
|
-
| Act | autonomous_goal | "refactor Loop.run and run rubocop" | Normal multi-step agent work: decompose into ordered work units, each may use one or more tools. |
|
|
213
|
+
## Intent routing
|
|
214
|
+
|
|
215
|
+
There is no request type. Greeting / howto / recall still use `request_intent`
|
|
216
|
+
for cheap short-circuits. Everything else is a goal: TaskSummarizer compass + CORE_TOOLS.
|
|
217
|
+
|
|
218
|
+
| Intent | Example | Behavior |
|
|
219
|
+
|--------|---------|----------|
|
|
220
|
+
| How-to | "how to do a ping sweep of a subnet using hping3?" | Short explanation with example commands only. No tools. |
|
|
221
|
+
| Greeting | "Howdy, it's cloudy." / "hi" | Fixed short ack. No tools, no LLM, no weather echo. |
|
|
222
|
+
| Recall | "what did I just say?" / "how did you respond?" | Cheap prior-turn answer from the session transcript. |
|
|
223
|
+
| Live recon | "using hping3 what live hosts can you find in this subnet?" | Needs in-scope / authorized wording, or `ai.agent.recon_authorized=true`. |
|
|
224
|
+
| Goal | "refactor Loop.run and run rubocop" / "what color is a cherry" | Task compass + CORE_TOOLS. There is no statement/question type. |
|
|
244
225
|
|
|
245
226
|
The `shell` tool also blocks hping3 / nmap-style sweep commands when recon is
|
|
246
227
|
not authorized. On how-to asks, memory SOPs about repo rubocop/rake hygiene are
|