pwn 0.5.628 → 0.5.631

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +44 -36
  3. data/bin/pwn +35 -1
  4. data/bin/pwn_setup +64 -0
  5. data/documentation/AI-Integration.md +50 -11
  6. data/documentation/AWS.md +3 -3
  7. data/documentation/Agent-Tool-Registry.md +24 -0
  8. data/documentation/Banner.md +1 -1
  9. data/documentation/Blockchain.md +3 -3
  10. data/documentation/Bounty.md +4 -4
  11. data/documentation/BurpSuite.md +5 -2
  12. data/documentation/CLI-Drivers.md +29 -12
  13. data/documentation/Configuration.md +92 -65
  14. data/documentation/Contributing.md +14 -4
  15. data/documentation/Cron.md +5 -5
  16. data/documentation/Diagrams.md +4 -4
  17. data/documentation/Drivers.md +4 -4
  18. data/documentation/Extrospection.md +162 -152
  19. data/documentation/FFI.md +61 -24
  20. data/documentation/Fuzzing.md +4 -1
  21. data/documentation/General-PWN-Usage.md +13 -1
  22. data/documentation/Hardware.md +11 -7
  23. data/documentation/Home.md +9 -9
  24. data/documentation/How-PWN-Works.md +13 -12
  25. data/documentation/Installation.md +201 -37
  26. data/documentation/Metasploit.md +7 -4
  27. data/documentation/Mistakes.md +22 -22
  28. data/documentation/NmapIt.md +3 -0
  29. data/documentation/Persistence.md +8 -5
  30. data/documentation/Plugins.md +11 -11
  31. data/documentation/Reporting.md +5 -2
  32. data/documentation/SAST.md +1 -1
  33. data/documentation/SDR.md +55 -17
  34. data/documentation/Sessions.md +5 -5
  35. data/documentation/Skills-Memory-Learning.md +82 -69
  36. data/documentation/Swarm.md +26 -6
  37. data/documentation/Transparent-Browser.md +11 -8
  38. data/documentation/Troubleshooting.md +66 -10
  39. data/documentation/WWW.md +2 -2
  40. data/documentation/What-is-PWN.md +11 -11
  41. data/documentation/Why-PWN.md +4 -4
  42. data/documentation/diagrams/agent-tool-registry.svg +120 -109
  43. data/documentation/diagrams/ai-integration-tool-calling.svg +76 -65
  44. data/documentation/diagrams/aws-cloud-security.svg +1 -1
  45. data/documentation/diagrams/burp-vs-zap-preference.svg +27 -27
  46. data/documentation/diagrams/code-scanning-sast.svg +1 -1
  47. data/documentation/diagrams/cron-scheduling.svg +1 -1
  48. data/documentation/diagrams/dot/_THEME.md +1 -1
  49. data/documentation/diagrams/dot/agent-tool-registry.dot +6 -4
  50. data/documentation/diagrams/dot/ai-integration-tool-calling.dot +4 -3
  51. data/documentation/diagrams/dot/aws-cloud-security.dot +1 -1
  52. data/documentation/diagrams/dot/burp-vs-zap-preference.dot +1 -1
  53. data/documentation/diagrams/dot/code-scanning-sast.dot +1 -1
  54. data/documentation/diagrams/dot/cron-scheduling.dot +1 -1
  55. data/documentation/diagrams/dot/driver-framework.dot +1 -1
  56. data/documentation/diagrams/dot/extrospection-world-awareness.dot +1 -1
  57. data/documentation/diagrams/dot/history-to-drivers.dot +1 -1
  58. data/documentation/diagrams/dot/memory-skills-detailed.dot +27 -5
  59. data/documentation/diagrams/dot/mistakes-negative-feedback.dot +6 -6
  60. data/documentation/diagrams/dot/overall-pwn-architecture.dot +7 -5
  61. data/documentation/diagrams/dot/persistence-filesystem.dot +6 -4
  62. data/documentation/diagrams/dot/plugin-ecosystem.dot +1 -1
  63. data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +31 -10
  64. data/documentation/diagrams/dot/pwn-repl-prototyping.dot +1 -1
  65. data/documentation/diagrams/dot/reporting-pipeline.dot +1 -1
  66. data/documentation/diagrams/dot/sdr-radio-flow.dot +16 -12
  67. data/documentation/diagrams/dot/sessions-cron-automation.dot +1 -1
  68. data/documentation/diagrams/dot/swarm-multi-agent.dot +8 -2
  69. data/documentation/diagrams/driver-framework.svg +1 -1
  70. data/documentation/diagrams/extrospection-world-awareness.svg +129 -129
  71. data/documentation/diagrams/history-to-drivers.svg +32 -32
  72. data/documentation/diagrams/memory-skills-detailed.svg +268 -137
  73. data/documentation/diagrams/mistakes-negative-feedback.svg +51 -51
  74. data/documentation/diagrams/overall-pwn-architecture.svg +188 -171
  75. data/documentation/diagrams/persistence-filesystem.svg +120 -89
  76. data/documentation/diagrams/plugin-ecosystem.svg +1 -1
  77. data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +407 -255
  78. data/documentation/diagrams/pwn-repl-prototyping.svg +1 -1
  79. data/documentation/diagrams/reporting-pipeline.svg +1 -1
  80. data/documentation/diagrams/sdr-radio-flow.svg +181 -146
  81. data/documentation/diagrams/sessions-cron-automation.svg +1 -1
  82. data/documentation/diagrams/swarm-multi-agent.svg +156 -119
  83. data/documentation/pwn-REPL.md +8 -7
  84. data/documentation/pwn-ai-Agent.md +57 -29
  85. data/lib/pwn/ai/agent/dispatch.rb +1 -1
  86. data/lib/pwn/ai/agent/extrospection.rb +39 -39
  87. data/lib/pwn/ai/agent/learning.rb +1 -1
  88. data/lib/pwn/ai/agent/loop.rb +40 -0
  89. data/lib/pwn/ai/agent/metrics.rb +1 -1
  90. data/lib/pwn/ai/agent/tools/extrospection.rb +20 -20
  91. data/lib/pwn/config.rb +3 -3
  92. data/lib/pwn/ffi/hack_rf.rb +119 -0
  93. data/lib/pwn/ffi/soapy_sdr.rb +165 -3
  94. data/lib/pwn/memory_index.rb +1 -1
  95. data/lib/pwn/plugins/repl.rb +26 -2
  96. data/lib/pwn/sdr/decoder/adsb.rb +1 -1
  97. data/lib/pwn/sdr/decoder/base.rb +30 -16
  98. data/lib/pwn/sdr/decoder/flex.rb +378 -120
  99. data/lib/pwn/sdr/decoder/rtl433.rb +1 -1
  100. data/lib/pwn/sdr/decoder/rtty.rb +1 -1
  101. data/lib/pwn/sdr/decoder.rb +1 -1
  102. data/lib/pwn/sdr/gqrx.rb +7 -7
  103. data/lib/pwn/setup.rb +563 -0
  104. data/lib/pwn/version.rb +1 -1
  105. data/lib/pwn.rb +1 -0
  106. data/spec/lib/pwn/sdr/decoder/flex_spec.rb +67 -0
  107. data/spec/lib/pwn/setup_spec.rb +28 -0
  108. data/third_party/pwn_rdoc.jsonl +40 -12
  109. metadata +5 -1
