pwn 0.5.651 → 0.5.652

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87ce6374516629bc195970447a1af7654566791f1493711e69f418bd72d60836
4
- data.tar.gz: 1bc09b0d752bd2545150c2cf9c9bb42972481af3dfc39c05d98cfe13507005a4
3
+ metadata.gz: 6fd0197b1fa729406ea99bbe598d3730d27e3c6881251c374af0f894ea541729
4
+ data.tar.gz: 492617f851780cf17c04fcdecdd4eb491e54b2bcf115b04997f3972507528d3a
5
5
  SHA512:
6
- metadata.gz: 5b2969e88240d7e28fd15fc4eff26338e7f1cbe8260696a5315049bb687613144988ba40d021c35a6d5605f143459b89a5bc65fc850db5c07f67015ca85251fa
7
- data.tar.gz: 43cdfb1b3a4129cacfe3767d14d19f5bf138732e7234b9092e5ddf4ad10e4f7c5390759646f9c8e16d1ead8ab6b87fbe7109779901d0f3cf2c17ff714825c266
6
+ metadata.gz: ad8894f7551643e63ec4819d7a2513e3114d0f2649eb21ea8b9554e150319a7df0d62e6c46d9979d5c0462c5617f054f93f2140c81704b74fa3d8f763c428d90
7
+ data.tar.gz: f84e73f55040588558281b2941a41b602b2f3a6471c5cbbacdd7afc42a9b2dbf91c8c9c01e68079dcaedee03a25aad25eb17558d3ffec62f0ce8539f5e6ef1a5
data/README.md CHANGED
@@ -24,57 +24,68 @@
24
24
 
25
25
  #### **What is PWN** ####
26
26
 
27
- PWN (pronounced /pōn/ - *pone*) is an open-source **offensive-security
28
- automation framework** and **continuous-security-integration** platform.
29
- It gives security researchers, red teamers, penetration testers and
30
- vulnerability researchers a single, scriptable Ruby surface over the entire
31
- offensive toolchain - from OSINT and network discovery, through web / cloud /
32
- hardware / radio exploitation, to reporting and disclosure - and puts a
33
- **self-improving, tool-calling, multi-agent AI** on top of it.
27
+ PWN (pronounced *pone*, like "own" with a p) is an open-source Ruby toolkit for
28
+ **offensive security automation**. One workspace ties together the tools you
29
+ already use: OSINT, network scanning, web and cloud testing, hardware and
30
+ radio, reporting, and disclosure. A **tool-calling AI agent** sits on top and
31
+ can run those same methods for you.
32
+
33
+ Red teamers, pentesters, and vulnerability researchers get one place to script
34
+ and automate instead of gluing together a pile of separate CLIs.
34
35
 
35
36
  **In numbers:** 66 `PWN::Plugins` · 48 `PWN::SAST` rules · 90 `PWN::AWS`
36
37
  service wrappers · 21 `PWN::WWW` site drivers · 53 `bin/pwn_*` CLI drivers ·
37
- 5 LLM engines · 10 agent toolsets · 45+ LLM-callable tools.
38
+ 5 LLM engines · 12 agent toolsets · 78 LLM-callable tools.
38
39
 
39
40
  Full page: [What is PWN](documentation/What-is-PWN.md)
40
41
 
41
42
  #### **Why PWN** ####
42
43
 
43
- Offensive security is a *toolchain problem*. PWN's bet is that the right
44
- abstraction is **plain Ruby methods with a uniform `opts = {}` signature**,
45
- exposed simultaneously to a human in a REPL, an LLM in a tool-calling loop, a
46
- shell script in CI, and a cron job at 3 am - all open-source and auditable,
47
- which matters when the caller is autonomous.
44
+ Offensive work is hard because the *tools* do not fit together. PWN's fix is
45
+ simple: every capability is a plain Ruby method with the same `opts = {}`
46
+ shape. That one idea means the *same* code runs:
47
+
48
+ - live in the REPL
49
+ - from an LLM agent in a tool loop
50
+ - in a shell script or CI job
51
+ - on a cron schedule while you sleep
52
+
53
+ The whole stack is open source and easy to read. That matters when software
54
+ is driving security decisions without you watching every click.
48
55
 
49
56
  Full page: [Why PWN](documentation/Why-PWN.md)
50
57
 
51
58
  #### **How PWN Works** ####
52
59
 
53
- Five layers, edges only ever go down:
60
+ PWN is five layers. Dependencies only point downward, so each level stays
61
+ small and easy to swap:
54
62
 
55
63
  ![PWN Overall Architecture](documentation/diagrams/overall-pwn-architecture.svg)
56
64
 
57
- The AI layer closes a **self-improvement loop** on every turn - Metrics +
58
- Learning + **Mistakes** (introspection / negative feedback) joined with
59
- Snapshot + Drift + Intel + RF + **Web** (extrospection) - plus browser-backed **`extro_verify`** / **`extro_watch`** and RF **`extro_rf_tune`** sensing - via `extro_correlate`, so the
60
- agent knows whether a failure was *its* fault or *the world* changed -
61
- **and does not repeat the same mistake twice**:
65
+ On every turn the AI layer runs a **feedback loop**. It checks inward
66
+ (Metrics, Learning, and **Mistakes**: what failed last time) and outward
67
+ (Snapshot, Drift, Intel, RF, and **Web**: did the host or network change?).
68
+ Live checks use browser-backed **`extro_verify`** / **`extro_watch`** and RF
69
+ **`extro_rf_tune`**. `extro_correlate` joins those views so the agent can tell
70
+ *"I messed up"* from *"the world moved"*, and **does not repeat the same
71
+ mistake**:
62
72
 
63
73
  ![pwn-ai Feedback Learning Loop](documentation/diagrams/pwn-ai-feedback-learning-loop.svg)
64
74
 
65
- Failures are fingerprinted cross-session (`~/.pwn/mistakes.json`), tagged
66
- `[REPEATING]` / `[REGRESSED]`, and their **fix** is handed straight back inline
67
- on the next recurrence:
75
+ Failures are fingerprinted across sessions (`~/.pwn/mistakes.json`), tagged
76
+ `[REPEATING]` / `[REGRESSED]`, and when the same slip shows up again the saved
77
+ **fix** is dropped straight back into the prompt:
68
78
 
69
79
  ![Mistakes Negative-Feedback Loop](documentation/diagrams/mistakes-negative-feedback.svg)
70
80
 
71
- And **Swarm** runs multiple personas - each a full tool-calling agent,
72
- optionally on a *different* LLM engine - over a shared append-only bus:
81
+ **Swarm** runs several personas at once. Each is a full tool-calling agent,
82
+ optionally on a *different* LLM engine, talking over a shared append-only
83
+ message bus:
73
84
 
74
85
  ![Swarm Multi-Agent](documentation/diagrams/swarm-multi-agent.svg)
75
86
 
76
87
  Full pages: [How PWN Works](documentation/How-PWN-Works.md) ·
77
- [All 27 Data-Flow Diagrams](documentation/Diagrams.md)
88
+ [All data-flow diagrams](documentation/Diagrams.md)
78
89
 
79
90
  ---
80
91
 
@@ -105,7 +116,7 @@ Rebuild every SVG from its Graphviz source:
105
116
 
106
117
  PWN is a **single gem** with a built-in post-install doctor/provisioner -
107
118
  `pwn setup` - that detects your package manager (`apt` · `dnf` · `pacman` ·
108
- `brew` · `port`) and installs exactly the OS headers + external tools each
119
+ `brew` · `port`) and installs the OS headers and external tools each
109
120
  `PWN::` capability needs. Tested on Kali/Debian/Ubuntu, Fedora, Arch, macOS.
110
121
 
111
122
  ```
@@ -166,7 +177,7 @@ $ cd /opt/pwn && git pull && rake install && pwn setup
166
177
  ```
167
178
  $ pwn --ai 'What ports are listening on this host?'
