pwn 0.5.699 → 0.5.700

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5d7edeea1940ad56143190285565ba9bd76f4d78a47294238eafaad1d002686f
4
- data.tar.gz: c3a594906ca8d239b8f5dfc3fe3343ec718bf1a71e3c85334b3b6db7e852b5fe
3
+ metadata.gz: ffcafd562bd8aa67973626a722c45396187996c5e6ac878a004622c6fc40f335
4
+ data.tar.gz: 9e33ac68ac5f9574e8fc5243deda6745ed3300854af398cb33bbbfa2916fc95d
5
5
  SHA512:
6
- metadata.gz: fee1edba85d565609b592498feff5eaf38bc01a4771af2a2e22f3719d1eac7faaf54c8f8772837358cf5cbf18db59736aee90fe4a7114c1e6353be423d42e2e8
7
- data.tar.gz: 4ad32cb15b7bd78d0fa150cf63379ecf61184b84a902426a3581a558b48b17b0a7bc23048a2d2576155b538403e9472a1ebe542a8154eece95a36e4106e352f9
6
+ metadata.gz: eb91f1c79739e3c6289f1d16bb53b23f6a0d7467943cdf2a8a20217e7a40e6bbfef2a60e0513cb487ee6b53a8efd9a5e6b15b562e1f0d68d05c1c7fe3880aac9
7
+ data.tar.gz: 7ae7c8c7070a8f48a47a6336556f264ac05a98a41f1a10fcb1b49692eaa24c926af34c4d1792b822d1bd817ee3b26a89aa7ba5d08d11c976a6ceab154b74ce67
@@ -1,158 +1,158 @@
1
- 9ed39d8 fix(gem): re-launch to successfully publish pwn gem with MFA/OTP code fed via clarify + process submit per updated pwn_sdlc (fix 401 from previous re-launches; version 0.5.598 local)
2
- 5c6238e fix(gem): re-launch to successfully publish with MFA/OTP code fed via clarify + process submit per updated pwn_sdlc (fix 401 from previous re-launches; version 0.5.597 local)
3
- fae4112 fix(gem): re-launch to successfully publish with MFA/OTP code fed via clarify + process submit per updated pwn_sdlc (fix 401 from previous re-launches; version 0.5.596 local)
4
- dea2987 fix(gem): re-launch again to successfully publish with MFA/OTP code fed via clarify + process submit per updated pwn_sdlc (fix 401 from previous re-launches)
5
- 7191a91 fix(gem): re-launch to successfully publish pwn gem with MFA/OTP code fed via clarify + process submit per updated pwn_sdlc (fix 401 from previous tests)
6
- b3588ca fix(gem): re-launch to successfully publish pwn gem with MFA/OTP handling per updated pwn_sdlc (fix 401 from previous test)
7
- fbcd5fe test(mfa): exercise rubygems MFA/OTP prompt handling during gem push per updated pwn_sdlc
8
- ab7c2e1 Merge pull request #947 from support-0dayInc/master
9
- cdcd118 fix(ai): resolve empty response from PWN::AI::Anthropic by fixing error handling in anthropic_rest_call and adding response checks
10
- d4b0843 Merge pull request #946 from support-0dayInc/master
11
- 132f55a fix(repl): robust SHIFT+ENTER multiline for pwn-ai (oneshot Reline bindings + always-true confirm, removed plain-enter override + /opt/pwn capture ref, debug scripts /tmp only per rule)
12
- df1bcfa fix(repl): pwn-ai SHIFT+ENTER now works with text on the line (persistent add_key_binding + save/restore + expanded seqs + string fallback); add bin/capture_shift_enter.rb + instructions in code; rubocop 0 on 658 files; full git_commit.sh completion
13
- f3c1088 fix(repl): pwn-ai SHIFT+ENTER now works with text on the line (persistent add_key_binding + save/restore key_bindings instead of oneshot; allows multiple newlines in multi-line LLM prompt); tmux advice; rubocop 0; full git_commit.sh completion
14
- ae0a81a fix(repl): pwn-ai multiline now strictly SHIFT+ENTER only (byte arrays, no .bytes, cleaned seqs); add tmux/terminator extended-keys advice in code + banner; always-true confirm on readmultiline; full git_commit.sh completion
15
- c005375 Merge pull request #944 from ninp0/master
16
- 67e33a4 git_commit.sh and build_gem.sh - implement upstream sync & code merge into developer forks so everyone is using the latest
17
- 213ea70 git_commit.sh and build_gem.sh - implement upstream sync & code merge into developer forks so everyone is using the latest
18
- b0d976c git_commit.sh and build_gem.sh - implement upstream sync & code merge into developer forks so everyone is using the latest
19
- b92f728 Merge pull request #943 from support-0dayInc/master
20
- c1ff9e9 chore(rdoc): add rdoc >=6.0 to Gemfile + safe RDoc::Task require in Rakefile for Ruby 4.0+; full git_commit.sh completion
21
- 6ab3fbb chore(gemspec): remove rdoc pin (bundled with Ruby); cleanup stray file; full git_commit.sh completion
22
- f13b5c3 chore(gemspec): remove rdoc pin (bundled with Ruby, was causing rake rdoc LoadError in upgrade_pwn.sh); full git_commit.sh completion
23
- ee20f7f chore(gemspec/bundle): fix rdoc empty pin + robust ^ anchored parser (skip comments) + align rubocop to meshtastic 0.0.163 reqs; pwn_autoinc_version pure load shim (bypass for uninstalled pwn gem); 0 rubocop offenses; full ./git_commit.sh to completion (background+notify, dynamic rvm use .)
24
- dc4edba chore(gemspec/bundle): fix rdoc empty pin + robust ^ anchored parser (skip comments) + align rubocop to meshtastic 0.0.163 reqs; pwn_autoinc_version pure load shim (bypass for uninstalled pwn gem); 0 rubocop offenses; full ./git_commit.sh to completion (background+notify, dynamic rvm use .)
25
- 34bb907 chore: full completion run of ./git_commit.sh (shim fixed pwn_autoinc_version, dynamic rvm use ., no kill)
26
- b472d7a chore: increase timeout values (hermes config + tool defaults) to allow full ./git_commit.sh runs without clamping (terminal 7200s, process wait, foreground max 7200s, child etc). Use background + notify_on_complete for long gem upgrade steps.
27
- 2da3021 fix(repl): pwn-ai multiline now strictly SHIFT+ENTER only (byte arrays for bindings, removed all alternative mentions from comments and code); 0 offenses
28
- feb0bfd fix(repl): pwn-ai multiline now strictly SHIFT+ENTER only (byte arrays for bindings, removed all alternative mentions from comments and code); 0 offenses
29
- 00afb5f Merge pull request #942 from ninp0/master
30
- 3805a4d build_gem.sh - #bugfixes
31
- 96cb92c build_gem.sh - #bugfixes
32
- bbdfa27 Gemfile - bump to latest gem versions
33
- 31d96b7 Merge pull request #941 from ninp0/master
34
- 780cf29 Merge fixes
35
- b3eb44e Merge pull request #940 from support-0dayInc/master
36
- 1b03a34 feat(ai): support xAI SuperGrok OAuth in PWN::AI::Grok + PWN::Config (access_token in encrypted vault alongside key); fix pwn-ai multiline (more SHIFT+ENTER seqs for terminals + Ctrl+J/Alt+Enter fallback); add rspec; 0 RuboCop offenses
37
- 9405352 Merge fixes
38
- 459ebec Merge branch 'master' of ssh://github.com/ninp0/pwn
39
- 2480d6d Merge pull request #939 from support-0dayInc/master
40
- c1eed04 feat(repl): support multi-line manual/prompt submissions for pwn-ai (SHIFT+ENTER = newline, ENTER = submit; multi-line paste compatible via Reline)
41
- e44c38b Gemfile - bump rdoc to 7.0.4
42
- 9c68eb6 fix(cli): support pwn --version + align Gemfile pins for meshtastic/yard/rubocop compat to enable clean gem install (0.5.568)
43
- 3aa705a Merge branch '0dayInc:master' into master
44
- ce9ee36 feat(ai): add Hermes-equivalent memory, sessions, agents(delegation), cron to pwn-ai agent + PWN::Memory/Sessions/Cron + integration in REPL hook/Config + Pry commands + specs. RuboCop 0.
45
- 35b12e0 Merge pull request #938 from support-0dayInc/master
46
- 479b3cf fix(repl): remove 'Hermes-equivalent' string from pwn-ai banner (and command description + spec for consistency)
47
- 1b61587 fix(ai): pwn-ai now reliably executes CLI commands (e.g. what does `id` return?) and PWN modules when the agent is instructed; stricter system prompts + backtick intent pre-processing + robust regex block extraction + Open3 capture + observation feedback loop in the REPL hook. Updated pwn-ai banner with concrete examples.
48
- 8f8791c feat(ai): pwn-ai command as Hermes-equivalent agent TUI (task instruction + PWN/CLI tool exec); scale PWN::Config w/ skills folder in pwn_env_path parent (pwn-ai aware for autonomy)
49
- 0b765c6 Merge pull request #937 from support-0dayInc/master
50
- 579c75a feat(ai): add PWN::AI::Anthropic module supporting Anthropic as AI provider (Claude models, get_models + chat with history)
51
- 745309a Merge pull request #936 from ninp0/master
52
- 2ba84a7 PWN::AI::Agent::VulnGen module - restore proper system_role_content for prompt context
53
- 961c0b7 Merge pull request #935 from support-0dayInc/master
54
- ff60b0d Prepare LifecycleAuthzReplay for PR
55
- 9bb4a18 Fix lifecycle authz replay build validation
56
- 5d0bde8 Add LifecycleAuthzReplay evidence bundle core with coverage tracking
57
- d12ee56 Merge pull request #933 from support-0dayInc/master
58
- 7e4635c Address PR review feedback for VulnGen
59
- 5c78cfb Fix VulnGen exception handling
60
- 9f74e14 Refine VulnGen report structure and add template
61
- 6b31c5b Merge pull request #932 from ninp0/master
62
- cf8de20 Gemfile - bump gem versions
63
- 8ef7695 Gemfile - bump gem versions
64
- 0184d29 Merge pull request #931 from ninp0/master
65
- 0612fec PWN::Plugins::BurpSuite module - filter by highlight color within #get_proxy_history #get_websocket_history #get_sitemap methods
66
- 7bfe448 PWN::Plugins::BurpSuite module - filter by highlight color within #get_proxy_history #get_websocket_history #get_sitemap methods
67
- dd25c04 Merge pull request #930 from ninp0/master
68
- db3ceab PWN::Plugins::BurpSuite module - reduce default sleep between history requests for AI introspection threads (faster AI analysis on most recent HTTP request / response pairs)
69
- 0e37747 Merge pull request #929 from ninp0/master
70
- 899335e PWN::Plugins::BurpSuite module - change default limit for AI introspection threads from 10 to 3 for faster AI analysis on most recent HTTP request / response pairs
71
- ab7b971 Merge pull request #928 from ninp0/master
72
- 962585f .rubocop.yml - Bump max method lines for PWN::Plugins::BurpSuite module
73
- 4928402 PWN::Plugins::BurpSuite module - slight tweaks to ensure AI analysis occurs on most recent HTTP request / response pairs prior to moving onto older ones
74
- 067ae4b Merge pull request #927 from ninp0/master
75
- 7270921 PWN::Plugins::BurpSuite module - change default limit for AI introspection threads from 200 to 10 for faster AI analysis on most recent HTTP request / response pairs
76
- 76f09a3 Merge pull request #926 from ninp0/master
77
- 4c51b0f PWN::Plugins::BurpSuite module - performance enhancements for AI introspection threads
78
- cac02bf Merge pull request #925 from ninp0/master
79
- 41f1c86 PWN::Plugins::BurpSuite module - add backtrace logs to /tmp if introspection threads fail.
80
- 5b0977b PWN::Plugins::BurpSuite module - add backtrace logs to /tmp if introspection threads fail.
81
- c3d3e6d Merge pull request #924 from ninp0/master
82
- 6c97dec PWN::AI::Agent::* modules - update help methods to show how to use PWN::AI::Agent::*.analyze methods. Also incorporate numerous markdown types for PWN::AI::Agent::VulnGen module.
83
- 567680a PWN::AI::Agent::* modules - update help methods to show how to use PWN::AI::Agent::*.analyze methods. Also incorporate numerous markdown types for PWN::AI::Agent::VulnGen module.
84
- c430ceb Merge pull request #923 from ninp0/master
85
- d135fa8 Gemfile - re-readd rdoc gem and align versioning to bundled rdoc in ruby version declared in .ruby-version. Also ensure lowest supported ruby version that bundles rdoc (i.e. ruby-4.0.0) is enforced within pwn.gemspec
86
- 7a6f7b2 Merge pull request #922 from ninp0/master
87
- ae3d6a3 Gemfile - re-remove rdoc gem :-/
88
- 32dc270 Gemfile - re-add rdoc gem :-/
89
- af7a772 Merge pull request #921 from ninp0/master
90
- 35e4ab1 Rakefile - change require "rdoc/task" to just "rdoc"
91
- 073cf29 Merge pull request #920 from ninp0/master
92
- 29c2a03 PWN::AI::Agent::VulnGen module - Initial creation && more #bugfixes for rSpec written for PWN::AI::Agent module
93
- b576db8 PWN::AI::Agent::VulnGen module - Initial creation && more #bugfixes for rSpec written for PWN::AI::Agent module
94
- 3b6b2fc More #bugfixes for PWN::AI::Agent namespace
95
- ad17b71 Merge pull request #919 from ninp0/master
96
- 0457547 More #bugfixes for PWN::AI::Agent namespace
97
- de0a762 RSpec #bugfixes for PWN::AI::Agent namespace
98
- 1427ccf Decouple agentic AI analysis from PWN modules (i.e. Create a specific PWN::AI::Agent namespace for all PWN modules that leverage PWN::AI::Introspection.reflect_on for autonomous analysis.
99
- fdb6d08 PWN::Plugins::BurpSuite module - migrate PWN::AI::Introspection logic into first agentic AI module, PWN::AI::Agent::BurpSuite
100
- 49e1284 Merge pull request #918 from ninp0/master
101
- 4790390 rubocop --auto-gen-config
102
- 9dd31af Gemfile - Comment out rdoc as ruby-4.0.1 now bundles rdoc
103
- 232ca54 Gemfile - nump versions
104
- 2971dda Gemfile - nump versions
105
- d806b2f Merge pull request #917 from ninp0/master
106
- 3a735e2 Rspec - add flex_spec.rb
107
- 22b802e PWN::Plugins::BurpSuite module - when PWN::Env[:ai][:introspection] is true, only perform AI Introspection (i.e. Agentic Analysis) on targets in scope. This includes sitemap, proxy history, and websocket history introspection threads
108
- b2980b5 PWN::SDR::Decoder::POCSAG module - rubocop #bugfixes
109
- 56e5010 PWN::SDR modules - update FrequencyAllocation to support multiple ranges, enhance measure_signal_strength to dynamically calculate max_attempts based upon precision value passed, and initial implementation of a POCSAG decoder
110
- 54b51ab Merge pull request #916 from ninp0/master
111
- 4a25368 Gemfile - bump to latest versions
112
- 3d2861a Merge pull request #915 from ninp0/master
113
- 5a3a506 .ruby-version - Bump to 4.0.0 #MerryChristmas
114
- cb249ee Merge pull request #914 from ninp0/master
115
- 1b28011 PWN::SDR::GQRX - scan log name bugfix when keep_looping = true
116
- a233e14 PWN::SDR::GQRX - provide a brief intermission between scan loops
117
- fcfe78e pwn_gqrx_scanner driver - arbitrary bugfixes and implement --keep-looping feature #bugfix
118
- b1b18c0 pwn_gqrx_scanner driver - arbitrary bugfixes and implement --keep-looping feature #bugfix
119
- 7242109 Merge pull request #913 from ninp0/master
120
- 48089fa pwn_gqrx_scanner driver - arbitrary bugfixes and implement --keep-looping feature
121
- dfaadfd PWN::SDR::GQRX - #bugfix in logging incorrect demodulator_mode
122
- 33478f3 Merge pull request #912 from ninp0/master
123
- 8ae84d4 PWN::SDR::Decoder::RDS module - fill up line as much as possible prior to truncation
124
- 1725dfa PWN::SDR::Decoder::RDS module - newline/radio text longer than terminal width #bugfix
125
- 9e846e2 PWN::SDR::Decoder::RDS module - faster display / newline #bugfix
126
- 9502cd6 PWN::SDR::GQRX module - faster measure_signal_strength w/o sacrificing accuracy and finalize PWN::SDR::Decoder::RDS module
127
- 3a4aed5 Merge pull request #911 from ninp0/master
128
- 3b111be PWN::SDR::GQRX module - migrate RDS decoding to PWN::SDR::Decoder::RDS module #bugfixes
129
- bef0875 Merge pull request #910 from ninp0/master
130
- 12eef9e PWN::SDR::GQRX module - move RDS decoding to PWN::SDR::Decoder namespace and move String / Integer monkey patches for cast signals into PWN::SDR module instead
131
- 365d999 PWN::SDR::GQRX module - drastically improved measure_signal_strength, increasing speed and accuracy
132
- da96d10 Merge pull request #909 from ninp0/master
133
- dff5304 PWN::SDR::GQRX module - drastically improved measure_signal_strength, increasing speed and accuracy
134
- 3b6eb8a Merge pull request #908 from ninp0/master
135
- c191aab PWN::SDR::GQRX module - signal logging #bugfix
136
- f850b6d Merge pull request #907 from ninp0/master
137
- dc914e3 PWN::SDR::GQRX module - drastically improved edge detection, RDS decoding on WFM, better signal strength measurement, and reduced complexity
138
- 29db14b Merge pull request #906 from ninp0/master
139
- c5c47bb Generisize wrapper scripts used for building / resintalling gemset / etc
140
- 5d4d4d0 PWN::SDR modules - cleanup / enhancements
141
- a8c4272 Merge pull request #905 from ninp0/master
142
- c46fc97 Work out dep snaffu
143
- de8590f Gemfile - pull in latest versions (address CVE in meshtastic gem)
144
- cdced0f PWN::SDR::GQRX module - Bandwidth overlap #enhancements / #bugfixes
145
- 72c3c44 Merge pull request #904 from ninp0/master
146
- 6bf1401 PWN::Plugins::GQRX module - move to new PWN::SDR namespace, w/ complete overhaul. Move profiles into PWN::SDR::FrequencyAllocationModule, move anyy SDR related modules to the PWN::SDR namespace (e.g. FlipperZero, etc). Implement edge detection in PWN::SDR::GQRX, smoothing signals discovered for better accuracy, speed up scans, etc.
147
- 41deb49 Merge pull request #903 from ninp0/master
148
- f31464d PWN::Plugins::BurpSuite module - smarter delays within introspection threads depending on type
149
- d96576c Merge pull request #902 from ninp0/master
150
- b0ab5ad PWN::Plugins::BurpSuite module - split introspection thread into separate ones to increase throughput
151
- cfa0c66 Merge pull request #901 from ninp0/master
152
- cc14d6c PWN::Plugins::BurpSuite module - implement WebSocket history AI instrospection
153
- 121b30d Merge pull request #900 from ninp0/master
154
- 0f3de48 PWN::Plugins::BurpSuite module - sync sitemap and proxy notes to rely upon first generated to speed up AI introspection and iliminate redundancy #slight_tweak
155
- 5321ea9 Merge pull request #899 from ninp0/master
156
- 3d25845 .rubocop.yml - Tweak to support PWN::Plugins:BurpSuite module
157
- 43db0e4 Merge pull request #898 from ninp0/master
158
- e20f47d PWN::Plugins::BurpSuite module - sync sitemap and proxy notes to rely upon first generated to speed up AI introspection and iliminate redundant introspection
1
+ 27c8b2b5 Merge pull request #1009 from ninp0/master
2
+ 3af915b9 `pwn-ai` - deal with ReadTimeout when dealing w/ large payloads
3
+ a06f59d6 Merge pull request #1008 from ninp0/master
4
+ 3a87fdd5 `pwn-ai` - deal with HTTP 502, 503, 504 responses from LLM provider
5
+ 7fde94c2 Merge pull request #1007 from ninp0/master
6
+ 7a11fabd `pwn-ai` - Create timeout bounds for `shell` and `pwn_eval` tools ranging from 30-10_800 seconds incrementing 180 seconds until command completes or timeout after 3hrs is triggered steering a different approach. Also added `/model` command suite (with command completion) to quickly list / switch providers/model in an active `pwn-ai` session that persist cross-session
7
+ 74890a72 Merge pull request #1006 from ninp0/master
8
+ 05609003 PWN::AI::RedTeam namespace - extend modules to include attack methods described in OWASP Top 10 for LLM Applications 2025 / 2026 && AI Red Teaming Solutions Taxonomy
9
+ 12c51f86 Merge pull request #1005 from ninp0/master
10
+ 9a9511a5 Better Google Workspace authZ within `pwn-ai` #rubocop_fixes
11
+ 3563cf03 Better Google Workspace authZ within `pwn-ai`
12
+ 88fa6bd0 Better Google Workspace authZ within `pwn-ai`
13
+ 7aeeb7c1 Merge pull request #1004 from ninp0/master
14
+ 31d74e1d Add default skills for the entire PWN namespace
15
+ b13d6392 pwn-ai - toggle-debug tmp file output bugfixes
16
+ 341b0063 Merge pull request #1003 from ninp0/master
17
+ 0422844d pwn-ai - begin implementing command menu, add path completion, and default cwe, capec, and ATT&CK skills
18
+ 2bb98aa8 pwn-ai - begin implementing command menu, add path completion, and default cwe, capec, and ATT&CK skills
19
+ b891eec4 Merge pull request #1002 from ninp0/master
20
+ 6f20948b .ruby-version - Bump to 4.0.6 && implement `toggle-debug` in pwn REPL to gernerate `pwn-ai` logs for troubleshooting unexpected behavior
21
+ 2a1026a9 .ruby-version - Bump to 4.0.6 && implement `toggle-debug` in pwn REPL to gernerate `pwn-ai` logs for troubleshooting unexpected behavior
22
+ bee1d16e Merge pull request #1001 from ninp0/master
23
+ d9bc8906 `pwn-ai` - implement verbose logging to /tmp and STDOUT when `toggle-pwn-ai-debug` == true
24
+ 21433603 Merge pull request #1000 from ninp0/master
25
+ ed4f4963 `pwn setup --migrate` - include default set of skills that live in /opt/pwn/etc/default_skills
26
+ fed5a3be PWN::AI::Agent::Registry module - implement tool priority order preferences (including broader list of tools), `spin.stop` object #bugfix in `pwn-ai`, and documentation updates
27
+ c99edf8b PWN::AI::Agent::Registry module - implement tool priority order preferences (including broader list of tools), `spin.stop` object #bugfix in `pwn-ai`, and documentation updates
28
+ b5cb837b Merge pull request #999 from ninp0/master
29
+ 3e26dfdb pwn-ai - eliminate request types and consolidate into the same logic (i.e. question vs statement vs autonomous_goal simply become autonomous_goal)
30
+ c8b19465 pwn-ai #bugfixes / #enhancements related to autonomous_goal completion
31
+ 67d30408 Merge pull request #998 from ninp0/master
32
+ c83b239e More `spin.stop` object #bugfixes in `pwn-ai` and enhancement when submitting a statement.
33
+ ba022c5c Merge pull request #997 from ninp0/master
34
+ 16c21652 PWN::AI::Agent::Registry module - implement tool priority order preferences, `spin.stop` object #bugfix in `pwn-ai`, and documentation updates
35
+ 2fd461a7 Merge pull request #996 from ninp0/master
36
+ 212ac1be spinner bugfixes
37
+ 270223c2 Merge pull request #995 from ninp0/master
38
+ 64cc08fa pwn setup - Implement cron worker line entry to ensure pwn-ai cron jobs are executed on the schedule in which they're defined #bugfixesd
39
+ f63e9e58 pwn setup - Implement cron worker line entry to ensure pwn-ai cron jobs are executed on the schedule in which they're defined
40
+ 79d9ed03 Merge pull request #994 from ninp0/master
41
+ 206c6211 Added PWN::WWW::GitHub module and removed PWN::AI::RedTeam::ModelDenialOfService module - too expensive / exhausts tokens too quickly.
42
+ 20fc78c4 Merge pull request #993 from ninp0/master
43
+ f8359e61 RL feedback loop enhancements
44
+ 2c4d7df0 Merge pull request #992 from ninp0/master
45
+ ee44dc6d Faster memory recall for current session and distinguish between users statements, questions, and autonomous goal requests where the latter requires a task breakdown.
46
+ 8ff5835b Merge pull request #991 from ninp0/master
47
+ f62af554 When using pwn-vault command within the pwn REPL driver, do not allow the editor to leave until PWN::Config confirms a valid config...this prevents cumbersome decrypt/re-edit/encrypt pwn.yaml tasks to get back into the pwn REPL.
48
+ c96b74ea Merge pull request #990 from ninp0/master
49
+ de9505b6 Decouple ollama and openwebui by creating each as their own provider, memory recall enhancements, more resislient request parsing when using ollama or openwebui
50
+ ad53a14e Merge pull request #989 from ninp0/master
51
+ 55b0183a README.md - update Groks take on `pwn-ai`.
52
+ 908f6ab9 Merge pull request #988 from ninp0/master
53
+ 2f3a0ea8 PWN::AI::Grok, PWN::AI::Anthropic, and PWN::AI::OpenAI - persist oauth bearer tokens to pwn.yaml when refresh token are used to refresh AuthZ
54
+ e881ca80 Merge pull request #987 from ninp0/master
55
+ ff56c555 ~/.pwn - keep files lean in RL feedback loopy
56
+ 9df6e56e pwn-ai - t retrieve context in current session morr quickly
57
+ 210f41ee Merge pull request #986 from ninp0/master
58
+ 7d5488a7 Merge remote-tracking branch 'upstream/master'
59
+ af2a13eb pwn-ai - task summarizer to convey task objectives for long running autonomous tasks which drives tools to complete each task until originally submitted user request is complete #round2.
60
+ 716fa2a8 Merge pull request #985 from ninp0/master
61
+ b03457ac pwn-ai - task summarizer to convey task objectives for long running autonomous tasks which drives tools to complete each task until originally submitted user request is complete.
62
+ 9722b8e5 Merge pull request #984 from ninp0/master
63
+ 5854f34a pwn-ai - task summarizer to convey task objectives for long running autonomous tasks, iteration exhaustion, and memory recall / learning outcome #bugfixes
64
+ 85f6b6d7 Merge pull request #983 from ninp0/master
65
+ 066088e5 pwn-ai - Implement a task summarizer to convey task objectives for long running autonomous tasks
66
+ 0efb7de9 Merge pull request #982 from ninp0/master
67
+ 989c3cea more autonomous fixes
68
+ d44703ac Merge pull request #981 from ninp0/master
69
+ 2dfd5762 PWN::AI::Agent::Tools::Shell module - long-running shell timeouts should no longer spam IOError errors to STDOUT
70
+ c0440049 Merge pull request #980 from ninp0/master
71
+ 27ade080 Reinforced learning feedback loop enhancements - better support for long autonomous tasks #round2
72
+ 9701e708 Merge pull request #979 from ninp0/master
73
+ 52c76428 Reinforced learning feedback loop enhancements - better support for long autonomous tasks
74
+ be84dd69 Merge pull request #978 from ninp0/master
75
+ 6311b03e #rubocop_fix
76
+ c758c22b PWN::Plugins::HackerOne module - cast to hacker api #bump_gem_version_compatibility
77
+ 8b0aaf79 PWN::Plugins::HackerOne module - cast to hacker api
78
+ 712962e1 Merge pull request #977 from ninp0/master
79
+ 6ecd9f29 doocumentation updates
80
+ 13d8d16f Merge pull request #976 from ninp0/master
81
+ 6333e3e4 Reinforced learning feedback loop enhancements && documentation updates
82
+ 690654ec Merge pull request #975 from ninp0/master
83
+ 0a644588 Reinforced learning feedback loop enhancements && documentation updates
84
+ a23567b7 Merge remote-tracking branch 'upstream/master'
85
+ 4330a39a Reinforced learning residual: P26 version-claim widen + pwn_eval EvalWithLocation + style
86
+ 1ddd9df5 Reinforced learning residual: deepen P17 budget_hot + P26 claim filter + pwn_eval self-heal
87
+ 85534396 Reinforced learning feedback loop: close P0/P1/P2/P17 weakness set
88
+ f3f86bdb Merge pull request #974 from ninp0/master
89
+ fd964ed4 Reinforced learning feedback loop enhancements && documentation updates
90
+ 6533fc41 Merge pull request #973 from ninp0/master
91
+ 33235063 Reinforced learning feedback loop enhancements && add oAuth support for PWN::AI::OpenAI && PWN::AI::Anthropic
92
+ 97fcfc90 Merge pull request #972 from ninp0/master
93
+ 3e66ada6 Reinforced learning feedback loop enhancements, convert ollama provider to stream for faster response times, and refresh documentation to reflect latest features
94
+ ebb9c280 Reinforced learning feedback loop enhancements and convert ollama provider to stream for faster response times
95
+ 4e7ef952 Merge pull request #971 from ninp0/master
96
+ c8286237 Github install-matrix - arbiitrary fixes.
97
+ 29ca2745 Merge pull request #970 from ninp0/master
98
+ 516af396 pwn_ai_red_team Driver - Initial commit to enable targeted LLM penetration testing (e.g. Jail Breaking, Prompt Injection, etc.)
99
+ 02a33526 Merge pull request #969 from ninp0/master
100
+ cd97809f Github install-matrix - arbiitrary fixes.
101
+ 04d271d5 Merge pull request #968 from ninp0/master
102
+ b9111aef More ~/.pwn resilience checking following upgrades
103
+ 310df119 Merge pull request #967 from ninp0/master
104
+ d041088e Work towards getting install-matrix workflow operable
105
+ 1f089d04 Merge pull request #966 from ninp0/master
106
+ ffee333f Ensure pwn-ai skills conform to https://agentskills.io/specification
107
+ bf484647 Ensure pwn-ai skills conform to https://agentskills.io/specification
108
+ 97b444c0 Merge pull request #965 from ninp0/master
109
+ 6a000929 More reinforcement learning feedback loop enhancements
110
+ 5ace30cb Merge pull request #964 from ninp0/master
111
+ d72fe894 Documentation / DFD updates to reflect proper configs / SDR decoder fixes #rake_fixes
112
+ de3f5557 Documentation / DFD updates to reflect proper configs / SDR decoder fixes
113
+ 2b279191 Merge pull request #963 from ninp0/master
114
+ f988e881 Learning FeedBack Loop - enhancements to support smaller LLMs, refined easier installation, and updates to documentation / DFDs
115
+ 677fcdc1 Learning FeedBack Loop - enhancements to support smaller, local models
116
+ a9cc3625 Merge pull request #962 from ninp0/master
117
+ 0cf0c7de README.md - prefer PWN gif over static png
118
+ 5904e90d Extrospection tweaks to support things like, what song is playing on a specific FM station, what planes are flying over me, what are strongest RF signals around me, tell me the weather in Tokyo, has the bug bounty page been updated, any known exploits in Apache in 2026, what devices are connected to this laptop, etc.
119
+ 690c7c1a fix(gqrx): restore regular-scan edge detection + sane squelch for fm_radio
120
+ d94f1243 chore: clear rubocop/rake; extrospection limbs + GQRX scanner polish
121
+ 90a41a68 Extrospection tweaks to support things like, what song is playing on a specific FM station, what planes are flying over me, what are strongest RF signals around me, tell me the weather in Tokyo, has the bug bounty page been updated, any known exploits in Apache in 2026, what devices are connected to this laptop, etc.
122
+ 1949b9e5 Merge pull request #961 from ninp0/master
123
+ 79278f1d Gemfile - pull in latest gem versions, documentation/Configuration.md - exhaustively document pwn.yaml && rename some key/value pairs for clarity.
124
+ 5ceb5f6d Merge pull request #960 from ninp0/master
125
+ 611da4ac More documentation updates and native ruby SDR decoders
126
+ 6831b63f More documentation updates, enhanced "learning from mistakes", and added a few SDR decoders
127
+ d65364a5 More documentation updates, enhanced "learning from mistakes", and added a few SDR decoders
128
+ 68160bc2 Merge pull request #959 from ninp0/master
129
+ fe461f73 More documentation tweaks
130
+ 55392d25 Merge pull request #958 from ninp0/master
131
+ c85981c9 Cron bugfixes. PWN::AI - feedback loop improvements / extrospection to mirror introspection. Also overhaul README.md , implement more documentation, and DFDs easier to understand, implement `pwn --ai` option within pwn REPL driver, remove deprecated pwn-irc command in favor of PWN::AI::Agent::Tools::Swarm module, etc.
132
+ afaad9bc Cron bugfixes. PWN::AI - feedback loop improvements / extrospection to mirror introspection. Also overhaul README.md , implement more documentation, and make DFDs easier to evaluate.
133
+ 7d580052 PWN::AI:Grok module - implement oauth. PWN::AI - feedback loop improvements. Also overhaul README.md , implement more documenration, and DFDs.
134
+ f37a4f9b PWN::AI:Grok module - implement oauth. PWN::AI - feedback loop improvements. Also overhaul README.md , implement more documenration, and DFDs.
135
+ 00a4ea0c Merge pull request #957 from ninp0/master
136
+ c477a034 Remove backup file
137
+ ee35abbe Merge pull request #956 from ninp0/master
138
+ 5119246d Numerous #bugfixes / stability fixes for pwn-ai
139
+ 0bdcb3b2 Merge pull request #955 from support-0dayInc/master
140
+ b9093859 fix(ai): PWN::AI::Grok.obtain_oauth_bearer_token now reliable for singular long-lived enrollment; guard for secret+Basic auth+error handling+public method; clear user steps for one-time pwn-vault persist (GPG signed for 0dayinc/pwn merge)
141
+ ae6a4902 fix(ai): correct PWN::AI::Grok oauth trigger to pass hash arg + guard per pwn_sdlc reference; remove debug puts
142
+ 3314cedd Merge pull request #954 from ninp0/master
143
+ b12a2745 Gemfile - bump meshtastic version
144
+ 0eb50ed7 pwn-ai REPL command - minor bugfixes / optimizations
145
+ ec7cfdee Merge pull request #953 from support-0dayInc/master
146
+ 1cf42886 feat(ai): PWN::AI::Grok calls authorize endpoint (URL construction + code exchange) only when oauth configured for bearer_token (xAI SuperGrok); full pwn_sdlc pipeline
147
+ 83abdf0d Merge remote-tracking branch 'upstream/master'
148
+ 53b2b752 Merge pull request #952 from ninp0/master
149
+ c6e12194 PWN::Plugins::REPL module - bugfixes in pwn-asm / pwn-ai commands within PWN prototyping REPL. (#951)
150
+ 77436d17 PWN::Plugins::REPL module - bugfixes in pwn-asm / pwn-ai commands within PWN prototyping REPL.
151
+ 04659d7e Merge remote-tracking branch 'upstream/master'
152
+ cbad0e52 pwn: feat(pwn-ai): implement pwn-ai command in pwn REPL driver as an agentic AI harness (GPG signed for 0dayinc/pwn merge) (#950)
153
+ 09213be5 feat(pwn-ai): implement pwn-ai command in pwn REPL driver as an agentic AI harness (GPG signed for 0dayinc/pwn merge requirement)
154
+ d950414f Implement pwn-ai command in pwn REPL driver as an agentic AI harness.
155
+ 94d4bb3e Merge pull request #949 from support-0dayInc/master
156
+ 6a169ab4 Finalize pwn gem visibility outside /opt/pwn (ruby-4.0.5@pwn gemset), MFA/OTP prompt handling for rvmsudo gem push $latest_gem in git_commit.sh, pwn-ai REPL driver anthropic (and other) provider response visibility in TUI + system_role_content override bug fix (full pwn_sdlc pipeline)
157
+ d3497740 Merge remote-tracking branch 'upstream/master'
158
+ e6be6df5 Finalize pwn gem visibility outside /opt/pwn (ruby-4.0.5@pwn gemset), MFA/OTP prompt handling for rvmsudo gem push in git_commit.sh, pwn-ai REPL driver anthropic (and other) provider response visibility in TUI + system_role_content override bug fix (full pwn_sdlc pipeline)
@@ -855,9 +855,10 @@ module PWN
855
855
  err = opts[:error]
856
856
  return false unless err
857
857
 
858
- return PWN::AI::HttpRetry.retryable?(error: err) if defined?(PWN::AI::HttpRetry) && PWN::AI::HttpRetry.respond_to?(:retryable?)
858
+ return true if defined?(PWN::AI::HttpRetry) && PWN::AI::HttpRetry.respond_to?(:retryable?) &&
859
+ PWN::AI::HttpRetry.retryable?(error: err)
859
860
 
860
- err.message.to_s.match?(/HTTP 50[234]|Gateway Time-out|stream absolute timeout/i)
861
+ err.message.to_s.match?(/HTTP 50[234]|Gateway Time-out|stream absolute timeout|tool_use_id|tool_result/i)
861
862
  rescue StandardError
862
863
  false
863
864
  end
@@ -905,6 +906,29 @@ module PWN
905
906
  nil
906
907
  end
907
908
 
909
+ private_class_method def self.payload_sig(opts = {})
910
+ Digest::SHA256.hexdigest("#{opts[:name]}|#{opts[:args]}")[0, 16]
911
+ rescue StandardError
912
+ "nosig-#{opts[:name]}"
913
+ end
914
+
915
+ private_class_method def self.note_same_payload!(opts = {})
916
+ sig = payload_sig(opts)
917
+ counts = Thread.current[:pwn_same_payload] ||= Hash.new(0)
918
+ counts[sig] += 1
919
+ counts[sig]
920
+ end
921
+
922
+ private_class_method def self.no_progress_result(opts = {})
923
+ name = opts[:name].to_s
924
+ sig = payload_sig(opts)
925
+ JSON.generate(
926
+ success: false,
927
+ error: "no_progress: identical #{name} payload repeated (#{sig}). Change the command.",
928
+ result: { stdout: '', stderr: "no_progress: #{name}", exit: 2 }
929
+ )
930
+ end
931
+
908
932
  # Repeat circuit-breaker. `count` is max(per-turn, persistent) so a
909
933
  # signature that already failed in a PREVIOUS session trips the guard
910
934
  # on its FIRST recurrence here — the agent does not get to burn the
@@ -922,7 +946,7 @@ module PWN
922
946
  Mistakes.extinguish!(signature: sig, args: opts[:args], shape: opts[:shape], force: true) if sig
923
947
  end
924
948
  Thread.current[:pwn_extinguished] ||= {}
925
- Thread.current[:pwn_extinguished][opts[:name].to_s] = true
949
+ Thread.current[:pwn_extinguished][payload_sig(name: opts[:name], args: opts[:args])] = true
926
950
 
927
951
  guard = "[pwn-ai/mistakes] EXTINGUISHED / REPEATED FAILURE — this #{opts[:name]} failure signature has " \
928
952
  "occurred #{count}× (across sessions). DO NOT retry it verbatim. Apply the " \
@@ -1447,23 +1471,72 @@ module PWN
1447
1471
  end
1448
1472
  head << rest.shift if rest.any? && rest.first[:role].to_s == 'assistant' && rest.first[:content].to_s.start_with?('PLAN:')
1449
1473
 
1450
- tool_idxs = rest.each_index.select { |i| rest[i][:role].to_s == 'tool' }
1451
- drop_before = tool_idxs.length > keep_pairs ? tool_idxs[-keep_pairs] : 0
1452
- start = drop_before
1453
- start -= 1 if start.positive? && rest[start - 1] && rest[start - 1][:role].to_s == 'assistant'
1454
- kept = rest[start..] || []
1474
+ pairs = []
1475
+ idx = 0
1476
+ while idx < rest.length
1477
+ if rest[idx][:role].to_s == 'assistant'
1478
+ group = [rest[idx]]
1479
+ idx += 1
1480
+ while idx < rest.length && rest[idx][:role].to_s == 'tool'
1481
+ group << rest[idx]
1482
+ idx += 1
1483
+ end
1484
+ pairs << group
1485
+ elsif rest[idx][:role].to_s == 'tool'
1486
+ # Orphan tool_result with no preceding tool_use — drop it.
1487
+ idx += 1
1488
+ else
1489
+ pairs << [rest[idx]]
1490
+ idx += 1
1491
+ end
1492
+ end
1493
+ collapsed = []
1494
+ pairs.each do |pair|
1495
+ tool = pair.find { |m| m[:role].to_s == 'tool' }
1496
+ prev = collapsed.last&.find { |m| m[:role].to_s == 'tool' }
1497
+ next if tool && prev && tool[:content].to_s.strip == prev[:content].to_s.strip
1498
+
1499
+ collapsed << pair
1500
+ end
1501
+ kept = collapsed.last(keep_pairs).flatten
1455
1502
  kept.each do |m|
1456
1503
  next unless m[:role].to_s == 'tool' && m[:content].to_s.length > max_chars
1457
1504
 
1458
1505
  m[:content] = "#{m[:content].to_s[0, max_chars]}…[compacted]"
1459
1506
  end
1460
1507
  messages.replace(head + kept)
1508
+ repair_tool_history!(messages: messages)
1461
1509
  messages
1462
1510
  rescue StandardError => e
1463
1511
  warn "[pwn-ai/loop] compact_history swallowed: #{e.class}: #{e.message}"
1464
1512
  opts[:messages]
1465
1513
  end
1466
1514
 
1515
+ private_class_method def self.repair_tool_history!(opts = {})
1516
+ messages = opts[:messages]
1517
+ return messages unless messages.is_a?(Array)
1518
+
1519
+ open_ids = []
1520
+ kept = []
1521
+ messages.each do |msg|
1522
+ role = msg[:role].to_s
1523
+ case role
1524
+ when 'assistant'
1525
+ open_ids = Array(msg[:tool_calls] || msg['tool_calls']).map { |tc| (tc[:id] || tc['id']).to_s }
1526
+ when 'tool'
1527
+ tid = (msg[:tool_call_id] || msg['tool_call_id']).to_s
1528
+ next if tid.empty? || !open_ids.include?(tid)
1529
+ when 'user'
1530
+ open_ids = []
1531
+ end
1532
+ kept << msg
1533
+ end
1534
+ messages.replace(kept)
1535
+ messages
1536
+ rescue StandardError
1537
+ opts[:messages]
1538
+ end
1539
+
1467
1540
  # 3.2 — local models cannot afford auto_introspect (judge+prm+critic+
1468
1541
  # sentinel+extro) on every success. Default :failure_only when local.
1469
1542
  private_class_method def self.should_auto_introspect?(opts = {})
@@ -2322,6 +2395,7 @@ module PWN
2322
2395
  end
2323
2396
  Thread.current[:pwn_request_intent] = intent
2324
2397
  Thread.current[:pwn_extinguished] = {}
2398
+ Thread.current[:pwn_same_payload] = Hash.new(0)
2325
2399
  debug_progress(msg: "intent=#{intent} engine=#{engine}", debug: opts[:debug])
2326
2400
  expose_current_session(session_id: session_id)
2327
2401
  Mistakes.check_user_correction(request: request, session_id: session_id) if defined?(Mistakes)
@@ -2502,6 +2576,7 @@ module PWN
2502
2576
 
2503
2577
  t0 = Time.now
2504
2578
  begin
2579
+ repair_tool_history!(messages: messages)
2505
2580
  msg = call_engine(messages: messages, tools: tools, ts_state: ts_state)
2506
2581
  rescue StandardError => e
2507
2582
  if engine_transient?(error: e)
@@ -2634,14 +2709,17 @@ module PWN
2634
2709
  started = Time.now
2635
2710
  argv_s = args.is_a?(String) ? args.to_s : args.inspect
2636
2711
  debug_progress(msg: "tool #{name} start:\n#{argv_s}", keep_newlines: true, cap: 0, tee: nil)
2637
- if Thread.current[:pwn_extinguished].is_a?(Hash) && Thread.current[:pwn_extinguished][name]
2638
- raw = JSON.generate(
2639
- success: false,
2640
- error: "extinguished_repeat: #{name} already failed this signature this turn — change args or tool",
2641
- result: { stdout: '', stderr: "extinguished_repeat: #{name}", exit: 2 }
2642
- )
2712
+ sig = payload_sig(name: name, args: args)
2713
+ if Thread.current[:pwn_extinguished].is_a?(Hash) && Thread.current[:pwn_extinguished][sig]
2714
+ raw = no_progress_result(name: name, args: args)
2643
2715
  else
2644
2716
  raw = Dispatch.call(tool_call: tc)
2717
+ same_n = note_same_payload!(name: name, args: args)
2718
+ if same_n >= 3
2719
+ Thread.current[:pwn_extinguished] ||= {}
2720
+ Thread.current[:pwn_extinguished][sig] = true
2721
+ raw = no_progress_result(name: name, args: args)
2722
+ end
2645
2723
  end
2646
2724
  tools_called += 1
2647
2725
  tele = record_metrics(name: name, started: started, raw: raw, args: args, session_id: session_id, engine: engine, ts_state: ts_state)
@@ -130,7 +130,8 @@ module PWN
130
130
  last_advanced_from: nil,
131
131
  last_advance_brief: nil,
132
132
  tools_on_task: 0,
133
- evidence_blob: ''
133
+ evidence_blob: '',
134
+ task_evidence: {}
134
135
  }
135
136
  end
136
137
 
@@ -911,7 +912,9 @@ module PWN
911
912
  blob = coverage_blob(state: state, messages: opts[:messages])
912
913
  n = plan.length
913
914
  plan.each_with_index.filter_map do |item, i|
914
- next if item.empty? || item_covered?(item: item, blob: blob)
915
+ slice = state[:task_evidence].is_a?(Hash) ? state[:task_evidence][i].to_s : ''
916
+ use = host_shaped_task?(item: item) && !slice.empty? ? slice : blob
917
+ next if item.empty? || item_covered?(item: item, blob: use)
915
918
 
916
919
  { idx: i, item: item, label: "task #{i + 1}/#{n}: #{item}" }
917
920
  end
@@ -1371,7 +1374,7 @@ module PWN
1371
1374
  /\b(implement\w*|fix|patch\w*|chang\w*|improv\w*|write|apply|wire|refactor\w*)\b/
1372
1375
  )
1373
1376
  return :discover if s.match?(
1374
- /\b(locat\w*|find|read|inspect|recon\w*|understand|decompos\w*|map|identif\w*|gather|discover|enumerat\w*|scan|probe|determin\w*|root cause|where and why|track|navigat\w*|browse|goto)\b/
1377
+ /\b(locat\w*|find|read|inspect|recon\w*|understand|decompos\w*|map|identif\w*|gather|discover|enumerat\w*|scan|probe|determin\w*|analy[sz]e|analysis|root cause|where and why|track|navigat\w*|browse|goto)\b/
1375
1378
  )
1376
1379
 
1377
1380
  :generic
@@ -1432,6 +1435,19 @@ module PWN
1432
1435
  ''
1433
1436
  end
1434
1437
 
1438
+ HOST_TASK_RX = /
1439
+ \b(?:hosts|subnet|address|mask|cidr|alive|reachab\w*|ipv4|ipv6|live\s+host)
1440
+ /ix
1441
+ HOST_IP_RX = %r{
1442
+ \b(?!127\.)(?:\d{1,3}\.){3}\d{1,3}(?:/\d{1,2})?\b
1443
+ }x
1444
+
1445
+ private_class_method def self.host_shaped_task?(opts = {})
1446
+ opts[:item].to_s.match?(HOST_TASK_RX)
1447
+ rescue StandardError
1448
+ false
1449
+ end
1450
+
1435
1451
  private_class_method def self.item_covered?(opts = {})
1436
1452
  item = opts[:item].to_s
1437
1453
  blob = opts[:blob].to_s.downcase
@@ -1442,6 +1458,8 @@ module PWN
1442
1458
  when :verify
1443
1459
  blob.match?(VERIFY_DONE_RX) || blob.match?(VERIFY_RAN_RX)
1444
1460
  else
1461
+ return blob.match?(HOST_IP_RX) if host_shaped_task?(item: item)
1462
+
1445
1463
  # discover / present / generic: some real tool evidence, not empty / tiny JSON
1446
1464
  blob.strip.length >= 40
1447
1465
  end
@@ -1467,10 +1485,15 @@ module PWN
1467
1485
  min_tools = browse_hit ? 1 : DISCOVER_MIN_TOOLS
1468
1486
  on_task = opts[:state].is_a?(Hash) ? opts[:state][:tools_on_task].to_i : 0
1469
1487
  return false if on_task < min_tools
1488
+
1489
+ host_ok = host_shaped_task?(item: opts[:item]) && HOST_IP_RX.match?(opts[:result].to_s)
1490
+ return host_ok if host_shaped_task?(item: opts[:item])
1470
1491
  return false unless item_covered?(item: opts[:item], blob: joined)
1471
1492
 
1493
+ return true if host_ok || phase == :present || browse_hit
1494
+
1472
1495
  intent_s = (Array(opts[:intents]) + Array(opts[:names])).join(' ')
1473
- task_intent_match?(item: opts[:item], intent: intent_s) || phase == :present || browse_hit
1496
+ task_intent_match?(item: opts[:item], intent: intent_s)
1474
1497
  else
1475
1498
  false
1476
1499
  end
@@ -1489,6 +1512,12 @@ module PWN
1489
1512
  nxt_p = task_phase(item: nxt)
1490
1513
  return false if nxt_p == :generic
1491
1514
  return false if cur_p == nxt_p
1515
+
1516
+ if host_shaped_task?(item: opts[:item])
1517
+ idx = opts[:state][:plan_idx].to_i
1518
+ ev = opts[:state][:task_evidence].is_a?(Hash) ? opts[:state][:task_evidence][idx].to_s : ''
1519
+ return false unless HOST_IP_RX.match?(ev)
1520
+ end
1492
1521
  return false unless task_intent_match?(item: nxt, intent: opts[:intent]) || nxt_p == :present
1493
1522
 
1494
1523
  true
@@ -1636,11 +1665,14 @@ module PWN
1636
1665
  state[:counts][name.to_s] += 1
1637
1666
  state[:total] += 1
1638
1667
  state[:since_emit] += 1
1639
- state[:tools_on_task] = state[:tools_on_task].to_i + 1
1668
+ state[:tools_on_task] = state[:tools_on_task].to_i + 1 unless name.to_s.match?(/^(memory|session|skills)_recall$/)
1640
1669
  state[:emitted_for_batch] = false
1641
1670
  chunk = "#{name} #{preview} #{rs.to_s[0, 800]}"
1642
1671
  state[:evidence_blob] = "#{state[:evidence_blob]} #{chunk}"
1643
1672
  state[:evidence_blob] = state[:evidence_blob][-16_000..] if state[:evidence_blob].to_s.length > 20_000
1673
+ te = (state[:task_evidence] ||= {})
1674
+ idx = state[:plan_idx].to_i
1675
+ te[idx] = "#{te[idx]} #{chunk}"
1644
1676
  intent = intent_phrase(tools: [{ name: name.to_s, args: args }])
1645
1677
  # Live R2-local signal from tool outcome (executive idx only).
1646
1678
  # Full ORM/PRM credit stays in Reward during auto_introspect.
data/lib/pwn/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.5.699'
4
+ VERSION = '0.5.700'
5
5
  end
@@ -461,6 +461,70 @@ describe PWN::AI::Agent::Loop do # rubocop:disable Metrics/BlockLength
461
461
  expect(hop).to match(/compact_history!/)
462
462
  end
463
463
 
464
+ it 'keeps distinct tool results instead of six copies of the same empty cut' do
465
+ msgs = [
466
+ { role: 'system', content: 'sys' },
467
+ { role: 'user', content: 'goal' },
468
+ { role: 'assistant', content: '', tool_calls: [{ id: 'good' }] },
469
+ { role: 'tool', tool_call_id: 'good', name: 'shell', content: 'inet 10.3.3.20/27 brd 10.3.3.31 eth0' }
470
+ ]
471
+ 8.times do |n|
472
+ msgs << { role: 'assistant', content: '', tool_calls: [{ id: "c#{n}" }] }
473
+ msgs << { role: 'tool', tool_call_id: "c#{n}", name: 'shell', content: "\n" }
474
+ end
475
+ out = described_class.send(:compact_history!, messages: msgs)
476
+ tool_bodies = out.select { |m| m[:role].to_s == 'tool' }.map { |m| m[:content].to_s }
477
+ expect(tool_bodies).to include('inet 10.3.3.20/27 brd 10.3.3.31 eth0')
478
+ expect(tool_bodies.count { |c| c.strip.empty? }).to be <= 1
479
+ end
480
+
481
+ it 'keeps an assistant with two tool_calls glued to both tool results' do
482
+ msgs = [
483
+ { role: 'system', content: 'sys' },
484
+ { role: 'user', content: 'goal' },
485
+ {
486
+ role: 'assistant', content: '',
487
+ tool_calls: [{ id: 'toolu_a' }, { id: 'toolu_b' }]
488
+ },
489
+ { role: 'tool', tool_call_id: 'toolu_a', name: 'memory_recall', content: 'prior findings' },
490
+ { role: 'tool', tool_call_id: 'toolu_b', name: 'skills_recall', content: 'cwe skill' }
491
+ ]
492
+ 8.times do |n|
493
+ msgs << { role: 'assistant', content: '', tool_calls: [{ id: "c#{n}" }] }
494
+ msgs << { role: 'tool', tool_call_id: "c#{n}", name: 'shell', content: "out#{n}" }
495
+ end
496
+ out = described_class.send(:compact_history!, messages: msgs)
497
+ ids = out.select { |m| m[:role].to_s == 'tool' }.map { |m| m[:tool_call_id].to_s }
498
+ ids.each do |tid|
499
+ prev = nil
500
+ out.each do |m|
501
+ break if m[:role].to_s == 'tool' && m[:tool_call_id].to_s == tid
502
+
503
+ prev = m if m[:role].to_s == 'assistant'
504
+ end
505
+ call_ids = Array(prev && prev[:tool_calls]).map { |tc| (tc[:id] || tc['id']).to_s }
506
+ expect(call_ids).to include(tid)
507
+ end
508
+ end
509
+
510
+ it 'drops orphan tool results that have no matching tool_use' do
511
+ msgs = [
512
+ { role: 'system', content: 'sys' },
513
+ { role: 'user', content: 'goal' },
514
+ { role: 'tool', tool_call_id: 'toolu_orphan', name: 'shell', content: 'stray' },
515
+ { role: 'assistant', content: '', tool_calls: [{ id: 'toolu_ok' }] },
516
+ { role: 'tool', tool_call_id: 'toolu_ok', name: 'shell', content: 'ok' }
517
+ ]
518
+ out = described_class.send(:repair_tool_history!, messages: msgs)
519
+ expect(out.map { |m| m[:tool_call_id] }).not_to include('toolu_orphan')
520
+ end
521
+
522
+ it 'extinguishes a repeated identical payload by signature, not the whole tool' do
523
+ src = File.read(described_class.method(:run).source_location.first)
524
+ expect(src).to match(/no_progress|same_payload|payload_sig/)
525
+ expect(src).not_to match(/pwn_extinguished\[opts\[:name\]\.to_s\] = true/)
526
+ end
527
+
464
528
  it 'records a timeout increment mistake instead of treating success:true as ok' do
465
529
  tmp = Dir.mktmpdir
466
530
  stub_const('PWN::AI::Agent::Mistakes::MISTAKES_FILE', File.join(tmp, 'mistakes.json'))
@@ -894,6 +894,57 @@ describe PWN::AI::Agent::TaskSummarizer do
894
894
  expect(described_class.plan_open?(state: st)).to eq true
895
895
  end
896
896
 
897
+ it 'does not complete a subnet scan on leftover identify text or Nmap/scan word salad' do
898
+ st = described_class.fresh(request: 'what hosts are alive on this subnet?')
899
+ st[:plan] = [
900
+ 'Identify the local network address and mask',
901
+ 'Scan the identified subnet for active or reachable hosts',
902
+ 'Present the list of discovered live host IP addresses'
903
+ ]
904
+ st[:plan_idx] = 0
905
+ 3.times do |i|
906
+ described_class.record!(
907
+ state: st,
908
+ name: 'shell',
909
+ args: { 'command' => "ip -4 addr #{i}" },
910
+ result: '{"success":true,"result":{"stdout":"inet 10.3.3.20/27 brd 10.3.3.31 eth0","exit":0}}'
911
+ )
912
+ end
913
+ expect(st[:plan_idx]).to eq 1
914
+ 3.times do
915
+ described_class.record!(
916
+ state: st,
917
+ name: 'shell',
918
+ args: { 'command' => 'nmap -sn 10.3.3.20/27 | grep Nmap | cut -d " " -f 2' },
919
+ result: '{"success":true,"result":{"stdout":"Nmap\\nscan\\nscan\\nscan\\nscan","exit":0}}'
920
+ )
921
+ end
922
+ expect(st[:plan_idx]).to eq 1
923
+ end
924
+
925
+ it 'does not finish an analysis task on recall plus one recon shell' do
926
+ st = described_class.fresh(request: 'exhaustively analyze the running app then write a PDF')
927
+ st[:plan] = [
928
+ 'Carry out the requested analysis using the named skills and live evidence',
929
+ 'Write the requested report to /tmp/container_pentest-p4.pdf'
930
+ ]
931
+ st[:plan_idx] = 0
932
+ described_class.record!(
933
+ state: st, name: 'memory_recall', args: { 'query' => 'securebank' },
934
+ result: '{"success":true,"result":{"x":{"value":"old findings list that is easily over 40 characters long"}}}'
935
+ )
936
+ described_class.record!(
937
+ state: st, name: 'skills_recall', args: { 'query' => 'cwe' },
938
+ result: '{"success":true,"result":[{"name":"cwe","snippet":"more than forty characters of skill text here"}]}'
939
+ )
940
+ described_class.record!(
941
+ state: st, name: 'shell',
942
+ args: { 'command' => 'docker ps; curl -s http://127.0.0.1:5000/ | head' },
943
+ result: '{"success":true,"result":{"stdout":"permission denied docker.sock\\nHTTP/1.1 200 OK Kestrel","exit":0}}'
944
+ )
945
+ expect(st[:plan_idx]).to eq 0
946
+ end
947
+
897
948
  it 'a verify task is covered after the verifier ran, even with remaining offenses' do
898
949
  st = described_class.fresh(request: 'run rubocop')
899
950
  st[:plan] = [
@@ -359,17 +359,21 @@
359
359
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.maybe_refresh_extro_snapshot! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.maybe_refresh_extro_snapshot!`: "}]}
360
360
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.mistake_ts Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.mistake_ts`: "}]}
361
361
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.needs_host_work? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.needs_host_work?`: "}]}
362
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.no_progress_result Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.no_progress_result`: "}]}
362
363
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.normalize_llm Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.normalize_llm`: Supported Method Parameters\n\nmsg = PWN::AI::Agent::Loop.normalize_llm(\n\nresponse: 'required - chat_with_tools response Hash from any provider'\n\n)\n"}]}
364
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.note_same_payload! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.note_same_payload!`: "}]}
363
365
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.ollama_wire_messages Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.ollama_wire_messages`: Supported Method Parameters\n\nwire = PWN::AI::Agent::Loop.ollama_wire_messages(\n\nmessages: 'required - in-memory OpenAI-ish messages (may have String args)'\n\n)\n\nReturns a deep-copied array safe for Ollama / Open WebUI ollama/api/chat:\n\nparses JSON-string function.arguments into Hash/Array objects\n\ncoerces nil assistant content to ” when tool_calls present (Open WebUI GenerateChatCompletionForm rejects content:null alone)\n\ndrops _native_content / _text_tool_coerced / thinking private keys\n\nstringifies Hash/Array message content (tool results) to JSON text\n\n"}]}
364
366
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.ollama_wire_tool_call Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.ollama_wire_tool_call`: "}]}
365
367
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.openai_wire_messages Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.openai_wire_messages`: Supported Method Parameters\n\nwire = PWN::AI::Agent::Loop.openai_wire_messages(\n\nmessages: 'required - in-memory OpenAI-ish messages (may have Hash args / internal keys)'\n\n)\n\nReturns a deep-copied array safe for OpenAI / xAI chat.completions:\n\ndrops _native_content / _text_tool_coerced / thinking private keys\n\nstringifies function.arguments maps\n\ncoerces Hash/non-string content to JSON/string (nil kept for assistant tool turns)\n\n"}]}
366
368
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.openai_wire_tool_call Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.openai_wire_tool_call`: "}]}
367
369
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.parse_tool_arguments Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.parse_tool_arguments`: "}]}
370
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.payload_sig Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.payload_sig`: "}]}
368
371
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.plan_first Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.plan_first`: "}]}
369
372
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.publish_usage Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.publish_usage`: "}]}
370
373
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.quiet_debug_tui! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.quiet_debug_tui!`: "}]}
371
374
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.recall_target Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.recall_target`: "}]}
372
375
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.record_metrics Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.record_metrics`: "}]}
376
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.repair_tool_history! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.repair_tool_history!`: "}]}
373
377
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.request_intent Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.request_intent`: "}]}
374
378
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.request_need Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.request_need`: "}]}
375
379
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.request_unsatisfied? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.request_unsatisfied?`: "}]}
@@ -670,6 +674,7 @@
670
674
  {"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.handoff_to_next? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.handoff_to_next?`: "}]}
671
675
  {"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.help Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.help`: "}]}
672
676
  {"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.heuristic_decompose Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.heuristic_decompose`: Supported Method Parameters\n\ntasks = PWN::AI::Agent::TaskSummarizer.heuristic_decompose(\n\ngoal: 'required - user goal string'\n\n)\n"}]}
677
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.host_shaped_task? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.host_shaped_task?`: "}]}
673
678
  {"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.howto_goal? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.howto_goal?`: "}]}
674
679
  {"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.immutable_request_line Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.immutable_request_line`: "}]}
675
680
  {"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.intent_phase Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.intent_phase`: "}]}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.699
4
+ version: 0.5.700
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.