@@ -1,4 +1,4 @@
1
- # Configuration `~/.pwn/pwn.yaml`
1
+ # Configuration - `~/.pwn/pwn.yaml`
2
2
 
3
3
  Everything configurable in PWN lives in **one encrypted YAML file**, loaded by
4
4
  `PWN::Config.refresh_env` at driver startup and exposed in-process as the
@@ -8,20 +8,25 @@ frozen constant **`PWN::Env`** (a redacted copy is available as
8
8
  The file is **AES-encrypted at rest** by `PWN::Plugins::Vault`. Its key/IV
9
9
  live in a sibling **`~/.pwn/pwn.yaml.decryptor`** file (or in
10
10
  `PWN_DECRYPTOR_KEY` / `PWN_DECRYPTOR_IV` env vars). Never edit `pwn.yaml`
11
- by hand use the **`pwn-vault`** REPL command, which decrypts → opens
11
+ by hand - use the **`pwn-vault`** REPL command, which decrypts → opens
12
12
  `$EDITOR` → re-encrypts → reloads `PWN::Env`.
13
13
 
14
14
  If `~/.pwn/pwn.yaml` does not exist on first run, `PWN::Config.default_env`
15
15
  writes a fully-commented template with every key below (values set to
16
- `'optional - '` / `'required - '` placeholder strings), encrypts it, and
16
+ `'optional - ...'` / `'required - ...'` placeholder strings), encrypts it, and
17
17
  generates the decryptor.
18
18
 