168
179
  $ echo "$LONG_PROMPT" | pwn --ai -
169
- $ pwn -Y ./ci/pwn.yaml --ai 'Run pwn_sast against ./src and summarise HIGH findings' > findings.txt
180
+ $ pwn -Y ./ci/pwn.yaml --ai 'Run pwn_sast against ./src and summarize HIGH findings' > findings.txt
170
181
  ```
171
182
 
172
183
  **Provision a CI runner / Docker image:**
@@ -206,13 +217,13 @@ Highlights:
206
217
  [SAST](documentation/SAST.md) ·
207
218
  [AI Integration](documentation/AI-Integration.md)
208
219
 
209
- I hope you enjoy PWN - and remember: **always have permission** before any
210
- security testing. Now go pwn all the things (responsibly)!
220
+ Remember: **always have permission** before any security testing. Then go
221
+ pwn all the things (responsibly).
211
222
 
212
223
  ---
213
224
 
214
225
  ### **Keep Us Caffeinated** ###
215
- If you've found this project useful and you're interested in supporting our efforts, we invite you to take a brief moment to keep us caffeinated:
226
+ If this project helped you and you want to support the work, keep us caffeinated:
216
227
 
217
228
  [![Coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://buymeacoff.ee/0dayinc)
218
229
 
@@ -1,7 +1,7 @@
1
1
  # AI / LLM Integration - `PWN::AI`
2
2
 
3
3
  One agent loop, five interchangeable engines. Swap providers by changing one
4
- line in `~/.pwn/pwn.yaml`; the tool-calling contract is normalised so the
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
 
7
7
  ![Multi-provider integration](diagrams/ai-integration-tool-calling.svg)
@@ -20,7 +20,7 @@ generates the decryptor.
20
20
  > [doctor](Installation.md#pwn-setup--the-post-install-doctor--provisioner)
21
21
  > reports whether `~/.pwn/`, `pwn.yaml`, its decryptor, and an AI-engine key
22
22
  > are present, and exits non-zero for CI if any are missing.
23
- > After `gem update pwn`, run `pwn setup --migrate --fix` `PWN::Migrate`
23
+ > After `gem update pwn`, run `pwn setup --migrate --fix` - `PWN::Migrate`
24
24
  > deep-merges any keys the new `PWN::Config.env_template` added into your
25
25
  > encrypted `pwn.yaml` **without overwriting your values**.
26
26
 
@@ -269,7 +269,7 @@ PWN::Config.refresh_env
269
269
  | `ai.agent.critic` | Boolean | `false` | `PWN::AI::Agent::Curriculum.critic` (S3) | Tool-armed constitutional self-critic reviews (and may `shell`/`extro_verify`) every final answer before it is returned. |
270
270
  | `ai.agent.red_team_plan` | Boolean | `false` | `PWN::AI::Agent::Curriculum.red_team_plan` (S4) | Adversarial review of the `plan_first` numbered plan, grounded in Metrics/Mistakes/`extro_drift` telemetry, before the first dispatch. |
271
271
  | `ai.agent.counterfactual` | Boolean | `false` | `PWN::AI::Agent::Curriculum.counterfactual` (S2) | On `[REPEATING]`, fork an alt-persona branch, judge both, and record the `(loser, winner)` DPO preference pair. |
272
- | `ai.agent.hindsight` | Boolean | `true` | `PWN::AI::Agent::Curriculum.hindsight` (C3) | Hindsight Experience Replay relabel a failed trajectory as `success:true` for whatever it *did* accomplish. Free positive samples from failures. |
272
+ | `ai.agent.hindsight` | Boolean | `true` | `PWN::AI::Agent::Curriculum.hindsight` (C3) | Hindsight Experience Replay - relabel a failed trajectory as `success:true` for whatever it *did* accomplish. Free positive samples from failures. |
273
273
  | `ai.agent.verify_as_reward` | Boolean | `false` | `PWN::AI::Agent::Reward.verify_as_reward` (E3) | Ground the LLM judge score by browser-verifying any checkable claim in the final via `extro_verify`; verdict caps/floors `Reward.judge`. |
274
274
  | `ai.agent.extrospection.web.anchors` | Array\<String\> | `DEFAULT_WEB_ANCHORS` | `PWN::AI::Agent::Extrospection.probe_web` | URLs the headless browser fingerprints on `extro_snapshot(sections:[:web])`. Alias: `web_anchors`. |
275
275
  | `ai.agent.extrospection.web.proxy` | String | - | `Extrospection.probe_web` / `.verify` / `.watch` | Upstream proxy for `PWN::Plugins::TransparentBrowser` (e.g. `tor`, `http://127.0.0.1:8080`). |
@@ -36,11 +36,11 @@ invokes `PWN::Cron.run(<id>)` on schedule.
36
36
  | `curriculum_train_weekly` | `0 4 * * 0` | `PWN::AI::Agent::Curriculum.train_and_gate(dry_run: true)` |
37
37
  | `learning_consolidate_nightly` | `0 5 * * *` | `PWN::AI::Agent::Learning.consolidate` |
38
38
 
39
- - **practice** top unresolved `Mistakes` under `Reward.judge`; auto-`resolve` with ≥2 holdouts
40
- - **offline_judge** P3 backfill of ORM/PRM labels + W3 calibration from PLAN `p(success)=` so `:failure_only` local introspect does not starve the corpus; also runs **P10** `Reward.warm_sentinel` so the R3 ring can fill on local hosts
41
- - **dedupe (P13)** legacy alias `offline_judge_nightly` counts as the same job; `install_defaults` will not double-seed `30 3 * * *` and disables the alias when both exist
42
- - **train** export SFT + balanced DPO, LoRA-train `pwn-vN+1`, replay Mistakes.top, promote only on win. `dry_run: false` only with a trainer+GPU
43
- - **consolidate** M1/M3 memory GC so the injected MEMORY block stays high-signal
39
+ - **practice** - top unresolved `Mistakes` under `Reward.judge`; auto-`resolve` with ≥2 holdouts
40
+ - **offline_judge** - P3 backfill of ORM/PRM labels + W3 calibration from PLAN `p(success)=` so `:failure_only` local introspect does not starve the corpus; also runs **P10** `Reward.warm_sentinel` so the R3 ring can fill on local hosts
41
+ - **dedupe (P13)** - legacy alias `offline_judge_nightly` counts as the same job; `install_defaults` will not double-seed `30 3 * * *` and disables the alias when both exist
42
+ - **train** - export SFT + balanced DPO, LoRA-train `pwn-vN+1`, replay Mistakes.top, promote only on win. `dry_run: false` only with a trainer+GPU
43
+ - **consolidate** - M1/M3 memory GC so the injected MEMORY block stays high-signal
44
44
 
45
45
  See [Reinforcement Learning](Reinforcement-Learning.md).
46
46
 
@@ -84,7 +84,7 @@ Override / extend via `PWN::Env[:ai][:agent][:extrospection][:web][:anchors]`; s
84
84
  | **`extro_osint`** | **Aggregate public OSINT APIs (phone / IP / domain / FCC ID / patent / VIN / MAC / callsign / person / company / SEC / CourtListener / Federal Register / UK Police / OTX / URLHaus / openFDA / NPPES / Nominatim / EPSS / CISA KEV / Microlink / vital records / Shodan / Hunter / AbuseIPDB / VT / HIBP / Wayback) + social/identity feeds (Keybase / Gravatar / Mastodon / Bluesky / HN / StackExchange / npm / PyPI / RubyGems / crates / DockerHub / Codeberg / Steam / Telegram + ~100-site presence sweep) + local-tool bridges (theHarvester / spiderfoot / amass / recon-ng)** | `observations[]` (`category: :osint`) |
85
85
  | **`extro_serial`** | **Open serial device · optional payload · drain response · disconnect** | `observations[]` (`category: :serial`) |
86
86
  | **`extro_telecomm`** | **BareSIP inventory / status / dial / hangup (never launches baresip)** | `observations[]` (`category: :telecomm`) |
