pwn 0.5.668 → 0.5.669

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +15 -0
  3. data/README.md +4 -4
  4. data/documentation/AI-Integration.md +5 -3
  5. data/documentation/Agent-Tool-Registry.md +18 -14
  6. data/documentation/Configuration.md +2 -0
  7. data/documentation/Contributing.md +13 -0
  8. data/documentation/Diagrams.md +1 -1
  9. data/documentation/Home.md +4 -4
  10. data/documentation/How-PWN-Works.md +6 -6
  11. data/documentation/Persistence.md +17 -0
  12. data/documentation/Reinforcement-Learning.md +39 -39
  13. data/documentation/SDR.md +1 -1
  14. data/documentation/Sessions.md +1 -0
  15. data/documentation/Skills-Memory-Learning.md +2 -0
  16. data/documentation/What-is-PWN.md +3 -3
  17. data/documentation/diagrams/agent-tool-registry.svg +43 -43
  18. data/documentation/diagrams/ai-integration-tool-calling.svg +112 -85
  19. data/documentation/diagrams/dot/agent-tool-registry.dot +4 -4
  20. data/documentation/diagrams/dot/ai-integration-tool-calling.dot +7 -3
  21. data/documentation/diagrams/dot/memory-skills-detailed.dot +2 -2
  22. data/documentation/diagrams/dot/overall-pwn-architecture.dot +6 -4
  23. data/documentation/diagrams/dot/persistence-filesystem.dot +1 -1
  24. data/documentation/diagrams/dot/sdr-radio-flow.dot +1 -1
  25. data/documentation/diagrams/memory-skills-detailed.svg +182 -182
  26. data/documentation/diagrams/overall-pwn-architecture.svg +154 -146
  27. data/documentation/diagrams/persistence-filesystem.svg +6 -6
  28. data/documentation/diagrams/sdr-radio-flow.svg +1 -1
  29. data/documentation/pwn-ai-Agent.md +29 -13
  30. data/lib/pwn/ai/agent/loop.rb +189 -1
  31. data/lib/pwn/ai/agent/prompt_builder.rb +24 -5
  32. data/lib/pwn/ai/agent/task_summarizer.rb +40 -3
  33. data/lib/pwn/ai/agent/tools/shell.rb +32 -0
  34. data/lib/pwn/memory_index.rb +17 -2
  35. data/lib/pwn/plugins/repl.rb +36 -7
  36. data/lib/pwn/version.rb +1 -1
  37. data/spec/lib/pwn/ai/agent/loop_spec.rb +31 -0
  38. data/spec/lib/pwn/ai/agent/task_summarizer_spec.rb +10 -0
  39. data/spec/lib/pwn/ai/agent/tools/shell_spec.rb +21 -0
  40. data/spec/lib/pwn/plugins/repl_pwn_vault_spec.rb +134 -0
  41. data/third_party/pwn_rdoc.jsonl +5 -0
  42. metadata +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21fe6bb04741fbc78392d434588c1c86d0f605db0988bfa2192f68e9baa870ec
4
- data.tar.gz: cf66359fb95bb12f08705d11dd304625878115902133d9e1ad0f8becfa8fb83a
3
+ metadata.gz: 746a770eb9c9d4d410cd3fff4deb631ac67476a8d4f01ba7cf17c8414d4930d9
4
+ data.tar.gz: 0aa9628ff2b8f80ed5b06fe682d8c252d4609c3545c96b68dd3890897de3d402
5
5
  SHA512:
6
- metadata.gz: 35f079f6d7c765c6395f490f07c06ce3494b81487bba31c978367fc2b8a23a421a6b1d9a68cda02592fd94868ca343a13c441323b6e1dee0656f46ade8c88aef
7
- data.tar.gz: b9a45751eaf30849ac1c98bd8d603df89d8522fb950dfc830f188769b0fc8e7b69848ed1f71053f7053da24a85e0c2f56f0f9a2c26b95de2040835a7e9871c47
6
+ metadata.gz: adee5114bbd4a83820b12f591d334aeec378f5bf47d7b51d10e3ee9d14497e08207ee532eb2eab7881cb8bb2a1f8910ef6a83712b8b3cb1f7ed7d25cc14f0312
7
+ data.tar.gz: 5343e693c473baf4112b47b1c8a932a22b6ec46ddf1998c34e828aa79483d7c350bce500ed502f015944960b8e8ec867028f4261f11ddd57360853286778a829
data/CONTRIBUTING.md CHANGED
@@ -11,3 +11,18 @@ PWN Contribution Rules:
11
11
  - 'Submit Pull Requests'
12
12
  - 'Pass Upstream Tests'
13
13
  - end
14
+
15
+ ## Documentation after code changes
16
+
17
+ Whenever code under this repo changes:
18
+
19
+ 1. Clear RuboCop on the paths you touched (`bundle exec rubocop -a <paths>`).
20
+ 2. Run the full suite (`bundle exec rake`) and fix failures.
21
+ 3. Only then refresh user docs: `README.md`, `documentation/*`, and
22
+ `documentation/diagrams/dot/*.dot` (rebuild with
23
+ `documentation/diagrams/build.sh`).
24
+ 4. Keep user-facing markdown in plain US English (ASCII hyphens, no marketing
25
+ filler, no internal agent backlog codes).
26
+
27
+ Do not commit documentation while lint or tests are still red.
28
+ See also `documentation/Contributing.md`.
data/README.md CHANGED
@@ -35,7 +35,7 @@ and automate instead of gluing together a pile of separate CLIs.
35
35
 
36
36
  **In numbers:** 66 `PWN::Plugins` · 48 `PWN::SAST` rules · 90 `PWN::AWS`
37
37
  service wrappers · 21 `PWN::WWW` site drivers · 53 `bin/pwn_*` CLI drivers ·
38
- 5 LLM engines · 12 agent toolsets · 78 LLM-callable tools.
38
+ 6 LLM engines · 12 agent toolsets · 82 LLM-callable tools.
39
39
 
40
40
  Full page: [What is PWN](documentation/What-is-PWN.md)
41
41
 
@@ -46,7 +46,7 @@ Here's what `grok-4.5` has to say about pwn (more specifically `pwn-ai`):
46
46
  pwn.ai:grok/grok-4.5/0:500K[CURRENT_VERSION]:002 >>> Briefly describe your take on the reinforced learning feedback loop implemented within `pwn-ai` in clear, concise English so that a human understands your response.