19
+ > **Before configuring**, run `pwn setup` - the
20
+ > [doctor](Installation.md#pwn-setup--the-post-install-doctor--provisioner)
21
+ > reports whether `~/.pwn/`, `pwn.yaml`, its decryptor, and an AI-engine key
22
+ > are present, and exits non-zero for CI if any are missing.
23
+
19
24
  ---
20
25
 
21
26
  ## Full annotated example
22
27
 
23
28
  ```yaml
24
- # ~/.pwn/pwn.yaml (shown DECRYPTED file is AES-encrypted on disk)
29
+ # ~/.pwn/pwn.yaml (shown DECRYPTED - file is AES-encrypted on disk)
25
30
 
26
31
  ai:
27
32
  active: grok # Which engine backs `pwn-ai`. One of: openai | anthropic | grok | gemini | ollama.
@@ -29,12 +34,12 @@ ai:
29
34
 
30
35
  grok:
31
36
  base_uri: https://api.x.ai/v1 # xAI API base URL. Override for a self-hosted proxy / private endpoint.
32
- key: xai-… # xAI API key. If blank AND no oauth.* below, PWN prompts interactively at load.
33
- model: grok-4.5 # Model id sent on every chat / tool-loop request.
37
+ key: xai-... # xAI API key. If blank AND no oauth.* below, PWN prompts interactively at load.
38
+ model: <model-id> # Model id sent on every chat / tool-loop request. See provider docs / API for currently-supported ids.
34
39
  system_role_content: 'You are an ethically hacking xAI Grok agent.' # Base system prompt (MEMORY/SKILLS/LEARNING/EXTROSPECTION blocks are appended to this).
35
40
  temp: 1.0 # Sampling temperature passed to the chat endpoint.
36
41
  max_prompt_length: 256000 # Soft input-context ceiling (chars) used for prompt truncation / chunking.
37
- oauth: # RFC-8628 device-flow (SuperGrok subscription) public client, no client_secret.
42
+ oauth: # RFC-8628 device-flow (SuperGrok subscription) - public client, no client_secret.
38
43
  refresh_token: ~ # Durable OAuth refresh token; enables silent re-auth without an API key.
39
44
  bearer_token: ~ # Short-lived OAuth access JWT; auto-refreshed each run when refresh_token is set.
40
45
  client_id: b1a00492-073a-47ea-816f-4c329264a828 # xAI's PUBLIC OAuth client id for the "Grok CLI" application (not sensitive).
@@ -45,8 +50,8 @@ ai:
45
50
 
46
51
  openai:
47
52
  base_uri: https://api.openai.com/v1 # OpenAI API base URL. Override for Azure OpenAI / VPC gateway / local proxy.
48
- key: sk-… # OpenAI API key (`sk-…`). Prompted interactively if blank.
49
- model: gpt-4o # Model id sent on every chat / tool-loop request.
53
+ key: sk-... # OpenAI API key (`sk-...`). Prompted interactively if blank.
54
+ model: <model-id> # Model id sent on every chat / tool-loop request. See provider docs / API for currently-supported ids.
50
55
  system_role_content: 'You are an ethically hacking OpenAI agent.' # Base system prompt for this engine.
51
56
  temp: 1.0 # Sampling temperature.
52
57
  max_prompt_length: 128000 # Soft input-context ceiling (chars) for truncation / chunking.
@@ -54,8 +59,8 @@ ai:
54
59
 
55
60
  anthropic:
56
61
  base_uri: https://api.anthropic.com/v1 # Anthropic API base URL. Override for Bedrock / private gateway.
57
- key: sk-ant-… # Anthropic API key (`sk-ant-…`). Prompted interactively if blank.
58
- model: claude-3-5-sonnet-20240620 # Model id sent on every chat / tool-loop request.
62
+ key: sk-ant-... # Anthropic API key (`sk-ant-...`). Prompted interactively if blank.
63
+ model: <model-id> # Model id sent on every chat / tool-loop request. See provider docs / API for currently-supported ids.
59
64
  system_role_content: 'You are an ethically hacking Anthropic agent.' # Base system prompt for this engine.
60
65
  temp: 1.0 # Sampling temperature.
61
66
  max_tokens: 8192 # Max OUTPUT tokens per response. Raise if tool-call JSON truncates.
@@ -63,26 +68,40 @@ ai:
63
68
 
64
69
  gemini:
65
70
  base_uri: https://generativelanguage.googleapis.com/v1beta # Google Generative Language API base URL.
66
- key: AIza # Google AI Studio API key (`AIza…`). Prompted interactively if blank.
67
- model: gemini-2.5-pro # Model id sent on every chat / tool-loop request.
71
+ key: AIza... # Google AI Studio API key (`AIza...`). Prompted interactively if blank.
72
+ model: <model-id> # Model id sent on every chat / tool-loop request. See provider docs / API for currently-supported ids.
68
73
  system_role_content: 'You are an ethically hacking Gemini agent.' # Base system prompt for this engine.
69
74
  temp: 1.0 # Sampling temperature.
70
- max_prompt_length: 1000000 # Soft input-context ceiling (chars) Gemini supports very large contexts.
75
+ max_prompt_length: 1000000 # Soft input-context ceiling (chars) - Gemini supports very large contexts.
71
76
 
72
77
  ollama:
73
- base_uri: https://ollama.local # REQUIRED for ollama Open WebUI / ollama-serve base URL (no vendor default).
74
- key: eyJ # Open WebUI JWT (Settings → Account → API Key). Prompted if blank.
75
- model: llama3.1:70b # Local model tag as `ollama list` shows it.
78
+ base_uri: https://ollama.local # REQUIRED for ollama - Open WebUI / ollama-serve base URL (no vendor default).
79
+ key: eyJ... # Open WebUI JWT (Settings → Account → API Key). Prompted if blank.
80
+ model: <local-model-tag> # Local model tag exactly as `ollama list` shows it.
81
+ embed_model: <embed-model-tag> # Embedding model for PWN::MemoryIndex (relevance-ranked MEMORY). Must be pulled locally.
76
82
  system_role_content: 'You are an ethically hacking Ollama agent.' # Base system prompt for this engine.
77
- temp: 1.0 # Sampling temperature.
78
- max_prompt_length: 32000 # Soft input-context ceiling (chars) tune per local model's real context window.
83
+ temp: 1.0 # Sampling temperature (used on the FINAL text-only turn - tool-bearing turns are pinned low for deterministic routing).
84
+ num_ctx: 32768 # Context window passed to /api/chat options.num_ctx. Ollama's default (2048) is too small for the pwn-ai system prompt.
85
+ keep_alive: 30m # How long ollama keeps the model resident between iterations (avoids reload latency mid-turn).
86
+ prompt_budget: # Per-block caps applied by PromptBuilder.budget so a small model spends attention on the request, not the harness.
87
+ memory: 6 # Max MEMORY entries injected (relevance-ranked via PWN::MemoryIndex when available).
88
+ metrics: 3 # Max TOOL EFFECTIVENESS rows.
89
+ mistakes: 3 # Max KNOWN MISTAKES / FIXES rows.
90
+ learning: 2 # Max recent LEARNING outcomes shown.
91
+ extro: false # Gate the (heaviest) EXTROSPECTION block entirely for local models.
92
+ max_prompt_length: 32000 # Soft input-context ceiling (chars) - tune per local model's real context window.
93
+
94
+ reflect_engine: ~ # Teacher-student reflection: EXECUTE on ai.active, but write durable lessons via THIS engine (nil = same as active). Lets a local model act while a frontier model authors the Memory :lesson entries it reads back.
79
95
 
80
96
  agent:
81
97
  native_tools: true # Use provider-native tool_calls / function-calling. false → legacy text-parsed tool protocol.
82
98
  max_iters: 25 # Hard cap on tool-call rounds per user turn before a forced final answer.
83
99
  max_depth: 3 # Recursion guard: how many levels deep agent_ask/agent_debate sub-agents may spawn sub-agents.
84
100
  auto_introspect: true # Run Learning.auto_introspect (outcome logging + lesson mining) after every final answer.
85
- auto_extrospect: false # Optional ambient baseline (host/repo/env ONLY never launches burpsuite/zaproxy/msf/gqrx). Sense tools (intel/verify/watch/rf_tune/observe) stay on-demand.
101
+ auto_extrospect: false # Optional ambient baseline (host/repo/env ONLY - never launches burpsuite/zaproxy/msf/gqrx). Sense tools (intel/verify/watch/rf_tune/observe) stay on-demand.
102
+ plan_first: ~ # Plan-then-act pre-pass: force the model to externalise a numbered tool plan BEFORE its first dispatch. nil = auto (true when ai.active == ollama).
103
+ tool_router: false # Dynamic tool-set slimming: ship only Registry::CORE_TOOLS + top-K keyword-relevant schemas per turn (helps small models route correctly).
104
+ escalation_persona: ~ # Swarm persona name to ask for a 3-line corrective hint once a local model burns ≥ Loop::ESCALATE_AFTER_FAILS in-turn failures. nil = disabled.
86
105
  toolsets: ~ # Allow-list of toolsets exposed to the agent. nil = all. Valid: cron, extrospection, learning, memory, metrics, pwn, sessions, skills, swarm, terminal.
87
106
  extrospection:
88
107
  web:
@@ -93,12 +112,12 @@ ai:
93
112
  max_anchors: 8 # Cap on how many anchors are rendered per snapshot (protects run time).
94
113
  per_page_timeout: 15 # Seconds before a single page render is abandoned and recorded as unreachable.
95
114
  screenshot: false # Persist a PNG per anchor to ~/.pwn/extrospection/web/ (disk-heavy; off by default).
96
- allow_targets: false # true → also merge top-level `targets:` into anchors (opt-in off so in-scope hosts aren't touched unprompted).
115
+ allow_targets: false # true → also merge top-level `targets:` into anchors (opt-in - off so in-scope hosts aren't touched unprompted).
97
116
  rf:
98
117
  host: 127.0.0.1 # GQRX remote-control host for extro_rf_tune.
99
118
  port: 7356 # GQRX remote-control port.
100
119
  settle_secs: 8 # Seconds to sample RDS after tuning (max 30).
101
- ttl: 300 # Observation TTL for :rf (songs change keep short).
120
+ ttl: 300 # Observation TTL for :rf (songs change - keep short).
102
121
 
103
122
  plugins:
104
123
  asm:
@@ -108,15 +127,15 @@ plugins:
108
127
  bitcoin:
109
128
  rpc_host: localhost # bitcoind JSON-RPC host for PWN::Blockchain::BTC.
110
129
  rpc_port: 8332 # bitcoind JSON-RPC port.
111
- rpc_user: # bitcoind RPC username (rpcauth / rpcuser in bitcoin.conf).
112
- rpc_pass: # bitcoind RPC password. Redacted in PWN::EnvRedacted.
130
+ rpc_user: ... # bitcoind RPC username (rpcauth / rpcuser in bitcoin.conf).
131
+ rpc_pass: ... # bitcoind RPC password. Redacted in PWN::EnvRedacted.
113
132
  hunter:
114
- api_key: # hunter.how API key passed as api_key: to PWN::Plugins::Hunter.search.
133
+ api_key: ... # hunter.how API key - passed as api_key: to PWN::Plugins::Hunter.search.
115
134
  jira_data_center:
116
135
  base_uri: https://jira.company.com/rest/api/latest # Jira Data Center REST base URL.
117
- token: # Jira Personal Access Token for PWN::Plugins::JiraDataCenter. Redacted.
136
+ token: ... # Jira Personal Access Token for PWN::Plugins::JiraDataCenter. Redacted.
118
137
  meshtastic:
119
- admin_key: # Public key authorised to send admin messages to mesh nodes via `pwn-mesh`.
138
+ admin_key: ... # Public key authorised to send admin messages to mesh nodes via `pwn-mesh`.
120
139
  serial:
121
140
  port: /dev/ttyUSB0 # Serial device path for a locally-attached Meshtastic node.
122
141
  baud: 115200 # Serial baud rate.
@@ -131,33 +150,33 @@ plugins:
131
150
  pass: large4cats # MQTT password (public Meshtastic broker default shown). Redacted.
132
151
  channel:
133
152
  active: LongFast # Which named channel block below `pwn-mesh` uses for TX/RX.
134
- LongFast: # Channel definition name is arbitrary, referenced by `active:` above.
153
+ LongFast: # Channel definition - name is arbitrary, referenced by `active:` above.
135
154
  psk: 'AQ==' # Channel pre-shared key (base64). 'AQ==' = Meshtastic default public key. Redacted.
136
155
  region: US/UT # LoRa region tag (regulatory band).
137
156
  topic: 2/e/# # MQTT topic filter to subscribe/publish for this channel.
138
157
  channel_num: 8 # Meshtastic channel index (slot number on the device).
139
- from: '!deadbeef' # Sender node id used on outbound packets. Optional defaults to !<mqtt client_id>.
158
+ from: '!deadbeef' # Sender node id used on outbound packets. Optional - defaults to !<mqtt client_id>.
140
159
  PWN: # Example second (private) channel definition.
141
- psk: # Private channel pre-shared key (base64). Redacted.
160
+ psk: ... # Private channel pre-shared key (base64). Redacted.
142
161
  region: US/UT # LoRa region tag for this channel.
143
162
  topic: 2/e/PWN/# # MQTT topic filter for this channel.
144
163
  channel_num: 99 # Meshtastic channel index for this channel.
145
164
  shodan:
146
- api_key: # Shodan API key passed as api_key: to PWN::Plugins::Shodan.*. Redacted.
165
+ api_key: ... # Shodan API key - passed as api_key: to PWN::Plugins::Shodan.*. Redacted.
147
166
 
148
167
  memory:
149
- enabled: true # Reserve persistent-memory subsystem on/off (currently always active; future gate).
168
+ enabled: true # Reserve - persistent-memory subsystem on/off (currently always active; future gate).
150
169
  provider: file # Storage backend for PWN::Memory: file (~/.pwn/memory.json). `sqlite` reserved.
151
170
 
152
171
  sessions:
153
- enabled: true # Reserve transcript recording on/off (currently always active; future gate).
172
+ enabled: true # Reserve - transcript recording on/off (currently always active; future gate).
154
173
  provider: jsonl # Transcript format under ~/.pwn/sessions/ (one .jsonl per session).
155
174
 
156
175
  cron:
157
- enabled: true # Reserve scheduled-job subsystem on/off (currently always active; future gate).
176
+ enabled: true # Reserve - scheduled-job subsystem on/off (currently always active; future gate).
158
177
  provider: yaml # Job store format for PWN::Cron (~/.pwn/cron/jobs.yml).
159
178
 
160
- targets: # Optional engagement-scope URLs/hosts. Merged into :web snapshot anchors
179
+ targets: # Optional - engagement-scope URLs/hosts. Merged into :web snapshot anchors
161
180
  - https://target.example.com # ONLY when ai.agent.extrospection.web.allow_targets: true.
162
181
  | `ai.agent.extrospection.rf.host` | String | `127.0.0.1` | `Extrospection.rf_tune` | GQRX remote-control host for the RF sense organ. |
163
182
  | `ai.agent.extrospection.rf.port` | Integer | `7356` | `Extrospection.rf_tune` | GQRX remote-control port. |
@@ -172,7 +191,7 @@ targets: # Optional — engagement-scope URLs/hosts. M
172
191
  ```ruby
173
192
  PWN::Env[:ai][:active] # => :grok
174
193
  PWN::Env.dig(:ai, :agent, :max_iters) # => 25
175
- PWN::EnvRedacted[:ai][:grok][:key] # => ">>> REDACTED >>> "
194
+ PWN::EnvRedacted[:ai][:grok][:key] # => ">>> REDACTED >>> ..."
176
195
 
177
196
  # Edit + re-encrypt + reload without leaving the REPL:
178
197
  pwn-vault
@@ -185,29 +204,34 @@ PWN::Config.refresh_env
185
204
 
186
205
  ## Exhaustive key reference
187
206
 
188
- ### `ai` AI engines & agent loop
207
+ ### `ai` - AI engines & agent loop
189
208
 
190
209
  | Key path | Type | Default | Consumed by | Purpose |
191
210
  |---|---|---|---|---|
192
211
  | `ai.active` | String | `grok` | `PWN::Config.refresh_env`, `PWN::AI::Agent::Loop`, `PWN::Plugins::REPL`, `PWN::Cron` | Which AI engine backs `pwn-ai`. One of `openai` · `anthropic` · `grok` · `gemini` · `ollama`. |
193
212
  | `ai.module_reflection` | Boolean | `false` | `PWN::AI::Agent::Reflect`, `PWN::SAST::*`, `PWN::Plugins::BurpSuite` | Master gate for LLM-driven self-analysis (SAST triage, Burp finding enrichment, `Learning.llm_reflect`). |
194
213
  | `ai.<engine>.base_uri` | String | provider default | `PWN::AI::<Engine>.rest_call` | Override the API base URL (self-hosted proxy, private endpoint, Azure/VPC gateway). **Required** for `ollama`. |
195
- | `ai.<engine>.key` | String | | `PWN::AI::<Engine>` | API key / bearer token. If blank AND no OAuth is configured, PWN prompts interactively at load. |
196
- | `ai.<engine>.model` | String | provider default | `PWN::AI::<Engine>.chat` / `.chat_tool_loop` | Model id sent on every request (e.g. `grok-4.5`, `gpt-4o`, `claude-3-5-sonnet-20240620`, `gemini-2.5-pro`, `llama3.1:70b`). |
214
+ | `ai.<engine>.key` | String | - | `PWN::AI::<Engine>` | API key / bearer token. If blank AND no OAuth is configured, PWN prompts interactively at load. |
215
+ | `ai.<engine>.model` | String | provider default | `PWN::AI::<Engine>.chat` / `.chat_tool_loop` | Model id sent on every request. Use whatever id the provider / `ollama list` currently exposes - PWN never hard-codes a specific model. |
197
216
  | `ai.<engine>.system_role_content` | String | ethical-hacker persona | `PWN::AI::Agent::PromptBuilder`, `PWN::Plugins::REPL` | Base system prompt prepended to MEMORY / SKILLS / LEARNING / EXTROSPECTION blocks. |
198
217
  | `ai.<engine>.temp` | Float | `1.0` | `PWN::AI::<Engine>.chat` | Sampling temperature. |
199
218
  | `ai.<engine>.max_prompt_length` | Integer | per-engine | `PWN::AI::<Engine>`, `PWN::Plugins::REPL` | Soft input-context ceiling used for prompt truncation / chunking. |
200
219
  | `ai.anthropic.max_tokens` | Integer | `8192` | `PWN::AI::Anthropic.chat_tool_loop` | Max **output** tokens per response. Raise if tool-call JSON truncates. |
201
220
  | `ai.openai.max_tokens` | Integer | `16384` | `PWN::AI::OpenAI.chat` | Max **output** tokens per response. Mapped to OpenAI's wire param `max_completion_tokens` (legacy env key `max_completion_tokens` still accepted). |
202
- | `ai.grok.oauth.refresh_token` | String | | `PWN::AI::Grok.resolve_auth` | Durable OAuth refresh token (from `PWN::AI::Grok.obtain_oauth_bearer_token` device flow). Enables silent re-auth without an API key. |
203
- | `ai.grok.oauth.bearer_token` | String | | `PWN::AI::Grok.resolve_auth` | Short-lived OAuth access JWT. Auto-refreshed each run when `refresh_token` is present; live-cached back into this hash. |
221
+ | `ai.ollama.embed_model` | String | provider default | `PWN::MemoryIndex` | Local embedding model tag used to build `~/.pwn/memory.idx` for **relevance-ranked** MEMORY injection. Falls back to substring recall when unset / unreachable. |
222
+ | `ai.ollama.num_ctx` | Integer | `32768` | `PWN::AI::Ollama.chat_with_tools` | Context window sent as `options.num_ctx` on the native `/api/chat` call. Ollama's own default (2048) truncates the pwn-ai system prompt. |
223
+ | `ai.ollama.keep_alive` | String | `30m` | `PWN::AI::Ollama.chat_with_tools` | How long the model stays resident in ollama between iterations of a single turn. |
224
+ | `ai.ollama.prompt_budget` | Hash | `{memory:6, metrics:3, mistakes:3, learning:2, extro:false}` | `PWN::AI::Agent::PromptBuilder.budget` | Per-block caps on injected context so a small local model spends its attention on the request, not the harness. Any engine may set this. |
225
+ | `ai.reflect_engine` | Symbol \| `nil` | `nil` (= `ai.active`) | `PWN::AI::Agent::Reflect.on`, `Learning.reflect` | **Teacher-student** override: run the task on `ai.active`, but generate durable lessons via *this* engine. Lets a local model execute while a frontier model writes the Memory it reads back. |
226
+ | `ai.grok.oauth.refresh_token` | String | - | `PWN::AI::Grok.resolve_auth` | Durable OAuth refresh token (from `PWN::AI::Grok.obtain_oauth_bearer_token` device flow). Enables silent re-auth without an API key. |
227
+ | `ai.grok.oauth.bearer_token` | String | - | `PWN::AI::Grok.resolve_auth` | Short-lived OAuth access JWT. Auto-refreshed each run when `refresh_token` is present; live-cached back into this hash. |
204
228
  | `ai.grok.oauth.client_id` | String | Grok-CLI public id | `PWN::AI::Grok` | Override the public OAuth client id used for device-flow / refresh. |
205
- | `ai.grok.oauth.client_secret` | String | | `PWN::Config.refresh_env`, `PWN::AI::Grok` | Only for confidential-client OAuth flows. Unused by the default public Grok-CLI client. |
229
+ | `ai.grok.oauth.client_secret` | String | - | `PWN::Config.refresh_env`, `PWN::AI::Grok` | Only for confidential-client OAuth flows. Unused by the default public Grok-CLI client. |
206
230
  | `ai.grok.oauth.scope` | String | see example | `PWN::AI::Grok` | OAuth scope string requested during device-flow enrollment. |
207
231
  | `ai.grok.oauth.token_uri` | String | `https://auth.x.ai/oauth2/token` | `PWN::AI::Grok` | OAuth token endpoint (override for enterprise IdP). |
208
232
  | `ai.grok.oauth.enroll` | Boolean | `false` | `PWN::AI::Grok` | `true` → always run RFC-8628 device-flow enrollment on load, even when `ai.grok.key` is set. |
209
233
 
210
- ### `ai.agent` pwn-ai autonomous loop
234
+ ### `ai.agent` - pwn-ai autonomous loop
211
235
 
212
236
  | Key path | Type | Default | Consumed by | Purpose |
213
237
  |---|---|---|---|---|
@@ -217,27 +241,30 @@ PWN::Config.refresh_env
217
241
  | `ai.agent.auto_introspect` | Boolean | `true` | `PWN::AI::Agent::Learning.auto_introspect` | Run outcome logging + lesson mining after every final answer. Toggle live via `learning_auto_introspect_toggle`. |
218
242
  | `ai.agent.auto_extrospect` | Boolean | `false` | `PWN::AI::Agent::Extrospection.auto_extrospect` | Optional ambient baseline after every final answer (`AUTO_SECTIONS` = host/repo/env only; never spawns GUI/JVM tools). Prefer on-demand sense tools (`intel`/`verify`/`watch`/`rf_tune`/`observe`). Toggle live via `extro_auto_toggle`. |
219
243
  | `ai.agent.toolsets` | Array\<String\> \| `nil` | `nil` (all) | `bin/pwn`, `PWN::Plugins::REPL`, `PWN::AI::Agent::Registry` | Allow-list of toolsets exposed to the agent. Valid: `cron`, `extrospection`, `learning`, `memory`, `metrics`, `pwn`, `sessions`, `skills`, `swarm`, `terminal`. |
244
+ | `ai.agent.plan_first` | Boolean \| `nil` | `nil` (auto: `true` when `ai.active == ollama`) | `PWN::AI::Agent::Loop.plan_first` | Plan-then-act pre-pass: the model must emit a numbered tool plan (as an assistant message) *before* it may dispatch anything. Cheap chain-of-thought scaffolding for local models. |
245
+ | `ai.agent.tool_router` | Boolean | `false` | `PWN::AI::Agent::Registry.definitions` | Dynamic tool-set slimming: expose only `Registry::CORE_TOOLS` + the top-K keyword-relevant schemas for *this* request. Ties break on historical `Metrics` success rate so the router itself is a learned component. |
246
+ | `ai.agent.escalation_persona` | String \| `nil` | `nil` | `PWN::AI::Agent::Loop.escalate` → `Swarm.ask` | Circuit-breaker: once a local model accumulates ≥ `Loop::ESCALATE_AFTER_FAILS` in-turn failures, ask this Swarm persona for a 3-line corrective hint (injected as a synthetic tool result). The local model still authors the final answer so Learning/Metrics stay attributed. |
220
247
  | `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`. |
221
- | `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`). |
248
+ | `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`). |
222
249
  | `ai.agent.extrospection.web.max_anchors` | Integer | `8` | `Extrospection.probe_web` | Cap on anchors rendered per snapshot. |
