pwn 0.5.682 → 0.5.684
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/README.md +11 -10
- data/documentation/Agent-Tool-Registry.md +13 -9
- data/documentation/CLI-Drivers.md +27 -28
- data/documentation/Configuration.md +7 -5
- data/documentation/Contributing.md +2 -2
- data/documentation/Cron.md +11 -7
- data/documentation/Diagrams.md +2 -2
- data/documentation/General-PWN-Usage.md +1 -1
- data/documentation/Home.md +7 -6
- data/documentation/How-PWN-Works.md +9 -9
- data/documentation/Installation.md +1 -1
- data/documentation/Persistence.md +2 -1
- data/documentation/Plugins.md +3 -3
- data/documentation/Reinforcement-Learning.md +103 -101
- data/documentation/SAST.md +1 -1
- data/documentation/Session-Workflow.md +152 -0
- data/documentation/Sessions.md +2 -1
- data/documentation/Troubleshooting.md +2 -2
- data/documentation/What-is-PWN.md +3 -3
- data/documentation/diagrams/agent-tool-registry.svg +152 -152
- data/documentation/diagrams/cron-scheduling.svg +141 -121
- data/documentation/diagrams/dot/agent-tool-registry.dot +4 -4
- data/documentation/diagrams/dot/cron-scheduling.dot +10 -7
- data/documentation/diagrams/dot/driver-framework.dot +1 -1
- data/documentation/diagrams/dot/overall-pwn-architecture.dot +4 -4
- data/documentation/diagrams/dot/persistence-filesystem.dot +1 -1
- data/documentation/diagrams/dot/plugin-ecosystem.dot +2 -2
- data/documentation/diagrams/dot/task-summarizer.dot +18 -16
- data/documentation/diagrams/driver-framework.svg +1 -1
- data/documentation/diagrams/overall-pwn-architecture.svg +93 -93
- data/documentation/diagrams/persistence-filesystem.svg +4 -4
- data/documentation/diagrams/plugin-ecosystem.svg +101 -100
- data/documentation/diagrams/task-summarizer.svg +166 -156
- data/documentation/pwn-ai-Agent.md +9 -4
- data/lib/pwn/ai/agent/dispatch.rb +52 -1
- data/lib/pwn/ai/agent/loop.rb +198 -159
- data/lib/pwn/ai/agent/open_goal.rb +83 -0
- data/lib/pwn/ai/agent/policy.rb +2 -3
- data/lib/pwn/ai/agent/prompt_builder.rb +16 -13
- data/lib/pwn/ai/agent/registry.rb +6 -9
- data/lib/pwn/ai/agent/tools/sessions.rb +32 -0
- data/lib/pwn/ai/agent/tools/skills.rb +56 -0
- data/lib/pwn/ai/agent.rb +1 -0
- data/lib/pwn/ai/anthropic.rb +0 -1
- data/lib/pwn/ai/gemini.rb +0 -1
- data/lib/pwn/ai/grok.rb +0 -1
- data/lib/pwn/ai/ollama.rb +0 -1
- data/lib/pwn/ai/open_ai.rb +0 -1
- data/lib/pwn/ai/open_web_ui.rb +0 -1
- data/lib/pwn/config.rb +2 -2
- data/lib/pwn/cron.rb +18 -5
- data/lib/pwn/plugins/repl.rb +43 -1
- data/lib/pwn/plugins/tty_spinner.rb +109 -13
- data/lib/pwn/sessions.rb +82 -0
- data/lib/pwn/version.rb +1 -1
- data/spec/integration/persistence_roundtrip_spec.rb +2 -1
- data/spec/integration/prompt_builder_spec.rb +3 -3
- data/spec/integration/reinforced_feedback_loop_spec.rb +6 -11
- data/spec/lib/pwn/ai/agent/dispatch_spec.rb +38 -82
- data/spec/lib/pwn/ai/agent/loop_spec.rb +284 -11
- data/spec/lib/pwn/ai/agent/open_goal_spec.rb +37 -0
- data/spec/lib/pwn/ai/agent/prompt_builder_spec.rb +7 -3
- data/spec/lib/pwn/ai/agent/registry_spec.rb +16 -9
- data/spec/lib/pwn/ai/agent/tools/sessions_spec.rb +5 -0
- data/spec/lib/pwn/ai/agent/tools/skills_spec.rb +16 -0
- data/spec/lib/pwn/ai/red_team/test_case_engine_spec.rb +20 -0
- data/spec/lib/pwn/cron_spec.rb +13 -3
- data/spec/lib/pwn/plugins/repl_spec.rb +26 -0
- data/spec/lib/pwn/plugins/tty_spinner_spec.rb +44 -0
- data/spec/lib/pwn/sessions_spec.rb +29 -0
- data/spec/spec_helper.rb +6 -0
- data/third_party/pwn_rdoc.jsonl +28 -1
- metadata +4 -1
|
@@ -102,7 +102,7 @@ $ pwn --ai "run bin/pwn_sast against ./src and push findings to DefectDojo"
|
|
|
102
102
|
|
|
103
103
|
## What the agent can call
|
|
104
104
|
|
|
105
|
-
13 toolsets · **
|
|
105
|
+
13 toolsets · **87 tools** - full table at
|
|
106
106
|
[Agent Tool Registry](Agent-Tool-Registry.md).
|
|
107
107
|
|
|
108
108
|
The two that matter most:
|
|
@@ -144,7 +144,7 @@ There is no request type. Every request gets an English task compass.
|
|
|
144
144
|
- Advancement needs a PRM +1 streak or a clear phase shift after tools on the active task (not a blind every-3-tools hop).
|
|
145
145
|
- REPL contract: `on_tool.call('task', full_summary_text, '')` - result empty, no truncation.
|
|
146
146
|
|
|
147
|
-
**Long-run pressure:**
|
|
147
|
+
**Long-run pressure:** budget-hot turns skip extra counterfactual forks. The last iteration strips tools only when the original request is already satisfied. Scars and overconfidence do not lower this request's `max_iters` (default 777). Task state and Learning still flush on the exhaust path.
|
|
148
148
|
|
|
149
149
|

