pwn 0.5.670 → 0.5.673

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/README.md +9 -7
  4. data/documentation/Agent-Tool-Registry.md +17 -5
  5. data/documentation/Configuration.md +15 -8
  6. data/documentation/Diagrams.md +2 -2
  7. data/documentation/Home.md +2 -2
  8. data/documentation/How-PWN-Works.md +11 -9
  9. data/documentation/Installation.md +3 -1
  10. data/documentation/Mistakes.md +3 -0
  11. data/documentation/Persistence.md +4 -1
  12. data/documentation/Reinforcement-Learning.md +90 -73
  13. data/documentation/Skills-Memory-Learning.md +28 -4
  14. data/documentation/What-is-PWN.md +8 -7
  15. data/documentation/Why-PWN.md +3 -2
  16. data/documentation/diagrams/agent-tool-registry.svg +188 -160
  17. data/documentation/diagrams/dot/agent-tool-registry.dot +7 -4
  18. data/documentation/diagrams/dot/memory-skills-detailed.dot +12 -5
  19. data/documentation/diagrams/dot/overall-pwn-architecture.dot +4 -3
  20. data/documentation/diagrams/dot/persistence-filesystem.dot +2 -1
  21. data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +11 -4
  22. data/documentation/diagrams/dot/reinforcement-learning.dot +8 -3
  23. data/documentation/diagrams/memory-skills-detailed.svg +252 -210
  24. data/documentation/diagrams/overall-pwn-architecture.svg +21 -12
  25. data/documentation/diagrams/persistence-filesystem.svg +127 -113
  26. data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +449 -397
  27. data/documentation/diagrams/reinforcement-learning.svg +276 -239
  28. data/documentation/pwn-ai-Agent.md +31 -19
  29. data/lib/pwn/ai/agent/curriculum.rb +13 -4
  30. data/lib/pwn/ai/agent/dispatch.rb +3 -0
  31. data/lib/pwn/ai/agent/learning.rb +100 -14
  32. data/lib/pwn/ai/agent/loop.rb +114 -26
  33. data/lib/pwn/ai/agent/metrics.rb +52 -4
  34. data/lib/pwn/ai/agent/mistakes.rb +158 -1
  35. data/lib/pwn/ai/agent/policy.rb +935 -0
  36. data/lib/pwn/ai/agent/prompt_builder.rb +26 -5
  37. data/lib/pwn/ai/agent/reflect.rb +11 -3
  38. data/lib/pwn/ai/agent/registry.rb +18 -3
  39. data/lib/pwn/ai/agent/reward.rb +360 -48
  40. data/lib/pwn/ai/agent/task_summarizer.rb +37 -16
  41. data/lib/pwn/ai/agent/tool_guard.rb +157 -0
  42. data/lib/pwn/ai/agent/tools/policy.rb +76 -0
  43. data/lib/pwn/ai/agent/tools/ruby_eval.rb +27 -1
  44. data/lib/pwn/ai/agent/tools/shell.rb +28 -32
  45. data/lib/pwn/ai/agent.rb +2 -0
  46. data/lib/pwn/config.rb +7 -0
  47. data/lib/pwn/version.rb +1 -1
  48. data/spec/integration/reinforced_feedback_loop_spec.rb +35 -9
  49. data/spec/lib/pwn/ai/agent/learning_spec.rb +119 -3
  50. data/spec/lib/pwn/ai/agent/loop_spec.rb +0 -1
  51. data/spec/lib/pwn/ai/agent/metrics_spec.rb +10 -0
  52. data/spec/lib/pwn/ai/agent/mistakes_spec.rb +33 -0
  53. data/spec/lib/pwn/ai/agent/policy_spec.rb +165 -0
  54. data/spec/lib/pwn/ai/agent/reward_spec.rb +75 -0
  55. data/spec/lib/pwn/ai/agent/signal_hygiene_spec.rb +118 -0
  56. data/spec/lib/pwn/ai/agent/tool_guard_spec.rb +61 -0
  57. data/spec/lib/pwn/ai/agent/tools/policy_spec.rb +18 -0
  58. data/spec/support/sandbox.rb +2 -0
  59. data/third_party/pwn_rdoc.jsonl +83 -2
  60. metadata +8 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df46a72d0f582458534c1bcfcbdc0fcbf121cf002828ff5da313a5cf5eddea37
4
- data.tar.gz: c4bf47cbbe4e7ad22d52104f4fa9af499c06176cae9b93500652956428abe4a2
3
+ metadata.gz: 9640ee1c83ff54dc1e10246d519a448d648806e30b35b579284b23708b5b9924
4
+ data.tar.gz: 2cbd3b2296d32ad6d068d276c3badbfa599065c668bbec7ac58fa2baf84651d7
5
5
  SHA512:
6
- metadata.gz: c51242fc7542f675245804852cb313d75a8779675032148585cfde8afab392934d9da03eef08765d1339bca64732c7c3d7350a6ff76a366801c36e5b9e315df5
7
- data.tar.gz: 983ff27f8a551664fbc42a5d72357389fee1aaeeb67da5c7b82e4704fa54c06d469aa4589585369c48eca7441193644fd837a08049ee3a560a6bb99f424ba007
6
+ metadata.gz: fa11ac68afcc6cde52bc207526a50cf53283ac59dd89340f25f303329562e7d34c7a02cbd286ca6fe34fffcaa307a9b0e3f9c03c03c89dca3788f9150f702f0a
7
+ data.tar.gz: c9bd66494f36503ba864a7c97af7d7a77b2d9502a502ed04c897ce08e2e693982efe79a43abc4c12d95e1d4b4b97ea3a1ec6fba61b0711599e025bcc2b19618d
data/.rubocop.yml CHANGED
@@ -9,7 +9,7 @@ Lint/UselessRescue:
9
9
  Metrics/AbcSize:
10
10
  Max: 720
11
11
  Metrics/BlockLength:
12
- Max: 292
12
+ Max: 320
13
13
  Metrics/BlockNesting:
14
14
  Max: 6
15
15
  Metrics/ClassLength:
data/README.md CHANGED
@@ -35,7 +35,7 @@ and automate instead of gluing together a pile of separate CLIs.
35
35
 
36
36
  **In numbers:** 66 `PWN::Plugins` · 48 `PWN::SAST` rules · 90 `PWN::AWS`
37
37
  service wrappers · 21 `PWN::WWW` site drivers · 53 `bin/pwn_*` CLI drivers ·
38
- 6 LLM engines · 12 agent toolsets · 82 LLM-callable tools.
38
+ 6 LLM engines · 13 agent toolsets · 85 LLM-callable tools.
39
39
 
40
40
  Full page: [What is PWN](documentation/What-is-PWN.md)
41
41
 
@@ -66,7 +66,7 @@ My take: pwn-ai implements a **closed-loop, dual-horizon, self-and-world-aware r
66
66
 
67
67
  - fast aversive conditioning (Mistakes),
68
68
  - value estimates for actions (Metrics),
69
- - episode scoring and replay (Learning/Reward),
69
+ - episode scoring and replay (Learning/Reward, cheap LLM ORM with overlap last),
70
70
  - deliberate practice (Curriculum),
71
71
  - and an external reality check (Extrospection),
72
72
  - with a slower supervised/DPO hatch only when the diet and gates look sane.
@@ -96,12 +96,13 @@ small and easy to swap:
96
96
  ![PWN Overall Architecture](documentation/diagrams/overall-pwn-architecture.svg)
97
97
 