223
250
  | `ai.agent.extrospection.web.per_page_timeout` | Integer | `15` | `Extrospection` (headless browser) | Seconds before a page render is abandoned. |
224
251
  | `ai.agent.extrospection.web.screenshot` | Boolean | `false` | `Extrospection.probe_web` / `.watch` | Persist a PNG per anchor to `~/.pwn/extrospection/web/`. |
225
- | `ai.agent.extrospection.web.allow_targets` | Boolean | `false` | `Extrospection.web_anchors` | Merge top-level `targets:` into the anchor list (opt-in off by default to avoid touching in-scope hosts unprompted). |
252
+ | `ai.agent.extrospection.web.allow_targets` | Boolean | `false` | `Extrospection.web_anchors` | Merge top-level `targets:` into the anchor list (opt-in - off by default to avoid touching in-scope hosts unprompted). |
226
253
 
227
- ### `plugins` module credentials & wiring
254
+ ### `plugins` - module credentials & wiring
228
255
 
229
256
  | Key path | Type | Default | Consumed by | Purpose |
230
257
  |---|---|---|---|---|
231
- | `plugins.asm.arch` | String | `DetectOS.arch` | `PWN::Plugins::REPL` (`pwn-asm`) | Target architecture for the inline assembler / disassembler prompt (`x86_64`, `arm64`, ). |
258
+ | `plugins.asm.arch` | String | `DetectOS.arch` | `PWN::Plugins::REPL` (`pwn-asm`) | Target architecture for the inline assembler / disassembler prompt (`x86_64`, `arm64`, ...). |
232
259
  | `plugins.asm.endian` | String | `DetectOS.endian` | `PWN::Plugins::REPL` (`pwn-asm`) | Endianness for the inline assembler (`little` / `big`). |