47
47
 
48
48
  [ <TIMESTAMP> → pwn-ai → task ] Goal: Briefly describe your take on the reinforced learning feedback loop implemented within `pwn-ai` in clear, concise English so that a human understands your response.
49
- Tangible tasks (6) each task may leverage one or more tools to complete its objective(s):
49
+ Tangible tasks (6) - each task may use one or more tools to complete its objective(s):
50
50
  task 1/6: Review available knowledge of pwn-ai architecture and any reinforced learning elements
51
51
  task 2/6: Identify the key stages of the feedback loop used for reinforcement
52
52
  task 3/6: Summarize how actions, rewards, and model updates connect in that loop
@@ -58,7 +58,7 @@ pwn.ai:grok/grok-4.5/0:500K[CURRENT_VERSION]:002 >>> Briefly describe your take
58
58
 
59
59
  **My take, in plain English:**
60
60
 
61
- pwn-ais reinforced learning loop is less a classic offline RL trainer and more a living, multi-store control system wrapped around an agent turn. My take is that it is one of the more complete in-context self-improvement stacks Ive seen in an agent harness, and also that its real power and its main failure modes come from the same place: it learns loudly in the prompt long before it learns quietly in weights.
61
+ pwn-ai's reinforced learning loop is less a classic offline RL trainer and more a living, multi-store control system wrapped around an agent turn. My take is that it is one of the more complete in-context self-improvement stacks I've seen in an agent harness, and also that its real power and its main failure modes come from the same place: it learns loudly in the prompt long before it learns quietly in weights.
62
62
 
63
63
  ## Bottom line
64
64
 
@@ -71,7 +71,7 @@ My take: pwn-ai implements a **closed-loop, dual-horizon, self-and-world-aware r
71
71
  - and an external reality check (Extrospection),
72
72
  - with a slower supervised/DPO hatch only when the diet and gates look sane.
73
73
 