87
- | **`extro_packet`** | **Inventory · bounded live capture · pcap summarise (tshark/PacketFu)** | `observations[]` (`category: :packet`) |
87
+ | **`extro_packet`** | **Inventory · bounded live capture · pcap summarize (tshark/PacketFu)** | `observations[]` (`category: :packet`) |
88
88
  | **`extro_vision`** | **OCR (tesseract/RTesseract) · barcode/QR (zbarimg)** | `observations[]` (`category: :vision`) |
89
89
  | **`extro_voice`** | **TTS (espeak-ng/festival/spd-say) · STT (whisper) · inventory** | `observations[]` (`category: :voice`) |
90
90
  | `extro_correlate` | **Join** introspection ↔ extrospection | - actionable findings |
@@ -397,7 +397,7 @@ PWN::Env[:ai][:agent][:extrospection][:telecomm] = {
397
397
 
398
398
  ## `extro_packet` - Packet sense organ
399
399
 
400
- Bounded L2/L3 sensing via `tshark` / `tcpdump` + pcap summarisation through
400
+ Bounded L2/L3 sensing via `tshark` / `tcpdump` + pcap summarization through
401
401
  `PWN::Plugins::Packet` / tshark hierarchy & conversations:
402
402
 
403
403
  | action | Effect |
@@ -498,7 +498,7 @@ use **Chicago** so the catalog stays portable.
498
498
  ### RF / SDR sense organ (`extro_rf_tune` + `:rf` observations)
499
499
 
500
500
  - "Tune 433.92 MHz - is the target's garage/gate remote fixed-code or rolling?"
501
- - "Sweep the 900 MHz ISM band near the badge reader and log anything > 40 dBFS."
501
+ - "Sweep the 900 MHz ISM band near the badge reader and log anything > -40 dBFS."
502
502
  - "What's broadcasting on 101.1 FM right now - grab RDS PI/PS so we can prove SDR is live."
503
503
  - "Sample 868.3 MHz for 15 s - does the smart-meter mesh look like Wireless M-Bus?"
504
504
  - "Any ADS-B traffic squawking over the client's campus (near ORD)?"
@@ -551,7 +551,7 @@ use **Chicago** so the catalog stays portable.
551
551
  ### Packet sense organ (`extro_packet`)
552
552
 
553
553
  - "Capture 30 s on `eth0` while I trigger the IoT hub - what does it phone home to?"
554
- - "Summarise `/tmp/eng.pcap` - top talkers, cleartext creds, weird ports."
554
+ - "Summarize `/tmp/eng.pcap` - top talkers, cleartext creds, weird ports."
555
555
  - "BPF `udp port 5353` - is mDNS leaking hostnames and service records on the guest VLAN?"
556
556
  - "Grab 50 packets of the OT segment - Modbus/TCP or something proprietary?"
557
557
  - "Do we see the camera's RTSP creds in the clear during that capture?"
@@ -625,7 +625,7 @@ use **Chicago** so the catalog stays portable.
625
625
  | "subdomain / CT log / ASN / whois / FCC ID / VIN / MAC OUI / EPSS / KEV / Wayback / pivot @user / Keybase / Gravatar / social sweep / theHarvester / amass" | `extro_osint` |
626
626
  | "UART / ttyUSB / U-Boot / AT command / Flipper / JTAG banner" | `extro_serial` |
627
627
  | "SIP / PBX / IVR / BareSIP / dial / hangup" | `extro_telecomm` |
628
- | "capture on iface / summarise pcap / mDNS / Modbus / RTSP creds" | `extro_packet` |
628
+ | "capture on iface / summarize pcap / mDNS / Modbus / RTSP creds" | `extro_packet` |
629
629
  | "OCR sticker / decode QR / read badge / BIOS screenshot" | `extro_vision` |
630
630
  | "transcribe wav / TTS pretext / whisper offline" | `extro_voice` |
631
631
  | "watch URL / did the page change / silent patch / scope updated / TLS rotated" | `extro_watch` |
@@ -4,7 +4,7 @@
4
4
 
5
5
  ```bash
6
6
  $ pwn # interactive REPL
7
- $ pwn --ai "scan 10.0.0.0/24 with NmapIt and summarise open services"
7
+ $ pwn --ai "scan 10.0.0.0/24 with NmapIt and summarize open services"
8
8
  $ pwn_nmap_discover_tcp_udp -t 10.0.0.0/24 -o out/ # headless driver
9
9
  ```
10
10
 
@@ -76,5 +76,4 @@
76
76
 
77
77
  ---
78
78
 
79
- <sub>Generated by pwn-ai. Edit any `.md` directly; edit any diagram in
80
- `documentation/diagrams/dot/*.dot` then run `./build.sh`.</sub>
79
+ <sub>Edit any `.md` directly. Edit diagrams in `documentation/diagrams/dot/*.dot`, then run `./build.sh`.</sub>
@@ -1,6 +1,6 @@
1
1
  # How PWN Works
2
2
 
3
- PWN is five layers, each visible in the source tree. Edges only ever go
3
+ PWN is five layers, each visible in the source tree. Edges only go
4
4
  **down** one layer (or sideways within a layer), which is why the diagrams
5
5
  below have no criss-crossing lines.
6
6
 
@@ -47,7 +47,7 @@ call, and [Reinforcement Learning](Reinforcement-Learning.md) for how
47
47
  `Plugins` (66) · `SAST` (48) · `WWW` (21) · `AWS` (90) · `SDR` · `Blockchain` ·
48
48
  `Bounty` · `Reports` · `FFI` · `Banner` · **`Setup`** · **`Migrate`**. Each is
49
49
  a plain module of `public_class_method def self.x(opts = {})` methods -
50
- callable identically from the REPL, from `pwn_eval`, or from a driver.
50
+ callable the same way from the REPL, from `pwn_eval`, or from a driver.
51
51
 
52
52
  ## L4 - Persistence (`~/.pwn/`)
53
53
 
@@ -57,22 +57,22 @@ autofixes every file in it after a `gem update pwn`:
57
57
 
58
58
  ![~/.pwn map](diagrams/persistence-filesystem.svg)
59
59
 
60
- See [Persistence](Persistence.md) for the byte-level layout of each file and
60
+ See [Persistence](Persistence.md) for the layout of each file and
61
61
  [Installation § Upgrading](Installation.md#upgrading--pwn-state-migration-pwnmigrate)
62
62
  for the migrator.
63
63
 
64
64
  ## The feedback loop
65
65
 
66
- The reason L2 exists is to close this loop on every turn - successes
67
- become skills/lessons, **failures become fingerprinted mistakes with fixes**,
68
- **world-state is sensed on demand** (`extro_verify` / `extro_watch` /
69
- `extro_rf_tune` / `extro_osint` / `extro_serial` / `extro_telecomm` /
70
- `extro_packet` / `extro_vision` / `extro_voice` / `extro_intel`) and
71
- correlated against those failures, an **LLM judge scores the final** and a
72
- **process reward model tags each tool step**, and **all six prompt blocks**
73
- (MEMORY · SKILLS · LEARNING · KNOWN MISTAKES/FIXES · TOOL EFFECTIVENESS ·
74
- EXTROSPECTION) are re-injected into the very next system prompt.
75
- Nightly cron practises the top unresolved Mistakes; weekly cron cuts a
66
+ L2 exists to close this loop on every turn - successes become skills and
67
+ lessons, **failures become fingerprinted mistakes with fixes**, **world state
68
+ is sensed on demand** (`extro_verify` / `extro_watch` / `extro_rf_tune` /
69
+ `extro_osint` / `extro_serial` / `extro_telecomm` / `extro_packet` /
70
+ `extro_vision` / `extro_voice` / `extro_intel`) and correlated against those
71
+ failures, an **LLM judge scores the final answer** and a **process reward
72
+ model tags each tool step**, and **all six prompt blocks** (MEMORY · SKILLS ·
73
+ LEARNING · KNOWN MISTAKES/FIXES · TOOL EFFECTIVENESS · EXTROSPECTION) are
74
+ re-injected into the next system prompt.
75
+ Nightly cron practices the top unresolved Mistakes; weekly cron builds a
76
76
  LoRA and only promotes it if it beats the previous adapter on that same
77
77
  mistake set:
78
78
 
@@ -147,11 +147,11 @@ pwn setup [--check] [--deps] [--profile NAME] [--list-profiles]
147
147
 
148
148
  ---
149
149
 
150
- ## Upgrading `~/.pwn` state migration (`PWN::Migrate`)
150
+ ## Upgrading - `~/.pwn` state migration (`PWN::Migrate`)
151
151
 
152
152
  PWN persists a growing set of files under `~/.pwn` (encrypted config,
153
153
  memory, learning, metrics, mistakes, extrospection, cron, agents, skills,
154
- sessions, swarm, curriculum, finetune, ). Each file is owned by a different
154
+ sessions, swarm, curriculum, finetune, ...). Each file is owned by a different
155
155
  module and each release can add keys or change shape. `PWN::Migrate` closes
156
156
  that gap so `gem update pwn` never leaves you with a `KeyError` or a silent
157
157
  empty-fallback.
@@ -185,7 +185,7 @@ Everything is idempotent and dry-run capable. The plain `pwn` launcher also
185
185
  prints a one-line drift warning on startup whenever `~/.pwn/.schema`
186
186
  predates the running gem (`PWN::Migrate.needed?`).
187
187
 
188
- Schema `v1` also seeds `PWN::Cron.install_defaults` the nightly
188
+ Schema `v1` also seeds `PWN::Cron.install_defaults` - the nightly
189
189
  `curriculum_practice` and weekly `curriculum_train` self-improvement jobs
190
190
  (see [Reinforcement Learning](Reinforcement-Learning.md)).
191
191
 
@@ -269,7 +269,7 @@ PWN::Migrate.check # human report + { compatible:[], inco
269
269
  PWN::Migrate.run(fix: true, dry_run:false)# backup → ordered migrations → per-file repair → vault backfill
270
270
  PWN::Migrate.vault_drift # keys env_template has that your pwn.yaml is missing
271
271
  PWN::Migrate.backfill_vault # deep-merge those keys under your values, re-encrypt
272
- PWN::Migrate::STATE_FILES # declarative registry of every ~/.pwn artefact
272
+ PWN::Migrate::STATE_FILES # declarative registry of every ~/.pwn artifact
273
273
  PWN::Migrate::SCHEMA_VERSION # bump when a state file changes shape
274
274
  ```
275
275
 
@@ -12,7 +12,7 @@ once one is found so the avoidance lesson becomes an actionable correction.
12
12
 
13
13
  ## The failure fingerprint
14
14
 
15
- A "mistake" is keyed by `sha12(tool + normalised_error)`. Normalisation strips
15
+ A "mistake" is keyed by `sha12(tool + normalised_error)`. Normalization strips
16
16
  volatile bits - paths, hex addresses, `:LINE`, `port N`, timestamps, UUIDs,
17
17
  PIDs - so `NoMethodError ... at foo.rb:42` and `... at foo.rb:99` collapse to
18
18
  **one** signature and its `:count` climbs. **That count *is* the repeat
@@ -22,7 +22,7 @@ detector**, and it survives across sessions.
22
22
  |---|---|
23
23
  | `signature` | 12-hex-char sha of `(tool, normalised_error)` - stable across runs |
24
24
  | `tool` | component the failure was in (`shell`, `pwn_eval`, `assumption`, `assistant_answer`, a module name...) |
25
- | `error` | normalised error text (paths/lines/addrs/ts stripped) |
25
+ | `error` | normalized error text (paths/lines/addrs/ts stripped) |
26
26
  | `count` | **cross-session** recurrence count - drives `[REPEATING]` at ≥ 3 |
27
27
  | `resolved` / `fix` | set by `mistakes_resolve` - promoted to a `PWN::Memory` `:lesson` |
28
28
  | `regressed` | auto-set when a *resolved* signature recurs - reopened as `[REGRESSED]` |
@@ -104,8 +104,8 @@ upgraded", "the HackRF was unplugged", or "the target DOM moved". See
104
104
 
105
105
  `Mistakes.resolve` writes a DPO preference into `~/.pwn/preferences.jsonl`:
106
106
 
107
- - **rejected** the failing snippet / action
108
- - **chosen** prefers `structured_fix.winning_trace` (+ strategy/tool) when
107
+ - **rejected** - the failing snippet / action
108
+ - **chosen** - prefers `structured_fix.winning_trace` (+ strategy/tool) when
109
109
  present; falls back to `AVOID_ARGS` / fix prose only when no trace exists
110
110
 
111
111
  Curriculum auto-resolve always attaches a winning tool trace so the ledger
@@ -37,34 +37,34 @@ path closes the weight loop; without a trainer the path is **export-ready**
37
37
  Metrics.changepoints (E1 CUSUM) ──► Mistakes(cause: :env_drift)
38
38
  ```
39
39
 
40
- ## Tier 1 Reward signal (`PWN::AI::Agent::Reward`)
40
+ ## Tier 1 - Reward signal (`PWN::AI::Agent::Reward`)
41
41
 
42
42
  | ID | Method | What it does | Beats |
43
43
  |----|--------|-------------|-------|
44
44
  | **R1** | `.judge` | LLM Outcome Reward Model → `{score:0..1, verdict:, rationale:, key_step:}`. Replaces `infer_success` regex. | Reflexion (binary self-eval) |
45
- | **R2** | `.prm` | Process Reward Model per-tool-step `+1/0/−1` written into `Sessions[:step_reward]`. | Lightman '23 (math only) first PRM on security tooling |
46
- | **R3** | `.sentinel` | proxy vs judge vs (1 user_correction_rate); >0.15 gap → `Mistakes.record(tool:'reward_signal')`. | novel |
47
- | **R4** | `.semantic_ok` | `grep exit 1` ≠ failure. `Loop.record_metrics` records Metrics on `:ok`, Mistakes on `!semantic_ok`. Kills phantom `31f1871b8a15`. | bugfix |
45
+ | **R2** | `.prm` | Process Reward Model - per-tool-step `+1/0/-1` written into `Sessions[:step_reward]`. | Lightman '23 (math only) - first PRM on security tooling |
46
+ | **R3** | `.sentinel` | proxy vs judge vs (1 - user_correction_rate); >0.15 gap → `Mistakes.record(tool:'reward_signal')`. | - novel |
47
+ | **R4** | `.semantic_ok` | `grep exit 1` ≠ failure. `Loop.record_metrics` records Metrics on `:ok`, Mistakes on `!semantic_ok`. Kills phantom `31f1871b8a15`. | - bugfix |
48
48
 
49
- ## Tier 2 Credit assignment & replay
49
+ ## Tier 2 - Credit assignment & replay
50
50
 
51
51
  | ID | Where | What |
52
52
  |----|-------|------|
53
53
  | **C1** | `Registry.rank` + `Metrics.{ucb,thompson,advantage}` | score = α·keyword_sim + β·advantage + γ·UCB1. Untried tools get exploration bonus. |
54
- | **C2** | `Learning.exemplars_for` | priority = judge_score × e^(−Δt/30d) × keyword_sim. |
55
- | **C3** | `Curriculum.hindsight` | HER relabel failed trajectory with achieved-goal as `success: 'soft'` + tags `hindsight/her/soft`. Soft rows are excluded from SFT and 0.35×-weighted in C2 exemplars. |
56
- | **C4** | `Learning.{compress_exemplar,build_skill_from_session}` | keep only `step_reward > 0` minimal sufficient trace. |
54
+ | **C2** | `Learning.exemplars_for` | priority = judge_score × e^(t/30d) × keyword_sim. |
55
+ | **C3** | `Curriculum.hindsight` | HER - relabel failed trajectory with achieved-goal as `success: 'soft'` + tags `hindsight/her/soft`. Soft rows are excluded from SFT and 0.35×-weighted in C2 exemplars. |
56
+ | **C4** | `Learning.{compress_exemplar,build_skill_from_session}` | keep only `step_reward > 0` - minimal sufficient trace. |
57
57
 
58
- ## Tier 3 Memory that stays high-signal
58
+ ## Tier 3 - Memory that stays high-signal
59
59
 
60
60
  | ID | Where | What |
61
61
  |----|-------|------|
62
62
  | **M1** | `Learning.consolidate` → `semantic_merge` | embed `:lesson`, greedy cosine ≥0.92, `Reflect.on("merge → 1 imperative")`. |
63
63
  | **M2** | `MemoryIndex.recall_semantic` | score = 0.6·sim + 0.25·recency + 0.15·importance (Park '23). |
64
- | **M3** | `Memory.remember(source:,confidence:,importance:,ttl:)` | consolidate evicts by `(age/ttl)/(importance×confidence)` heuristic garbage self-evicts. |
64
+ | **M3** | `Memory.remember(source:,confidence:,importance:,ttl:)` | consolidate evicts by `(age/ttl)/(importance×confidence)` - heuristic garbage self-evicts. |
65
65
  | **M4** | `Learning.note_outcome` | outcomes → `learning.jsonl` ONLY. Memory `:lesson` reserved for reflect/resolve/human. `purge_noise` GCs pre-R1 garbage. |
66
66
 
67
- ## Tier 4 Curriculum & self-play (`PWN::AI::Agent::Curriculum`)
67
+ ## Tier 4 - Curriculum & self-play (`PWN::AI::Agent::Curriculum`)
68
68
 
69
69
  | ID | Method | What |
70
70
  |----|--------|------|
@@ -73,7 +73,7 @@ path closes the weight loop; without a trainer the path is **export-ready**
73
73
  | **S3** | `.critic` | tool-armed constitutional critic (can `shell`/`extro_verify` the claim). |
74
74
  | **S4** | `.red_team_plan` | adversarial plan review grounded in Metrics/Mistakes/extro_drift telemetry. |
75
75
 
76
- ## Tier 5 Close the weight loop
76
+ ## Tier 5 - Close the weight loop
77
77
 
78
78
  | ID | Where | What |
79
79
  |----|-------|------|
@@ -81,7 +81,7 @@ path closes the weight loop; without a trainer the path is **export-ready**
81
81
  | **W2** | `Curriculum.train_and_gate` | SFT+DPO → unsloth/axolotl LoRA → `ollama create pwn-vN+1` → **gate v2** (resolved margin + mean judge + smoke). **Without a trainer: export-only** (`weight_loop: :export_ready`). |
82
82
  | **W3** | `Curriculum.calibrate` + `Metrics.{record_calibration,calibration}` | plan_first `p(success)` vs actual → per-engine Brier/overconfidence. |
83
83
 
84
- ## Tier 6 Deepen the intro↔extro join
84
+ ## Tier 6 - Deepen the intro↔extro join
85
85
 
86
86
  | ID | Where | What |
87
87
  |----|-------|------|
@@ -95,11 +95,11 @@ path closes the weight loop; without a trainer the path is **export-ready**
95
95
  :ai:
96
96
  :module_reflection: false # gates Reflect lesson writing (not ORM alone)
97
97
  :agent:
98
- :critic: null # S3 nil = ON for remote engines, OFF for ollama
99
- :red_team_plan: null # S4 same auto policy
100
- :counterfactual: null # S2 same auto policy
98
+ :critic: null # S3 - nil = ON for remote engines, OFF for ollama
99
+ :red_team_plan: null # S4 - same auto policy
100
+ :counterfactual: null # S2 - same auto policy
101
101
  :hindsight: true # C3 (default true; soft-success, 0.35× in C2)
102
- :verify_as_reward: null # E3 nil = auto (~10% local / always remote on CLAIM_RX)
102
+ :verify_as_reward: null # E3 - nil = auto (~10% local / always remote on CLAIM_RX)
103
103
  :reward_llm: null # nil = ORM/PRM use LLM teacher on remote even if module_reflection is false
104
104
  :local_introspect: :failure_only # ollama cost policy; remote always introspects
105
105
  :introspect_every_n: 3
@@ -124,7 +124,7 @@ PWN::Cron.install_defaults
124
124
  `curriculum_hindsight` · `curriculum_offline_judge` ·
125
125
  `curriculum_preference_balance` · `learning_purge_noise`
126
126
 
127
- ## Design claims (architecture weight promotion requires a trainer)
127
+ ## Design claims (architecture - weight promotion requires a trainer)
128
128
 
129
129
  1. **Process reward on real security tool traces** (R2)
130
130
  2. **Automatic blame attribution** self vs env-drift via CUSUM×correlate (E1+E2)
@@ -140,18 +140,18 @@ PWN::Cron.install_defaults
140
140
  | **P1** | `Curriculum.practice` cooldown + natural prompts | Hard-skips `reward_signal` / parked / `needs_code_change`; N-night zero-score cooldown parks thrash; reproducers are natural user tasks, never signature dumps. |
141
141
  | **P2** | R4 `semantic_ok` + structured resolve | `31f1871b8a15`-class exit≠0 phantoms stay closed via structured holdouts. |
142
142
  | **P3** | `Curriculum.offline_judge` | Scores last-24h sessions under ORM/PRM so local `:failure_only` introspect does not starve labels. Cron nightly. |
143
- | **P4** | `Reward.proxy_distrust` | When sentinel fires, Metrics.to_context / Registry.rank haircut proxy rates actionable, not just another Mistakes row. |
143
+ | **P4** | `Reward.proxy_distrust` | When sentinel fires, Metrics.to_context / Registry.rank haircut proxy rates - actionable, not just another Mistakes row. |
144
144
  | **R3** | `Reward.sentinel` ring buffer | Fixed-N (`SENTINEL_WINDOW=40`) `{judge,proxy}` window replaces decaying `proxy_sum`/`proxy_n`. Means are always ∈[0,1]; `set_proxy_distrust` refuses proxy∉[0,1]; `reset_sentinel` wipes corrupt state without touching prefs. Legacy decay×`to_i` files auto-clear stuck distrust on load. |
145
145
  | **P5** | `Curriculum.preference_balance` + `export_dpo` source-cap | Surfaces W1 monoculture **and enforces** ≤40% per source at export (`DPO_SOURCE_CAP`); critic/counterfactual auto-ON for remote engines so the diet rebalances online. |
146
146
  | **P6** | W2 honesty | Docs + `train_and_gate` return `weight_loop: :export_ready` when `trainer: null`. |
147
147
  | **P7** | W3 as controller | Engine Brier > 0.35 or overconfidence > 0.25 (n≥8) → force plan_first + critic, cap max_iters at 12. `offline_judge` also records calibration from PLAN `p(success)=` so the controller can fire under `:failure_only`. |
148
- | **P8** | Remote reward teacher | `agent.reward_llm` nil → ORM/PRM use the LLM teacher on remote engines even when `module_reflection` is false. Local ollama stays heuristic unless explicitly enabled. PRM prompts carry R4 tags so benign recon exits score 0 not 1. |
148
+ | **P8** | Remote reward teacher | `agent.reward_llm` nil → ORM/PRM use the LLM teacher on remote engines even when `module_reflection` is false. Local ollama stays heuristic unless explicitly enabled. PRM prompts carry R4 tags so benign recon exits score 0 not -1. |
149
149
  | **P9** | W1 pair geometry + write-time quota | Critic chosen = **revised full answer** (not `CORRECTION:` flaw prose). Resolve prefers `structured_fix.winning_trace`. Counterfactual tags `:real_dispatch` vs `:imagined`. `record_preference` enforces `WRITE_SOURCE_CAP=0.40` online (trajectory shapes force-land). |
150
150
  | **P10** | `Reward.warm_sentinel` | Backfills R3 ring from scored Learning outcomes so local `:failure_only` hosts reach `SENTINEL_WINDOW` without waiting for live remote introspect. `offline_judge` calls it every night. |
151
151
  | **P11** | W2 gate v2 | Promote only when candidate wins on resolved margin **and** mean judge **and** frozen smoke set (uname/pwd/ruby) does not regress. Coarse `resolved(N+1)>resolved(N)` alone cannot self-promote eval memorisation. |
152
152
  | **P12** | SFT quality gate | `export_finetune` drops HER/soft + score&lt;`SFT_MIN_SCORE` (0.6), de-dupes per session by best score, PRM-compresses traces (`compress_finetune_trace`). |
153
153
  | **P13** | Cron offline_judge dedupe | `install_defaults` treats `offline_judge_nightly` as alias of `curriculum_offline_judge` and disables duplicates so the 30 3 * * * slot runs once. |
154
- | **P14** | Practice → DPO geometry | `Curriculum.practice` records `chosen: winning_trace` (+ final), `shape: :winning_trace` never first-3-lines fix prose. |
154
+ | **P14** | Practice → DPO geometry | `Curriculum.practice` records `chosen: winning_trace` (+ final), `shape: :winning_trace` - never first-3-lines fix prose. |
155
155
  | **P15** | Ledger hygiene | `Reward.usable_preference?` / `scrub_preferences` / geometry filter in `export_dpo` drop `CORRECTION:` prose, resolve-without-trace, and chosen≪rejected. `preference_balance(scrub:true)` reports `trajectory_fraction`. |
156
156
  | **P16** | R3 warm for real | `warm_sentinel` fills from scored **and** success-boolean outcomes, returns `proxy_distrust`, runs `sentinel` once full so controllers can engage. |
157
157
  | **P17** | Budget-exhaustion skill | Practice prioritises `agent_loop`/`assistant_answer`; natural prompts teach finish-under-N; Loop hard-stops empty-final thrash and tightens max_iters when budget fingerprints dominate. |
@@ -161,7 +161,7 @@ PWN::Cron.install_defaults
161
161
  | **P21** | Resolve trajectory-only | `Mistakes.resolve` writes W1 only when `structured_fix.winning_trace` ≥40 chars (`shape: :winning_trace`). Prose-only resolve still updates Memory + structured_fix; it does **not** flood DPO. |
162
162
  | **P22** | W3 calibration live | `Loop.plan_first` stashes `p(success)=` on `Thread.current[:pwn_plan_predicted]`; `Learning.recover_predicted_from_session` + `Curriculum.calibrate` light the Brier/overconfidence controller under `:failure_only`. |
163
163
  | **P23** | Short-horizon budget practice | Budget-exhaustion fingerprints get natural "finish under N" prompts; practice auto-resolve requires N≥2 holdouts at judge≥0.7 **and** a real winning_trace (no long-prose resolve). |
164
- | **P24** | Critic cost under budget-hot | When `budget_exhaustion_hot?`, `auto_introspect` forces `critic(text_only: true)` single Reflect/heuristic shot, no tool-armed persona swarm that burns the remaining iteration budget. |
164
+ | **P24** | Critic cost under budget-hot | When `budget_exhaustion_hot?`, `auto_introspect` forces `critic(text_only: true)` - single Reflect/heuristic shot, no tool-armed persona swarm that burns the remaining iteration budget. |
165
165
  | **P25** | Write-time trajectory gate | `Reward.record_preference` refuses non-`TRAJECTORY_SHAPES` unless `force:` / `user_correction`. Write-time source quota **still** applies to trajectory pairs so winning_trace cannot re-monoculture the ledger. |
166
166
 
167
167
  ## Preference / trajectory signal quality (current ops posture)
@@ -180,7 +180,7 @@ and source diversity, not missing tiers:
180
180
  8. Resolve/record_preference are trajectory-only at write time (P21/P25); write-time source quota still caps traj monoculture.
181
181
  9. Without unsloth/axolotl **or** a clean preference diet, `train_and_gate` stays `weight_loop: :export_ready` (honest).
182
182
 
183
- ## Design-priority STATUS (post P14P25)
183
+ ## Design-priority STATUS (post P14-P25)
184
184
 
185
185
  Collapse of the review-driven priority order into a living table. Stop minting new P-numbers for chores already covered; track these outcomes instead.
186
186
 
data/documentation/SDR.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  | Module | Purpose |
12
12
  |---|---|
13
- | **`GQRX`** | Remote-control a running GQRX instance over TCP: tune, set demod, squelch, record, `get_spectrum_snapshot` (pure-Ruby FFT - median NF, relative peak/prominence, **plan-parametric** min-distance & 6 dB BW), `fast_scan_range` (**always RAW @ sample_rate** panoramic capture; band-plan IF deferred to refine/decoder; `#fft_plan_geometry` derives sep/merge/refine/snap from `(plan_bw, step, res)`; local-FFT refine + S-meter confirm; schema-parity with `scan_range`) |
13
+ | **`GQRX`** | Remote-control a running GQRX instance over TCP: tune, set demod, squelch, record, `get_spectrum_snapshot` (pure-Ruby FFT - median NF, relative peak/prominence, **plan-parametric** min-distance & -6 dB BW), `fast_scan_range` (**always RAW @ sample_rate** panoramic capture; band-plan IF deferred to refine/decoder; `#fft_plan_geometry` derives sep/merge/refine/snap from `(plan_bw, step, res)`; local-FFT refine + S-meter confirm; schema-parity with `scan_range`) |
14
14
  | `FlipperZero` | Serial control of Flipper (sub-GHz, NFC, IR, iButton) |
15
15
  | `RFIDler` | 125 kHz RFID reader/emulator |
16
16
  | `SonMicroRFID` | SM130 13.56 MHz reader |
@@ -20,7 +20,7 @@
20
20
  ## CLI
21
21
 
22
22
  ```bash
23
- # FFT sweep - plan-parametric peak geometry + local-FFT refine for exact centres
23
+ # FFT sweep - plan-parametric peak geometry + local-FFT refine for exact centers
24
24
  # Works for ALL band plans (CW 150 Hz → FLEX 20 kHz → FM 200 kHz → GPS 30 MHz)
25
25
  pwn_gqrx_scanner -a pager_flex --fft-scan # alias: flex_pager
26
26
  pwn_gqrx_scanner -a fm_radio --fft-scan --min-snr-db 18
@@ -46,8 +46,8 @@ invariants already on each plan (`bandwidth` → `plan_bw_hz`, `precision` →
46
46
  | Capture IF | **Always** `M RAW sample_rate` (IQRECORD is demod IF - never plan FM/20 kHz) |
47
47
  | Peak height / prom | Relative: `median_nf + 12 dB`, prom ≥ 8 dB |
48
48
  | Peak min-distance | `#fft_plan_geometry` → `sep_hz = max(0.5·plan, step, floor)` |
49
- | Occupied BW | 6 dB-from-peak contour, hard-capped to `± plan_bw` |
50
- | Center | Power-weighted centroid of 6 dB lobe → raster snap |
49
+ | Occupied BW | -6 dB-from-peak contour, hard-capped to `± plan_bw` |
50
+ | Center | Power-weighted centroid of -6 dB lobe → raster snap |
51
51
  | Merge | `tol = max(½ plan, step, ½ measured_bw, 2·res)` |
52
52
  | Refine window | ~0.6·plan (capped so next neighbour is outside); local high-res FFT |
53
53
  | Strength lock | Auto from live S-meter NF + 8 dB unless `-S` given |
@@ -9,10 +9,10 @@ appended as JSON-per-line to `~/.pwn/sessions/<id>.jsonl`.
9
9
 
10
10
  - `learning_reflect(session_id:)` mines them for durable lessons → Memory.
11
11
  - `learning_distill_skill(name:, session_id:)` turns a winning run into a
12
- reusable Skill (only steps with `step_reward > 0` are kept the minimal
12
+ reusable Skill (only steps with `step_reward > 0` are kept - the minimal
13
13
  sufficient trace).
14
14
  - `Reward.prm(request:, session_id:)` back-labels every tool step in the
15
- transcript with `step_reward: +1/0/−1` for credit assignment.
15
+ transcript with `step_reward: +1/0/-1` for credit assignment.
16
16
  - `Reward.judge(request:, final:, session_id:)` grades the whole run.
17
17
  - `sessions_view` lets you (or a later agent) re-read exactly what happened.
18
18
  - Swarm maps each persona to its own session so its private context survives
@@ -41,7 +41,7 @@ its own performance, turns wins into permanent capability, and - critically -
41
41
  9. Found a fix for a mistake → mistakes_resolve(sig, fix) → Memory :lesson "AVOID X - FIX: Y"
42
42
  10. (weekly, cron) Learning.export_finetune (P12: min_score + PRM-compress) +
43
43
  Reward.export_dpo (≤40%/src, P15 geometry scrub) → ~/.pwn/finetune/*.jsonl → LoRA over the local
44
- model via Curriculum.train_and_gate (P11 gate v2) the ONLY step that
44
+ model via Curriculum.train_and_gate (P11 gate v2) - the ONLY step that
45
45
  changes weights, not just the scaffold. Without a trainer this stays export-ready.
46
46
  11. Next launch: PromptBuilder injects the budgeted blocks → the model already knows:
47
47
  MEMORY · SKILLS · LEARNING · KNOWN MISTAKES/FIXES · TOOL EFFECTIVENESS · EXTROSPECTION
@@ -48,7 +48,7 @@ fallback) as its **web sense organ** - the counterpart to `probe_rf`'s ears:
48
48
  | `extro_verify(claim:, kind:)` | **Proactive self fact-check** - render NVD/CVE.org, rubygems/PyPI, a cited URL, or DuckDuckGo HTML and return `:confirmed` / `:refuted` / `:unknown`. `:refuted` → `Mistakes.record(tool:'assumption', ...)` |
49
49
  | `revalidate_memory` (cron) | Garbage-collect stale `PWN::Memory` `:fact` entries by re-`verify()`ing every one containing a CVE / version / URL |
50
50
 
51
- All four honour `proxy:` (Burp / `tor`) so attribution stays controlled, reuse
51
+ All four honor `proxy:` (Burp / `tor`) so attribution stays controlled, reuse
52
52
  **one** browser handle across anchors, and `close` in an `ensure`. See
53
53
  [Extrospection](Extrospection.md) for the full loop.
54
54
 
@@ -20,7 +20,7 @@ $ pwn setup --deps --dry-run # show the apt/dnf/pacman/brew/port commands wi
20
20
  See [Installation](Installation.md#pwn-setup--the-post-install-doctor--provisioner)
21
21
  for the full profile table and `PWN::Setup` API.
22
22
 
23
- ## `[pwn] ~/.pwn schema is stale run pwn setup --migrate` on launch
23
+ ## `[pwn] ~/.pwn schema is stale - run pwn setup --migrate` on launch
24
24
 
25
25
  Your `~/.pwn` state files were written by an older PWN release than the one
26
26
  now running. The launcher checks `PWN::Migrate.needed?` on every start.
@@ -39,7 +39,7 @@ your encrypted `~/.pwn/pwn.yaml` **under** your existing values. See
39
39
 
40
40
  ## `KeyError` / `NoMethodError for nil` reading memory / metrics / mistakes / cron / agents
41
41
 
42
- Same cause the on-disk shape predates the current loader.
42
+ Same cause - the on-disk shape predates the current loader.
43
43
  `pwn setup --migrate --fix` will quarantine or repair the offending file
44
44
  and re-seed a valid one on next write.
45
45
 
@@ -1,20 +1,18 @@
1
1
  # What is PWN
2
2
 
3
- **PWN** (pronounced /pōn/ - "pone") is an open-source **offensive-security
4
- automation framework** and **continuous-security-integration** platform,
5
- distributed as a Ruby gem.
3
+ **PWN** (pronounced /pon/ - "pone") is an open-source **offensive security
4
+ automation** framework, shipped as a Ruby gem.
6
5
 
7
- It gives security researchers, red teamers, bug-bounty hunters and DevSecOps
8
- engineers a single, scriptable surface over the entire offensive toolchain -
9
- from OSINT and network discovery, through web/cloud/hardware/radio
10
- exploitation, to reporting and disclosure - and puts a **self-improving,
11
- tool-calling AI agent** on top of it.
6
+ It gives security researchers, red teamers, bug-bounty hunters, and DevSecOps
7
+ engineers one scriptable surface over the offensive toolchain - OSINT and
8
+ network discovery, web/cloud/hardware/radio work, reporting, and disclosure -
9
+ with a **tool-calling AI agent** on top that can run the same methods.
12
10
 
13
11
  ## In numbers
14
12
 
15
13
  | Namespace | Count | What it is |
16
14
  |---|---|---|
17
- | `PWN::Plugins::*` | **66** | Wrappers for external + native tooling (Burp, Nmap, Metasploit, Shodan, browsers, serial, ...) |
15
+ | `PWN::Plugins::*` | **66** | Wrappers for external and native tooling (Burp, Nmap, Metasploit, Shodan, browsers, serial, ...) |
18
16
  | `PWN::SAST::*` | **48** | Static-analysis rules across C/Java/Go/Python/Ruby/Scala/PHP/TS |
19
17
  | `PWN::AWS::*` | **90** | One module per AWS service for cloud enumeration |
20
18
  | `PWN::WWW::*` | **21** | Site-specific browser automations (HackerOne, BugCrowd, Google, LinkedIn, ...) |
@@ -24,32 +22,32 @@ tool-calling AI agent** on top of it.
24
22
  | `bin/pwn_*` | **53** | Headless CLI drivers for CI/CD |
25
23
  | Agent toolsets | **12** · **78 tools** | terminal · pwn · memory · skills · sessions · learning · metrics · extrospection · cron · swarm |
26
24
 
27
- ## The three ways to use it
25
+ ## Three ways to use it
28
26
 
29
- 1. **`pwn` REPL** - a Pry shell with the whole `PWN::` namespace pre-loaded.
30
- Prototype an attack chain interactively, one method call at a time.
27
+ 1. **`pwn` REPL** - a Pry shell with the whole `PWN::` namespace loaded.
28
+ Prototype an attack chain one method call at a time.
31
29
  2. **`pwn-ai`** - a natural-language TUI (or `pwn --ai "..."` one-shot) where an
32
- LLM plans and executes those same method calls for you, records what
33
- worked, and gets better at it.
30
+ LLM plans and runs those same method calls, records what worked, and
31
+ improves over time.
34
32
  3. **`bin/pwn_*` drivers** - thin CLIs over the plugins, for cron and CI/CD.
35
33
 
36
34
  ## What makes it different
37
35
 
38
- - **Everything is Ruby, everything is a method.** No YAML DSLs, no plugins-in-a-
39
- black-box. If you can call it in the REPL, the AI agent can call it, a driver
36
+ - **Everything is Ruby, everything is a method.** No YAML DSLs, no black-box
37
+ plugins. If you can call it in the REPL, the AI agent can call it, a driver
40
38
  can call it, and a cron job can call it.
41
- - **Closed self-improvement loop.** Metrics + Learning + **Reward** (ORM/PRM
42
- judge, sentinel) + **Curriculum** (mistake-driven self-play, HER,
43
- regression-gated LoRA) on the introspection side; Snapshot + Drift + Intel
44
- + Verify on the extrospection side; joined by `extro_correlate`, which
45
- tells the agent whether a failure was *its* fault or *the world* changed -
46
- and writes the lesson back into the prompt for next time.
39
+ - **Closed feedback loop.** Metrics + Learning + **Reward** (ORM/PRM judge,
40
+ sentinel) + **Curriculum** (mistake-driven self-play, HER, regression-gated
41
+ LoRA) on the introspection side; Snapshot + Drift + Intel + Verify on the
42
+ extrospection side; joined by `extro_correlate`, which tells the agent
43
+ whether a failure was *its* fault or *the world* changed - and writes the
44
+ lesson back into the next prompt.
47
45
  - **Native multi-agent.** `PWN::AI::Agent::Swarm` runs personas (each a full
48
46
  tool-calling agent, optionally on a *different* LLM engine) that debate,
49
- broadcast and share an append-only bus - no IRC daemon, no external service.
47
+ broadcast, and share an append-only bus - no IRC daemon, no external service.
50
48
  - **Self-healing state.** `PWN::Setup` (doctor/provisioner) + `PWN::Migrate`
51
49
  (schema-stamped `~/.pwn` verifier/auto-migrator) make `gem install pwn` →
52
- `pwn setup` the entire install *and* upgrade story on every OS.
50
+ `pwn setup` the full install and upgrade path on every supported OS.
53
51
 
54
52
  ![Overall Architecture](diagrams/overall-pwn-architecture.svg)
55
53
 
@@ -2,20 +2,20 @@
2
2
 
3
3
  ## The problem
4
4
 
5
- Offensive security is a **toolchain problem**. A single engagement touches
5
+ Offensive security is a **toolchain problem**. One engagement may touch
6
6
  `nmap`, `burp`, `msfconsole`, a headless browser, `adb`, `gqrx`, three cloud
7
7
  consoles, a fuzzer, `radare2`, a spreadsheet of findings, and a bug-bounty
8
- submission form. Each tool has its own config, its own output format, and its
9
- own idea of what a "target" is. Gluing them together is 80 % of the job - and
10
- that glue is rewritten, badly, on every engagement.
8
+ form. Each tool has its own config, its own output format, and its own idea
9
+ of what a "target" is. Gluing them together is most of the job - and that
10
+ glue gets rewritten, badly, on every engagement.
11
11
 
12
- Meanwhile, LLM agents are extraordinary at *planning* attack chains but have no
13
- reliable, auditable way to *execute* them against a real host.
12
+ LLM agents are strong at *planning* attack chains, but they still need a
13
+ reliable, auditable way to *run* those steps on a real host.
14
14
 
15
15
  ## The design bet
16
16
 
17
17
  PWN bets that the right abstraction is **plain Ruby methods with a uniform
18
- `opts = {}` signature**, exposed simultaneously to:
18
+ `opts = {}` signature**, exposed at the same time to:
19
19
 
20
20
  - a human in a REPL,
21
21
  - an LLM in a tool-calling loop,
@@ -23,8 +23,8 @@ PWN bets that the right abstraction is **plain Ruby methods with a uniform
23
23
  - a cron job at 3 am.
24
24
 
25
25
  Because every capability is a method, the same line of code works in all four
26
- contexts. Because every method is open-source Ruby, it's auditable - critical
27
- when the caller is an autonomous agent.
26
+ places. Because every method is open-source Ruby, you can read it - which is
27
+ critical when the caller is an autonomous agent.
28
28
 
29
29
  ## Why open primitives matter
30
30
 
@@ -35,13 +35,14 @@ when the caller is an autonomous agent.
35
35
  | Agent output is a PDF | Agent output is a `PWN::Reports` object *and* a distilled skill *and* a memory entry |
36
36
  | One vendor's model | Five interchangeable engines; swarm can pit them against each other |
37
37
 
38
- ## Why the self-improvement loop matters
38
+ ## Why the feedback loop matters
39
39
 
40
- A pentest framework that doesn't learn repeats the same dead-end scans forever.
41
- PWN records **per-tool success rate**, **per-task outcome**, **host drift**,
42
- and **external CVE intel**, then correlates them so tomorrow's run starts where
43
- today's finished. See [Skills, Memory & Learning](Skills-Memory-Learning.md),
44
- [Reinforcement Learning](Reinforcement-Learning.md) and
40
+ A pentest framework that does not learn repeats the same dead-end scans
41
+ forever. PWN records **per-tool success rate**, **per-task outcome**, **host
42
+ drift**, and **external CVE intel**, then correlates them so tomorrow's run
43
+ can start where today's left off. See
44
+ [Skills, Memory & Learning](Skills-Memory-Learning.md),
45
+ [Reinforcement Learning](Reinforcement-Learning.md), and
45
46
  [Extrospection](Extrospection.md).
46
47
 
47
48
  **Next:** [How PWN Works](How-PWN-Works.md)
@@ -41,14 +41,14 @@ commands.
41
41
  | Keystroke | Works on | Notes |
42
42
  |---|---|---|
43
43
  | **SHIFT + ENTER** | kitty · wezterm · foot · alacritty · ghostty · xterm · Konsole · iTerm2 · Windows Terminal · Terminator¹ | preferred; requires the emulator to encode modified Enter |
44
- | **ALT + ENTER** | *everything*, incl. all VTE terminals | universal fallback every emulator sends `\e\r` |
44
+ | **ALT + ENTER** | *everything*, incl. all VTE terminals | universal fallback - every emulator sends `\e\r` |
45
45
  | trailing **`\`** + ENTER | *everything* | bash/irb/psql-style continuation; `\` is stripped on submit |
46
46
 
47
- ¹ Terminator (and every other libvte host GNOME Terminal, Tilix,
47
+ ¹ Terminator (and every other libvte host - GNOME Terminal, Tilix,
48
48
  xfce4-terminal, Guake, Ptyxis) cannot distinguish SHIFT+ENTER from
49
49
  ENTER at the escape-sequence level ([GNOME/vte #2601](https://gitlab.gnome.org/GNOME/vte/-/issues/2601),
50
50
  [#2607](https://gitlab.gnome.org/GNOME/vte/-/issues/2607)). For
51
- Terminator specifically, pwn ships a GTK plugin that fixes it install
51
+ Terminator specifically, pwn ships a GTK plugin that fixes it - install
52
52
  with:
53
53
 
54
54
  ```console
@@ -72,7 +72,7 @@ $ pwn --ai "run bin/pwn_sast against ./src and push findings to DefectDojo"
72
72
  by `Curriculum.hindsight`; `Reflect.on` writes durable lessons via
73
73
  `ai.reflect_engine` (teacher-student - a frontier engine may author the
74
74
  lesson a local engine reads); `Reward.sentinel` warns when success_rate ≠
75
- judge_mean ≠ (1 user_correction_rate); when `auto_extrospect` is also on,
75
+ judge_mean ≠ (1 - user_correction_rate); when `auto_extrospect` is also on,
76
76
  `Extrospection.auto_extrospect` runs (`AUTO_SECTIONS = host/repo/env` only -
77
77
  never toolchain/rf/web, never launches Burp/ZAP/msf/gqrx). Transcript is
78
78
  flushed to `~/.pwn/sessions/`.
@@ -118,7 +118,7 @@ full `Loop.run` under a persona overlay) that share a JSONL bus. See
118
118
  local.
119
119
  - `PWN::AI::Agent::Learning.export_finetune` + `Reward.export_dpo` turn every
120
120
  successful session and every preference pair into supervised / DPO
121
- datasets under `~/.pwn/finetune/` `Curriculum.train_and_gate` then
121
+ datasets under `~/.pwn/finetune/` - `Curriculum.train_and_gate` then
122
122
  LoRA-tunes the local model and promotes only under **gate v2** (resolved
123
123
  margin + mean judge + frozen smoke set). Preference pairs use trajectory
124
124
  geometry (P9/P14/P15): revised answers / winning traces, not `CORRECTION:` prose; `scrub_preferences` + export filter; practice lands `shape: :winning_trace`.
data/lib/pwn/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.5.651'
4
+ VERSION = '0.5.652'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.651
4
+ version: 0.5.652
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.