233
260
  | `plugins.blockchain.bitcoin.rpc_host` | String | `localhost` | `PWN::Blockchain::BTC` | bitcoind JSON-RPC host. |
234
261
  | `plugins.blockchain.bitcoin.rpc_port` | Integer | `8332` | `PWN::Blockchain::BTC` | bitcoind JSON-RPC port. |
235
- | `plugins.blockchain.bitcoin.rpc_user` | String | | `PWN::Blockchain::BTC` | bitcoind RPC username. |
236
- | `plugins.blockchain.bitcoin.rpc_pass` | String | | `PWN::Blockchain::BTC` | bitcoind RPC password. |
237
- | `plugins.hunter.api_key` | String | | `PWN::Plugins::Hunter` | hunter.how API key (passed as `api_key:` to `Hunter.search`). |
238
- | `plugins.jira_data_center.base_uri` | String | | `PWN::Plugins::JiraDataCenter` | Jira DC REST base (e.g. `https://jira.company.com/rest/api/latest`). |
239
- | `plugins.jira_data_center.token` | String | | `PWN::Plugins::JiraDataCenter` | Jira Personal Access Token. |
240
- | `plugins.meshtastic.admin_key` | String | | `PWN::Plugins::REPL` (`pwn-mesh`) | Public key authorised to send admin messages to mesh nodes. |
262
+ | `plugins.blockchain.bitcoin.rpc_user` | String | - | `PWN::Blockchain::BTC` | bitcoind RPC username. |
263
+ | `plugins.blockchain.bitcoin.rpc_pass` | String | - | `PWN::Blockchain::BTC` | bitcoind RPC password. |
264
+ | `plugins.hunter.api_key` | String | - | `PWN::Plugins::Hunter` | hunter.how API key (passed as `api_key:` to `Hunter.search`). |
265
+ | `plugins.jira_data_center.base_uri` | String | - | `PWN::Plugins::JiraDataCenter` | Jira DC REST base (e.g. `https://jira.company.com/rest/api/latest`). |
266
+ | `plugins.jira_data_center.token` | String | - | `PWN::Plugins::JiraDataCenter` | Jira Personal Access Token. |
267
+ | `plugins.meshtastic.admin_key` | String | - | `PWN::Plugins::REPL` (`pwn-mesh`) | Public key authorised to send admin messages to mesh nodes. |
241
268
  | `plugins.meshtastic.serial.port` | String | `/dev/ttyUSB0` | `pwn-mesh` (serial) | Serial device path for a locally-attached Meshtastic node. |
