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 +4 -4
- data/README.md +41 -30
- data/documentation/AI-Integration.md +1 -1
- data/documentation/Configuration.md +2 -2
- data/documentation/Cron.md +5 -5
- data/documentation/Extrospection.md +5 -5
- data/documentation/General-PWN-Usage.md +1 -1
- data/documentation/Home.md +1 -2
- data/documentation/How-PWN-Works.md +13 -13
- data/documentation/Installation.md +4 -4
- data/documentation/Mistakes.md +4 -4
- data/documentation/Reinforcement-Learning.md +23 -23
- data/documentation/SDR.md +4 -4
- data/documentation/Sessions.md +2 -2
- data/documentation/Skills-Memory-Learning.md +1 -1
- data/documentation/Transparent-Browser.md +1 -1
- data/documentation/Troubleshooting.md +2 -2
- data/documentation/What-is-PWN.md +22 -24
- data/documentation/Why-PWN.md +16 -15
- data/documentation/pwn-REPL.md +3 -3
- data/documentation/pwn-ai-Agent.md +2 -2
- data/lib/pwn/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6fd0197b1fa729406ea99bbe598d3730d27e3c6881251c374af0f894ea541729
|
|
4
|
+
data.tar.gz: 492617f851780cf17c04fcdecdd4eb491e54b2bcf115b04997f3972507528d3a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
28
|
-
automation
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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 ·
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
60
|
+
PWN is five layers. Dependencies only point downward, so each level stays
|
|
61
|
+
small and easy to swap:
|
|
54
62
|
|
|
55
63
|

|
|
56
64
|
|
|
57
|
-
|
|
58
|
-
Learning
|
|
59
|
-
Snapshot
|
|
60
|
-
|
|
61
|
-
|
|
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
|

|
|
64
74
|
|
|
65
|
-
Failures are fingerprinted
|
|
66
|
-
`[REPEATING]` / `[REGRESSED]`, and
|
|
67
|
-
|
|
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
|

|
|
70
80
|
|
|
71
|
-
|
|
72
|
-
optionally on a *different* LLM engine
|
|
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
|

|
|
75
86
|
|
|
76
87
|
Full pages: [How PWN Works](documentation/How-PWN-Works.md) ·
|
|
77
|
-
[All
|
|
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
|
|
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
|
|
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
|
-
|
|
210
|
-
|
|
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
|
|
226
|
+
If this project helped you and you want to support the work, keep us caffeinated:
|
|
216
227
|
|
|
217
228
|
[](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
|
|
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
|

|
|
@@ -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`
|
|
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
|
|
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`). |
|
data/documentation/Cron.md
CHANGED
|
@@ -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**
|
|
40
|
-
- **offline_judge**
|
|
41
|
-
- **dedupe (P13)**
|
|
42
|
-
- **train**
|
|
43
|
-
- **consolidate**
|
|
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
|
|
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
|
|
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 >
|
|
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
|
-
- "
|
|
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 /
|
|
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` |
|
data/documentation/Home.md
CHANGED
|
@@ -76,5 +76,4 @@
|
|
|
76
76
|
|
|
77
77
|
---
|
|
78
78
|
|
|
79
|
-
<sub>
|
|
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
|
|
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
|
|
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
|

|
|
59
59
|
|
|
60
|
-
See [Persistence](Persistence.md) for the
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
`
|
|
70
|
-
`
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
Nightly cron
|
|
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
|
|
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,
|
|
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`
|
|
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
|
|
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
|
|
data/documentation/Mistakes.md
CHANGED
|
@@ -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)`.
|
|
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` |
|
|
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**
|
|
108
|
-
- **chosen**
|
|
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
|
|
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
|
|
46
|
-
| **R3** | `.sentinel` | proxy vs judge vs (1
|
|
47
|
-
| **R4** | `.semantic_ok` | `grep exit 1` ≠ failure. `Loop.record_metrics` records Metrics on `:ok`, Mistakes on `!semantic_ok`. Kills phantom `31f1871b8a15`. |
|
|
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
|
|
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^(
|
|
55
|
-
| **C3** | `Curriculum.hindsight` | HER
|
|
56
|
-
| **C4** | `Learning.{compress_exemplar,build_skill_from_session}` | keep only `step_reward > 0`
|
|
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
|
|
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)`
|
|
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
|
|
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
|
|
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
|
|
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
|
|
99
|
-
:red_team_plan: null # S4
|
|
100
|
-
:counterfactual: null # S2
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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<`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`
|
|
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)`
|
|
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 P14
|
|
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 &
|
|
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
|
|
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 |
|
|
50
|
-
| Center | Power-weighted centroid of
|
|
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 |
|
data/documentation/Sessions.md
CHANGED
|
@@ -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
|
|
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
|
|
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)
|
|
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
|
|
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
|
|
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
|
|
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 /
|
|
4
|
-
automation framework
|
|
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
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
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
|
-
##
|
|
25
|
+
## Three ways to use it
|
|
28
26
|
|
|
29
|
-
1. **`pwn` REPL** - a Pry shell with the whole `PWN::` namespace
|
|
30
|
-
Prototype an attack chain
|
|
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
|
|
33
|
-
|
|
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
|
|
39
|
-
|
|
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
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
50
|
+
`pwn setup` the full install and upgrade path on every supported OS.
|
|
53
51
|
|
|
54
52
|

|
|
55
53
|
|
data/documentation/Why-PWN.md
CHANGED
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## The problem
|
|
4
4
|
|
|
5
|
-
Offensive security is a **toolchain problem**.
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
13
|
-
reliable, auditable way to *
|
|
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
|
|
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
|
-
|
|
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
|
|
38
|
+
## Why the feedback loop matters
|
|
39
39
|
|
|
40
|
-
A pentest framework that
|
|
41
|
-
PWN records **per-tool success rate**, **per-task outcome**, **host
|
|
42
|
-
and **external CVE intel**, then correlates them so tomorrow's run
|
|
43
|
-
today's
|
|
44
|
-
[
|
|
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)
|
data/documentation/pwn-REPL.md
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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/`
|
|
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