pwn 0.5.686 → 0.5.688
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.ruby-version +1 -1
- data/Gemfile +3 -3
- data/README.md +3 -4
- data/documentation/Agent-Tool-Registry.md +2 -2
- data/documentation/Configuration.md +5 -4
- data/documentation/General-PWN-Usage.md +1 -1
- data/documentation/Home.md +1 -1
- data/documentation/How-PWN-Works.md +1 -1
- data/documentation/Mistakes.md +1 -1
- data/documentation/Reinforcement-Learning.md +4 -6
- data/documentation/Troubleshooting.md +1 -1
- data/documentation/pwn-REPL.md +1 -1
- data/documentation/pwn-ai-Agent.md +2 -3
- data/lib/pwn/ai/agent/curriculum.rb +2 -2
- data/lib/pwn/ai/agent/dispatch.rb +1 -1
- data/lib/pwn/ai/agent/learning.rb +150 -32
- data/lib/pwn/ai/agent/loop.rb +291 -129
- data/lib/pwn/ai/agent/prompt_builder.rb +47 -29
- data/lib/pwn/ai/agent/registry.rb +2 -1
- data/lib/pwn/ai/agent/reward.rb +9 -0
- data/lib/pwn/ai/agent/swarm.rb +3 -1
- data/lib/pwn/ai/agent/task_summarizer.rb +23 -6
- data/lib/pwn/ai/agent/tool_guard.rb +109 -0
- data/lib/pwn/ai/agent/tools/ruby_eval.rb +44 -20
- data/lib/pwn/ai/agent/tools/shell.rb +17 -4
- data/lib/pwn/ai/agent/tools/skills.rb +63 -2
- data/lib/pwn/ai/anthropic.rb +25 -5
- data/lib/pwn/ai/gemini.rb +25 -5
- data/lib/pwn/ai/grok.rb +30 -13
- data/lib/pwn/ai/http_retry.rb +78 -0
- data/lib/pwn/ai/ollama.rb +25 -5
- data/lib/pwn/ai/open_ai.rb +26 -13
- data/lib/pwn/ai/open_web_ui.rb +25 -5
- data/lib/pwn/ai.rb +1 -0
- data/lib/pwn/config.rb +1 -1
- data/lib/pwn/plugins/log.rb +183 -41
- data/lib/pwn/plugins/repl.rb +50 -15
- data/lib/pwn/plugins/transparent_browser.rb +16 -2
- data/lib/pwn/sessions.rb +50 -1
- data/lib/pwn/version.rb +1 -1
- data/spec/integration/reinforced_feedback_loop_spec.rb +9 -11
- data/spec/lib/pwn/ai/agent/loop_spec.rb +180 -20
- data/spec/lib/pwn/ai/agent/prompt_builder_spec.rb +3 -0
- data/spec/lib/pwn/ai/agent/registry_spec.rb +1 -1
- data/spec/lib/pwn/ai/agent/reward_spec.rb +13 -0
- data/spec/lib/pwn/ai/agent/swarm_spec.rb +6 -0
- data/spec/lib/pwn/ai/agent/task_summarizer_spec.rb +36 -0
- data/spec/lib/pwn/ai/agent/tool_guard_spec.rb +46 -0
- data/spec/lib/pwn/ai/agent/tools/ruby_eval_spec.rb +24 -0
- data/spec/lib/pwn/ai/agent/tools/shell_spec.rb +10 -0
- data/spec/lib/pwn/ai/agent/tools/skills_spec.rb +29 -0
- data/spec/lib/pwn/ai/grok_spec.rb +22 -0
- data/spec/lib/pwn/ai/http_retry_spec.rb +55 -0
- data/spec/lib/pwn/plugins/log_spec.rb +170 -19
- data/spec/lib/pwn/plugins/repl_pwn_vault_spec.rb +14 -4
- data/spec/lib/pwn/plugins/transparent_browser_spec.rb +8 -0
- data/spec/lib/pwn/sessions_spec.rb +24 -0
- data/third_party/pwn_rdoc.jsonl +41 -5
- data/tmp_pwn_critic_skills_flaw.txt +9 -0
- metadata +11 -8
|
@@ -25,12 +25,15 @@ describe PWN::Plugins::Log do
|
|
|
25
25
|
expect(PWN::Plugins::Log).to respond_to(:progress)
|
|
26
26
|
expect(PWN::Plugins::Log).to respond_to(:debug_enabled?)
|
|
27
27
|
expect(PWN::Plugins::Log).to respond_to(:debug_log_path)
|
|
28
|
+
expect(PWN::Plugins::Log).to respond_to(:next_request_log!)
|
|
29
|
+
expect(PWN::Plugins::Log).to respond_to(:finish_request_log!)
|
|
28
30
|
|
|
29
31
|
tee = StringIO.new
|
|
30
|
-
|
|
31
|
-
expect(path).to match(%r{\A/tmp/pwn-ai-DEBUG-.+\.log\z})
|
|
32
|
-
expect(File.file?(path)).to eq(true)
|
|
32
|
+
PWN::Plugins::Log.start_debug(tee: tee, path: nil)
|
|
33
33
|
expect(PWN::Plugins::Log.debug_enabled?).to eq(true)
|
|
34
|
+
path = PWN::Plugins::Log.next_request_log!(session_id: "sess#{Process.pid}")
|
|
35
|
+
expect(path).to eq("/tmp/pwn-ai-DEBUG-sess#{Process.pid}-R1.log")
|
|
36
|
+
expect(File.file?(path)).to eq(true)
|
|
34
37
|
expect(PWN::Plugins::Log.debug_log_path).to eq(path)
|
|
35
38
|
|
|
36
39
|
ok = PWN::Plugins::Log.progress(msg: 'Loop.run start request=hi', which_self: PWN::AI::Agent::Loop)
|
|
@@ -61,21 +64,166 @@ describe PWN::Plugins::Log do
|
|
|
61
64
|
expect(tee.string).to include('after-loud')
|
|
62
65
|
end
|
|
63
66
|
|
|
64
|
-
it '
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
PWN::Plugins::Log.progress(msg: '
|
|
71
|
-
|
|
72
|
-
expect(
|
|
73
|
-
expect(
|
|
74
|
-
expect(
|
|
67
|
+
it 'tees debug lines with raw ANSI, not PS1 SOH/STX markers' do
|
|
68
|
+
tee = StringIO.new
|
|
69
|
+
PWN::Plugins::Log.start_debug(
|
|
70
|
+
tee: tee,
|
|
71
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-ansi.log"
|
|
72
|
+
)
|
|
73
|
+
PWN::Plugins::Log.progress(msg: 'stage-line', which_self: PWN::AI::Agent::Loop)
|
|
74
|
+
shown = tee.string
|
|
75
|
+
expect(shown).to include('stage-line')
|
|
76
|
+
expect(shown).to include("\e[35m")
|
|
77
|
+
expect(shown).not_to include("\001")
|
|
78
|
+
expect(shown).not_to include("\002")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'writes a multiline final body when keep_newlines is set' do
|
|
82
|
+
path = PWN::Plugins::Log.start_debug(
|
|
83
|
+
tee: StringIO.new,
|
|
84
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-finalbody.log"
|
|
85
|
+
)
|
|
86
|
+
PWN::Plugins::Log.progress(
|
|
87
|
+
msg: "final text:\nline-one\nline-two",
|
|
88
|
+
which_self: PWN::AI::Agent::Loop,
|
|
89
|
+
keep_newlines: true,
|
|
90
|
+
cap: 65_536
|
|
91
|
+
)
|
|
92
|
+
body = File.read(path)
|
|
93
|
+
expect(body).to include("final text:\nline-one\nline-two")
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'writes a full tool request/result with no char cap when cap is 0' do
|
|
97
|
+
path = PWN::Plugins::Log.start_debug(
|
|
98
|
+
tee: StringIO.new,
|
|
99
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-toolio.log"
|
|
100
|
+
)
|
|
101
|
+
blob = 'x' * 8_000
|
|
102
|
+
PWN::Plugins::Log.progress(
|
|
103
|
+
msg: "tool pwn_eval request:\n#{blob}\nresult:\n#{blob}",
|
|
104
|
+
which_self: PWN::AI::Agent::Loop,
|
|
105
|
+
keep_newlines: true,
|
|
106
|
+
cap: 0,
|
|
107
|
+
tee: nil
|
|
108
|
+
)
|
|
109
|
+
body = File.read(path)
|
|
110
|
+
expect(body).to include('tool pwn_eval request:')
|
|
111
|
+
expect(body).to include(blob)
|
|
112
|
+
expect(body).to include("result:\n#{blob}")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'timestamps an Interrupt line into the open request log' do
|
|
116
|
+
expect(PWN::Plugins::Log).to respond_to(:note_interrupt!)
|
|
117
|
+
path = PWN::Plugins::Log.start_debug(
|
|
118
|
+
tee: StringIO.new,
|
|
119
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-int.log"
|
|
120
|
+
)
|
|
121
|
+
ok = PWN::Plugins::Log.note_interrupt!(where: 'CTRL+C')
|
|
122
|
+
expect(ok).to eq true
|
|
123
|
+
body = File.read(path)
|
|
124
|
+
expect(body).to match(/\[DEBUG \d{4}-\d{2}-\d{2} /)
|
|
125
|
+
expect(body).to include('Interrupt')
|
|
126
|
+
expect(body).to include('CTRL+C')
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'still timestamps Interrupt when progress reentrancy is stuck mid-write' do
|
|
130
|
+
path = PWN::Plugins::Log.start_debug(
|
|
131
|
+
tee: StringIO.new,
|
|
132
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-int-stuck.log"
|
|
133
|
+
)
|
|
134
|
+
Thread.current[:pwn_log_progress] = true
|
|
135
|
+
ok = PWN::Plugins::Log.note_interrupt!(where: 'CTRL+C')
|
|
136
|
+
expect(ok).to eq true
|
|
137
|
+
body = File.read(path)
|
|
138
|
+
expect(body).to include('Interrupt')
|
|
139
|
+
expect(body).to include('CTRL+C')
|
|
140
|
+
expect(body).to match(/at=|→ pwn-ai → Interrupt/)
|
|
141
|
+
ensure
|
|
142
|
+
Thread.current[:pwn_log_progress] = false
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'timestamps an exception and backtrace into the open request log' do
|
|
146
|
+
expect(PWN::Plugins::Log).to respond_to(:note_exception!)
|
|
147
|
+
path = PWN::Plugins::Log.start_debug(
|
|
148
|
+
tee: StringIO.new,
|
|
149
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-exc.log"
|
|
150
|
+
)
|
|
151
|
+
err = NoMethodError.new("undefined method '+' for nil")
|
|
152
|
+
err.set_backtrace(['/opt/pwn/lib/pwn/ai/grok.rb:470:in grok_rest_call', 'loop.rb:1'])
|
|
153
|
+
ok = PWN::Plugins::Log.note_exception!(error: err, where: 'Loop.run')
|
|
154
|
+
expect(ok).to eq true
|
|
155
|
+
body = File.read(path)
|
|
156
|
+
expect(body).to include('NoMethodError')
|
|
157
|
+
expect(body).to include("undefined method '+' for nil")
|
|
158
|
+
expect(body).to include('grok.rb:470')
|
|
159
|
+
expect(body).to include('Loop.run')
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it 'mirrors TUI tool/task/result rows into the request log without ANSI' do
|
|
163
|
+
expect(PWN::Plugins::Log).to respond_to(:mirror_tui!)
|
|
164
|
+
path = PWN::Plugins::Log.start_debug(
|
|
165
|
+
tee: StringIO.new,
|
|
166
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-tui.log"
|
|
167
|
+
)
|
|
168
|
+
ok = PWN::Plugins::Log.mirror_tui!(
|
|
169
|
+
msg: "\e[33m[ 2026-08-20 11:00:00-0600 → pwn-ai → pwn_eval ]\e[0m\n {\"code\":\"1+1\"}\n"
|
|
170
|
+
)
|
|
171
|
+
expect(ok).not_to be_nil
|
|
172
|
+
PWN::Plugins::Log.mirror_tui!(msg: "2026-08-20 11:00:01-0600 → result\n {\"value\":\"2\"}\n")
|
|
173
|
+
PWN::Plugins::Log.mirror_tui!(msg: '[ 2026-08-20 11:00:00-0600 → pwn-ai → task ] navigate')
|
|
174
|
+
body = File.read(path)
|
|
175
|
+
expect(body).to include('[ 2026-08-20 11:00:00-0600 → pwn-ai → pwn_eval ]')
|
|
176
|
+
expect(body).to include('{"code":"1+1"}')
|
|
177
|
+
expect(body).to include('→ result')
|
|
178
|
+
expect(body).to include('→ pwn-ai → task')
|
|
179
|
+
expect(body).not_to include("\e[33m")
|
|
180
|
+
expect(body).not_to include("\e[0m")
|
|
75
181
|
end
|
|
76
182
|
|
|
77
|
-
it '
|
|
78
|
-
|
|
183
|
+
it 'opens one debug log per request: SESSION_ID-R1 then SESSION_ID-R2' do
|
|
184
|
+
tee = StringIO.new
|
|
185
|
+
sid = "abc#{Process.pid}"
|
|
186
|
+
PWN::Plugins::Log.start_debug(tee: tee)
|
|
187
|
+
first = PWN::Plugins::Log.next_request_log!(session_id: sid)
|
|
188
|
+
PWN::Plugins::Log.progress(msg: 'req-one', which_self: PWN::AI::Agent::Loop)
|
|
189
|
+
PWN::Plugins::Log.finish_request_log!(iter: 1, tools_called: 0, engine_s: 0.1, final_chars: 4)
|
|
190
|
+
second = PWN::Plugins::Log.next_request_log!(session_id: sid)
|
|
191
|
+
PWN::Plugins::Log.progress(msg: 'req-two', which_self: PWN::AI::Agent::Loop)
|
|
192
|
+
expect(first).to eq("/tmp/pwn-ai-DEBUG-#{sid}-R1.log")
|
|
193
|
+
expect(second).to eq("/tmp/pwn-ai-DEBUG-#{sid}-R2.log")
|
|
194
|
+
expect(File.read(first)).to include('req-one')
|
|
195
|
+
expect(File.read(first)).to include('footer iter=1')
|
|
196
|
+
expect(File.read(first)).not_to include('req-two')
|
|
197
|
+
expect(File.read(second)).to include('req-two')
|
|
198
|
+
expect(File.read(second)).not_to include('req-one')
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it 'does not roll RN when a request log is already open' do
|
|
202
|
+
tee = StringIO.new
|
|
203
|
+
sid = "nest#{Process.pid}"
|
|
204
|
+
PWN::Plugins::Log.start_debug(tee: tee)
|
|
205
|
+
first = PWN::Plugins::Log.next_request_log!(session_id: sid)
|
|
206
|
+
second = PWN::Plugins::Log.next_request_log!(session_id: sid)
|
|
207
|
+
expect(second).to eq(first)
|
|
208
|
+
expect(second).to eq("/tmp/pwn-ai-DEBUG-#{sid}-R1.log")
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'does not TracePoint PWN calls unless trace: true' do
|
|
212
|
+
path = PWN::Plugins::Log.start_debug(
|
|
213
|
+
tee: StringIO.new,
|
|
214
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-notrace.log"
|
|
215
|
+
)
|
|
216
|
+
PWN::AI::Agent::OpenGoal.current if defined?(PWN::AI::Agent::OpenGoal)
|
|
217
|
+
body = File.read(path)
|
|
218
|
+
expect(body).not_to match(/PWN::AI::Agent::OpenGoal\.current/)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it 'traces PWN module calls into the same debug log when trace: true' do
|
|
222
|
+
path = PWN::Plugins::Log.start_debug(
|
|
223
|
+
tee: StringIO.new,
|
|
224
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-#{Time.now.to_i}.log",
|
|
225
|
+
trace: true
|
|
226
|
+
)
|
|
79
227
|
PWN::AI::Agent::OpenGoal.current if defined?(PWN::AI::Agent::OpenGoal)
|
|
80
228
|
body = File.read(path)
|
|
81
229
|
expect(body).to match(/PWN::AI::Agent::OpenGoal/)
|
|
@@ -94,7 +242,8 @@ describe PWN::Plugins::Log do
|
|
|
94
242
|
stub_const('PWN::AI::Agent::SymNameProbe', probe)
|
|
95
243
|
PWN::Plugins::Log.start_debug(
|
|
96
244
|
tee: StringIO.new,
|
|
97
|
-
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-sym.log"
|
|
245
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-sym.log",
|
|
246
|
+
trace: true
|
|
98
247
|
)
|
|
99
248
|
expect { PWN::AI::Agent::SymNameProbe.ping }.not_to raise_error
|
|
100
249
|
end
|
|
@@ -108,7 +257,8 @@ describe PWN::Plugins::Log do
|
|
|
108
257
|
stub_const('PWN::AI::Agent::ArgProbe', probe)
|
|
109
258
|
path = PWN::Plugins::Log.start_debug(
|
|
110
259
|
tee: StringIO.new,
|
|
111
|
-
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-args.log"
|
|
260
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-args.log",
|
|
261
|
+
trace: true
|
|
112
262
|
)
|
|
113
263
|
PWN::AI::Agent::ArgProbe.echo(
|
|
114
264
|
msg: 'hello-browser',
|
|
@@ -132,7 +282,8 @@ describe PWN::Plugins::Log do
|
|
|
132
282
|
stub_const('PWN::AI::Agent::ArgProbe', probe)
|
|
133
283
|
path = PWN::Plugins::Log.start_debug(
|
|
134
284
|
tee: StringIO.new,
|
|
135
|
-
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-redact.log"
|
|
285
|
+
path: "/tmp/pwn-ai-DEBUG-#{Process.pid}-redact.log",
|
|
286
|
+
trace: true
|
|
136
287
|
)
|
|
137
288
|
PWN::AI::Agent::ArgProbe.echo(
|
|
138
289
|
header: 'Bearer eyJhbGciOiJIUzI1NiJ9.aaa.bbb',
|
|
@@ -12,7 +12,7 @@ describe 'pwn-vault Config RuntimeError retry' do
|
|
|
12
12
|
let(:vault_src) { File.read(PWN::Plugins::Vault.method(:edit).source_location.first) }
|
|
13
13
|
let(:block) do
|
|
14
14
|
start = repl_src.index("Pry::Commands.create_command 'pwn-vault'")
|
|
15
|
-
stop = repl_src.index("Pry::Commands.create_command 'toggle-
|
|
15
|
+
stop = repl_src.index("Pry::Commands.create_command 'toggle-debug'")
|
|
16
16
|
repl_src[start...stop]
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -133,10 +133,10 @@ describe 'pwn-vault Config RuntimeError retry' do
|
|
|
133
133
|
end
|
|
134
134
|
end
|
|
135
135
|
|
|
136
|
-
describe 'toggle-
|
|
136
|
+
describe 'toggle-debug' do
|
|
137
137
|
let(:repl_src) { File.read(PWN::Plugins::REPL.method(:add_commands).source_location.first) }
|
|
138
138
|
let(:block) do
|
|
139
|
-
start = repl_src.index("Pry::Commands.create_command 'toggle-
|
|
139
|
+
start = repl_src.index("Pry::Commands.create_command 'toggle-debug'")
|
|
140
140
|
stop = repl_src.index("Pry::Commands.create_command 'toggle-pwn-ai-speaks'")
|
|
141
141
|
repl_src[start...stop]
|
|
142
142
|
end
|
|
@@ -145,6 +145,7 @@ describe 'toggle-pwn-ai-debug' do
|
|
|
145
145
|
expect(block).to include('PWN::Plugins::Log.start_debug')
|
|
146
146
|
expect(block).to include('PWN::Plugins::Log.stop_debug')
|
|
147
147
|
expect(block).to include('pwn-ai-DEBUG')
|
|
148
|
+
expect(block).to include('-R')
|
|
148
149
|
end
|
|
149
150
|
end
|
|
150
151
|
|
|
@@ -157,9 +158,18 @@ describe 'pwn-ai debug final answer placement' do
|
|
|
157
158
|
|
|
158
159
|
it 'prints the green final after Loop.run and does not pp the session after it' do
|
|
159
160
|
expect(hook).to match(/Loop\.run\(/)
|
|
160
|
-
expect(hook).to match(/\\e\[32m
|
|
161
|
+
expect(hook).to match(/\\e\[32m#\{final\}/)
|
|
162
|
+
expect(hook).not_to include('[0, 280]')
|
|
163
|
+
expect(hook).not_to include('[0, 700]')
|
|
161
164
|
native = hook[hook.index('final = PWN::AI::Agent::Loop.run')..hook.index("request.replace('nil')")]
|
|
165
|
+
expect(native).not_to include('\001')
|
|
162
166
|
expect(native).not_to match(/pp PWN::Sessions\.load/)
|
|
163
167
|
expect(native).to match(/\$stdout\.flush/)
|
|
164
168
|
end
|
|
169
|
+
|
|
170
|
+
it 'mirrors TUI task/tool/result rows into the debug RN log' do
|
|
171
|
+
expect(hook).to include('mirror_tui!')
|
|
172
|
+
expect(hook).to include('→ pwn-ai →')
|
|
173
|
+
expect(hook).to include('→ result')
|
|
174
|
+
end
|
|
165
175
|
end
|
|
@@ -12,4 +12,12 @@ describe PWN::Plugins::TransparentBrowser do
|
|
|
12
12
|
help_response = PWN::Plugins::TransparentBrowser
|
|
13
13
|
expect(help_response).to respond_to :help
|
|
14
14
|
end
|
|
15
|
+
|
|
16
|
+
it 'caps Watir element waits and Selenium page_load / script timeouts' do
|
|
17
|
+
src = File.read(described_class.method(:open).source_location.first)
|
|
18
|
+
expect(src).to match(/Watir\.default_timeout\s*=\s*15/)
|
|
19
|
+
expect(src).not_to match(/Watir\.default_timeout\s*=\s*900/)
|
|
20
|
+
expect(src).to match(/page_load\s*=\s*45/)
|
|
21
|
+
expect(src).to match(/script\s*=\s*30/)
|
|
22
|
+
end
|
|
15
23
|
end
|
|
@@ -90,4 +90,28 @@ describe PWN::Sessions do
|
|
|
90
90
|
ensure
|
|
91
91
|
FileUtils.rm_rf(tmp) if tmp
|
|
92
92
|
end
|
|
93
|
+
|
|
94
|
+
it 'to_llm_messages returns this session user/assistant turns for the next LLM call' do
|
|
95
|
+
tmp = Dir.mktmpdir
|
|
96
|
+
stub_const('PWN::Sessions::SESSIONS_DIR', tmp)
|
|
97
|
+
sid = 'llm_hist_sess'
|
|
98
|
+
PWN::Sessions.create(id: sid, title: 'hist')
|
|
99
|
+
PWN::Sessions.append(session_id: sid, role: 'user', content: 'where is OpenGoal?')
|
|
100
|
+
PWN::Sessions.append(session_id: sid, role: 'assistant', content: 'in open_goal.rb')
|
|
101
|
+
PWN::Sessions.append(session_id: sid, role: 'tool', content: 'ignore me')
|
|
102
|
+
PWN::Sessions.append(session_id: sid, role: 'user', content: 'and Loop.run?')
|
|
103
|
+
PWN::Sessions.append(session_id: sid, role: 'assistant', content: 'in loop.rb around resume?')
|
|
104
|
+
msgs = PWN::Sessions.to_llm_messages(session_id: sid)
|
|
105
|
+
expect(msgs.map { |m| m[:role] }).to eq(%w[user assistant user assistant])
|
|
106
|
+
expect(msgs.map { |m| m[:content] }).to include('where is OpenGoal?', 'in open_goal.rb', 'and Loop.run?', 'in loop.rb around resume?')
|
|
107
|
+
expect(msgs.none? { |m| m[:content].to_s.include?('ignore me') }).to eq true
|
|
108
|
+
skip_last = PWN::Sessions.to_llm_messages(session_id: sid, skip_request: 'and Loop.run?')
|
|
109
|
+
expect(skip_last.last[:content]).to eq('in loop.rb around resume?')
|
|
110
|
+
expect(skip_last.none? { |m| m[:content] == 'and Loop.run?' && m[:role] == 'user' }).to eq true
|
|
111
|
+
tiny = PWN::Sessions.to_llm_messages(session_id: sid, max_chars: 40)
|
|
112
|
+
expect(tiny.last[:content]).to include('loop.rb')
|
|
113
|
+
expect(tiny.map { |m| m[:content].to_s.length }.sum).to be <= 80
|
|
114
|
+
ensure
|
|
115
|
+
FileUtils.rm_rf(tmp) if tmp
|
|
116
|
+
end
|
|
93
117
|
end
|
data/third_party/pwn_rdoc.jsonl
CHANGED
|
@@ -283,6 +283,7 @@
|
|
|
283
283
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.infer_success Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.infer_success`: "}]}
|
|
284
284
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.introspective_lessons Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.introspective_lessons`: "}]}
|
|
285
285
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.lean! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.lean!`: "}]}
|
|
286
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.locate_skill_for_update Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.locate_skill_for_update`: "}]}
|
|
286
287
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.maybe_prune_outcomes! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.maybe_prune_outcomes!`: "}]}
|
|
287
288
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.merge_cluster Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.merge_cluster`: "}]}
|
|
288
289
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.note_outcome Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.note_outcome`: Supported Method Parameters\n\nentry = PWN::AI::Agent::Learning.note_outcome(\n\ntask: 'required - short description of what was attempted',\nsuccess: 'required - Boolean, did the attempt achieve its goal',\ndetails: 'optional - free-form notes / error / evidence',\nsession_id: 'optional - PWN::Sessions id this outcome belongs to',\ntags: 'optional - Array of String labels for later retrieval'\n\n)\n"}]}
|
|
@@ -296,13 +297,16 @@
|
|
|
296
297
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.recover_predicted_from_session Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.recover_predicted_from_session`: "}]}
|
|
297
298
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.reflect Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.reflect`: Supported Method Parameters\n\nreport = PWN::AI::Agent::Learning.reflect(\n\nsession_id: 'required - PWN::Sessions id to analyse',\ndry_run: 'optional - when true, do not write to Memory/Skills (default false)'\n\n)\n\nUses PWN::AI::Agent::Reflect (when available) to LLM-summarise the session into structured lessons. Falls back to a heuristic extractor when module_reflection is disabled so learning never stops.\n"}]}
|
|
298
299
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.reset Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.reset`: Supported Method Parameters\n\nPWN::AI::Agent::Learning.reset\n"}]}
|
|
300
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.rl_skill_notes Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.rl_skill_notes`: "}]}
|
|
299
301
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.semantic_merge Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.semantic_merge`: "}]}
|
|
300
302
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.sharegpt_role Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.sharegpt_role`: "}]}
|
|
301
303
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.should_gc_stores? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.should_gc_stores?`: "}]}
|
|
304
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.skill_body_without_frontmatter Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.skill_body_without_frontmatter`: "}]}
|
|
302
305
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.skills_dir Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.skills_dir`: "}]}
|
|
303
306
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.stats Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.stats`: Supported Method Parameters\n\nstats = PWN::AI::Agent::Learning.stats\n"}]}
|
|
304
307
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.to_context Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.to_context`: Supported Method Parameters\n\nctx = PWN::AI::Agent::Learning.to_context(\n\nlimit: 'optional - number of recent outcomes to surface (default 5)'\n\n)\n"}]}
|
|
305
308
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.transcript_text Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.transcript_text`: "}]}
|
|
309
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.update_skill Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.update_skill`: "}]}
|
|
306
310
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.verdict_for_score Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.verdict_for_score`: "}]}
|
|
307
311
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.weighted_judge_mean Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.weighted_judge_mean`: "}]}
|
|
308
312
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.active_engine Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.active_engine`: "}]}
|
|
@@ -319,9 +323,16 @@
|
|
|
319
323
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.budget_hit? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.budget_hit?`: "}]}
|
|
320
324
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.calibration_state Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.calibration_state`: "}]}
|
|
321
325
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.call_engine Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.call_engine`: Supported Method Parameters\n\nmsg = PWN::AI::Agent::Loop.call_engine(\n\nmessages: 'required - OpenAI-format messages array',\ntools: 'optional - OpenAI tools array'\n\n)\n\nReturns a normalised assistant message hash:\n\n{ role: 'assistant', content: String|nil,\n tool_calls: [ {id:, type:'function', function:{name:, arguments:}} ],\n _native_content: <provider raw> (when adapter needs round-trip) }\n"}]}
|
|
326
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.catalog_lookup? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.catalog_lookup?`: "}]}
|
|
327
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.chat_response_history Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.chat_response_history`: "}]}
|
|
322
328
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.compact_history! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.compact_history!`: "}]}
|
|
329
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.debug_final_text! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.debug_final_text!`: "}]}
|
|
330
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.debug_msgs_line Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.debug_msgs_line`: "}]}
|
|
323
331
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.debug_on? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.debug_on?`: "}]}
|
|
324
332
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.debug_progress Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.debug_progress`: "}]}
|
|
333
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.debug_snippet Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.debug_snippet`: "}]}
|
|
334
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.debug_tool_io! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.debug_tool_io!`: "}]}
|
|
335
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.debug_tools_line Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.debug_tools_line`: "}]}
|
|
325
336
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.default_interactive_toolsets Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.default_interactive_toolsets`: "}]}
|
|
326
337
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.degrade_text_only Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.degrade_text_only`: "}]}
|
|
327
338
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.dispatch_fail_n Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.dispatch_fail_n`: "}]}
|
|
@@ -330,6 +341,7 @@
|
|
|
330
341
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.evidence_enough_to_finalize? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.evidence_enough_to_finalize?`: "}]}
|
|
331
342
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.expose_current_session Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.expose_current_session`: "}]}
|
|
332
343
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.extract_recall_match Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.extract_recall_match`: "}]}
|
|
344
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.finish_debug_request! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.finish_debug_request!`: "}]}
|
|
333
345
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.guard_repeated_failure Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.guard_repeated_failure`: "}]}
|
|
334
346
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.help Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.help`: "}]}
|
|
335
347
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.incomplete_final? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.incomplete_final?`: "}]}
|
|
@@ -359,6 +371,7 @@
|
|
|
359
371
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.request_need Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.request_need`: "}]}
|
|
360
372
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.request_unsatisfied? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.request_unsatisfied?`: "}]}
|
|
361
373
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.run Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.run`: Supported Method Parameters\n\nfinal = PWN::AI::Agent::Loop.run(\n\nrequest: 'required - what the human typed',\nsession_id: 'optional - PWN::Sessions id (transcript is appended to it)',\nenabled_toolsets: 'optional - subset of Registry.toolsets, or nil for all',\non_tool: 'optional - ->(name, args, result) callback for live UI',\nsystem_role_content: 'optional - override default system prompt (built from session_id if not provided)'\n\n)\n"}]}
|
|
374
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.session_chat_history Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.session_chat_history`: "}]}
|
|
362
375
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.should_auto_introspect? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.should_auto_introspect?`: "}]}
|
|
363
376
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.stamped_effect Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.stamped_effect`: "}]}
|
|
364
377
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.start_debug_session Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.start_debug_session`: "}]}
|
|
@@ -495,6 +508,7 @@
|
|
|
495
508
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::PromptBuilder.extrospection_block Usage"},{"role":"assistant","content":"`PWN::AI::Agent::PromptBuilder.extrospection_block`: "}]}
|
|
496
509
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::PromptBuilder.help Usage"},{"role":"assistant","content":"`PWN::AI::Agent::PromptBuilder.help`: "}]}
|
|
497
510
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::PromptBuilder.host_line Usage"},{"role":"assistant","content":"`PWN::AI::Agent::PromptBuilder.host_line`: "}]}
|
|
511
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::PromptBuilder.host_load_block Usage"},{"role":"assistant","content":"`PWN::AI::Agent::PromptBuilder.host_load_block`: "}]}
|
|
498
512
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::PromptBuilder.learning_block Usage"},{"role":"assistant","content":"`PWN::AI::Agent::PromptBuilder.learning_block`: "}]}
|
|
499
513
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::PromptBuilder.memory_block Usage"},{"role":"assistant","content":"`PWN::AI::Agent::PromptBuilder.memory_block`: "}]}
|
|
500
514
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::PromptBuilder.metrics_block Usage"},{"role":"assistant","content":"`PWN::AI::Agent::PromptBuilder.metrics_block`: "}]}
|
|
@@ -590,6 +604,7 @@
|
|
|
590
604
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Reward.sentinel Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Reward.sentinel`: Supported Method Parameters\n\nr = PWN::AI::Agent::Reward.sentinel\n"}]}
|
|
591
605
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Reward.set_proxy_distrust Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Reward.set_proxy_distrust`: "}]}
|
|
592
606
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Reward.timeout_error? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Reward.timeout_error?`: "}]}
|
|
607
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::Reward.timeout_result? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Reward.timeout_result?`: "}]}
|
|
593
608
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Reward.usable_preference? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Reward.usable_preference?`: "}]}
|
|
594
609
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Reward.user_correction_rate Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Reward.user_correction_rate`: "}]}
|
|
595
610
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Reward.verify_as_reward Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Reward.verify_as_reward`: Supported Method Parameters\n\ng = PWN::AI::Agent::Reward.verify_as_reward(final: text)\n"}]}
|
|
@@ -630,6 +645,7 @@
|
|
|
630
645
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.arg_snippet Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.arg_snippet`: "}]}
|
|
631
646
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.authors Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
|
|
632
647
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.brief_fingerprint Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.brief_fingerprint`: "}]}
|
|
648
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.browse_shaped? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.browse_shaped?`: "}]}
|
|
633
649
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.bump_plan! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.bump_plan!`: "}]}
|
|
634
650
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.canonical_request Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.canonical_request`: Supported Method Parameters\n\ntext = PWN::AI::Agent::TaskSummarizer.canonical_request(\n\nrequest: 'required - raw user or wrapper string'\n\n)\n"}]}
|
|
635
651
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.capabilities_for Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.capabilities_for`: "}]}
|
|
@@ -689,12 +705,17 @@
|
|
|
689
705
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.authors Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.authors`: "}]}
|
|
690
706
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.bashism? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.bashism?`: "}]}
|
|
691
707
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.coerce_args Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.coerce_args`: "}]}
|
|
708
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.deadline_s Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.deadline_s`: "}]}
|
|
692
709
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.help Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.help`: "}]}
|
|
710
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.host_load Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.host_load`: "}]}
|
|
693
711
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.invalid_payload Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.invalid_payload`: "}]}
|
|
694
712
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.placeholder? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.placeholder?`: "}]}
|
|
695
713
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.present? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.present?`: "}]}
|
|
696
714
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.shell_bash? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.shell_bash?`: "}]}
|
|
697
715
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.shell_name Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.shell_name`: "}]}
|
|
716
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.timeout_lesson Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.timeout_lesson`: "}]}
|
|
717
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.timeout_prior_count Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.timeout_prior_count`: "}]}
|
|
718
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::ToolGuard.timeout_result Usage"},{"role":"assistant","content":"`PWN::AI::Agent::ToolGuard.timeout_result`: "}]}
|
|
698
719
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TransparentBrowser.analyze Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TransparentBrowser.analyze`: Supported Method Parameters\n\nai_analysis = PWN::AI::Agent::TransparentBrowser.analyze(\n\nrequest: 'required - current step in the JavaScript debugging session to analyze',\nsource_to_review: 'required - the block of JavaScript code in which the current step resides'\n\n)\n"}]}
|
|
699
720
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TransparentBrowser.authors Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TransparentBrowser.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
|
|
700
721
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TransparentBrowser.help Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TransparentBrowser.help`: "}]}
|
|
@@ -741,9 +762,9 @@
|
|
|
741
762
|
{"messages":[{"role":"user","content":"PWN::AI::Gemini.oa_messages_to_gemini Usage"},{"role":"assistant","content":"`PWN::AI::Gemini.oa_messages_to_gemini`: "}]}
|
|
742
763
|
{"messages":[{"role":"user","content":"PWN::AI::Grok.authors Usage"},{"role":"assistant","content":"`PWN::AI::Grok.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
|
|
743
764
|
{"messages":[{"role":"user","content":"PWN::AI::Grok.chat Usage"},{"role":"assistant","content":"`PWN::AI::Grok.chat`: Supported Method Parameters\n\nresponse = PWN::AI::Grok.chat(\n\nrequest: 'required - message to Grok'\nmodel: 'optional - model to use for text generation (defaults to PWN::Env[:ai][:grok][:model])',\ntemp: 'optional - creative response float (deafults to PWN::Env[:ai][:grok][:temp])',\nsystem_role_content: 'optional - context to set up the model behavior for conversation (Default: PWN::Env[:ai][:grok][:system_role_content])',\nresponse_history: 'optional - pass response back in to have a conversation',\nspeak_answer: 'optional speak answer using PWN::Plugins::Voice.text_to_speech (Default: nil)',\ntimeout: 'optional timeout in seconds (defaults to 900)',\nspinner: 'optional - display spinner (defaults to false)'\n\n)\n"}]}
|
|
744
|
-
{"messages":[{"role":"user","content":"PWN::AI::Grok.chat_with_tools Usage"},{"role":"assistant","content":"`PWN::AI::Grok.chat_with_tools`: Supported Method Parameters\n\nresponse = PWN::AI::Grok.chat_with_tools(\n\nmessages: 'required - full OpenAI-format messages array (system/user/assistant/tool)',\ntools: 'optional - OpenAI tools array [{type:\"function\", function:{...}}]',\ntool_choice: 'optional - \"auto\" | \"none\" | \"required\" | {type:\"function\", function:{name:..}}',\nmodel: 'optional - overrides PWN::Env[:ai][:grok][:model]',\ntemp: 'optional - temperature (defaults to PWN::Env[:ai][:grok][:temp] || 1)',\ntimeout: 'optional - seconds (default
|
|
765
|
+
{"messages":[{"role":"user","content":"PWN::AI::Grok.chat_with_tools Usage"},{"role":"assistant","content":"`PWN::AI::Grok.chat_with_tools`: Supported Method Parameters\n\nresponse = PWN::AI::Grok.chat_with_tools(\n\nmessages: 'required - full OpenAI-format messages array (system/user/assistant/tool)',\ntools: 'optional - OpenAI tools array [{type:\"function\", function:{...}}]',\ntool_choice: 'optional - \"auto\" | \"none\" | \"required\" | {type:\"function\", function:{name:..}}',\nmodel: 'optional - overrides PWN::Env[:ai][:grok][:model]',\ntemp: 'optional - temperature (defaults to PWN::Env[:ai][:grok][:temp] || 1)',\ntimeout: 'optional - seconds (default 180)',\nspinner: 'optional - display spinner (default false)'\n\n)\n\nReturns the raw chat/completions response Hash with :choices intact (including :message) — used by PWN::AI::Agent::Loop. xAI’s API is OpenAI-compatible for tool calling, so the request and response shapes are identical to PWN::AI::OpenAI.chat_with_tools.\n"}]}
|
|
745
766
|
{"messages":[{"role":"user","content":"PWN::AI::Grok.get_models Usage"},{"role":"assistant","content":"`PWN::AI::Grok.get_models`: Supported Method Parameters\n\nmodels = PWN::AI::Grok.get_models\n"}]}
|
|
746
|
-
{"messages":[{"role":"user","content":"PWN::AI::Grok.grok_rest_call Usage"},{"role":"assistant","content":"`PWN::AI::Grok.grok_rest_call`: Supported Method Parameters\n\ngrok_ai_rest_call(\n\ntoken: 'required - grok_ai bearer token',\nhttp_method: 'optional HTTP method (defaults to GET)\nbase_uri: 'optional base grok api URI (defaults to https://api.x.ai/v1)',\nrest_call: 'required rest call to make per the schema',\nparams: 'optional params passed in the URI or HTTP Headers',\nhttp_body: 'optional HTTP body sent in HTTP methods that support it e.g. POST',\ntimeout: 'optional timeout in seconds (defaults to
|
|
767
|
+
{"messages":[{"role":"user","content":"PWN::AI::Grok.grok_rest_call Usage"},{"role":"assistant","content":"`PWN::AI::Grok.grok_rest_call`: Supported Method Parameters\n\ngrok_ai_rest_call(\n\ntoken: 'required - grok_ai bearer token',\nhttp_method: 'optional HTTP method (defaults to GET)\nbase_uri: 'optional base grok api URI (defaults to https://api.x.ai/v1)',\nrest_call: 'required rest call to make per the schema',\nparams: 'optional params passed in the URI or HTTP Headers',\nhttp_body: 'optional HTTP body sent in HTTP methods that support it e.g. POST',\ntimeout: 'optional timeout in seconds (defaults to 180; 5 attempts)',\nspinner: 'optional - display spinner (defaults to false)'\n\n)\n"}]}
|
|
747
768
|
{"messages":[{"role":"user","content":"PWN::AI::Grok.help Usage"},{"role":"assistant","content":"`PWN::AI::Grok.help`: "}]}
|
|
748
769
|
{"messages":[{"role":"user","content":"PWN::AI::Grok.jwt_exp Usage"},{"role":"assistant","content":"`PWN::AI::Grok.jwt_exp`: "}]}
|
|
749
770
|
{"messages":[{"role":"user","content":"PWN::AI::Grok.oauth_token_expiring? Usage"},{"role":"assistant","content":"`PWN::AI::Grok.oauth_token_expiring?`: "}]}
|
|
@@ -752,6 +773,12 @@
|
|
|
752
773
|
{"messages":[{"role":"user","content":"PWN::AI::Grok.real_config_value? Usage"},{"role":"assistant","content":"`PWN::AI::Grok.real_config_value?`: "}]}
|
|
753
774
|
{"messages":[{"role":"user","content":"PWN::AI::Grok.refresh_oauth_bearer_token Usage"},{"role":"assistant","content":"`PWN::AI::Grok.refresh_oauth_bearer_token`: Supported Method Parameters\n\naccess_token = PWN::AI::Grok.refresh_oauth_bearer_token(\n\nrefresh_token: 'required - xAI OAuth refresh_token',\nclient_id: 'optional - defaults to public Grok-CLI client',\ntoken_uri: 'optional - defaults to https://auth.x.ai/oauth2/token'\n\n)\n\nExchanges a refresh_token for a fresh access_token at auth.x.ai. On success, writes :bearer_token (and a rotated :refresh_token if returned) back into the passed opts/oauth Hash so the live PWN::Env stays warm for the rest of the process. Also mirrors those values onto PWN::Env[:grok] when that Hash is available, then attempts to re-encrypt the updated tokens into ~/.pwn/pwn.yaml when the matching decryptor (key + iv) is present.\n"}]}
|
|
754
775
|
{"messages":[{"role":"user","content":"PWN::AI::Grok.sync_oauth_into_env Usage"},{"role":"assistant","content":"`PWN::AI::Grok.sync_oauth_into_env`: "}]}
|
|
776
|
+
{"messages":[{"role":"user","content":"PWN::AI::HttpRetry.authors Usage"},{"role":"assistant","content":"`PWN::AI::HttpRetry.authors`: "}]}
|
|
777
|
+
{"messages":[{"role":"user","content":"PWN::AI::HttpRetry.help Usage"},{"role":"assistant","content":"`PWN::AI::HttpRetry.help`: "}]}
|
|
778
|
+
{"messages":[{"role":"user","content":"PWN::AI::HttpRetry.max_attempts Usage"},{"role":"assistant","content":"`PWN::AI::HttpRetry.max_attempts`: "}]}
|
|
779
|
+
{"messages":[{"role":"user","content":"PWN::AI::HttpRetry.report_event Usage"},{"role":"assistant","content":"`PWN::AI::HttpRetry.report_event`: "}]}
|
|
780
|
+
{"messages":[{"role":"user","content":"PWN::AI::HttpRetry.retry_after_s Usage"},{"role":"assistant","content":"`PWN::AI::HttpRetry.retry_after_s`: "}]}
|
|
781
|
+
{"messages":[{"role":"user","content":"PWN::AI::HttpRetry.timeout_s Usage"},{"role":"assistant","content":"`PWN::AI::HttpRetry.timeout_s`: "}]}
|
|
755
782
|
{"messages":[{"role":"user","content":"PWN::AI::Ollama.assemble_native_chat_stream Usage"},{"role":"assistant","content":"`PWN::AI::Ollama.assemble_native_chat_stream`: "}]}
|
|
756
783
|
{"messages":[{"role":"user","content":"PWN::AI::Ollama.assemble_ollama_stream Usage"},{"role":"assistant","content":"`PWN::AI::Ollama.assemble_ollama_stream`: "}]}
|
|
757
784
|
{"messages":[{"role":"user","content":"PWN::AI::Ollama.assemble_openai_compat_stream Usage"},{"role":"assistant","content":"`PWN::AI::Ollama.assemble_openai_compat_stream`: "}]}
|
|
@@ -1881,19 +1908,26 @@
|
|
|
1881
1908
|
{"messages":[{"role":"user","content":"PWN::Plugins::JiraDataCenter.update_issue Usage"},{"role":"assistant","content":"`PWN::Plugins::JiraDataCenter.update_issue`: Supported Method Parameters\n\nissue_resp = PWN::Plugins::JiraDataCenter.update_issue(\n\nfields: 'required - fields to update in the issue (e.g. summary, description, labels, components, custom fields, etc.)',\nattachments: 'optional - array of attachment paths to upload to the issue (e.g. [\"/tmp/file1.txt\", \"/tmp/file2.txt\"])',\n\n)\n"}]}
|
|
1882
1909
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.append Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.append`: Supported Method Parameters\n\nPWN::Log.create( )\n"}]}
|
|
1883
1910
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.authors Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
|
|
1911
|
+
{"messages":[{"role":"user","content":"PWN::Plugins::Log.close_debug_file! Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.close_debug_file!`: "}]}
|
|
1884
1912
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.color_progress Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.color_progress`: "}]}
|
|
1885
1913
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.debug_enabled? Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.debug_enabled?`: "}]}
|
|
1886
1914
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.debug_log_path Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.debug_log_path`: "}]}
|
|
1887
|
-
{"messages":[{"role":"user","content":"PWN::Plugins::Log.
|
|
1915
|
+
{"messages":[{"role":"user","content":"PWN::Plugins::Log.finish_request_log! Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.finish_request_log!`: "}]}
|
|
1888
1916
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.format_debug_hash Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.format_debug_hash`: "}]}
|
|
1889
1917
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.format_progress Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.format_progress`: "}]}
|
|
1890
1918
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.format_trace_call Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.format_trace_call`: "}]}
|
|
1891
1919
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.help Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.help`: "}]}
|
|
1892
1920
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.inspect_debug Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.inspect_debug`: "}]}
|
|
1893
1921
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.loud_tui! Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.loud_tui!`: "}]}
|
|
1922
|
+
{"messages":[{"role":"user","content":"PWN::Plugins::Log.mirror_tui! Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.mirror_tui!`: "}]}
|
|
1923
|
+
{"messages":[{"role":"user","content":"PWN::Plugins::Log.next_debug_request_n Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.next_debug_request_n`: "}]}
|
|
1924
|
+
{"messages":[{"role":"user","content":"PWN::Plugins::Log.next_request_log! Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.next_request_log!`: "}]}
|
|
1925
|
+
{"messages":[{"role":"user","content":"PWN::Plugins::Log.note_exception! Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.note_exception!`: "}]}
|
|
1926
|
+
{"messages":[{"role":"user","content":"PWN::Plugins::Log.note_interrupt! Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.note_interrupt!`: "}]}
|
|
1927
|
+
{"messages":[{"role":"user","content":"PWN::Plugins::Log.open_debug_file! Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.open_debug_file!`: "}]}
|
|
1894
1928
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.progress Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.progress`: "}]}
|
|
1895
1929
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.quiet_tui! Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.quiet_tui!`: "}]}
|
|
1896
|
-
{"messages":[{"role":"user","content":"PWN::Plugins::Log.
|
|
1930
|
+
{"messages":[{"role":"user","content":"PWN::Plugins::Log.sanitize_debug_session_id Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.sanitize_debug_session_id`: "}]}
|
|
1897
1931
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.sanitize_debug_text Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.sanitize_debug_text`: "}]}
|
|
1898
1932
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.secret_key? Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.secret_key?`: "}]}
|
|
1899
1933
|
{"messages":[{"role":"user","content":"PWN::Plugins::Log.start_debug Usage"},{"role":"assistant","content":"`PWN::Plugins::Log.start_debug`: "}]}
|
|
@@ -2155,6 +2189,7 @@
|
|
|
2155
2189
|
{"messages":[{"role":"user","content":"PWN::Plugins::Tor.stop Usage"},{"role":"assistant","content":"`PWN::Plugins::Tor.stop`: Supported Method Parameters\n\nPWN::Plugins::Tor.stop(\n\ntor_obj: 'required - tor_obj returned from #start method'\n\n)\n"}]}
|
|
2156
2190
|
{"messages":[{"role":"user","content":"PWN::Plugins::Tor.switch_exit_node Usage"},{"role":"assistant","content":"`PWN::Plugins::Tor.switch_exit_node`: Supported Method Parameters\n\nPWN::Plugins::Tor.switch_exit_node(\n\ntor_obj: 'required - tor_obj returned from #start method',\nresponse_timeout: 'optional - float in seconds to timeout (default: 3.0)'\n\n)\n"}]}
|
|
2157
2191
|
{"messages":[{"role":"user","content":"PWN::Plugins::Tor.tor_control_cmd Usage"},{"role":"assistant","content":"`PWN::Plugins::Tor.tor_control_cmd`: Supported Method Parameters\n\ntor_ctrl_cmd(\n\ntor_obj: 'required - tor_obj returned from #start method'\ncmd: 'required - Tor control command to execute',\nresponse_timeout: 'optional - float in seconds to timeout (default: 3.0)'\n\n)\n"}]}
|
|
2192
|
+
{"messages":[{"role":"user","content":"PWN::Plugins::TransparentBrowser.apply_driver_timeouts! Usage"},{"role":"assistant","content":"`PWN::Plugins::TransparentBrowser.apply_driver_timeouts!`: "}]}
|
|
2158
2193
|
{"messages":[{"role":"user","content":"PWN::Plugins::TransparentBrowser.authors Usage"},{"role":"assistant","content":"`PWN::Plugins::TransparentBrowser.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
|
|
2159
2194
|
{"messages":[{"role":"user","content":"PWN::Plugins::TransparentBrowser.breakpoint_locations Usage"},{"role":"assistant","content":"`PWN::Plugins::TransparentBrowser.breakpoint_locations`: Supported Method Parameters\n\npage_state_arr = PWN::Plugins::TransparentBrowser.breakpoint_locations(\n\nbrowser_obj: 'required - browser_obj returned from #open method)'\n\n)\n"}]}
|
|
2160
2195
|
{"messages":[{"role":"user","content":"PWN::Plugins::TransparentBrowser.close Usage"},{"role":"assistant","content":"`PWN::Plugins::TransparentBrowser.close`: Supported Method Parameters\n\nbrowser_obj1 = PWN::Plugins::TransparentBrowser.close(\n\nbrowser_obj: 'required - browser_obj returned from #open method)'\n\n)\n"}]}
|
|
@@ -2722,7 +2757,7 @@
|
|
|
2722
2757
|
{"messages":[{"role":"user","content":"PWN::Sessions.append Usage"},{"role":"assistant","content":"`PWN::Sessions.append`: Supported Method Parameters\n\nPWN::Sessions.append(\n\nsession_id: 'required',\nrole: 'user|assistant|system|observation',\ncontent: 'the message or obs'\n\n)\n"}]}
|
|
2723
2758
|
{"messages":[{"role":"user","content":"PWN::Sessions.authors Usage"},{"role":"assistant","content":"`PWN::Sessions.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
|
|
2724
2759
|
{"messages":[{"role":"user","content":"PWN::Sessions.compact_transcript! Usage"},{"role":"assistant","content":"`PWN::Sessions.compact_transcript!`: "}]}
|
|
2725
|
-
{"messages":[{"role":"user","content":"PWN::Sessions.create Usage"},{"role":"assistant","content":"`PWN::Sessions.create`: Supported Method Parameters\n\nsession = PWN::Sessions.create(\n\ntitle: 'optional - human title',\nsource: 'optional - e.g. pwn-ai
|
|
2760
|
+
{"messages":[{"role":"user","content":"PWN::Sessions.create Usage"},{"role":"assistant","content":"`PWN::Sessions.create`: Supported Method Parameters\n\nsession = PWN::Sessions.create(\n\ntitle: 'optional - human title',\nsource: 'optional - e.g. pwn-ai',\nid: 'optional - fixed session id (tests / replay); default timestamp_hex'\n\n)\n"}]}
|
|
2726
2761
|
{"messages":[{"role":"user","content":"PWN::Sessions.delete Usage"},{"role":"assistant","content":"`PWN::Sessions.delete`: Supported Method Parameters\n\nPWN::Sessions.delete(\n\nsession_id: 'required',\nforce: 'optional - Boolean bypass pin policy (default false)'\n\n)\n"}]}
|
|
2727
2762
|
{"messages":[{"role":"user","content":"PWN::Sessions.help Usage"},{"role":"assistant","content":"`PWN::Sessions.help`: "}]}
|
|
2728
2763
|
{"messages":[{"role":"user","content":"PWN::Sessions.lean! Usage"},{"role":"assistant","content":"`PWN::Sessions.lean!`: Supported Method Parameters\n\nresult = PWN::Sessions.lean!(\n\ndry_run: 'optional - Boolean (default false)',\nretain_days: 'optional - drop unreferenced older than this',\nhot_days: 'optional - always keep newer than this',\nmax_files: 'optional - soft file cap after protections',\ncurrent_session_id: 'optional - never delete this id'\n\n)\n"}]}
|
|
@@ -2735,6 +2770,7 @@
|
|
|
2735
2770
|
{"messages":[{"role":"user","content":"PWN::Sessions.sessions_dir Usage"},{"role":"assistant","content":"`PWN::Sessions.sessions_dir`: Supported Method Parameters\n\ndir = PWN::Sessions.sessions_dir\n"}]}
|
|
2736
2771
|
{"messages":[{"role":"user","content":"PWN::Sessions.stats Usage"},{"role":"assistant","content":"`PWN::Sessions.stats`: Supported Method Parameters\n\nstats = PWN::Sessions.stats\n"}]}
|
|
2737
2772
|
{"messages":[{"role":"user","content":"PWN::Sessions.stub_session? Usage"},{"role":"assistant","content":"`PWN::Sessions.stub_session?`: "}]}
|
|
2773
|
+
{"messages":[{"role":"user","content":"PWN::Sessions.to_llm_messages Usage"},{"role":"assistant","content":"`PWN::Sessions.to_llm_messages`: "}]}
|
|
2738
2774
|
{"messages":[{"role":"user","content":"PWN::Sessions.to_response_history Usage"},{"role":"assistant","content":"`PWN::Sessions.to_response_history`: Supported Method Parameters\n\nhistory_for_ai = PWN::Sessions.to_response_history(session_id:) (converts transcript to the response_history format used by PWN::AI::* .chat)\n"}]}
|
|
2739
2775
|
{"messages":[{"role":"user","content":"PWN::Setup.ai_active_engine Usage"},{"role":"assistant","content":"`PWN::Setup.ai_active_engine`: "}]}
|
|
2740
2776
|
{"messages":[{"role":"user","content":"PWN::Setup.ai_key_configured? Usage"},{"role":"assistant","content":"`PWN::Setup.ai_key_configured?`: "}]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
pwn_critic swarm 20260819_214041_e6ff4d
|
|
2
|
+
REQUEST: what skills are available?
|
|
3
|
+
LIVE INDEX: /home/ninp0/.pwn/skills
|
|
4
|
+
LIVE COUNT: 103
|
|
5
|
+
CANDIDATE CLAIM: 103 skills, complete A-Z list
|
|
6
|
+
CANDIDATE LISTED: 24 names, last item truncated at "document-to-action-items -- Extract cited obligations, deadli"
|
|
7
|
+
MISSING COUNT: 79
|
|
8
|
+
VERDICT: FLAW
|
|
9
|
+
ONE LINE: Claims 103 skills from the live SKILLS index but the list stops at item 24 mid-word; 79 skills are omitted.
|