242
269
  | `plugins.meshtastic.serial.baud` | Integer | `115200` | `pwn-mesh` (serial) | Serial baud rate. |
243
270
  | `plugins.meshtastic.serial.bits` | Integer | `8` | `pwn-mesh` (serial) | Serial data bits. |
@@ -250,28 +277,28 @@ PWN::Config.refresh_env
250
277
  | `plugins.meshtastic.mqtt.pass` | String | `large4cats` | `pwn-mesh` | MQTT password. |
251
278
  | `plugins.meshtastic.channel.active` | String | `LongFast` | `pwn-mesh` | Which named channel block below is used for TX/RX. |
252
279
  | `plugins.meshtastic.channel.<NAME>.psk` | String (b64) | `AQ==` | `pwn-mesh` | Channel pre-shared key. |
253
- | `plugins.meshtastic.channel.<NAME>.region` | String | | `pwn-mesh` | LoRa region tag (e.g. `US/UT`). |
254
- | `plugins.meshtastic.channel.<NAME>.topic` | String | | `pwn-mesh` | MQTT topic filter to subscribe/publish (e.g. `2/e/#`). |
255
- | `plugins.meshtastic.channel.<NAME>.channel_num` | Integer | | `pwn-mesh` | Meshtastic channel index. |
280
+ | `plugins.meshtastic.channel.<NAME>.region` | String | - | `pwn-mesh` | LoRa region tag (e.g. `US/UT`). |
281
+ | `plugins.meshtastic.channel.<NAME>.topic` | String | - | `pwn-mesh` | MQTT topic filter to subscribe/publish (e.g. `2/e/#`). |
282
+ | `plugins.meshtastic.channel.<NAME>.channel_num` | Integer | - | `pwn-mesh` | Meshtastic channel index. |
256
283
  | `plugins.meshtastic.channel.<NAME>.from` | String | `!<mqtt client_id>` | `pwn-mesh` | Sender node id used on outbound packets. |