74
- It feels less like fine-tune the model forever and more like giving the agent a nervous system: pain, habit, memory, practice, and a rudimentary sense of whether the world changed. That is why it can improve overnight on a host with no trainer. It is also why health has to be measured by judge gap, repeating-mistake trend, trajectory fraction, and resolved scars rather than by tool success_rate alone.
74
+ It feels less like "fine-tune the model forever" and more like giving the agent a nervous system: pain, habit, memory, practice, and a rudimentary sense of whether the world changed. That is why it can improve overnight on a host with no trainer. It is also why health has to be measured by judge gap, repeating-mistake trend, trajectory fraction, and resolved scars rather than by tool success_rate alone.
75
75
  ```
76
76
 
77
77
  Offensive work is hard because the *tools* do not fit together. PWN's fix is
@@ -1,6 +1,6 @@
1
1
  # AI / LLM Integration - `PWN::AI`
2
2
 
3
- One agent loop, five interchangeable engines. Swap providers by changing one
3
+ One agent loop, six interchangeable engines. Swap providers by changing one
4
4
  line in `~/.pwn/pwn.yaml`; the tool-calling contract is normalized so the
5
5
  agent code never cares which model is behind it.
6
6
 
@@ -15,6 +15,7 @@ agent code never cares which model is behind it.
15
15
  | `grok` | `PWN::AI::Grok` | `key:` **or** `oauth: true` | OAuth = RFC-8628 device-code flow using xAI's public Grok-CLI client id (no secret) - see skill `xai_grok_oauth_device_flow` |
16
16
  | `gemini` | `PWN::AI::Gemini` | `key:` | function-calling native |
17
17
  | `ollama` | `PWN::AI::Ollama` | none | local - native `/api/chat` (`num_ctx`, `keep_alive`, low-temp + `format:'json'` on tool turns) and `/api/embed` for `PWN::MemoryIndex` |
18
+ | `openwebui` | `PWN::AI::OpenWebUI` | `key:` (JWT / API token) + `base_uri:` | Open WebUI gateway - OpenAI-compatible `/api/v1/chat/completions` plus proxied Ollama `/ollama/api/*` (including embed) |
18
19
 
19
20
  > PWN is **model-agnostic**. `ai.<engine>.model` is passed straight through to
20
21
  > the provider - the codebase and docs deliberately never name a specific
@@ -41,12 +42,13 @@ PWN::Env[:ai][:active] = :ollama
41
42
 
42
43
  The harness adapts to the *class* of engine, not the model name:
43
44
 
44
- | Concern | Frontier (`openai` · `anthropic` · `grok` · `gemini`) | Local (`ollama`) |
45
+ | Concern | Frontier (`openai` · `anthropic` · `grok` · `gemini`) | Local / gateway (`ollama` · `openwebui`) |
45
46
  |---|---|---|
46
47
  | **PromptBuilder.budget** | full MEMORY / METRICS / MISTAKES / LEARNING / EXTRO blocks | tightened via `ai.ollama.prompt_budget` (extro off by default) |
47
48
  | **MEMORY ranking** | relevance-ranked when a local Ollama `embed_model` is reachable, else newest-first | relevance-ranked via `PWN::MemoryIndex` (`~/.pwn/memory.idx`) |
48
49
  | **Tool schemas shipped** | all toolsets | `CORE_TOOLS` + top-K keyword matches when `ai.agent.tool_router` is on |
49
50
  | **Pre-pass** | none | `plan_first` numbered tool plan before first dispatch |
51
+ | **Intent route** | always | `request_intent` short-circuits how-to (text only) and unauthorized recon (refuse) on all engines; critical for ollama/openwebui |
50
52
  | **Few-shot** | none | `Learning.exemplars_for(request)` splices a prior successful trace |
51
53
  | **Dispatch parsing** | strict | tolerant - Levenshtein tool-name repair + JSON5-ish arg cleanup, each repair fingerprinted into `Mistakes` |
52
54
  | **Post-answer** | `auto_introspect` | `auto_introspect` **+** `fact_check_local_final` (auto `extro_verify` on CVE/version-shaped claims) |
@@ -78,7 +80,7 @@ puts resp[:content]
78
80
  ## Model diversity in Swarm
79
81
 
80
82
  Because each persona in [`agents.yml`](Swarm.md) can override `engine:`, an
81
- `agent_debate` can pit five *different providers* against each other - real
83
+ `agent_debate` can pit several *different providers* against each other - real
82
84
  antagonism, not one model role-playing three voices. The same mechanism backs
83
85
  `ai.agent.escalation_persona`: when a local model is stuck, `Loop.run` asks a
84
86
  frontier persona for a 3-line corrective hint and injects it as a synthetic
@@ -6,16 +6,16 @@ toolsets; the JSON-Schema for each tool is what the model actually sees.
6
6
 
7
7
  ![Tool registry](diagrams/agent-tool-registry.svg)
8
8
 
9
- ## Toolsets Tools (12 toolsets · 78 tools)
9
+ ## Toolsets to tools (12 toolsets · 82 tools)
10
10
 
11
11
  | Toolset | Tools | Backed by |
12
12
  |---|---|---|
13
13
  | `terminal` | `shell` | `Open3.capture3` on the host |
14
14
  | `pwn` | `pwn_eval` | `TOPLEVEL_BINDING.eval` in the live REPL process |
15
- | `memory` | `memory_remember` · `memory_recall` · `memory_forget` · `memory_clear` | `PWN::Memory` → `~/.pwn/memory.json` |
15
+ | `memory` | `memory_remember` · `memory_recall` · `memory_forget` · `memory_clear` · **`memory_lean`** | `PWN::Memory` → `~/.pwn/memory.json` |
16
16
  | `skills` | `skill_list` · `skill_view` · `skill_create` · `skill_add_reference` · `skill_delete` · `skill_migrate_legacy` | `~/.pwn/skills/<name>/SKILL.md` (**[agentskills.io](https://agentskills.io) spec**; legacy flat `*.md` auto-migrated) |
17
- | `sessions` | `sessions_list` · `sessions_view` · `sessions_current` · `sessions_delete` · `sessions_stats` | `PWN::Sessions` → `~/.pwn/sessions/` |
18
- | `learning` | `learning_note_outcome` · `learning_reflect` · `learning_distill_skill` · `learning_stats` · `learning_outcomes` · `learning_consolidate` · `learning_reset` · `learning_auto_introspect_toggle` · **`mistakes_list`** · **`mistakes_record`** · **`mistakes_resolve`** · **`mistakes_reset`** · **`reward_judge`** · **`reward_prm`** · **`reward_sentinel`** · **`reward_preferences`** · **`reward_export_dpo`** · **`reward_warm_sentinel`** · **`reward_scrub_preferences`** · **`reward_preference_balance`** · **`curriculum_practice`** · **`curriculum_train`** · **`curriculum_hindsight`** · **`curriculum_offline_judge`** · **`curriculum_preference_balance`** · **`learning_purge_noise`** | `PWN::AI::Agent::Learning` + `Mistakes` + `Reward` + `Curriculum` → `~/.pwn/learning.jsonl` + `~/.pwn/mistakes.json` + `~/.pwn/preferences.jsonl` + `~/.pwn/curriculum/` + `~/.pwn/finetune/` |
17
+ | `sessions` | `sessions_list` · `sessions_view` · `sessions_current` · `sessions_delete` · `sessions_stats` · **`sessions_lean`** | `PWN::Sessions` → `~/.pwn/sessions/` |
18
+ | `learning` | `learning_note_outcome` · `learning_reflect` · `learning_distill_skill` · `learning_stats` · `learning_outcomes` · `learning_consolidate` · `learning_reset` · `learning_auto_introspect_toggle` · **`learning_gc_stores`** · **`learning_purge_noise`** · **`mistakes_list`** · **`mistakes_record`** · **`mistakes_resolve`** · **`mistakes_reset`** · **`mistakes_lean`** · **`reward_judge`** · **`reward_prm`** · **`reward_sentinel`** · **`reward_preferences`** · **`reward_export_dpo`** · **`reward_warm_sentinel`** · **`reward_scrub_preferences`** · **`reward_preference_balance`** · **`curriculum_practice`** · **`curriculum_train`** · **`curriculum_hindsight`** · **`curriculum_offline_judge`** · **`curriculum_preference_balance`** | `PWN::AI::Agent::Learning` + `Mistakes` + `Reward` + `Curriculum` → `~/.pwn/learning.jsonl` + `~/.pwn/mistakes.json` + `~/.pwn/preferences.jsonl` + `~/.pwn/curriculum/` + `~/.pwn/finetune/` |
19
19
  | `reward` | **`reward_generator_mix`** | `PWN::AI::Agent::Reward.generator_mix` → online preference source-mix controller (`preferences.jsonl`) |
20
20
  | `curriculum` | **`curriculum_practice_kpi`** | `PWN::AI::Agent::Curriculum.practice_kpi` → `~/.pwn/curriculum_kpi.jsonl` |
21
21
  | `metrics` | `metrics_summary` · `metrics_reset` | `PWN::AI::Agent::Metrics` → `~/.pwn/metrics.json` |
@@ -23,18 +23,22 @@ toolsets; the JSON-Schema for each tool is what the model actually sees.
23
23
  | `cron` | `cron_list` · `cron_create` · `cron_run` · `cron_enable` · `cron_disable` · `cron_remove` | `PWN::Cron` → `~/.pwn/cron/jobs.yml` |
24
24
  | `swarm` | `agent_list` · `agent_spawn` · `agent_ask` · `agent_debate` · `agent_broadcast` · `swarm_bus` · `swarm_list` | `PWN::AI::Agent::Swarm` → `~/.pwn/agents.yml` + `~/.pwn/swarm/` |
25
25
 
26
- The `learning` toolset is deliberately fat: **Mistakes** (negative feedback),
27
- **Reward** (ORM/PRM/sentinel/DPO ledger) and **Curriculum** (self-play, HER,
28
- regression-gated LoRA) are all facets of the same self-improvement loop -
29
- see [Reinforcement Learning](Reinforcement-Learning.md). The thin `reward` and
30
- `curriculum` toolsets expose controller/KPI surfaces (`reward_generator_mix`,
31
- `curriculum_practice_kpi`) so personas can grant just those without the full
32
- learning surface.
26
+ The `learning` toolset is deliberately large: **Mistakes** (negative feedback),
27
+ **Reward** (outcome and process judges, sentinel, preference ledger) and
28
+ **Curriculum** (self-play, hindsight relabel, optional LoRA gate) are facets of
29
+ the same self-improvement loop - see [Reinforcement Learning](Reinforcement-Learning.md).
30
+ The thin `reward` and `curriculum` toolsets expose controller and KPI surfaces
31
+ (`reward_generator_mix`, `curriculum_practice_kpi`) so personas can grant just
32
+ those without the full learning surface.
33
+
34
+ **Store hygiene tools** (`memory_lean`, `sessions_lean`, `mistakes_lean`,
35
+ `learning_gc_stores`) trim ephemeral or oversized state without dropping
36
+ protected operator preferences, open mistakes, or gold outcomes.
33
37
 
34
38
  ## Dynamic tool-set slimming (`ai.agent.tool_router`)
35
39
 
36
40
  Shipping every schema on every turn overwhelms a small local model - the
37
- choice space is huge and it mis-routes (e.g. picks an RF tool for a git
41
+ choice space is huge and it mis-routes (for example, picks an RF tool for a git
38
42
  question). When `ai.agent.tool_router: true` **and** `Loop.run` passes the
39
43
  user request through as `relevance:`, `Registry.definitions` shrinks the
40
44
  pool to:
@@ -51,7 +55,7 @@ CORE_TOOLS = shell · pwn_eval · memory_remember · memory_recall
51
55
  PWN::AI::Agent::Registry.definitions(relevance: 'nmap sweep 10.0.0.0/8', top_k: 10)
52
56
  PWN::AI::Agent::Registry.rank(query: 'run a shell command') # inspect ranking
53
57
  PWN::AI::Agent::Registry.toolsets # → the 12 names above
54
- PWN::AI::Agent::Registry.all.count # → 78
58
+ PWN::AI::Agent::Registry.all.count # → 82
55
59
  ```
56
60
 
57
61
  Frontier engines leave `tool_router` off and receive the full set.
@@ -74,7 +78,7 @@ PWN::AI::Agent::Registry.register(
74
78
  end
75
79
  ```
76
80
 
77
- Drop the file in `lib/pwn/ai/agent/tools/`, it's auto-loaded on next launch.
81
+ Drop the file in `lib/pwn/ai/agent/tools/`. It is auto-loaded on next launch.
78
82
 
79
83
  ## Restricting a persona
80
84
 
@@ -106,6 +106,7 @@ ai:
106
106
  max_depth: 3 # Recursion guard: how many levels deep agent_ask/agent_debate sub-agents may spawn sub-agents.
107
107
  auto_introspect: true # Run Learning.auto_introspect (outcome logging + lesson mining) after every final answer.
108
108
  auto_extrospect: false # Optional ambient baseline (host/repo/env ONLY - never launches burpsuite/zaproxy/msf/gqrx). Sense tools (intel/verify/watch/rf_tune/observe) stay on-demand.
109
+ recon_authorized: false # Allow live subnet sweeps / raw-socket discovery tools this session
109
110
  plan_first: ~ # Plan-then-act pre-pass: force the model to externalize a numbered tool plan BEFORE its first dispatch. nil = auto (true when ai.active == ollama).
110
111
  tool_router: false # Dynamic tool-set slimming: ship only Registry::CORE_TOOLS + top-K keyword-relevant schemas per turn (helps small models route correctly).
111
112
  escalation_persona: ~ # Swarm persona name to ask for a 3-line corrective hint once a local model burns ≥ Loop::ESCALATE_AFTER_FAILS in-turn failures. nil = disabled.
@@ -271,6 +272,7 @@ PWN::Config.refresh_env
271
272
  | `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`. |
272
273
  | `ai.agent.auto_extrospect` | Boolean | `false` | `PWN::AI::Agent::Extrospection.auto_extrospect` | Optional ambient baseline after every final answer (`AUTO_SECTIONS` = host/repo/env only; never spawns GUI/JVM tools). Prefer on-demand sense tools (`intel`/`verify`/`watch`/`rf_tune`/`observe`). Toggle live via `extro_auto_toggle`. |
273
274
  | `ai.agent.toolsets` | Array\<String\> \| `nil` | `nil` (all) | `bin/pwn`, `PWN::Plugins::REPL`, `PWN::AI::Agent::Registry` | Allow-list of toolsets exposed to the agent. Valid: `cron`, `curriculum`, `extrospection`, `learning`, `memory`, `metrics`, `pwn`, `reward`, `sessions`, `skills`, `swarm`, `terminal`. |
275
+ | `ai.agent.recon_authorized` | Boolean | `false` | `PWN::AI::Agent::Loop.recon_authorized?` / shell guard | When true (or the user request contains in-scope / engagement language), live host-discovery tools may run. Default refuses unauthorized sweeps. |
274
276
  | `ai.agent.plan_first` | Boolean \| `nil` | `nil` (auto: `true` when `ai.active == ollama`) | `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. |
275
277
  | `ai.agent.tool_router` | Boolean | `false` | `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 so the router itself is a learned component. |
276
278
  | `ai.agent.escalation_persona` | String \| `nil` | `nil` | `PWN::AI::Agent::Loop.escalate` → `Swarm.ask` | Circuit-breaker: once a local model accumulates ≥ `Loop::ESCALATE_AFTER_FAILS` in-turn failures, ask this Swarm persona for a 3-line corrective hint (injected as a synthetic tool result). The local model still authors the final answer so Learning/Metrics stay attributed. |
@@ -60,3 +60,16 @@ rake # rubocop + rspec - must be zero offenses
60
60
  `third_party/pwn_rdoc.jsonl`, runs the gates, and pushes.
61
61
 
62
62
  [← Home](Home.md)
63
+
64
+ ## Documentation after code changes
65
+
66
+ When you change code under `/opt/pwn`:
67
+
68
+ 1. Clear RuboCop on the paths you touched (`bundle exec rubocop -a <paths>`).
69
+ 2. Run the test suite (`bundle exec rake`) and fix failures.
70
+ 3. Only then refresh user docs: `README.md`, `documentation/*`, and
71
+ `documentation/diagrams/dot/*.dot` (rebuild with `documentation/diagrams/build.sh`).
72
+ 4. Keep user-facing markdown in plain US English (ASCII hyphens, no marketing
73
+ filler, no internal agent backlog codes).
74
+
75
+ Do not commit doc refreshes while lint or tests are still red.
@@ -68,7 +68,7 @@ groups) so lines never criss-cross.
68
68
  [source](diagrams/dot/ai-integration-tool-calling.dot) · doc: [AI Integration](AI-Integration.md)
69
69
  ![ai-integration-tool-calling](diagrams/ai-integration-tool-calling.svg)
70
70
 
71
- ### Agent Tool Registry (12 toolsets · 78 tools)
71
+ ### Agent Tool Registry (12 toolsets · 82 tools)
72
72
  [source](diagrams/dot/agent-tool-registry.dot) · doc: [Agent Tool Registry](Agent-Tool-Registry.md)
73
73
  ![agent-tool-registry](diagrams/agent-tool-registry.svg)
74
74
 
@@ -3,7 +3,7 @@
3
3
  > **PWN** (/pōn/) - an open-source offensive-security automation framework and
4
4
  > continuous-security-integration platform written in Ruby.
5
5
  > 66 plugins · 48 SAST rules · 90 AWS wrappers · 21 WWW drivers · 53 CLI
6
- > drivers · 5 LLM engines · a self-improving multi-agent AI · one REPL.
6
+ > drivers · 6 LLM engines · a self-improving multi-agent AI · one REPL.
7
7
 
8
8
  **Repo root:** `/opt/pwn` · **This wiki:** `/opt/pwn/documentation/` ·
9
9
  **Rebuild diagrams:** `documentation/diagrams/build.sh`
@@ -35,8 +35,8 @@
35
35
 
36
36
  | | |
37
37
  |---|---|
38
- | [AI / LLM Integration](AI-Integration.md) | OpenAI · Anthropic · Grok (OAuth) · Gemini · Ollama |
39
- | [Agent Tool Registry](Agent-Tool-Registry.md) | 12 toolsets · **78** LLM-callable tools |
38
+ | [AI / LLM Integration](AI-Integration.md) | OpenAI · Anthropic · Grok (OAuth) · Gemini · Ollama · Open WebUI |
39
+ | [Agent Tool Registry](Agent-Tool-Registry.md) | 12 toolsets · **82** LLM-callable tools |
40
40
  | [Memory · Skills · Learning](Skills-Memory-Learning.md) | Introspection - the self-improvement loop |
41
41
  | [Mistakes](Mistakes.md) | **Negative feedback** - fingerprint failures · do-NOT-repeat · `[REPEATING]`/`[REGRESSED]` · inline self-correction |
42
42
  | [Reinforcement Learning](Reinforcement-Learning.md) | **`Reward` + `Curriculum`** - outcome/process judges · preference ledger · self-play practice · export-ready LoRA gate |
@@ -59,7 +59,7 @@
59
59
  | [SAST (48 rules)](SAST.md) | Static analysis + test-case engine |
60
60
  | [WWW (21 drivers)](WWW.md) | Browser automations for real sites |
61
61
  | [AWS (90 services)](AWS.md) | Cloud-security enumeration |
62
- | [SDR](SDR.md) | GQRX · FlipperZero · RFIDler · SonMicro · **Decoder::* (20)** · FFI-accelerated DSP |
62
+ | [SDR](SDR.md) | GQRX · FlipperZero · RFIDler · SonMicro · **Decoder::* (20 protocols + Base/DSP)** · FFI-accelerated DSP |
63
63
  | [Blockchain](Blockchain.md) | BTC · ETH helpers |
64
64
  | [Bounty](Bounty.md) | Lifecycle / auth-replay tooling |
65
65
  | [Reports](Reporting.md) | HTML/JSON output + DefectDojo/Jira |
@@ -12,7 +12,7 @@ Humans (`pwn` REPL, `pwn-ai` TUI), CI runners (`pwn --ai "..."`, `bin/pwn_*`),
12
12
  LLM providers (over HTTPS), and targets (hosts, web apps, clouds, radios,
13
13
  hardware).
14
14
 
15
- ## L1 - Entry points (`bin/`)
15
+ ## L1 - Entry points (`bin/`)
16
16
 
17
17
  | Entry | File | Purpose |
18
18
  |---|---|---|
@@ -23,13 +23,13 @@ hardware).
23
23
  | `bin/pwn_*` | 53 files | Thin OptionParser wrappers over one plugin each |
24
24
  | `PWN::Cron` | `lib/pwn/cron.rb` | Scheduled jobs → any of the above (nightly self-play + weekly weight-loop seeded by default) |
25
25
 
26
- ## L2 - AI agent core (`lib/pwn/ai/agent/`)
26
+ ## L2 - AI agent core (`lib/pwn/ai/agent/`)
27
27
 
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: English tasks primary - `emit_plan!` · `about_to` as `task k/n` + via tools · Loop `plan_context` injection · clearer `plan_idx` advance |
32
- | `Registry` | JSON-Schema function definitions grouped into 12 **toolsets** · **78 tools** |
31
+ | **`TaskSummarizer`** | Executive UX: English tasks primary - `emit_plan!` · `about_to` as `task k/n` + via tools · Loop `plan_context` injection · clearer `plan_idx` advance |
32
+ | `Registry` | JSON-Schema function definitions grouped into 12 **toolsets** · **82 tools** |
33
33
  | `Dispatch` / `Result` | execute a tool, capture stdout/value/error/duration |
34
34
  | `PromptBuilder` | inject MEMORY / SKILLS / LEARNING / **KNOWN MISTAKES + FIXES** / METRICS / EXTROSPECTION blocks |
35
35
  | `Metrics` · `Learning` · `Reflect` | **introspection** - how well am I doing? |
@@ -43,14 +43,14 @@ See [Agent Tool Registry](Agent-Tool-Registry.md) for every tool the LLM can
43
43
  call, and [Reinforcement Learning](Reinforcement-Learning.md) for how
44
44
  `Reward` + `Curriculum` close the weight-level loop.
45
45
 
46
- ## L3 - Capability namespaces (`lib/pwn/*`)
46
+ ## L3 - Capability namespaces (`lib/pwn/*`)
47
47
 
48
48
  `Plugins` (66) · `SAST` (48) · `WWW` (21) · `AWS` (90) · `SDR` · `Blockchain` ·
49
49
  `Bounty` · `Reports` · `FFI` · `Banner` · **`Setup`** · **`Migrate`**. Each is
50
50
  a plain module of `public_class_method def self.x(opts = {})` methods -
51
51
  callable the same way from the REPL, from `pwn_eval`, or from a driver.
52
52
 
53
- ## L4 - Persistence (`~/.pwn/`)
53
+ ## L4 - Persistence (`~/.pwn/`)
54
54
 
55
55
  Everything the framework remembers between processes lives in one directory.
56
56
  `PWN::Migrate` (schema-stamped, idempotent, dry-run capable) verifies and
@@ -28,6 +28,7 @@ Every byte PWN remembers between processes lives here.
28
28
  | `swarm/<id>/bus.jsonl` | `Swarm` | JSON-per-line | rm -rf | append-only multi-agent chat |
29
29
  | `swarm/<id>/personas.json` | `Swarm` | JSON | rm | persona → session_id map |
30
30
  | `curriculum/` | `PWN::AI::Agent::Curriculum` | JSONL | rm -rf | self-play reproducers · train/gate A/B eval sets |
31
+ | `curriculum_kpi.jsonl` | `PWN::AI::Agent::Curriculum.practice_kpi` | JSONL | rm | outer curriculum KPI snapshots (repeating-mistake trend) |
31
32
  | `finetune/*.jsonl` | `Learning.export_finetune` · `Reward.export_dpo` | ShareGPT / OpenAI / DPO JSONL | `rm` | supervised + preference datasets - feed to a LoRA over the local model |
32
33
  | `backup/<ts>/` | `PWN::Migrate` | tree copy | rm -rf | timestamped snapshot taken before every `--migrate --fix` |
33
34
  | `quarantine/` | `PWN::Migrate` | quarantined originals | rm -rf | corrupt/incompatible state files moved aside so the owner re-seeds |
@@ -78,3 +79,19 @@ metrics_reset(confirm: true) # tool telemetry (optional)
78
79
  ```
79
80
 
80
81
  [← Home](Home.md) · [Configuration](Configuration.md) · [Installation](Installation.md)
82
+
83
+ ## Store hygiene (lean / GC)
84
+
85
+ Keep `~/.pwn` small without dropping gold learning outcomes, open mistakes, or
86
+ protected operator preferences:
87
+
88
+ | Tool | What it trims |
89
+ |---|---|
90
+ | `memory_lean` | expired `session_*` keys and overlong values (`VALUE_MAX_CHARS`) |
91
+ | `sessions_lean` | stub/aged transcripts not pinned by gold outcomes or open mistakes |
92
+ | `mistakes_lean` | compact fields; age out resolved-once signatures whose fix already lives in Memory |
93
+ | `learning_gc_stores` | coordinated lean pass across memory, learning, mistakes, and sessions |
94
+
95
+ All four support `dry_run: true` (plan only). Protected `operator_pref_*`,
96
+ `process_sop_*`, and `mistake_fix_*` memory keys are never removed by lean.
97
+
@@ -12,30 +12,30 @@ every turn.
12
12
  ![Reinforcement-learning loop](diagrams/reinforcement-learning.svg)
13
13
 
14
14
  ```
15
- ┌────────────────────────────────────────────────┐
16
- request ──────►│ Loop.run
17
- plan_first ─► Curriculum.red_team_plan (S4)
18
- Dispatch ──► Reward.semantic_ok (R4)
19
- │ └► Mistakes.record(cause:) (E1) │
20
- guard ────► Curriculum.counterfactual (S2) │──► Reward.record_preference (W1)
21
- final ────► Curriculum.critic (S3)
22
- │ └► Reward.judge (ORM) (R1) │──► Reward.verify_as_reward (E3)
23
- │ └► Reward.prm (PRM) (R2) │──► Sessions[step_reward] (C4)
24
- │ └► Curriculum.hindsight (C3)
25
- │ └► Curriculum.calibrate (W3) │──► Metrics.calibration
26
- │ └► Reward.sentinel (R3) │──► Mistakes(reward_signal)
27
- └────────────────────────────────────────────────┘
28
-
29
- Learning.consolidate (M1 semantic-merge, M3 importance-evict)
30
- MemoryIndex.recall_semantic (M2 sim × recency × importance)
31
- Registry.rank (C1 keyword sim + advantage + UCB)
15
+ +------------------------------------------------+
16
+ request -----> | Loop.run |
17
+ | plan_first -> Curriculum.red_team_plan (S4) |
18
+ | Dispatch -> Reward.semantic_ok (R4) |
19
+ | -> Mistakes.record(cause:) |
20
+ | guard -> Curriculum.counterfactual (S2) |--> preference ledger (W1)
21
+ | final -> Curriculum.critic (S3) |
22
+ | -> Reward.judge (outcome) (R1) |--> verify_as_reward (E3)
23
+ | -> Reward.prm (process) (R2) |--> Sessions[step_reward] (C4)
24
+ | -> Curriculum.hindsight (C3) |
25
+ | -> Curriculum.calibrate (W3) |--> Metrics.calibration
26
+ | -> Reward.sentinel (R3) |--> Mistakes(reward_signal)
27
+ +------------------------------------------------+
28
+ |
29
+ Learning.consolidate (M1 semantic merge, M3 importance eviction)
30
+ MemoryIndex.recall_semantic (M2 similarity x recency x importance)
31
+ Registry.rank (C1 keyword fit + advantage + UCB)
32
32
  Learning.exemplars_for (C2 prioritized replay, C4 minimal trace)
33
-
34
- nightly cron ──► Curriculum.practice (S1) ──► Mistakes.resolve ──► preference (W1)
35
- weekly cron ──► Curriculum.train_and_gate (W2) ──► LoRA vN+1 ──► A/B gate ──► promote
36
-
37
- Extrospection.correlate rule 9 (E2 causal lead-lag)
38
- Metrics.changepoints (E1 CUSUM) ──► Mistakes(cause: :env_drift)
33
+ |
34
+ nightly cron --> Curriculum.practice (S1) --> Mistakes.resolve --> preference ledger (W1)
35
+ weekly cron --> Curriculum.train_and_gate (W2) --> optional LoRA --> A/B gate --> promote
36
+ |
37
+ Extrospection.correlate (E2 world vs self join)
38
+ Metrics.changepoints (E1) --> Mistakes(cause: :env_drift)
39
39
  ```
40
40
 
41
41
  ## Reward signal (`PWN::AI::Agent::Reward`)
@@ -48,7 +48,7 @@ every turn.
48
48
  | **R4** | `.semantic_ok` | Treats informational non-zero exits (e.g. `grep`/`rg` with no match) as benign. Metrics count them as OK; Mistakes only see true dispatch failures. |
49
49
  | - | `.warm_sentinel` | Backfills the sentinel window from scored Learning outcomes so local hosts can engage proxy distrust without waiting for live remote introspect. |
50
50
  | **W1** | `.record_preference` / `.export_dpo` | Preference ledger (`~/.pwn/preferences.jsonl`) from user corrections, resolve, counterfactual, critic, and practice. Caps per source; keeps trajectory-shaped pairs (winning traces / revised answers), not fix commentary. |
51
- | - | `.scrub_preferences` / `.preference_balance` / `.generator_mix` | Ledger hygiene and source-mix health so one channel cannot flood DPO export. |
51
+ | - | `.scrub_preferences` / `.preference_balance` / `.generator_mix` | Ledger hygiene and source-mix health so one channel cannot flood preference export. |
52
52
 
53
53
  ## Credit assignment and replay
54
54
 
@@ -85,7 +85,7 @@ every turn.
85
85
  ## Budget pressure (iteration ceiling)
86
86
 
87
87
  When unresolved `agent_loop` / `assistant_answer` budget-exhaustion fingerprints
88
- dominate, `Loop.budget_exhaustion_hot?` tightens the live turn:
88
+ dominate, the loop marks the budget path hot and tightens the live turn:
89
89
 
90
90
  - lower effective `max_iters` (stricter on local/ollama engines than remote)
91
91
  - **Last-iter force-final**: tools=nil on the final iteration so a text answer is required
@@ -98,11 +98,11 @@ Raising `ai.agent.max_iters` or resolving the scar returns normal runway.
98
98
 
99
99
  ## Intro and extro join
100
100
 
101
- | ID | Where | What |
102
- |----|-------|------|
103
- | **E1** | `Metrics.changepoints` + `Loop.attribute_cause` | Env-drift-attributed failures get `cause: :env_drift` and do not inflate `[REPEATING]`. |
104
- | **E2** | `Extrospection.correlate` | Lead-lag style joins ("tool X started failing after toolchain Y changed"). |
105
- | **E3** | `Reward.verify_as_reward` | Browser-backed claim checks can floor/cap the outcome score. |
101
+ | Where | What |
102
+ |-------|------|
103
+ | `Metrics.changepoints` + `Loop.attribute_cause` (**E1**) | Env-drift-attributed failures get `cause: :env_drift` and do not inflate `[REPEATING]`. |
104
+ | `Extrospection.correlate` (**E2**) | Lead-lag style joins ("tool X started failing after toolchain Y changed"). |
105
+ | `Reward.verify_as_reward` (**E3**) | Browser-backed claim checks can floor/cap the outcome score. |
106
106
 
107
107
  ## Config (`PWN::Env[:ai][:agent]`)
108
108
 
@@ -113,7 +113,7 @@ Raising `ai.agent.max_iters` or resolving the scar returns normal runway.
113
113
  :critic: null # S3 - nil = ON for remote engines, OFF for ollama
114
114
  :red_team_plan: null # S4 - same auto policy
115
115
  :counterfactual: null # S2 - same auto policy
116
- :hindsight: true # C3 - HER soft-relabel (default true)
116
+ :hindsight: true # C3 - hindsight relabel on failed turns (default true)
117
117
  :verify_as_reward: null # E3 - nil = auto sample on claim-shaped answers
118
118
  :reward_llm: null # nil = outcome/process judges use LLM teacher on remote
119
119
  :local_introspect: :failure_only # ollama cost policy; remote always introspects
@@ -168,21 +168,21 @@ keep it honest by:
168
168
 
169
169
  ## Design-priority STATUS
170
170
 
171
- Living flag authority for the reinforced feedback loop. Cite the Pri/ID here
172
- instead of inventing new milestone labels for the same theme.
171
+ Living checklist for the reinforced feedback loop. Cite the Pri/ID here instead
172
+ of inventing new milestone labels for the same theme.
173
173
 
174
174
  | Pri | ID | Control | Module(s) | Success criterion |
175
175
  |-----|----|---------|-----------|-------------------|
176
176
  | **P0** | W1 generator diversity | `Reward::TARGET_SOURCE_MIX` + `generator_mix` + mix-urgent force on critic/counterfactual | `reward.rb`, `curriculum.rb` | `generator_mix.healthy` OR `recommendation` not stuck on `suppress:mistakes_resolve`; trajectory_fraction ≥ 0.5 |
177
- | **P0** | Introspect budget | `Learning::INTROSPECT_SOFT_MS` / `HARD_MS`; stage skip under soft/hard / `budget_exhaustion_hot?` | `learning.rb` | `auto_introspect` returns `stages_skipped` when over soft; post-answer path cannot re-thrash tool critic |
178
- | **P1** | Local judge calibration | Heuristic score shrinkage + `confidence`; `Metrics.effective_rate` scales distrust by `judge_confidence` | `reward.rb`, `metrics.rb` | distrust×heuristic no longer fully replaces proxy; local no-trace highs capped |
179
- | **P1** | Practice outer KPI | `Curriculum.practice_kpi` / `repeating_trend` → `~/.pwn/curriculum_kpi.jsonl` | `curriculum.rb` | week-over-week `delta_repeating` ≤ 0 on budget fingerprints after practice nights |
180
- | **P2** | PRM sample efficiency | `PRM_MIN_N=5`, shrinkage to `PRM_FULL_N=20`, fleet coverage gate in `Registry.rank` | `metrics.rb`, `registry.rb` | `prm_advantage=0` until n≥5; rank delta=0 until ≥3 tools ready |
181
- | **P2** | STATUS over flag archaeology | This table | docs | New work cites Pri/ID here, not fresh comments for the same theme |
177
+ | **P0** | Introspect budget | `Learning::INTROSPECT_SOFT_MS` / `HARD_MS`; stage skip under soft/hard / budget-pressure mode | `learning.rb` | `auto_introspect` returns `stages_skipped` when over soft; post-answer path cannot re-thrash tool critic |
178
+ | **P0** | Local judge calibration | Heuristic score shrinkage + `confidence`; `Metrics.effective_rate` scales distrust by `judge_confidence` | `reward.rb`, `metrics.rb` | distrust×heuristic no longer fully replaces proxy; local no-trace highs capped |
179
+ | **P0** | Practice outer KPI | `Curriculum.practice_kpi` / `repeating_trend` → `~/.pwn/curriculum_kpi.jsonl` | `curriculum.rb` | week-over-week `delta_repeating` ≤ 0 on budget fingerprints after practice nights |
180
+ | **P0** | PRM sample efficiency | `PRM_MIN_N=5`, shrinkage to `PRM_FULL_N=20`, fleet coverage gate in `Registry.rank` | `metrics.rb`, `registry.rb` | `prm_advantage=0` until n≥5; rank delta=0 until ≥3 tools ready |
181
+ | **P0** | STATUS over flag archaeology | This table | docs | New work cites Pri/ID here, not fresh comments for the same theme |
182
182
  | **ops** | Nightly diet close | `offline_judge` → `scrub_preferences` + `generator_mix` + `practice_kpi` | `curriculum.rb` | Cron path returns `scrub`/`generator_mix`/`practice_kpi`; raw resolve prose does not survive the night |
183
183
  | **ops** | Shape backfill | `Reward.infer_shape` + scrub rewrite | `reward.rb` | Legacy shapeless rows get `winning_trace`/`revised_answer` when content warrants; traj_f measurable |
184
184
  | **ops** | Mix in prompt | `Metrics.to_context` emits `W1 MIX:` when unhealthy | `metrics.rb` | Unhealthy diet visible every turn without a tool call |
185
- | **P0** | Budget exhaust deepen | Last-iter force-final (tools=nil); skip CF when `budget_exhaustion_hot?`; hot caps 24 ollama / 75 remote; exhaust path `append_session`+`auto_introspect` | `loop.rb` | Exhaust returns a judged final, not a bare string; CF cannot re-enter under hot; last iter cannot tool-call |
185
+ | **P0** | Budget exhaust deepen | Last-iter force-final (tools=nil); skip CF under budget-pressure mode; hot caps 24 ollama / 75 remote; exhaust path `append_session`+`auto_introspect` | `loop.rb` | Exhaust returns a judged final, not a bare string; CF cannot re-enter under hot; last iter cannot tool-call |
186
186
 
187
187
  ### Config additions
188
188
 
data/documentation/SDR.md CHANGED
@@ -15,7 +15,7 @@
15
15
  | `RFIDler` | 125 kHz RFID reader/emulator |
16
16
  | `SonMicroRFID` | SM130 13.56 MHz reader |
17
17
  | `FrequencyAllocation` | ITU/FCC band-plan lookup - "what lives at 433.92 MHz?" |
18
- | **`Decoder::*`** | 20 protocol demodulators/decoders - `ADSB APT Bluetooth DECT FLEX GPS GSM Iridium LoRa LTE Morse P25 Pager POCSAG RDS RFID RTL433 RTTY WiFi ZigBee` |
18
+ | **`Decoder::*`** | 20 protocol demodulators/decoders (+ Base/DSP helpers) - `ADSB APT Bluetooth DECT FLEX GPS GSM Iridium LoRa LTE Morse P25 Pager POCSAG RDS RFID RTL433 RTTY WiFi ZigBee` |
19
19
 
20
20
  ## CLI
21
21
 
@@ -27,6 +27,7 @@ appended as JSON-per-line to `~/.pwn/sessions/<id>.jsonl`.
27
27
  | `sessions_view(session_id:, truncate:)` | Read entries |
28
28
  | `sessions_delete(session_id:)` | Prune noisy/dev transcripts so `reflect` corpus stays clean |
29
29
  | `sessions_stats` | totals across the whole directory |
30
+ | `sessions_lean` | prune stubs and aged unreferenced transcripts; compact oversized tool/assistant content (pins gold outcomes and open-mistake refs) |
30
31
 
31
32
  ## File format
32
33
 
@@ -113,6 +113,8 @@ the new format.
113
113
  | `learning_auto_introspect_toggle(enabled: false)` | during noisy fuzz loops |
114
114
  | `PWN::MemoryIndex.reset` | new engagement - drop the local embedding index (`memory.idx`) so it rebuilds against the fresh `memory.json` |
115
115
  | `PWN::AI::Agent::Learning.export_finetune(format: :sharegpt)` | you have enough **high-score** sessions for SFT (drops low scores / HER soft rows and compresses traces by process reward) |
116
+ | `memory_lean` / `sessions_lean` / `mistakes_lean` | trim ephemeral or oversized state; never drop protected prefs or open mistakes |
117
+ | `learning_gc_stores` | one coordinated lean pass across the RL stores (supports `dry_run: true`) |
116
118
 
117
119
  ## Example questions that trigger Introspection
118
120
 
@@ -16,11 +16,11 @@ with a **tool-calling AI agent** on top that can run the same methods.
16
16
  | `PWN::SAST::*` | **48** | Static-analysis rules across C/Java/Go/Python/Ruby/Scala/PHP/TS |
17
17
  | `PWN::AWS::*` | **90** | One module per AWS service for cloud enumeration |
18
18
  | `PWN::WWW::*` | **21** | Site-specific browser automations (HackerOne, BugCrowd, Google, LinkedIn, ...) |
19
- | `PWN::SDR::*` | **6** (+ **20** decoders) | GQRX, FlipperZero, RFIDler, SonMicro, band tables, `Decoder::{ADSB,POCSAG,RDS,LoRa,...}` |
19
+ | `PWN::SDR::*` | **6** (+ **20** protocol decoders + Base/DSP) | GQRX, FlipperZero, RFIDler, SonMicro, band tables, `Decoder::{ADSB,POCSAG,RDS,LoRa,...}` |
20
20
  | `PWN::FFI::*` | **8** | Native DSP/RF backends: Volk · Liquid · FFTW · RTLSdr · HackRF · AdalmPluto · SoapySDR · Stdio |
21
- | `PWN::AI::*` | **5** engines | OpenAI, Anthropic, Grok (OAuth device-flow), Gemini, Ollama |
21
+ | `PWN::AI::*` | **6** engines | OpenAI, Anthropic, Grok (OAuth device-flow), Gemini, Ollama, Open WebUI |
22
22
  | `bin/pwn_*` | **53** | Headless CLI drivers for CI/CD |
23
- | Agent toolsets | **12** · **78 tools** | terminal · pwn · memory · skills · sessions · learning · metrics · extrospection · cron · swarm · reward · curriculum |
23
+ | Agent toolsets | **12** · **82 tools** | terminal · pwn · memory · skills · sessions · learning · metrics · extrospection · cron · swarm · reward · curriculum |
24
24
 
25
25
  ## Three ways to use it
26
26