98
98
  On every turn the AI layer runs a **feedback loop**. It checks inward
99
- (Metrics, Learning, and **Mistakes**: what failed last time) and outward
99
+ (Metrics, Learning, **Mistakes**, and **Policy**: what failed last time, and
100
+ which tool the live Q / REINFORCE table currently prefers) and outward
100
101
  (Snapshot, Drift, Intel, RF, and **Web**: did the host or network change?).
101
102
  Live checks use browser-backed **`extro_verify`** / **`extro_watch`** and RF
102
103
  **`extro_rf_tune`**. `extro_correlate` joins those views so the agent can tell
103
104
  *"I messed up"* from *"the world moved"*, and **does not repeat the same
104
- mistake**:
105
+ mistake**. Policy is advice only. Planning still owns the task list:
105
106
 
106
107
  ![pwn-ai Feedback Learning Loop](documentation/diagrams/pwn-ai-feedback-learning-loop.svg)
107
108
 
@@ -139,9 +140,10 @@ The complete wiki lives in this repo at **[`documentation/Home.md`](documentatio
139
140
  | [Why PWN](documentation/Why-PWN.md) | [`pwn-ai` Agent](documentation/pwn-ai-Agent.md) | [Agent Tool Registry](documentation/Agent-Tool-Registry.md) | [SAST (48)](documentation/SAST.md) |
140
141
  | [How PWN Works](documentation/How-PWN-Works.md) | [CLI Drivers (53)](documentation/CLI-Drivers.md) | [Memory · Skills · Learning](documentation/Skills-Memory-Learning.md) | [AWS (90)](documentation/AWS.md) |
141
142
  | [Installation](documentation/Installation.md) | [Build a Driver](documentation/Drivers.md) | [Mistakes (neg-feedback)](documentation/Mistakes.md) | [WWW (21)](documentation/WWW.md) |
142
- | [General Usage](documentation/General-PWN-Usage.md) | | [Extrospection](documentation/Extrospection.md) | [SDR / Radio](documentation/SDR.md) |
143
- | [Configuration](documentation/Configuration.md) | | [Swarm (multi-agent)](documentation/Swarm.md) | [Hardware](documentation/Hardware.md) |
144
- | [`~/.pwn/` Persistence](documentation/Persistence.md) | | [Sessions](documentation/Sessions.md) · [Cron](documentation/Cron.md) | [Reports](documentation/Reporting.md) |
143
+ | [General Usage](documentation/General-PWN-Usage.md) | | [Reinforcement Learning](documentation/Reinforcement-Learning.md) | [SDR / Radio](documentation/SDR.md) |
144
+ | [Configuration](documentation/Configuration.md) | | [Extrospection](documentation/Extrospection.md) | [Hardware](documentation/Hardware.md) |
145
+ | [`~/.pwn/` Persistence](documentation/Persistence.md) | | [Swarm (multi-agent)](documentation/Swarm.md) | [Reports](documentation/Reporting.md) |
146
+ | | | [Sessions](documentation/Sessions.md) · [Cron](documentation/Cron.md) | |
145
147
  | **[All Diagrams](documentation/Diagrams.md)** (29) | | | [BurpSuite](documentation/BurpSuite.md) · [NmapIt](documentation/NmapIt.md) |
146
148
  | [Troubleshooting](documentation/Troubleshooting.md) | | | [Metasploit](documentation/Metasploit.md) · [Fuzzing](documentation/Fuzzing.md) |
147
149
  | [Contributing](documentation/Contributing.md) | | | [Blockchain](documentation/Blockchain.md) · [Bounty](documentation/Bounty.md) |
@@ -6,12 +6,12 @@ toolsets; the JSON-Schema for each tool is what the model actually sees.
6
6
 
7
7
  ![Tool registry](diagrams/agent-tool-registry.svg)
8
8
 
9
- ## Toolsets to tools (12 toolsets · 82 tools)
9
+ ## Toolsets to tools (13 toolsets · 85 tools)
10
10
 
11
11
  | Toolset | Tools | Backed by |
12
12
  |---|---|---|
13
- | `terminal` | `shell` | `Open3.capture3` on the host |
14
- | `pwn` | `pwn_eval` | `TOPLEVEL_BINDING.eval` in the live REPL process |
13
+ | `terminal` | `shell` | `Open3.capture3` on the host, after `PWN::AI::Agent::ToolGuard` |
14
+ | `pwn` | `pwn_eval` | `TOPLEVEL_BINDING.eval` in the live REPL process, after `ToolGuard` |
15
15
  | `memory` | `memory_remember` · `memory_recall` · `memory_forget` · `memory_clear` · **`memory_lean`** | `PWN::Memory` → `~/.pwn/memory.json` |
16
16
  | `skills` | `skill_list` · `skill_view` · `skill_create` · `skill_add_reference` · `skill_delete` · `skill_migrate_legacy` | `~/.pwn/skills/<name>/SKILL.md` (**[agentskills.io](https://agentskills.io) spec**; legacy flat `*.md` auto-migrated) |
17
17
  | `sessions` | `sessions_list` · `sessions_view` · `sessions_current` · `sessions_delete` · `sessions_stats` · **`sessions_lean`** | `PWN::Sessions` → `~/.pwn/sessions/` |
@@ -19,6 +19,7 @@ toolsets; the JSON-Schema for each tool is what the model actually sees.
19
19
  | `reward` | **`reward_generator_mix`** | `PWN::AI::Agent::Reward.generator_mix` → online preference source-mix controller (`preferences.jsonl`) |
20
20
  | `curriculum` | **`curriculum_practice_kpi`** | `PWN::AI::Agent::Curriculum.practice_kpi` → `~/.pwn/curriculum_kpi.jsonl` |
21
21
  | `metrics` | `metrics_summary` · `metrics_reset` | `PWN::AI::Agent::Metrics` → `~/.pwn/metrics.json` |
22
+ | `policy` | **`policy_stats`** · **`policy_evaluate`** · **`policy_recommend`** | `PWN::AI::Agent::Policy` → `~/.pwn/policy.json` + `~/.pwn/policy_traj.jsonl` |
22
23
  | `extrospection` | `extro_snapshot` · `extro_drift` · `extro_observe` · `extro_observations` · `extro_intel` · **`extro_watch`** · **`extro_verify`** · **`extro_rf_tune`** · **`extro_osint`** · **`extro_serial`** · **`extro_telecomm`** · **`extro_packet`** · **`extro_vision`** · **`extro_voice`** · `extro_correlate` · `extro_stats` · `extro_reset` · `extro_auto_toggle` | `PWN::AI::Agent::Extrospection` (+ Serial/Packet/OCR/Voice/BareSIP/TransparentBrowser/GQRX) → `~/.pwn/extrospection.json` |
23
24
  | `cron` | `cron_list` · `cron_create` · `cron_run` · `cron_enable` · `cron_disable` · `cron_remove` | `PWN::Cron` → `~/.pwn/cron/jobs.yml` |
24
25
  | `swarm` | `agent_list` · `agent_spawn` · `agent_ask` · `agent_debate` · `agent_broadcast` · `swarm_bus` · `swarm_list` | `PWN::AI::Agent::Swarm` → `~/.pwn/agents.yml` + `~/.pwn/swarm/` |
@@ -30,6 +31,17 @@ the same self-improvement loop - see [Reinforcement Learning](Reinforcement-Lear
30
31
  The thin `reward` and `curriculum` toolsets expose controller and KPI surfaces
31
32
  (`reward_generator_mix`, `curriculum_practice_kpi`) so personas can grant just
32
33
  those without the full learning surface.
34
+ `shell` and `pwn_eval` share `PWN::AI::Agent::ToolGuard`
35
+ (`lib/pwn/ai/agent/tool_guard.rb`) before they run. The guard remaps common
36
+ wrong keys, rejects ellipsis placeholders, refuses bash-only syntax unless
37
+ `ai.agent.shell_bash` is true (default runner is `/bin/sh`), and blocks live
38
+ host-discovery unless the request is in-scope or `ai.agent.recon_authorized`
39
+ is true.
40
+
41
+ The `policy` toolset is inspect-only. `policy_stats`, `policy_evaluate`, and
42
+ `policy_recommend` read the live Q / REINFORCE table. Reset is Ruby-only, so a
43
+ tool call cannot wipe the weights. `Registry.rank` may add a small Q-advantage
44
+ after a pair has been visited at least twice. Planning still owns the work.
33
45
 
34
46
  **Store hygiene tools** (`memory_lean`, `sessions_lean`, `mistakes_lean`,
35
47
  `learning_gc_stores`) trim ephemeral or oversized state without dropping
@@ -54,8 +66,8 @@ CORE_TOOLS = shell · pwn_eval · memory_remember · memory_recall
54
66
  ```ruby
55
67
  PWN::AI::Agent::Registry.definitions(relevance: 'nmap sweep 10.0.0.0/8', top_k: 10)
56
68
  PWN::AI::Agent::Registry.rank(query: 'run a shell command') # inspect ranking
57
- PWN::AI::Agent::Registry.toolsets # → the 12 names above
58
- PWN::AI::Agent::Registry.all.count # → 82
69
+ PWN::AI::Agent::Registry.toolsets # → the 13 names above
70
+ PWN::AI::Agent::Registry.all.count # → 85
59
71
  ```
60
72
 
61
73
  Frontier engines leave `tool_router` off and receive the full set.
@@ -109,10 +109,12 @@ ai:
109
109
  auto_introspect: true # Run Learning.auto_introspect (outcome logging + lesson mining) after every final answer.
110
110
  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.
111
111
  recon_authorized: false # Allow live subnet sweeps / raw-socket discovery tools this session
112
+ shell_bash: false # true → run shell via bash -lc (PIPESTATUS, [[ ]], process substitution). Default is /bin/sh.
112
113
  plan_first: ~ # Plan-then-act pre-pass: force the model to externalize a numbered tool plan BEFORE its first dispatch. nil = auto (true when ai.active == ollama).
113
114
  tool_router: false # Dynamic tool-set slimming: ship only Registry::CORE_TOOLS + top-K keyword-relevant schemas per turn (helps small models route correctly).
114
115
  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.
115
- toolsets: ~ # Allow-list of toolsets exposed to the agent. nil = all. Valid: cron, curriculum, extrospection, learning, memory, metrics, pwn, reward, sessions, skills, swarm, terminal.
116
+ policy: true # Live tabular Q / REINFORCE. Advisory only; never replaces TaskSummarizer / plan_first. false disables.
117
+ toolsets: ~ # Allow-list of toolsets exposed to the agent. nil = all. Valid: cron, curriculum, extrospection, learning, memory, metrics, policy, pwn, reward, sessions, skills, swarm, terminal.
116
118
  extrospection:
117
119
  web:
118
120
  anchors: # URLs the headless browser fingerprints on extro_snapshot(sections:[:web]). Alias: web_anchors.
@@ -275,16 +277,21 @@ PWN::Config.refresh_env
275
277
  | `ai.agent.max_depth` | Integer | `3` | `PWN::AI::Agent::Swarm` | Recursion guard for `agent_ask` / `agent_debate` sub-agents spawning sub-agents. |
276
278
  | `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`. |
277
279
  | `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`. |
278
- | `ai.agent.toolsets` | Array\<String\> \| `nil` | `nil` (all) | `bin/pwn`, `PWN::Plugins::REPL`, `PWN::AI::Agent::Registry` | Allow-list of toolsets exposed to the agent. Valid: `cron`, `curriculum`, `extrospection`, `learning`, `memory`, `metrics`, `pwn`, `reward`, `sessions`, `skills`, `swarm`, `terminal`. |
279
- | `ai.agent.recon_authorized` | Boolean | `false` | `PWN::AI::Agent::Loop.recon_authorized?` / shell guard | When true (or the user request contains in-scope / engagement language), live host-discovery tools may run. Default refuses unauthorized sweeps. |
280
+ | `ai.agent.toolsets` | Array\<String\> \| `nil` | `nil` (all) | `bin/pwn`, `PWN::Plugins::REPL`, `PWN::AI::Agent::Registry` | Allow-list of toolsets exposed to the agent. Valid: `cron`, `curriculum`, `extrospection`, `learning`, `memory`, `metrics`, `policy`, `pwn`, `reward`, `sessions`, `skills`, `swarm`, `terminal`. |
281
+ | `ai.agent.recon_authorized` | Boolean | `false` | `PWN::AI::Agent::ToolGuard.recon_authorized?` / `Loop.recon_authorized?` | When true (or the user request contains in-scope / engagement language), live host-discovery tools may run. Default refuses unauthorized sweeps. |
282
+ | `ai.agent.shell_bash` | Boolean | `false` | `PWN::AI::Agent::ToolGuard.shell_bash?` | When true, `shell` runs via `bash -lc` so bash-only syntax is allowed. Default is POSIX `/bin/sh` and bashisms are rejected with a rewrite hint. |
280
283
  | `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. |
281
284
  | `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. |
282
285
  | `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. |
283
- | `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. |
284
- | `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. |
285
- | `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. |
286
- | `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. |
287
- | `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`. |
286
+ | `ai.agent.critic` | Boolean | `false` | `PWN::AI::Agent::Curriculum.critic` | Tool-armed constitutional self-critic reviews (and may `shell`/`extro_verify`) every final answer before it is returned. |
287
+ | `ai.agent.red_team_plan` | Boolean | `false` | `PWN::AI::Agent::Curriculum.red_team_plan` | Adversarial review of the `plan_first` numbered plan, grounded in Metrics/Mistakes/`extro_drift` telemetry, before the first dispatch. |
288
+ | `ai.agent.counterfactual` | Boolean | `false` | `PWN::AI::Agent::Curriculum.counterfactual` | On `[REPEATING]`, fork an alt-persona branch, judge both, and record the `(loser, winner)` DPO preference pair. |
289
+ | `ai.agent.hindsight` | Boolean | `true` | `PWN::AI::Agent::Curriculum.hindsight` | Hindsight Experience Replay - relabel a failed trajectory as `success:true` for whatever it *did* accomplish. Free positive samples from failures. |
290
+ | `ai.agent.policy` | Boolean | `true` | `PWN::AI::Agent::Policy` | Live tabular Q-learning + REINFORCE. Records `(s,a,r,s')` per tool step, trains on `Reward.judge` at episode end, and adds a small Q-advantage term to `Registry.rank`. Advisory only: never replaces TaskSummarizer or plan_first. |
291
+ | `ai.agent.reward_llm` | Boolean \| `nil` | `nil` (auto: on for remote, off for ollama) | `PWN::AI::Agent::Reward.judge` / `.prm` | Use a cheap LLM teacher for outcome/process judges even when `module_reflection` is false. Local ollama stays heuristic unless this is `true`. |
292
+ | `ai.agent.reward_model` | String \| `nil` | `nil` | `Reward.judge` / `.prm` | Optional cheaper model id for the ORM/PRM chat. Falls back to `ai.reflect_model`, then the active engine default. |
293
+ | `ai.agent.reward_llm_timeout` | Integer | `12` | `Reward.judge` / `.prm` | Seconds for the cheap ORM chat (clamped 2..30). Fail fast to the overlap heuristic rather than a 900s hang. |
294
+ | `ai.agent.verify_as_reward` | Boolean | `false` | `PWN::AI::Agent::Reward.verify_as_reward` | Ground the LLM judge score by browser-verifying any checkable claim in the final via `extro_verify`; verdict caps/floors `Reward.judge`. |
288
295
  | `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`. |
289
296
  | `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`). |
290
297
  | `ai.agent.extrospection.web.max_anchors` | Integer | `8` | `Extrospection.probe_web` | Cap on anchors rendered per snapshot. |
@@ -60,7 +60,7 @@ groups) so lines never criss-cross.
60
60
  [source](diagrams/dot/mistakes-negative-feedback.dot) · doc: [Mistakes](Mistakes.md)
61
61
  ![mistakes-negative-feedback](diagrams/mistakes-negative-feedback.svg)
62
62
 
63
- ### Reinforcement Learning - Reward + Curriculum
63
+ ### Reinforcement Learning - Reward + Curriculum + Policy
64
64
  [source](diagrams/dot/reinforcement-learning.dot) · doc: [Reinforcement Learning](Reinforcement-Learning.md)
65
65
  ![reinforcement-learning](diagrams/reinforcement-learning.svg)
66
66
 
@@ -68,7 +68,7 @@ groups) so lines never criss-cross.
68
68
  [source](diagrams/dot/ai-integration-tool-calling.dot) · doc: [AI Integration](AI-Integration.md)
69
69
  ![ai-integration-tool-calling](diagrams/ai-integration-tool-calling.svg)
70
70
 
71
- ### Agent Tool Registry (12 toolsets · 82 tools)
71
+ ### Agent Tool Registry (13 toolsets · 85 tools)
72
72
  [source](diagrams/dot/agent-tool-registry.dot) · doc: [Agent Tool Registry](Agent-Tool-Registry.md)
73
73
  ![agent-tool-registry](diagrams/agent-tool-registry.svg)
74
74
 
@@ -36,10 +36,10 @@
36
36
  | | |
37
37
  |---|---|
38
38
  | [AI / LLM Integration](AI-Integration.md) | OpenAI · Anthropic · Grok (OAuth) · Gemini · Ollama · Open WebUI |
39
- | [Agent Tool Registry](Agent-Tool-Registry.md) | 12 toolsets · **82** LLM-callable tools |
39
+ | [Agent Tool Registry](Agent-Tool-Registry.md) | 13 toolsets · **85** LLM-callable tools |
40
40
  | [Memory · Skills · Learning](Skills-Memory-Learning.md) | Introspection - the self-improvement loop |
41
41
  | [Mistakes](Mistakes.md) | **Negative feedback** - fingerprint failures · do-NOT-repeat · `[REPEATING]`/`[REGRESSED]` · inline self-correction |
42
- | [Reinforcement Learning](Reinforcement-Learning.md) | **`Reward` + `Curriculum`** - outcome/process judges · preference ledger · self-play practice · export-ready LoRA gate |
42
+ | [Reinforcement Learning](Reinforcement-Learning.md) | **`Reward` + `Curriculum` + `Policy`** - outcome/process judges · preference ledger · self-play practice · live Q / REINFORCE (advisory) · export-ready LoRA gate |
43
43
  | [Extrospection](Extrospection.md) | World-awareness - snapshot · drift · intel · **watch** · **verify** · **rf_tune** · **osint** · serial · telecomm · packet · vision · voice · correlate |
44
44
  | [Swarm (Multi-Agent)](Swarm.md) | Personas · ask · debate · broadcast · shared bus |
45
45
  | [Sessions](Sessions.md) | Transcript persistence + reflection |
@@ -29,19 +29,19 @@ hardware).
29
29
  |---|---|
30
30
  | `Loop` | plan → **TaskSummarizer** briefs → dispatch tool_calls → observe → repeat until final answer; tightens runway when recent turns exhausted the budget |
31
31
  | **`TaskSummarizer`** | Executive UX: LLM/heuristic `request_kind` gates plans (only autonomous goals, including host-evidence Qs) - English tasks primary - `emit_plan!` · `about_to` as `task k/n` + via tools · Loop `plan_context` injection · clearer `plan_idx` advance |
32
- | `Registry` | JSON-Schema function definitions grouped into 12 **toolsets** · **82 tools** |
32
+ | `Registry` | JSON-Schema function definitions grouped into 13 **toolsets** · **85 tools** |
33
33
  | `Dispatch` / `Result` | execute a tool, capture stdout/value/error/duration |
34
- | `PromptBuilder` | inject MEMORY / SKILLS / LEARNING / **KNOWN MISTAKES + FIXES** / METRICS / EXTROSPECTION blocks |
35
- | `Metrics` · `Learning` · `Reflect` | **introspection** - how well am I doing? |
34
+ | `PromptBuilder` | inject MEMORY / SKILLS / LEARNING / **KNOWN MISTAKES + FIXES** / METRICS / **POLICY** / EXTROSPECTION / RECENT TURNS |
35
+ | `Metrics` · `Learning` · `Reflect` · **`Policy`** | **introspection** - how well am I doing? (Policy is live Q / REINFORCE, advisory rank only) |
36
36
  | `Mistakes` | **negative feedback** - fingerprint failures, do NOT repeat, `[REPEATING]`/`[REGRESSED]`, inline `correction_hint` |
37
- | **`Reward`** | outcome `judge` · per-step process credit · `sentinel` (proxy vs judge drift) · `semantic_ok` · DPO `preferences.jsonl` |
37
+ | **`Reward`** | cheap LLM outcome `judge` (heuristic overlap last) · per-step process credit · `sentinel` (proxy vs ORM-weighted judge) · `semantic_ok` · DPO `preferences.jsonl` |
38
38
  | **`Curriculum`** | mistake-driven self-play `practice` · `counterfactual` A/B · tool-armed `critic` · `red_team_plan` · `hindsight` (HER) · `train_and_gate` regression-gated LoRA |
39
39
  | `Extrospection` | **extrospection** - on-demand world sensing (`intel` · **`verify`** · **`watch`** · **`rf_tune`** · **`osint`** · `serial` · `telecomm` · `packet` · `vision` · `voice`) + ambient baseline (host · net · toolchain · repo · env · **rf** · **web**) joined to introspection via `correlate` |
40
40
  | `Swarm` | multi-agent personas over a shared JSONL bus |
41
41
 
42
42
  See [Agent Tool Registry](Agent-Tool-Registry.md) for every tool the LLM can
43
43
  call, and [Reinforcement Learning](Reinforcement-Learning.md) for how
44
- `Reward` + `Curriculum` close the weight-level loop.
44
+ `Reward` + `Curriculum` + `Policy` close the learning loop.
45
45
 
46
46
  ## L3 - Capability namespaces (`lib/pwn/*`)
47
47
 
@@ -69,10 +69,12 @@ lessons, **failures become fingerprinted mistakes with fixes**, **world state
69
69
  is sensed on demand** (`extro_verify` / `extro_watch` / `extro_rf_tune` /
70
70
  `extro_osint` / `extro_serial` / `extro_telecomm` / `extro_packet` /
71
71
  `extro_vision` / `extro_voice` / `extro_intel`) and correlated against those
72
- failures, an **LLM judge scores the final answer** and a **process reward
73
- model tags each tool step**, and **all six prompt blocks** (MEMORY · SKILLS ·
74
- LEARNING · KNOWN MISTAKES/FIXES · TOOL EFFECTIVENESS · EXTROSPECTION) are
75
- re-injected into the next system prompt.
72
+ failures, a **cheap LLM judge scores the final answer** (token overlap only if the engine is unavailable) and a **process reward
73
+ model tags each tool step**, **Policy records the live MDP step** and updates
74
+ Q / REINFORCE when the judge scores the turn, and **the prompt blocks**
75
+ (MEMORY · SKILLS · LEARNING · KNOWN MISTAKES/FIXES · TOOL EFFECTIVENESS ·
76
+ POLICY · EXTROSPECTION · RECENT TURNS) are re-injected into the next system
77
+ prompt.
76
78
  Nightly cron practices the top unresolved Mistakes; weekly cron builds a
77
79
  LoRA and only promotes it if it beats the previous adapter on that same
78
80
  mistake set:
@@ -187,7 +187,9 @@ predates the running gem (`PWN::Migrate.needed?`).
187
187
 
188
188
  Schema `v1` also seeds `PWN::Cron.install_defaults` - the nightly
189
189
  `curriculum_practice` and weekly `curriculum_train` self-improvement jobs
190
- (see [Reinforcement Learning](Reinforcement-Learning.md)).
190
+ (see [Reinforcement Learning](Reinforcement-Learning.md)). Live Policy
191
+ files (`policy.json`, `policy_traj.jsonl`) are created on first agent turn
192
+ when `ai.agent.policy` is on.
191
193
 
192
194
  From a checkout:
193
195
 
@@ -38,10 +38,13 @@ Loop.run --(same sig, count≥3)----> guard_repeated_failure (uses PERSISTENT c
38
38
  Loop.run --(failure w/ known fix)-> inline correction_hint ("seen 5×, sig=..., KNOWN FIX: ..."
39
39
  → self-corrects NEXT iteration)
40
40
  Loop.run --(user says "wrong")----> check_user_correction (flip last outcome + record)
41
+ Loop.run --(start of turn)--------> extinguish_parked! (close inbox scars that already have a known recipe)
41
42
  PromptBuilder <-------------------- Mistakes.to_context (KNOWN MISTAKES + KNOWN FIXES)
42
43
  model --(tool call)---------------> mistakes_record / mistakes_resolve
43
44
  ```
44
45
 
46
+ Repeating shell failures with a known recipe (`command is required`, missing path, not-found junk, syntax, raw-socket deny) are resolved in place instead of parked as "needs human". Only scars the loop cannot close stay in the operator inbox.
47
+
45
48
  ## Five ingest paths - nothing slips through
46
49
 
47
50
  | Source | Trigger | What is recorded |
@@ -16,6 +16,8 @@ Every byte PWN remembers between processes lives here.
16
16
  | **`preferences.jsonl`** | **`PWN::AI::Agent::Reward`** | JSON-per-line `{prompt,rejected,chosen,source}` | `rm` | **DPO/KTO/ORPO preference-pair ledger - user_correction · mistakes_resolve · counterfactual · critic · curriculum** |
17
17
  | **`mistakes.json`** | **`PWN::AI::Agent::Mistakes`** | **JSON `{sig → entry}`** | **`mistakes_reset`** | **failure fingerprints · cross-session count · fix · `[REPEATING]` · `[REGRESSED]`** |
18
18
  | `metrics.json` | `PWN::AI::Agent::Metrics` | JSON | `metrics_reset` | per-tool calls · success · avg_duration · last_error · **per-engine** sub-buckets · calibration |
19
+ | **`policy.json`** | **`PWN::AI::Agent::Policy`** | JSON `{q,h,visits,returns}` | `PWN::AI::Agent::Policy.reset` | Live Q table + REINFORCE logits. Advisory rank only. |
20
+ | **`policy_traj.jsonl`** | **`PWN::AI::Agent::Policy`** | JSON-per-line episodes | `PWN::AI::Agent::Policy.reset` | MDP trajectories `(s,a,r,s')` from each Loop turn |
19
21
  | `reward_sentinel.json` | `PWN::AI::Agent::Reward` | JSON | `rm` | proxy vs judge vs user-correction gap history |
20
22
  | `extrospection.json` | `PWN::AI::Agent::Extrospection` | JSON | `extro_reset` | host/net/toolchain/repo/env/**rf**/**web**/osint/serial/telecomm/packet/vision/voice snapshot + previous baseline + observations[] |
21
23
  | `extrospection/web/*.png` | `Extrospection` | PNG | `rm -rf` | headless-browser screenshots from `probe_web` / `extro_watch` (opt-in) |
@@ -76,6 +78,7 @@ extro_reset(confirm: true) # host snapshot + observations
76
78
  mistakes_reset(confirm: true) # failure fingerprints (host-specific errors)
77
79
  learning_reset(confirm: true) # task outcomes (optional)
78
80
  metrics_reset(confirm: true) # tool telemetry (optional)
81
+ PWN::AI::Agent::Policy.reset # live Q table + trajectory log (optional)
79
82
  ```
80
83
 
81
84
  [← Home](Home.md) · [Configuration](Configuration.md) · [Installation](Installation.md)
@@ -90,7 +93,7 @@ protected operator preferences:
90
93
  | `memory_lean` | expired `session_*` keys and overlong values (`VALUE_MAX_CHARS`) |
91
94
  | `sessions_lean` | stub/aged transcripts not pinned by gold outcomes or open mistakes |
92
95
  | `mistakes_lean` | compact fields; age out resolved-once signatures whose fix already lives in Memory |
93
- | `learning_gc_stores` | coordinated lean pass across memory, learning, mistakes, and sessions |
96
+ | `learning_gc_stores` | coordinated lean pass across memory, learning, mistakes, sessions, and Policy trajectories |
94
97
 
95
98
  All four support `dry_run: true` (plan only). Protected `operator_pref_*`,
96
99
  `process_sop_*`, and `mistake_fix_*` memory keys are never removed by lean.
@@ -1,51 +1,77 @@
1
1
  # Reinforcement Learning in pwn-ai
2
2
 
3
- pwn-ai runs an in-context learning loop that can also export training data for
4
- a local model. On hosts **with a trainer and GPU**, the path
3
+ pwn-ai learns while you work. Most of that learning stays **in context**: the
4
+ agent writes what happened to disk and puts the useful bits back into the next
5
+ prompt. On a host **with a trainer and a GPU**, the same data can also train a
6
+ local adapter.
5
7
 
6
8
  `Curriculum.practice` → `Reward.export_dpo` → `Curriculum.train_and_gate`
7
9
 
8
- can promote a new LoRA. Without a trainer the same path is **export-ready**
9
- (datasets plus a manual CLI). Live improvement still happens in-context on
10
- every turn.
10
+ That path can promote a new LoRA when the candidate beats the current one.
11
+ Without a trainer it still **exports** the datasets and a manual CLI. Live
12
+ improvement does not wait on weights.
11
13
 
12
14
  ![Reinforcement-learning loop](diagrams/reinforcement-learning.svg)
13
15
 
14
16
  ```
15
17
  +------------------------------------------------+
16
18
  request -----> | Loop.run |
17
- | plan_first -> Curriculum.red_team_plan (S4) |
18
- | Dispatch -> Reward.semantic_ok (R4) |
19
- | -> Mistakes.record(cause:) |
20
- | guard -> Curriculum.counterfactual (S2) |--> preference ledger (W1)
21
- | final -> Curriculum.critic (S3) |
22
- | -> Reward.judge (outcome) (R1) |--> verify_as_reward (E3)
23
- | -> Reward.prm (process) (R2) |--> Sessions[step_reward] (C4)
24
- | -> Curriculum.hindsight (C3) |
25
- | -> Curriculum.calibrate (W3) |--> Metrics.calibration
26
- | -> Reward.sentinel (R3) |--> Mistakes(reward_signal)
19
+ | plan_first -> Curriculum.red_team_plan (S4) |
20
+ | Dispatch -> Reward.semantic_ok (R4) |
21
+ | -> Mistakes.record(cause:) (E1) |
22
+ | guard -> Curriculum.counterfactual (S2) |--> preference ledger (W1)
23
+ | final -> Curriculum.critic (S3) |
24
+ | -> Reward.judge (outcome) (R1) |--> verify_as_reward (E3)
25
+ | -> Reward.prm (process) (R2) |--> Sessions[step_reward] (C4)
26
+ | -> Curriculum.hindsight (C3) |
27
+ | -> Curriculum.calibrate (W3) |--> Metrics.calibration
28
+ | -> Reward.sentinel (R3) |--> Mistakes(reward_signal)
27
29
  +------------------------------------------------+
28
30
  |
29
- Learning.consolidate (M1 semantic merge, M3 importance eviction)
31
+ Learning.consolidate (M1 merge, M3 importance-evict)
30
32
  MemoryIndex.recall_semantic (M2 similarity x recency x importance)
31
- Registry.rank (C1 keyword fit + advantage + UCB)
33
+ Registry.rank (C1 keyword + UCB + Q-advantage)
34
+ Policy (R5 live Q / REINFORCE on a judge-scored MDP)
32
35
  Learning.exemplars_for (C2 prioritized replay, C4 minimal trace)
33
36
  |
34
- nightly cron --> Curriculum.practice (S1) --> Mistakes.resolve --> preference ledger (W1)
37
+ nightly cron --> Curriculum.practice (S1) --> Mistakes.resolve --> preference (W1)
35
38
  weekly cron --> Curriculum.train_and_gate (W2) --> optional LoRA --> A/B gate --> promote
36
39
  |
37
- Extrospection.correlate (E2 world vs self join)
38
- Metrics.changepoints (E1) --> Mistakes(cause: :env_drift)
40
+ Extrospection.correlate (E2 world vs self)
41
+ Metrics.changepoints (E1 CUSUM) --> Mistakes(cause: :env_drift)
39
42
  ```
40
43
 
44
+ ## Live Policy on every turn (R5 · `PWN::AI::Agent::Policy`)
45
+
46
+ This is the live numeric controller. It does not replace planning.
47
+
48
+ | Piece | What it is |
49
+ |---|---|
50
+ | State | request kind, task family, plan quality, answer completeness, usable-result, last action, fail bin, and engine |
51
+ | Action | tool name, or `final` |
52
+ | Step reward | `Reward.semantic_ok` hygiene (`+0.05` / `-0.20`) |
53
+ | Terminal reward | `Reward.judge` score (skipped when the cheap proxy is untrusted and there is no judge) |
54
+ | Updates | Q-learning (`alpha=0.15`, `gamma=0.85`) and REINFORCE (`alpha=0.05`). Stored trajectories replay twice on warmup so a short table is not empty advice. |
55
+ | Budget | Eight finished episodes (live or warmup-credited) unlock greedy suggestions. Until then the prompt omits them. |
56
+ | Steer | Q-advantage in `Registry.rank` once the episode budget is met; keyword fit and CORE_TOOLS still come first |
57
+ | Files | `~/.pwn/policy.json`, `~/.pwn/policy_traj.jsonl` |
58
+ | Tools | `policy_stats` · `policy_evaluate` · `policy_recommend` (inspect only) |
59
+ | Off switch | `ai.agent.policy: false` |
60
+
61
+ Loop calls `begin_episode` before the first rank, `observe_step` after each
62
+ tool, and `finish` from `Learning.auto_introspect` (or Loop if introspect is
63
+ skipped). `Learning.gc_stores` can trim old trajectories without dropping
64
+ high-return / high-score episodes.
65
+
41
66
  ## Reward signal (`PWN::AI::Agent::Reward`)
42
67
 
43
68
  | ID | Method | What it does |
44
69
  |----|--------|--------------|
45
- | **R1** | `.judge` | Outcome score on `(request, final)` → `{score:0..1, verdict:, rationale:, key_step:}`. Replaces brittle success regexes. |
70
+ | **R1** | `.judge` | Cheap LLM outcome score on `(request, final)` → `{score:0..1, verdict:, rationale:, key_step:, source:}`. Calls the active engine `.chat` with a short timeout (default 12s). `Reflect.on` is used only when `module_reflection` is on. Fallback scores completeness, plan cover, claims, and tool-trace echo. Token overlap is only a small on-topic gate. |
46
71
  | **R2** | `.prm` | Process reward - per-tool-step `+1/0/-1` written into `Sessions[:step_reward]`. |
47
72
  | **R3** | `.sentinel` | Compares proxy success rate vs judge mean vs user-correction rate. A large gap fingerprints `reward_signal` so the agent distrusts a lying proxy. |
48
- | **R4** | `.semantic_ok` | Treats informational non-zero exits (e.g. `grep`/`rg` with no match) as benign. Metrics count them as OK; Mistakes only see true dispatch failures. |
73
+ | **R4** | `.semantic_ok` | Treats informational non-zero exits (for example `grep` / `rg` with no match) as benign. Metrics count them as OK; Mistakes only see true dispatch failures. |
74
+ | **R5** | `Policy` (live MDP) | Tabular Q-learning + REINFORCE on real Loop turns. Q-advantage is an advisory `Registry.rank` term and never replaces TaskSummarizer or plan_first. |
49
75
  | - | `.warm_sentinel` | Backfills the sentinel window from scored Learning outcomes so local hosts can engage proxy distrust without waiting for live remote introspect. |
50
76
  | **W1** | `.record_preference` / `.export_dpo` | Preference ledger (`~/.pwn/preferences.jsonl`) from user corrections, resolve, counterfactual, critic, and practice. Caps per source; keeps trajectory-shaped pairs (winning traces / revised answers), not fix commentary. |
51
77
  | - | `.scrub_preferences` / `.preference_balance` / `.generator_mix` | Ledger hygiene and source-mix health so one channel cannot flood preference export. |
@@ -54,9 +80,9 @@ every turn.
54
80
 
55
81
  | ID | Where | What |
56
82
  |----|-------|------|
57
- | **C1** | `Registry.rank` + `Metrics.{ucb,thompson,advantage,prm_advantage}` | Live tool choice blends keyword fit, historical advantage, exploration bonus, and process-reward signal. |
83
+ | **C1** | `Registry.rank` + `Metrics.{ucb,thompson,advantage,prm_advantage}` + `Policy.advantage` | Live tool choice blends keyword fit, historical advantage, exploration bonus, process-reward signal, and (once the episode budget is met) Q(s,a)-V(s). Neighbor states fill cold (s,a) pairs. |
58
84
  | **C2** | `Learning.exemplars_for` | Prior successful traces ranked by judge score, recency, and keyword fit. Low-score "proxy success" rows are dropped when judge distrust is high. |
59
- | **C3** | `Curriculum.hindsight` | On a failed goal, relabel what the trajectory *did* achieve (`success: 'soft'`). Soft rows stay out of hard SFT and are down-weighted in exemplars. |
85
+ | **C3** | `Curriculum.hindsight` | On a failed goal, relabel what the trajectory *did* achieve (`success: 'soft'`). Soft rows stay out of hard supervised export and are down-weighted in exemplars. |
60
86
  | **C4** | `Learning.compress_exemplar` / skill build | Keep steps with positive `step_reward` so few-shot traces stay short. |
61
87
 
62
88
  ## Memory that stays high-signal
@@ -77,9 +103,9 @@ every turn.
77
103
  | **S3** | `.critic` | Constitutional critic of the final answer (can use tools). Under budget pressure, runs text-only so it cannot burn the remaining iterations. |
78
104
  | **S4** | `.red_team_plan` | Adversarial review of the plan-first outline using Metrics / Mistakes / drift. |
79
105
  | - | `.offline_judge` | Score recent sessions with outcome + process judges, warm the sentinel, optional ledger scrub. Meant for nightly cron on local hosts that only introspect failures live. |
80
- | **C3** | `.hindsight` | HER relabel described above. |
106
+ | **C3** | `.hindsight` | Relabel described above. |
81
107
  | **W3** | `.calibrate` | Plan `p(success)=` vs actual outcome → per-engine Brier / overconfidence. Overconfidence can force plan_first + critic and tighten `max_iters`. |
82
- | **W2** | `.train_and_gate` | Export SFT + DPO → optional LoRA train → promote only if the candidate wins on resolved margin, mean judge, smoke set, and a healthy preference diet. Without a trainer: `weight_loop: :export_ready`. |
108
+ | **W2** | `.train_and_gate` | Export supervised + preference data → optional LoRA train → promote only if the candidate wins on resolved margin, mean judge, smoke set, and a healthy preference diet. Without a trainer: `weight_loop: :export_ready`. |
83
109
  | - | `.practice_kpi` | Week-over-week trend of repeating mistakes (outer curriculum health). |
84
110
 
85
111
  ## Budget pressure (iteration ceiling)
@@ -88,7 +114,7 @@ When unresolved `agent_loop` / `assistant_answer` budget-exhaustion fingerprints
88
114
  dominate, the loop marks the budget path hot and tightens the live turn:
89
115
 
90
116
  - lower effective `max_iters` (stricter on local/ollama engines than remote)
91
- - **Last-iter force-final**: tools=nil on the final iteration so a text answer is required
117
+ - last-iter force-final: tools=nil on the final iteration so a text answer is required
92
118
  - skip counterfactual / red-team forks that would spend more tool rounds
93
119
  - still flush TaskSummarizer state and Learning on the exhaust path
94
120
  - end-of-turn critic runs text-only under the same pressure
@@ -96,27 +122,50 @@ dominate, the loop marks the budget path hot and tightens the live turn:
96
122
  Practice prioritizes those scars with short-horizon "finish the task" prompts.
97
123
  Raising `ai.agent.max_iters` or resolving the scar returns normal runway.
98
124
 
125
+ ## Design-priority STATUS (post P14-P25)
126
+
127
+ This table is the flag authority. Stop minting new P-numbers for chores already
128
+ covered. Track these outcomes instead of hunting comments in the source.
129
+
130
+ | Pri | ID | Control | Module(s) | Success criterion |
131
+ |-----|----|---------|-----------|-------------------|
132
+ | **P0** | W1 generator diversity | `Reward::TARGET_SOURCE_MIX` + `generator_mix` + mix-urgent force on critic/counterfactual | `reward.rb`, `curriculum.rb` | `generator_mix.healthy` OR `recommendation` not stuck on `suppress:mistakes_resolve`; trajectory_fraction ≥ 0.5 |
133
+ | **P0** | Introspect budget | `Learning::INTROSPECT_SOFT_MS` / `HARD_MS`; stage skip under soft/hard / `budget_exhaustion_hot?` | `learning.rb` | `auto_introspect` returns `stages_skipped` when over soft; post-answer path cannot re-thrash tool critic |
134
+ | **P1** | Local judge calibration | Heuristic score shrinkage + `confidence`; `Metrics.effective_rate` scales distrust by `judge_confidence` | `reward.rb`, `metrics.rb` | distrust × heuristic no longer fully replaces proxy; local no-trace highs capped |
135
+ | **ops** | Cheap LLM ORM | Direct engine `.chat` for `Reward.judge` / `.prm`; optional `reward_model` / `reward_llm_timeout`; evidence-prior fallback last | `reward.rb` | remote turns grade with ORM even when `module_reflection` is off |
136
+ | **ops** | Outcome-signal haircut | `judge_sample_weight` (ORM 1.0, heuristic 0.25) in sentinel / `Learning.stats` / `Metrics.judge_rate` | `reward.rb`, `learning.rb`, `metrics.rb` | proxy distrust blends toward ORM scores, not bag-of-words overlap |
137
+ | **P1** | Practice outer KPI | `Curriculum.practice_kpi` / `repeating_trend` → `~/.pwn/curriculum_kpi.jsonl` | `curriculum.rb` | week-over-week `delta_repeating` ≤ 0 on budget fingerprints after practice nights |
138
+ | **P2** | PRM sample efficiency | `PRM_MIN_N=5`, shrinkage to `PRM_FULL_N=20`, fleet coverage gate in `Registry.rank` | `metrics.rb`, `registry.rb` | `prm_advantage=0` until n≥5; rank delta=0 until ≥3 tools ready |
139
+ | **P2** | STATUS over flag archaeology | This table | docs | New work cites Pri/ID here, not fresh P26+ comments for the same theme |
140
+ | **ops** | Nightly diet close | `offline_judge` → `scrub_preferences` + `generator_mix` + `practice_kpi` | `curriculum.rb` | Cron path returns `scrub`/`generator_mix`/`practice_kpi`; raw resolve prose does not survive the night |
141
+ | **ops** | Shape backfill | `Reward.infer_shape` + scrub rewrite | `reward.rb` | Legacy shapeless rows get `winning_trace`/`revised_answer` when content warrants; traj_f measurable |
142
+ | **ops** | Mix in prompt | `Metrics.to_context` emits `W1 MIX:` when unhealthy | `metrics.rb` | Unhealthy diet visible every turn without a tool call |
143
+ | **P0** | Budget exhaust deepen | Last-iter force-final (tools=nil); skip CF when `budget_exhaustion_hot?`; tighter caps 24 local / 75 remote; exhaust path `append_session`+`auto_introspect` | `loop.rb` | Exhaust returns a judged final, not a bare string; CF cannot re-enter under hot; last iter cannot tool-call |
144
+
99
145
  ## Intro and extro join
100
146
 
101
- | Where | What |
102
- |-------|------|
103
- | `Metrics.changepoints` + `Loop.attribute_cause` (**E1**) | Env-drift-attributed failures get `cause: :env_drift` and do not inflate `[REPEATING]`. |
104
- | `Extrospection.correlate` (**E2**) | Lead-lag style joins ("tool X started failing after toolchain Y changed"). |
105
- | `Reward.verify_as_reward` (**E3**) | Browser-backed claim checks can floor/cap the outcome score. |
147
+ | ID | Where | What |
148
+ |----|-------|------|
149
+ | **E1** | `Metrics.changepoints` + `Loop.attribute_cause` | Env-drift-attributed failures get `cause: :env_drift` and do not inflate `[REPEATING]`. |
150
+ | **E2** | `Extrospection.correlate` | Lead-lag style joins ("tool X started failing after toolchain Y changed"). |
151
+ | **E3** | `Reward.verify_as_reward` | Browser-backed claim checks can floor/cap the outcome score. |
106
152
 
107
153
  ## Config (`PWN::Env[:ai][:agent]`)
108
154
 
109
155
  ```yaml
110
156
  :ai:
111
- :module_reflection: false # gates Reflect lesson writing (not ORM alone)
157
+ :module_reflection: false # gates Reflect lesson writing (not the judge alone)
112
158
  :agent:
113
159
  :critic: null # S3 - nil = ON for remote engines, OFF for ollama
114
- :red_team_plan: null # S4 - same auto policy
115
- :counterfactual: null # S2 - same auto policy
160
+ :red_team_plan: null # S4 - same auto rule
161
+ :counterfactual: null # S2 - same auto rule
116
162
  :hindsight: true # C3 - hindsight relabel on failed turns (default true)
163
+ :policy: true # R5 - live tabular Q / REINFORCE (advisory rank only)
117
164
  :verify_as_reward: null # E3 - nil = auto sample on claim-shaped answers
118
165
  :reward_llm: null # nil = outcome/process judges use LLM teacher on remote
119
- :local_introspect: :failure_only # ollama cost policy; remote always introspects
166
+ :reward_model: null # optional cheaper model id for ORM/PRM (nil = engine default)
167
+ :reward_llm_timeout: 12 # cheap ORM chat timeout seconds (clamped 2..30)
168
+ :local_introspect: :failure_only # ollama cost rule; remote always introspects
120
169
  :introspect_every_n: 3
121
170
  :max_iters: 25 # hard cap; budget pressure may lower effective value
122
171
  ```
@@ -141,17 +190,18 @@ PWN::Cron.install_defaults
141
190
  `reward_preferences` · `reward_scrub_preferences` · `reward_preference_balance` ·
142
191
  `reward_export_dpo` · `reward_generator_mix` · `curriculum_practice` ·
143
192
  `curriculum_train` · `curriculum_hindsight` · `curriculum_offline_judge` ·
144
- `curriculum_preference_balance` · `curriculum_practice_kpi` ·
145
- `learning_purge_noise`
193
+ `curriculum_preference_balance` · `curriculum_practice_kpi` · `policy_stats` ·
194
+ `policy_evaluate` · `policy_recommend` · `learning_purge_noise`
146
195
 
147
- ## Design claims
196
+ ## What this stack actually does
148
197
 
149
198
  1. Process reward on real security tool traces, not only math demos (**R2**).
150
- 2. Automatic blame attribution: self vs environment drift (**E1** + **E2**).
199
+ 2. Automatic blame: self vs environment drift (**E1** + **E2**).
151
200
  3. Reward-hacking self-detection when proxy success diverges from the judge (**R3**).
152
201
  4. Mistake-driven curriculum with regression-gated LoRA promotion when a trainer exists (**S1** + **W2**).
153
202
  5. Preference pairs from normal agent work (corrections, resolve, critic, practice) with no separate human labelling queue (**W1**).
154
203
  6. Export and promote only when the preference diet is diverse and trajectory-shaped.
204
+ 7. Live tabular Q-learning + REINFORCE on real Loop turns, used only as advice next to planning (**R5**).
155
205
 
156
206
  ## Preference signal quality
157
207
 
@@ -166,39 +216,6 @@ keep it honest by:
166
216
  5. Requiring smoke checks and mean judge improvement before LoRA promote.
167
217
  6. Treating budget exhaustion as a first-class practice target so the agent learns to finish.
168
218
 
169
- ## Design-priority STATUS
170
-
171
- Living checklist for the reinforced feedback loop. Cite the Pri/ID here instead
172
- of inventing new milestone labels for the same theme.
173
-
174
- | Pri | ID | Control | Module(s) | Success criterion |
175
- |-----|----|---------|-----------|-------------------|
176
- | **P0** | W1 generator diversity | `Reward::TARGET_SOURCE_MIX` + `generator_mix` + mix-urgent force on critic/counterfactual | `reward.rb`, `curriculum.rb` | `generator_mix.healthy` OR `recommendation` not stuck on `suppress:mistakes_resolve`; trajectory_fraction ≥ 0.5 |
177
- | **P0** | Introspect budget | `Learning::INTROSPECT_SOFT_MS` / `HARD_MS`; stage skip under soft/hard / budget-pressure mode | `learning.rb` | `auto_introspect` returns `stages_skipped` when over soft; post-answer path cannot re-thrash tool critic |
178
- | **P0** | Local judge calibration | Heuristic score shrinkage + `confidence`; `Metrics.effective_rate` scales distrust by `judge_confidence` | `reward.rb`, `metrics.rb` | distrust×heuristic no longer fully replaces proxy; local no-trace highs capped |
179
- | **P0** | Practice outer KPI | `Curriculum.practice_kpi` / `repeating_trend` → `~/.pwn/curriculum_kpi.jsonl` | `curriculum.rb` | week-over-week `delta_repeating` ≤ 0 on budget fingerprints after practice nights |
180
- | **P0** | PRM sample efficiency | `PRM_MIN_N=5`, shrinkage to `PRM_FULL_N=20`, fleet coverage gate in `Registry.rank` | `metrics.rb`, `registry.rb` | `prm_advantage=0` until n≥5; rank delta=0 until ≥3 tools ready |
181
- | **P0** | STATUS over flag archaeology | This table | docs | New work cites Pri/ID here, not fresh comments for the same theme |
182
- | **ops** | Nightly diet close | `offline_judge` → `scrub_preferences` + `generator_mix` + `practice_kpi` | `curriculum.rb` | Cron path returns `scrub`/`generator_mix`/`practice_kpi`; raw resolve prose does not survive the night |
183
- | **ops** | Shape backfill | `Reward.infer_shape` + scrub rewrite | `reward.rb` | Legacy shapeless rows get `winning_trace`/`revised_answer` when content warrants; traj_f measurable |
184
- | **ops** | Mix in prompt | `Metrics.to_context` emits `W1 MIX:` when unhealthy | `metrics.rb` | Unhealthy diet visible every turn without a tool call |
185
- | **P0** | Budget exhaust deepen | Last-iter force-final (tools=nil); skip CF under budget-pressure mode; hot caps 24 ollama / 75 remote; exhaust path `append_session`+`auto_introspect` | `loop.rb` | Exhaust returns a judged final, not a bare string; CF cannot re-enter under hot; last iter cannot tool-call |
186
-
187
- ### Config additions
188
-
189
- ```yaml
190
- :ai:
191
- :agent:
192
- # Introspect budget (ms wall-clock inside auto_introspect)
193
- # INTROSPECT_SOFT_MS / HARD_MS are constants; override only via code/reload today.
194
- :critic: null # also force-on when generator_mix.urgent includes critic
195
- :counterfactual: null # also force-on when generator_mix.urgent includes counterfactual
196
- ```
197
-
198
- ### Tools (design-priority)
199
-
200
- `reward_generator_mix` · `curriculum_practice_kpi` (plus existing reward/curriculum set)
201
-
202
219
  ---
203
220
 
204
221
  **See also:** [pwn-ai Agent](pwn-ai-Agent.md) · [Mistakes](Mistakes.md) ·