257
- | `plugins.shodan.api_key` | String | | `PWN::Plugins::Shodan` | Shodan API key (passed as `api_key:` to `Shodan.*`). |
284
+ | `plugins.shodan.api_key` | String | - | `PWN::Plugins::Shodan` | Shodan API key (passed as `api_key:` to `Shodan.*`). |
258
285
 
259
286
  ### `memory` / `sessions` / `cron`
260
287
 
261
288
  | Key path | Type | Default | Consumed by | Purpose |
262
289
  |---|---|---|---|---|
263
- | `memory.enabled` | Boolean | `true` | `PWN::Memory` | Reserve persistent memory on/off (currently always active; future gate). |
290
+ | `memory.enabled` | Boolean | `true` | `PWN::Memory` | Reserve - persistent memory on/off (currently always active; future gate). |
264
291
  | `memory.provider` | String | `file` | `PWN::Memory` | Storage backend: `file` (`~/.pwn/memory.json`). `sqlite` reserved. |
265
- | `sessions.enabled` | Boolean | `true` | `PWN::Sessions` | Reserve transcript recording on/off (currently always active; future gate). |
292
+ | `sessions.enabled` | Boolean | `true` | `PWN::Sessions` | Reserve - transcript recording on/off (currently always active; future gate). |
266
293
  | `sessions.provider` | String | `jsonl` | `PWN::Sessions` | Transcript format under `~/.pwn/sessions/`. |
267
- | `cron.enabled` | Boolean | `true` | `PWN::Cron` | Reserve scheduled-job subsystem on/off (currently always active; future gate). |
294
+ | `cron.enabled` | Boolean | `true` | `PWN::Cron` | Reserve - scheduled-job subsystem on/off (currently always active; future gate). |
268
295
  | `cron.provider` | String | `yaml` | `PWN::Cron` | Job store format (`~/.pwn/cron/jobs.yml`). |
269
296
 
270
297
  ### Top-level / miscellaneous
271
298
 
272
299
  | Key path | Type | Default | Consumed by | Purpose |
273
300
  |---|---|---|---|---|
274
- | `targets` | Array\<String\> | | `PWN::AI::Agent::Extrospection.web_anchors` | Engagement-scope URLs/hosts. Merged into `:web` snapshot anchors when `ai.agent.extrospection.web.allow_targets: true`. |
301
+ | `targets` | Array\<String\> | - | `PWN::AI::Agent::Extrospection.web_anchors` | Engagement-scope URLs/hosts. Merged into `:web` snapshot anchors when `ai.agent.extrospection.web.allow_targets: true`. |
275
302
 
276
303
  ---
277
304
 
@@ -309,11 +336,11 @@ agent system prompt.
309
336
 
310
337
  `pwn.yaml` is the only file you edit; everything else is machine-written
311
338
  state. See **[Persistence](Persistence.md)** for the full map
312
- (`memory.json`, `learning.jsonl`, `mistakes.json`, `metrics.json`,
313
- `extrospection.json`, `sessions/`, `skills/`, `cron/`, `agents.yml`,
314
- `swarm/`).
339
+ (`memory.json`, `memory.idx`, `learning.jsonl`, `mistakes.json`,
340
+ `metrics.json`, `extrospection.json`, `sessions/`, `skills/`,
341
+ `finetune/`, `cron/`, `agents.yml`, `swarm/`).
315
342
 
316
- Multi-agent personas are **not** configured here they live in
343
+ Multi-agent personas are **not** configured here - they live in
317
344
  `~/.pwn/agents.yml` and are managed with `agent_spawn` / `agent_list`
318
345
  (see **[Swarm](Swarm.md)**).
319
346
 
@@ -4,10 +4,11 @@
4
4
 
5
5
  ```text
6
6
  lib/pwn/ # all namespaces
7
+ lib/pwn/setup.rb # PWN::Setup - doctor/provisioner data tables
7
8
  lib/pwn/plugins/ # 66 plugin modules
8
9
  lib/pwn/ai/agent/ # agent core
9
10
  lib/pwn/ai/agent/tools/ # LLM tool registrations
10
- bin/ # 52 pwn_* drivers
11
+ bin/ # 53 pwn_* drivers (incl. pwn_setup)
11
12
  spec/ # RSpec (incl. conventions_spec)
12
13
  documentation/ # this wiki + diagrams
13
14
  ```
@@ -15,7 +16,7 @@ documentation/ # this wiki + diagrams
15
16
  ## Conventions (enforced by `spec/conventions_spec.rb`)
16
17
 
17
18
  1. Every public module method is `public_class_method def self.name(opts = {})`.
18
- 2. Every arg-accepting `def self.*` uses **exactly** `(opts = {})` no
19
+ 2. Every arg-accepting `def self.*` uses **exactly** `(opts = {})` - no
19
20
  positional args, no keyword args.
20
21
  3. Every module has `self.help` returning a usage string.
21
22
  4. `# frozen_string_literal: true` at the top of every `.rb`.
@@ -23,9 +24,11 @@ documentation/ # this wiki + diagrams
23
24
  ## Quality gates
24
25
 
25
26
  ```bash
26
- rvmsudo rake # rubocop + rspec must be zero offenses
27
+ rake # rubocop + rspec - must be zero offenses
27
28
  ```
28
29
 
30
+ (`rvmsudo rake` on multi-user RVM installs.)
31
+
29
32
  ## Adding a plugin
30
33
 
31
34
  1. `lib/pwn/plugins/my_thing.rb` following the conventions above.
@@ -34,7 +37,14 @@ rvmsudo rake # rubocop + rspec — must be zero offenses
34
37
  4. Optional `bin/pwn_my_thing` driver (see [Drivers](Drivers.md)).
35
38
  5. Optional agent tool in `lib/pwn/ai/agent/tools/` (see
36
39
  [Agent Tool Registry](Agent-Tool-Registry.md)).