|
|
150
150
|
|
|
@@ -156,7 +156,7 @@ task_summary_every: 5 # verbose progress every N tools
|
|
|
156
156
|
task_summary_interval_s: 8.0 # or every N seconds (verbose)
|
|
157
157
|
task_summary_verbose: false # mid-flight Progress: lines
|
|
158
158
|
task_summary_llm: true # LLM task decompose (default on)
|
|
159
|
-
max_iters:
|
|
159
|
+
max_iters: 777 # scars / overconf do not lower this request
|
|
160
160
|
```
|
|
161
161
|
|
|
162
162
|
|
|
@@ -197,7 +197,7 @@ max_iters: 75 # budget pressure may lower the effective cap (s
|
|
|
197
197
|
| `reward_llm_timeout` | `12` | seconds for the cheap ORM chat (clamped 2..30) |
|
|
198
198
|
| `verify_as_reward` | `nil` (auto) | browser-grounded claim sample policy |
|
|
199
199
|
| `local_introspect` | `:failure_only` | ollama / openwebui end-of-turn introspect policy |
|
|
200
|
-
| `tool_preference` |
|
|
200
|
+
| `tool_preference` | same list as CORE_TOOLS (`memory_recall`, `session_recall`, `skills_recall`, `pwn_eval`, `shell`, `mistakes_record`, `mistakes_resolve`, `learning_note_outcome`, `memory_remember`) | Rank bonus + Policy suggested-action order |
|
|
201
201
|
| `defer_introspect` | `true` | Post-answer Learning on a background thread |
|
|
202
202
|
| `prompt_cache` | `true` | Engine-native prefix cache (not Ollama / Open WebUI) |
|
|
203
203
|
|
|
@@ -227,3 +227,8 @@ The `shell` tool also blocks hping3 / nmap-style sweep commands when recon is
|
|
|
227
227
|
not authorized. On how-to asks, memory SOPs about repo rubocop/rake hygiene are
|
|
228
228
|
kept out of the prompt so the model does not pivot into unrelated verification.
|
|
229
229
|
|
|
230
|
+
Keyword routing, unfinished-goal resume (`continue` / `resume`), and
|
|
231
|
+
write-then-read completion: [Session Workflow](Session-Workflow.md).
|
|
232
|
+
|
|
233
|
+
[← Home](Home.md)
|
|
234
|
+
|
|
@@ -47,7 +47,7 @@ module PWN
|
|
|
47
47
|
required = Array(entry.schema&.dig(:parameters, :required))
|
|
48
48
|
args = ToolGuard.coerce_args(args: args, required: required) if defined?(ToolGuard)
|
|
49
49
|
result = entry.handler.call(args)
|
|
50
|
-
JSON.generate(success: true, result: result)
|
|
50
|
+
JSON.generate(success: true, result: result, effect: effect(name: entry.name, args: args))
|
|
51
51
|
rescue StandardError => e
|
|
52
52
|
JSON.generate(
|
|
53
53
|
success: false,
|
|
@@ -281,6 +281,56 @@ module PWN
|
|
|
281
281
|
[]
|
|
282
282
|
end
|
|
283
283
|
|
|
284
|
+
# Effect of a tool call from NAME + ARGV only — never stdout.
|
|
285
|
+
# :write mutate, :browse navigate, :recall store lookup, :read/:eval observe.
|
|
286
|
+
WRITE_ARGV_RX = /
|
|
287
|
+
\bsed\s+-i\b|\bruby\s+-i\b|\btee\b|
|
|
288
|
+
(?:\s|\A)>{1,2}\s+\S|
|
|
289
|
+
File\.(?:write|open|binwrite)|IO\.write|
|
|
290
|
+
\bopen\s*\([^)]*['"]w|
|
|
291
|
+
\b(?:cp|mv|rm|mkdir|touch|chmod|chown)\b|
|
|
292
|
+
\bgit\s+(?:add|commit|rm)
|
|
293
|
+
/ix
|
|
294
|
+
BROWSE_ARGV_RX = /
|
|
295
|
+
TransparentBrowser|browser_obj|\.goto\b|dump_links|
|
|
296
|
+
watir|headless_?chrome|\bdevtools\b
|
|
297
|
+
/ix
|
|
298
|
+
RECALL_TOOLS = %w[
|
|
299
|
+
memory_recall session_recall skills_recall sessions_view
|
|
300
|
+
sessions_list sessions_current
|
|
301
|
+
].freeze
|
|
302
|
+
STORE_TOOLS = %w[
|
|
303
|
+
memory_remember mistakes_record mistakes_resolve
|
|
304
|
+
learning_note_outcome skill_create skill_add_reference
|
|
305
|
+
].freeze
|
|
306
|
+
|
|
307
|
+
public_class_method def self.effect(opts = {})
|
|
308
|
+
name = opts[:name].to_s
|
|
309
|
+
return :read if name.empty?
|
|
310
|
+
return :recall if RECALL_TOOLS.include?(name)
|
|
311
|
+
return :store if STORE_TOOLS.include?(name)
|
|
312
|
+
|
|
313
|
+
blob = argv_blob(args: opts[:args])
|
|
314
|
+
return :browse if blob.match?(BROWSE_ARGV_RX)
|
|
315
|
+
return :write if blob.match?(WRITE_ARGV_RX)
|
|
316
|
+
return :eval if name == 'pwn_eval'
|
|
317
|
+
|
|
318
|
+
:read
|
|
319
|
+
rescue StandardError
|
|
320
|
+
:read
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
private_class_method def self.argv_blob(opts = {})
|
|
324
|
+
args = opts[:args]
|
|
325
|
+
args = JSON.parse(args, symbolize_names: true) if args.is_a?(String) && args.strip.start_with?('{')
|
|
326
|
+
case args
|
|
327
|
+
when Hash then args.values.join(' ')
|
|
328
|
+
else args.to_s
|
|
329
|
+
end
|
|
330
|
+
rescue StandardError
|
|
331
|
+
opts[:args].to_s
|
|
332
|
+
end
|
|
333
|
+
|
|
284
334
|
private_class_method def self.symbolize(opts = {})
|
|
285
335
|
hash = opts[:hash] ||= {}
|
|
286
336
|
hash.each_with_object({}) { |(k, v), m| m[k.to_sym] = v }
|
|
@@ -306,6 +356,7 @@ module PWN
|
|
|
306
356
|
)
|
|
307
357
|
|
|
308
358
|
PWN::AI::Agent::Dispatch.repair_name(name: 'run_shell') # => 'shell'
|
|
359
|
+
PWN::AI::Agent::Dispatch.effect(name: 'shell', args: { command: 'ls' })
|
|
309
360
|
PWN::AI::Agent::Dispatch.tool_calls_from_text(text: 'shell(command="id")')
|
|
310
361
|
|
|
311
362
|
#{self}.authors
|