37
- 6. Update [Plugins.md](Plugins.md) and, if it changes a data flow, the
40
+ 6. **If it needs a native gem or external binary**, add **one row** to
41
+ `PWN::Setup::NATIVE_GEMS` or `PWN::Setup::TOOLCHAIN` in
42
+ `lib/pwn/setup.rb` (with `apt:`/`dnf:`/`pacman:`/`brew:`/`port:` package
43
+ names + the `plugins:` it unlocks) and, if it belongs in a capability
44
+ set, reference it from `PWN::Setup::PROFILES`. That single edit makes
45
+ `pwn setup` install it on every OS and every install path (gem, git,
46
+ Docker, Packer, Vagrant, CI). **Do not** add a new bash provisioner.
47
+ 7. Update [Plugins.md](Plugins.md) and, if it changes a data flow, the
38
48
  relevant `.dot` in `documentation/diagrams/dot/` → `./build.sh`.
39
49
 
40
50
  ## Commit / release
@@ -1,4 +1,4 @@
1
- # Cron Scheduled Autonomous Jobs
1
+ # Cron - Scheduled Autonomous Jobs
2
2
 
3
3
  `PWN::Cron` (`lib/pwn/cron.rb`) stores job definitions in
4
4
  `~/.pwn/cron/jobs.yml` and can install a matching system-`crontab` line that
@@ -22,7 +22,7 @@ invokes `PWN::Cron.run(<id>)` on schedule.
22
22
  | `cron_list` | id · name · schedule · enabled · last_run · last_status |
23
23
  | `cron_run(id:)` | Fire immediately (updates last_run/last_status) |
24
24
  | `cron_enable` / `cron_disable` | Toggle without deleting |
25
- | `cron_remove` | Delete from `jobs.yml` (does **not** scrub crontab `crontab -e` yourself) |
25
+ | `cron_remove` | Delete from `jobs.yml` (does **not** scrub crontab - `crontab -e` yourself) |
26
26
 
27
27
  ## Example
28
28
 
@@ -38,8 +38,8 @@ cron_create(
38
38
 
39
39
  At 02:00 the system cron fires `PWN::Cron.run`, which spins up a headless
40
40
  `pwn-ai` turn. With `auto_introspect` on (and optional `auto_extrospect` for
41
- the cheap `AUTO_SECTIONS` baseline), the run updates Learning/Metrics and,
42
- if enabled, host/repo/env posture so tomorrow's interactive session already
41
+ the cheap `AUTO_SECTIONS` baseline), the run updates Learning/Metrics - and,
42
+ if enabled, host/repo/env posture - so tomorrow's interactive session already
43
43
  knows what changed overnight. Sense tools (`intel`/`verify`/`watch`) stay
44
44
  on-demand; cron is not expected to launch Burp/ZAP/msf/GQRX.
45
45
 
@@ -54,7 +54,7 @@ cron_create(
54
54
  Weekly, headless-browser fact-check of every `PWN::Memory` `:fact` containing
55
55
  a CVE / version string / URL. Refuted entries get prefixed `[UNVERIFIED
56
56
  yyyy-mm-dd]` so the injected MEMORY block stops calcifying into
57
- confidently-wrong priors see [Extrospection § revalidate_memory](Extrospection.md).
57
+ confidently-wrong priors - see [Extrospection § revalidate_memory](Extrospection.md).
58
58
 
59
59
  **See also:** [Sessions](Sessions.md) · [Extrospection](Extrospection.md) ·
60
60
  [CLI Drivers](CLI-Drivers.md)
@@ -51,7 +51,7 @@ groups) so lines never criss-cross.
51
51
  [source](diagrams/dot/pwn-ai-feedback-learning-loop.dot) · doc: [Skills, Memory & Learning](Skills-Memory-Learning.md)
52
52
  ![pwn-ai-feedback-learning-loop](diagrams/pwn-ai-feedback-learning-loop.svg)
53
53
 
54
- ### Mistakes Negative-Feedback Loop
54
+ ### Mistakes - Negative-Feedback Loop
55
55
  [source](diagrams/dot/mistakes-negative-feedback.dot) · doc: [Mistakes](Mistakes.md)
56
56
  ![mistakes-negative-feedback](diagrams/mistakes-negative-feedback.svg)
57
57
 
@@ -67,15 +67,15 @@ groups) so lines never criss-cross.
67
67
  [source](diagrams/dot/memory-skills-detailed.dot) · doc: [Skills, Memory & Learning](Skills-Memory-Learning.md)
68
68
  ![memory-skills-detailed](diagrams/memory-skills-detailed.svg)
69
69
 
70
- ### Extrospection World Awareness
70
+ ### Extrospection - World Awareness
71
71
  [source](diagrams/dot/extrospection-world-awareness.dot) · doc: [Extrospection](Extrospection.md)
72
72
  ![extrospection-world-awareness](diagrams/extrospection-world-awareness.svg)
73
73
 
74
- ### Swarm Native Multi-Agent
74
+ ### Swarm - Native Multi-Agent
75
75
  [source](diagrams/dot/swarm-multi-agent.dot) · doc: [Swarm](Swarm.md)
76
76
  ![swarm-multi-agent](diagrams/swarm-multi-agent.svg)
77
77
 
78
- ### Cron Scheduled Jobs
78
+ ### Cron - Scheduled Jobs
79
79
  [source](diagrams/dot/cron-scheduling.dot) · doc: [Cron](Cron.md)
80
80
  ![cron-scheduling](diagrams/cron-scheduling.svg)
81
81
 
@@ -1,4 +1,4 @@
1
- # Drivers Turn a REPL Session into a Shipped Binary
1
+ # Drivers - Turn a REPL Session into a Shipped Binary
2
2
 
3
3
  A **driver** is a small executable in `bin/` that wires `OptionParser` to one
4
4
  or more `PWN::` calls. All 52 shipped `pwn_*` binaries follow the same
@@ -38,13 +38,13 @@ PWN::Reports::Fuzz.generate(result: result, dir_path: opts[:out]) if opts[:out]
38
38
  puts result
39
39
  ```
40
40
 
41
- ## Three artefact types from one REPL session
41
+ ## Three artifact types from one REPL session
42
42
 
43
- | Artefact | Made with | Consumed by |
43
+ | Artifact | Made with | Consumed by |
44
44
  |---|---|---|
45
45
  | `bin/pwn_<name>` | template above | shell / CI |
46
46
  | `~/.pwn/skills/<name>.md` | `learning_distill_skill` | every future pwn-ai prompt |
47
- | `cron` job | `cron_create(ruby: '')` | system crontab → unattended |
47
+ | `cron` job | `cron_create(ruby: '...')` | system crontab → unattended |
48
48
 
49
49
  **See also:** [CLI Drivers](CLI-Drivers.md) · [Cron](Cron.md) ·
50
50
  [Skills, Memory & Learning](Skills-Memory-Learning.md)