pwn 0.5.663 → 0.5.665

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.
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
  require 'tmpdir'
5
+ require 'fileutils'
5
6
 
6
7
  describe PWN::AI::Agent::Learning do
7
8
  it 'should display information for authors' do
@@ -86,4 +87,140 @@ describe PWN::AI::Agent::Learning do
86
87
  ensure
87
88
  FileUtils.rm_rf(tmp) if defined?(tmp) && tmp
88
89
  end
90
+
91
+ it 'P29 resyncs verdict after critic floor and strips request envelopes in to_context' do
92
+ tmp = Dir.mktmpdir
93
+ stub_const('PWN::AI::Agent::Learning::LEARNING_FILE', File.join(tmp, 'learning.jsonl'))
94
+ stub_const('PWN::Memory::MEMORY_FILE', File.join(tmp, 'memory.json'))
95
+
96
+ PWN::AI::Agent::Learning.reset
97
+
98
+ # Critic-capped solved-at-0.3 pattern (pre-P29 poison)
99
+ PWN::AI::Agent::Learning.note_outcome(
100
+ task: "REQUEST:\nwhats the bottom line?\n\nANSWER:\nfake bottom line",
101
+ success: false,
102
+ score: 0.3,
103
+ details: 'solved(0.3) heuristic overlap=0.75 ratio=1.0 | fake bottom line',
104
+ tags: %w[auto loop solved plan_cover_high]
105
+ )
106
+ PWN::AI::Agent::Learning.note_outcome(
107
+ task: 'real bare goal that failed',
108
+ success: false,
109
+ score: 0.22,
110
+ details: 'wrong(0.22) heuristic overlap=0.06 | blew up',
111
+ tags: %w[auto loop wrong]
112
+ )
113
+ PWN::AI::Agent::Learning.note_outcome(
114
+ task: 'successful scan',
115
+ success: true,
116
+ score: 0.9,
117
+ details: 'solved(0.9) ok',
118
+ tags: %w[auto loop solved]
119
+ )
120
+
121
+ # reconcile should flip solved→partial on the 0.3 row
122
+ rep = PWN::AI::Agent::Learning.reconcile_verdict_tags!
123
+ expect(rep[:repaired]).to be >= 1
124
+
125
+ rows = PWN::AI::Agent::Learning.outcomes(limit: 20)
126
+ fixed = rows.find { |r| (r[:score].to_f - 0.3).abs < 0.001 }
127
+ expect(Array(fixed[:tags])).to include('partial')
128
+ expect(Array(fixed[:tags])).not_to include('solved')
129
+ expect(fixed[:details]).to match(/\Apartial\(0\.30?\)/)
130
+
131
+ ctx = PWN::AI::Agent::Learning.to_context(limit: 5)
132
+ # envelope stripped
133
+ expect(ctx).to include('whats the bottom line?')
134
+ expect(ctx).not_to match(/REQUEST:\nwhats/)
135
+ # score visible
136
+ expect(ctx).to match(/\[0\.30\]/)
137
+ # RECENT OUTCOMES and RECENT FAILURES must not be identical dumps
138
+ # (dedupe by id) — with 1 success + 2 fails, outcomes shows mix
139
+ expect(ctx).to include('successful scan')
140
+ expect(ctx).to include('cause:')
141
+ ensure
142
+ FileUtils.rm_rf(tmp) if defined?(tmp) && tmp
143
+ end
144
+
145
+ it 'P29 verdict_for_score thresholds match Reward.judge' do
146
+ expect(PWN::AI::Agent::Learning.send(:verdict_for_score, score: 0.6)).to eq(:solved)
147
+ expect(PWN::AI::Agent::Learning.send(:verdict_for_score, score: 0.59)).to eq(:partial)
148
+ expect(PWN::AI::Agent::Learning.send(:verdict_for_score, score: 0.3)).to eq(:partial)
149
+ expect(PWN::AI::Agent::Learning.send(:verdict_for_score, score: 0.29)).to eq(:wrong)
150
+ end
151
+
152
+ it 'note_outcome enforces OUTCOME_DETAILS_MAX' do
153
+ tmp = Dir.mktmpdir
154
+ path = File.join(tmp, 'learning.jsonl')
155
+ stub_const('PWN::AI::Agent::Learning::LEARNING_FILE', path)
156
+ long = 'D' * (PWN::AI::Agent::Learning::OUTCOME_DETAILS_MAX + 100)
157
+ e = PWN::AI::Agent::Learning.note_outcome(task: 'policy details cap', success: true, details: long, tags: %w[spec])
158
+ expect(e[:details].bytesize).to be <= PWN::AI::Agent::Learning::OUTCOME_DETAILS_MAX
159
+ ensure
160
+ FileUtils.rm_rf(tmp) if tmp
161
+ end
162
+
163
+ it 'prune_outcomes! keeps gold/high-value and enforces MAX_OUTCOME_ROWS' do
164
+ tmp = Dir.mktmpdir
165
+ path = File.join(tmp, 'learning.jsonl')
166
+ stub_const('PWN::AI::Agent::Learning::LEARNING_FILE', path)
167
+ stub_const('PWN::AI::Agent::Learning::MAX_OUTCOME_ROWS', 30)
168
+ stub_const('PWN::AI::Agent::Learning::EXEMPLARS_POOL_MIN', 5)
169
+ stub_const('PWN::AI::Agent::Learning::FAILURE_WINDOW_MIN', 5)
170
+ stub_const('PWN::AI::Agent::Learning::OUTCOME_RECENT_DAYS', 1)
171
+ stub_const('PWN::AI::Agent::Learning::OUTCOME_RETAIN_DAYS', 2)
172
+
173
+ now = Time.now.utc
174
+ rows = []
175
+ # gold protected
176
+ 5.times do |i|
177
+ rows << {
178
+ id: "g#{i}", task: "gold task #{i}", success: true, score: 0.9,
179
+ session_id: "sid_g#{i}", details: 'ok', tags: %w[auto],
180
+ timestamp: (now - (10 * 86_400)).iso8601
181
+ }
182
+ end
183
+ # high-value tag protected
184
+ rows << {
185
+ id: 'hv1', task: 'needs human row', success: false, score: 0.2,
186
+ session_id: 'sid_hv', details: 'x', tags: %w[needs_human],
187
+ timestamp: (now - (20 * 86_400)).iso8601
188
+ }
189
+ # old low-value noise (should be droppable)
190
+ 40.times do |i|
191
+ rows << {
192
+ id: "n#{i}", task: "noise #{i}", success: false, score: 0.1,
193
+ session_id: "sid_n#{i}", details: 'noise', tags: %w[auto loop partial],
194
+ timestamp: (now - (30 * 86_400)).iso8601
195
+ }
196
+ end
197
+ File.open(path, 'w') { |f| rows.each { |r| f.puts(JSON.generate(r)) } }
198
+
199
+ res = PWN::AI::Agent::Learning.prune_outcomes!
200
+ kept = File.readlines(path).map { |l| JSON.parse(l, symbolize_names: true) }
201
+ ids = kept.map { |r| r[:id] }
202
+ expect(ids).to include('g0', 'hv1')
203
+ expect(kept.size).to be <= 30
204
+ expect(res[:kept]).to eq(kept.size)
205
+ ensure
206
+ FileUtils.rm_rf(tmp) if tmp
207
+ end
208
+
209
+ it 'consolidate respects MAX_MEMORY_ENTRIES and PROTECT prefixes' do
210
+ tmp = Dir.mktmpdir
211
+ mem_path = File.join(tmp, 'memory.json')
212
+ stub_const('PWN::Memory::MEMORY_FILE', mem_path)
213
+ PWN::Memory.clear(force: true)
214
+ PWN::Memory.remember(key: :operator_pref_keep, value: 'must survive', category: :preference)
215
+ 25.times do |i|
216
+ PWN::Memory.remember(key: :"bulk_#{i}", value: "lesson body #{i} unique #{i}", category: :lesson, importance: 0.1, confidence: 0.1)
217
+ end
218
+ res = PWN::AI::Agent::Learning.consolidate(max_entries: 10)
219
+ mem = PWN::Memory.load
220
+ expect(mem.keys).to include(:operator_pref_keep)
221
+ expect(mem.size).to be <= 10
222
+ expect(res[:remaining]).to eq(mem.size)
223
+ ensure
224
+ FileUtils.rm_rf(tmp) if tmp
225
+ end
89
226
  end
@@ -60,6 +60,48 @@ describe PWN::AI::Agent::Loop do
60
60
  expect(src).to match(/task_summary_plan!.*relevance_query|relevance_query.*inject_task_focus!/m)
61
61
  end
62
62
 
63
+ it 'P17 evidence_enough does not early-final on bare success while plan open' do
64
+ # Multi-step English plan mid-flight + tool {"success":true} must NOT
65
+ # force text-only — that blocked legitimate completion.
66
+ loop_mod = described_class
67
+ msgs = [
68
+ { role: 'user', content: 'fix p17' },
69
+ { role: 'tool', content: '{"success":true,"result":{"stdout":"a"}}' },
70
+ { role: 'tool', content: '{"success":true,"result":{"stdout":"b"}}' },
71
+ { role: 'tool', content: '{"success":true,"result":{"stdout":"c"}}' }
72
+ ]
73
+ open_plan = { plan: %w[identify determine inspect implement verify confirm], plan_idx: 2 }
74
+ r_open = loop_mod.send(
75
+ :evidence_enough_to_finalize?,
76
+ messages: msgs, turn_fails: {}, i: 5, max_iters: 40,
77
+ request: 'fix p17', plan_steps: 6, ts_state: open_plan
78
+ )
79
+ expect(r_open).to be false
80
+
81
+ last_plan = { plan: %w[identify implement verify], plan_idx: 2 }
82
+ msgs_mut = msgs + [
83
+ { role: 'tool', content: '{"success":true,"result":{"stdout":"0 offenses detected"}}' }
84
+ ]
85
+ r_mut = loop_mod.send(
86
+ :evidence_enough_to_finalize?,
87
+ messages: msgs_mut, turn_fails: {}, i: 5, max_iters: 40,
88
+ request: 'fix p17', plan_steps: 3, ts_state: last_plan
89
+ )
90
+ expect(r_mut).to be true
91
+
92
+ r_bare = loop_mod.send(
93
+ :evidence_enough_to_finalize?,
94
+ messages: msgs, turn_fails: {}, i: 5, max_iters: 40,
95
+ request: 'fix p17', plan_steps: 3, ts_state: last_plan
96
+ )
97
+ expect(r_bare).to be false
98
+
99
+ # call site must pass ts_state
100
+ src = File.read(loop_mod.method(:run).source_location.first)
101
+ expect(src).to match(/evidence_enough_to_finalize\?\([\s\S]*?ts_state: ts_state/)
102
+ expect(src).to match(/English-task gate/)
103
+ end
104
+
63
105
  it 'does not put TaskSummarizer into Reward credit paths' do
64
106
  # Loop may call TaskSummarizer executive APIs, not Reward.judge from TaskSummarizer
65
107
  ts = File.read(PWN::AI::Agent::TaskSummarizer.method(:plan).source_location.first)
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
+ require 'tmpdir'
5
+ require 'fileutils'
4
6
 
5
7
  describe PWN::AI::Agent::Mistakes do
6
8
  it 'should display information for authors' do
@@ -62,4 +64,77 @@ describe PWN::AI::Agent::Mistakes do
62
64
  expect(got[:structured_fix][:strategy]).to eq 'typo'
63
65
  expect(got[:structured_fix][:holdout_tests].length).to eq 2
64
66
  end
67
+
68
+ it 'enforces SAMPLE_ARGS_MAX SNIPPET_MAX ERROR_MAX SESSIONS_KEEP on record' do
69
+ tmp = Dir.mktmpdir
70
+ path = File.join(tmp, 'mistakes.json')
71
+ stub_const('PWN::AI::Agent::Mistakes::MISTAKES_FILE', path)
72
+ FileUtils.rm_f(path)
73
+ long_err = 'E' * (PWN::AI::Agent::Mistakes::ERROR_MAX + 200)
74
+ long_args = 'A' * (PWN::AI::Agent::Mistakes::SAMPLE_ARGS_MAX + 80)
75
+ m = nil
76
+ 5.times do |i|
77
+ m = PWN::AI::Agent::Mistakes.record(
78
+ tool: 'shell',
79
+ error: long_err,
80
+ args: long_args,
81
+ session_id: "sess_#{i}"
82
+ )
83
+ end
84
+ expect(m[:snippet].to_s.bytesize).to be <= PWN::AI::Agent::Mistakes::SNIPPET_MAX
85
+ expect(m[:error].to_s.bytesize).to be <= PWN::AI::Agent::Mistakes::ERROR_MAX
86
+ expect(m[:sample_args].to_s.bytesize).to be <= PWN::AI::Agent::Mistakes::SAMPLE_ARGS_MAX
87
+ expect(Array(m[:sessions]).length).to be <= PWN::AI::Agent::Mistakes::SESSIONS_KEEP
88
+ expect(m[:count]).to eq(5)
89
+ ensure
90
+ FileUtils.rm_rf(tmp) if tmp
91
+ end
92
+
93
+ it 'lean! keeps unresolved and REPEATING scars; caps resolved via MAX_RESOLVED_KEPT' do
94
+ tmp = Dir.mktmpdir
95
+ path = File.join(tmp, 'mistakes.json')
96
+ stub_const('PWN::AI::Agent::Mistakes::MISTAKES_FILE', path)
97
+ stub_const('PWN::AI::Agent::Mistakes::MAX_RESOLVED_KEPT', 2)
98
+ stub_const('PWN::AI::Agent::Mistakes::RESOLVED_MIN_AGE_DAYS', 0)
99
+ FileUtils.rm_f(path)
100
+
101
+ open_m = PWN::AI::Agent::Mistakes.record(tool: 'open_tool', error: 'still broken open')
102
+ rep = nil
103
+ 3.times { rep = PWN::AI::Agent::Mistakes.record(tool: 'rep_tool', error: 'repeat me') }
104
+ expect(rep[:count]).to be >= PWN::AI::Agent::Mistakes::REPEAT_THRESHOLD
105
+
106
+ resolved_sigs = []
107
+ 4.times do |i|
108
+ m = PWN::AI::Agent::Mistakes.record(tool: "done_#{i}", error: "once #{i}")
109
+ PWN::AI::Agent::Mistakes.resolve(signature: m[:signature], fix: "fix #{i}")
110
+ # age resolved_at into the past for drop eligibility
111
+ store = PWN::AI::Agent::Mistakes.load
112
+ store[m[:signature].to_sym][:resolved_at] = (Time.now.utc - (40 * 86_400)).iso8601
113
+ store[m[:signature].to_sym][:count] = 1
114
+ PWN::AI::Agent::Mistakes.save(store: store)
115
+ resolved_sigs << m[:signature]
116
+ end
117
+
118
+ res = PWN::AI::Agent::Mistakes.lean!
119
+ store = PWN::AI::Agent::Mistakes.load
120
+ expect(store.keys.map(&:to_s)).to include(open_m[:signature], rep[:signature])
121
+ resolved_left = store.values.count { |e| e[:resolved] && e[:fix].to_s != '' }
122
+ expect(resolved_left).to be <= 2
123
+ expect(res[:remaining]).to be <= store.size
124
+ ensure
125
+ FileUtils.rm_rf(tmp) if tmp
126
+ end
127
+
128
+ it 'resolve clamps fix to FIX_MAX' do
129
+ tmp = Dir.mktmpdir
130
+ path = File.join(tmp, 'mistakes.json')
131
+ stub_const('PWN::AI::Agent::Mistakes::MISTAKES_FILE', path)
132
+ FileUtils.rm_f(path)
133
+ m = PWN::AI::Agent::Mistakes.record(tool: 't', error: 'e')
134
+ long_fix = 'F' * (PWN::AI::Agent::Mistakes::FIX_MAX + 50)
135
+ got = PWN::AI::Agent::Mistakes.resolve(signature: m[:signature], fix: long_fix)
136
+ expect(got[:fix].bytesize).to eq(PWN::AI::Agent::Mistakes::FIX_MAX)
137
+ ensure
138
+ FileUtils.rm_rf(tmp) if tmp
139
+ end
65
140
  end
@@ -18,7 +18,7 @@ describe PWN::Memory do
18
18
  it 'should support remember/recall/forget/clear' do
19
19
  tmp = Dir.mktmpdir
20
20
  stub_const('PWN::Memory::MEMORY_FILE', File.join(tmp, 'memory.json'))
21
- PWN::Memory.clear
21
+ PWN::Memory.clear(force: true)
22
22
  PWN::Memory.remember(key: :test_fact, value: 'pwn-ai test memory', category: :fact)
23
23
  res = PWN::Memory.recall(query: 'test')
24
24
  expect(res.keys).to include(:test_fact)
@@ -42,4 +42,49 @@ describe PWN::Memory do
42
42
  ensure
43
43
  FileUtils.rm_rf(tmp) if tmp
44
44
  end
45
+
46
+ it 'enforces VALUE_MAX_CHARS on remember' do
47
+ tmp = Dir.mktmpdir
48
+ stub_const('PWN::Memory::MEMORY_FILE', File.join(tmp, 'memory.json'))
49
+ PWN::Memory.clear(force: true)
50
+ long = 'x' * (PWN::Memory::VALUE_MAX_CHARS + 50)
51
+ PWN::Memory.remember(key: :long_val, value: long, category: :fact)
52
+ v = PWN::Memory.load[:long_val][:value]
53
+ expect(v.bytesize).to be <= (PWN::Memory::VALUE_MAX_CHARS + 20)
54
+ expect(v).to include('[compacted]')
55
+ ensure
56
+ FileUtils.rm_rf(tmp) if tmp
57
+ end
58
+
59
+ it 'refuses forget/clear on protected keys without force' do
60
+ tmp = Dir.mktmpdir
61
+ stub_const('PWN::Memory::MEMORY_FILE', File.join(tmp, 'memory.json'))
62
+ PWN::Memory.clear(force: true)
63
+ PWN::Memory.remember(key: :operator_pref_test, value: 'keep', category: :preference)
64
+ PWN::Memory.remember(key: :process_sop_test, value: 'keep', category: :lesson)
65
+ expect { PWN::Memory.forget(key: :operator_pref_test) }.to raise_error(/protected/)
66
+ expect { PWN::Memory.forget(key: :process_sop_test) }.to raise_error(/protected/)
67
+ expect { PWN::Memory.clear }.to raise_error(/force:true/)
68
+ expect(PWN::Memory.forget(key: :operator_pref_test, force: true)).to be true
69
+ expect(PWN::Memory.load.keys).not_to include(:operator_pref_test)
70
+ ensure
71
+ FileUtils.rm_rf(tmp) if tmp
72
+ end
73
+
74
+ it 'lean! drops expired session_* but keeps protected prefixes' do
75
+ tmp = Dir.mktmpdir
76
+ stub_const('PWN::Memory::MEMORY_FILE', File.join(tmp, 'memory.json'))
77
+ PWN::Memory.clear(force: true)
78
+ PWN::Memory.remember(key: :operator_pref_x, value: 'pref', category: :preference)
79
+ PWN::Memory.remember(key: :session_old, value: 'ephemeral', category: :fact)
80
+ mem = PWN::Memory.load
81
+ mem[:session_old][:timestamp] = (Time.now.utc - (PWN::Memory::EPHEMERAL_TTL_SECS + 100)).iso8601
82
+ PWN::Memory.save(mem: mem)
83
+ res = PWN::Memory.lean!
84
+ expect(res[:removed]).to be >= 1
85
+ expect(PWN::Memory.load.keys).to include(:operator_pref_x)
86
+ expect(PWN::Memory.load.keys).not_to include(:session_old)
87
+ ensure
88
+ FileUtils.rm_rf(tmp) if tmp
89
+ end
45
90
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
+ require 'tmpdir'
5
+ require 'fileutils'
4
6
 
5
7
  describe PWN::Sessions do
6
8
  it 'should display information for authors' do
@@ -19,7 +21,44 @@ describe PWN::Sessions do
19
21
  PWN::Sessions.append(session_id: s[:id], role: 'user', content: 'test input')
20
22
  t = PWN::Sessions.load(session_id: s[:id])
21
23
  expect(t.size).to be >= 2
22
- PWN::Sessions.delete(session_id: s[:id])
24
+ # Hot sessions are pinned — force required for intentional delete.
25
+ expect { PWN::Sessions.delete(session_id: s[:id]) }.to raise_error(/protected/)
26
+ PWN::Sessions.delete(session_id: s[:id], force: true)
23
27
  expect(PWN::Sessions.list.any? { |x| x[:id] == s[:id] }).to be false
24
28
  end
29
+
30
+ it 'caps tool/assistant content on append per TOOL_CONTENT_MAX/ASSISTANT_CONTENT_MAX' do
31
+ s = PWN::Sessions.create(title: 'cap test')
32
+ tool_big = 'T' * (PWN::Sessions::TOOL_CONTENT_MAX + 100)
33
+ asst_big = 'A' * (PWN::Sessions::ASSISTANT_CONTENT_MAX + 100)
34
+ PWN::Sessions.append(session_id: s[:id], role: 'tool', content: tool_big)
35
+ PWN::Sessions.append(session_id: s[:id], role: 'assistant', content: asst_big)
36
+ rows = PWN::Sessions.load(session_id: s[:id])
37
+ tool = rows.find { |e| e[:role] == 'tool' }
38
+ asst = rows.find { |e| e[:role] == 'assistant' }
39
+ expect(tool[:content].bytesize).to be <= (PWN::Sessions::TOOL_CONTENT_MAX + 20)
40
+ expect(asst[:content].bytesize).to be <= (PWN::Sessions::ASSISTANT_CONTENT_MAX + 20)
41
+ expect(tool[:content]).to include('[compacted]')
42
+ ensure
43
+ PWN::Sessions.delete(session_id: s[:id], force: true) if s
44
+ end
45
+
46
+ it 'lean! respects MIN_STUB_BYTES and HOT_DAYS pins' do
47
+ tmp = Dir.mktmpdir
48
+ stub_const('PWN::Sessions::SESSIONS_DIR', tmp)
49
+ hot = PWN::Sessions.create(title: 'hot')
50
+ PWN::Sessions.append(session_id: hot[:id], role: 'user', content: 'substantive user line here')
51
+ # cold stub: tiny file outside hot window
52
+ stub_id = '19990101_000000_deadbeef'
53
+ stub_path = File.join(tmp, "#{stub_id}.jsonl")
54
+ File.write(stub_path, %({"role":"system","content":"Session started","timestamp":"1999-01-01T00:00:00Z"}
55
+ ))
56
+ File.utime(Time.at(0), Time.at(0), stub_path)
57
+ res = PWN::Sessions.lean!(current_session_id: hot[:id])
58
+ expect(File.exist?(File.join(tmp, "#{hot[:id]}.jsonl"))).to be true
59
+ expect(File.exist?(stub_path)).to be false
60
+ expect(res[:deleted]).to be >= 1
61
+ ensure
62
+ FileUtils.rm_rf(tmp) if tmp
63
+ end
25
64
  end
@@ -256,39 +256,50 @@
256
256
  {"messages":[{"role":"user","content":"PWN::AI::Agent::HackerOne.analyze Usage"},{"role":"assistant","content":"`PWN::AI::Agent::HackerOne.analyze`: Supported Method Parameters\n\nai_analysis = PWN::AI::Agent::HackerOne.analyze(\n\nrequest: 'required - dataset to analyze, such as bounty program details, scope details, or hacktivity details'\ntype: 'required - type of analysis to perform, such as :bounty_programs, :scope_details, or :hacktivity'\n\n)\n"}]}
257
257
  {"messages":[{"role":"user","content":"PWN::AI::Agent::HackerOne.authors Usage"},{"role":"assistant","content":"`PWN::AI::Agent::HackerOne.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
258
258
  {"messages":[{"role":"user","content":"PWN::AI::Agent::HackerOne.help Usage"},{"role":"assistant","content":"`PWN::AI::Agent::HackerOne.help`: "}]}
259
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.atomic_jsonl_write Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.atomic_jsonl_write`: "}]}
259
260
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.authors Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
260
261
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.auto_introspect Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.auto_introspect`: Supported Method Parameters\n\nPWN::AI::Agent::Learning.auto_introspect(\n\nsession_id: 'required - id of the just-completed session',\nrequest: 'optional - original user request (for outcome logging)',\nfinal: 'optional - final assistant answer (for outcome logging)'\n\n)\n\nCalled by Loop.run when PWN::Env[:agent] is truthy. Never raises — learning must not break the primary loop.\n"}]}
261
262
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.auto_introspect_enabled? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.auto_introspect_enabled?`: "}]}
262
263
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.build_skill_from_session Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.build_skill_from_session`: "}]}
264
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.cause_crumb Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.cause_crumb`: "}]}
263
265
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.checkable_claim? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.checkable_claim?`: "}]}
264
266
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.compress_exemplar Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.compress_exemplar`: "}]}
265
267
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.compress_finetune_trace Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.compress_finetune_trace`: "}]}
266
268
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.consolidate Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.consolidate`: Supported Method Parameters\n\nremoved = PWN::AI::Agent::Learning.consolidate(\n\nmax_entries: 'optional - hard cap on PWN::Memory size (default MAX_MEMORY_ENTRIES)'\n\n)\n\nDeduplicates near-identical lesson values and prunes the oldest entries once the cap is exceeded so the injected MEMORY block stays high-signal.\n"}]}
269
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.display_task Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.display_task`: "}]}
267
270
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.distill_skill Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.distill_skill`: Supported Method Parameters\n\nskill = PWN::AI::Agent::Learning.distill_skill(\n\nname: 'required - snake_case name for the new skill',\nsession_id: 'optional - PWN::Sessions id to mine (uses its transcript)',\ncontent: 'optional - explicit markdown body; overrides transcript mining',\nreferences: 'optional - Array of reference URLs / CWE / CVE / ATT&CK ids'\n\n)\n"}]}
268
271
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.exemplars_for Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.exemplars_for`: Supported Method Parameters\n\nmsgs = PWN::AI::Agent::Learning.exemplars_for(\n\nrequest: 'required - current user request',\nlimit: 'optional - max exemplar traces to return (default 1)',\nmax_msgs: 'optional - cap on messages per exemplar (default 6)'\n\n)\n\nRetrieval-augmented BEHAVIOUR: keyword-matches request against prior successful outcomes in learning.jsonl, loads the matching session, and compresses its (user, tool, assistant) trace into a short few-shot exemplar Loop.run splices between system and user. Local models are dramatically better with 1 concrete example than with 25 abstract lessons.\n"}]}
269
272
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.export_finetune Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.export_finetune`: "}]}
270
273
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.fact_check_local_final Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.fact_check_local_final`: "}]}
271
274
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.flip_last_outcome Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.flip_last_outcome`: "}]}
272
275
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.fold_judge_into_metrics Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.fold_judge_into_metrics`: "}]}
276
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.gc_stores! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.gc_stores!`: Supported Method Parameters\n\nresult = PWN::AI::Agent::Learning.gc_stores!(\n\ndry_run: 'optional - Boolean (default false)',\ncurrent_session_id: 'optional - never delete this sessions id',\nmax_entries: 'optional - Memory consolidate cap',\nmax_rows: 'optional - learning.jsonl cap',\nretain_days: 'optional - outcome / session age floor'\n\n)\n"}]}
273
277
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.help Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.help`: "}]}
274
278
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.heuristic_lessons Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.heuristic_lessons`: "}]}
275
279
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.infer_success Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.infer_success`: "}]}
276
280
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.introspective_lessons Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.introspective_lessons`: "}]}
281
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.lean! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.lean!`: "}]}
282
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.maybe_prune_outcomes! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.maybe_prune_outcomes!`: "}]}
277
283
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.merge_cluster Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.merge_cluster`: "}]}
278
284
  {"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"}]}
279
285
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.outcomes Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.outcomes`: Supported Method Parameters\n\nrows = PWN::AI::Agent::Learning.outcomes(\n\nlimit: 'optional - max entries returned newest-first (default 50)',\nsuccess: 'optional - filter by Boolean outcome',\ntag: 'optional - filter by tag substring'\n\n)\n"}]}
286
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.prefer_primary_tasks Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.prefer_primary_tasks`: "}]}
280
287
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.process_sop_text? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.process_sop_text?`: "}]}
281
288
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.promote_process_lesson Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.promote_process_lesson`: "}]}
289
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.prune_outcomes! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.prune_outcomes!`: Supported Method Parameters\n\nresult = PWN::AI::Agent::Learning.prune_outcomes!(\n\ndry_run: 'optional - Boolean (default false)',\nmax_rows: 'optional - hard cap (default MAX_OUTCOME_ROWS)',\nretain_days: 'optional - age floor for low-value drop',\nrecent_days: 'optional - always keep newer than this'\n\n)\n\nKeep gold RL rows (success+score>=0.6+session_id), recent window, high-value tags, and near-miss failures. Dedupe by task+success keeping best score. Truncate details. Never sacrifices exemplar pool.\n"}]}
282
290
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.purge_noise Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.purge_noise`: Supported Method Parameters\n\nPWN::AI::Agent::Learning.purge_noise\n\nOne-shot GC of the pre-R1 garbage: drops every PWN::Memory entry matching the old ‘SUCCESS: <req> — <final>` / `Avoid repeating failure pattern from <tool>: {“success”:true` shapes. Run once after upgrading; subsequent writes never produce these.\n"}]}
291
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.reconcile_verdict_tags! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.reconcile_verdict_tags!`: "}]}
283
292
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.recover_predicted_from_session Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.recover_predicted_from_session`: "}]}
284
293
  {"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"}]}
285
294
  {"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"}]}
286
295
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.semantic_merge Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.semantic_merge`: "}]}
287
296
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.sharegpt_role Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.sharegpt_role`: "}]}
297
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.should_gc_stores? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.should_gc_stores?`: "}]}
288
298
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.skills_dir Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.skills_dir`: "}]}
289
299
  {"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"}]}
290
300
  {"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"}]}
291
301
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.transcript_text Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.transcript_text`: "}]}
302
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Learning.verdict_for_score Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Learning.verdict_for_score`: "}]}
292
303
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.active_engine Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.active_engine`: "}]}
293
304
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.agent_flag Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.agent_flag`: "}]}
294
305
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Loop.append_session Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Loop.append_session`: "}]}
@@ -357,6 +368,7 @@
357
368
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Mistakes.find Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Mistakes.find`: Supported Method Parameters\n\nentry = PWN::AI::Agent::Mistakes.find(\n\nsignature: 'optional - exact signature to fetch',\ntool: 'optional - with error:, compute signature and fetch',\nerror: 'optional - raw error text (used with tool:)'\n\n)\n"}]}
358
369
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Mistakes.for_tool Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Mistakes.for_tool`: Supported Method Parameters\n\nrows = PWN::AI::Agent::Mistakes.for_tool(\n\ntool: 'required - tool name',\nunresolved_only: 'optional - default false'\n\n)\n"}]}
359
370
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Mistakes.help Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Mistakes.help`: "}]}
371
+ {"messages":[{"role":"user","content":"PWN::AI::Agent::Mistakes.lean! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Mistakes.lean!`: Supported Method Parameters\n\nresult = PWN::AI::Agent::Mistakes.lean!(\n\ndry_run: 'optional - Boolean (default false)',\nmax_resolved_kept: 'optional - cap on resolved-with-fix records',\nresolved_min_age_days: 'optional - age before resolved count=1 may drop'\n\n)\n\nCompact text fields on every record. Never drops unresolved, regressed, or high-count repeaters. Aged resolved-once fixes may drop after Memory already holds mistake_fix_<sig>.\n"}]}
360
372
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Mistakes.load Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Mistakes.load`: Supported Method Parameters\n\nstore = PWN::AI::Agent::Mistakes.load\n"}]}
361
373
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Mistakes.normalize_error Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Mistakes.normalize_error`: "}]}
362
374
  {"messages":[{"role":"user","content":"PWN::AI::Agent::Mistakes.park Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Mistakes.park`: "}]}
@@ -1220,11 +1232,13 @@
1220
1232
  {"messages":[{"role":"user","content":"PWN::FFI::Volk.sqrt Usage"},{"role":"assistant","content":"`PWN::FFI::Volk.sqrt`: Supported Method Parameters\n\nout = PWN::FFI::Volk.sqrt(samples: Array<Float>)\n"}]}
1221
1233
  {"messages":[{"role":"user","content":"PWN::FFI::Volk.unpack_s16le Usage"},{"role":"assistant","content":"`PWN::FFI::Volk.unpack_s16le`: Supported Method Parameters\n\nsamples = PWN::FFI::Volk.unpack_s16le(\n\ndata: 'required - raw String of little-endian signed 16-bit PCM'\n\n) Returns Array<Float> normalised to -1.0..1.0 (same contract as PWN::SDR::Decoder::DSP.unpack_s16le). VOLK treats ‘scalar` as a divisor, so pass 32768.0 to get unit-range floats.\n"}]}
1222
1234
  {"messages":[{"role":"user","content":"PWN::Memory.authors Usage"},{"role":"assistant","content":"`PWN::Memory.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
1223
- {"messages":[{"role":"user","content":"PWN::Memory.clear Usage"},{"role":"assistant","content":"`PWN::Memory.clear`: Supported Method Parameters\n\nPWN::Memory.clear\n"}]}
1224
- {"messages":[{"role":"user","content":"PWN::Memory.forget Usage"},{"role":"assistant","content":"`PWN::Memory.forget`: Supported Method Parameters\n\nPWN::Memory.forget(key: :some_key)\n"}]}
1235
+ {"messages":[{"role":"user","content":"PWN::Memory.clear Usage"},{"role":"assistant","content":"`PWN::Memory.clear`: Supported Method Parameters\n\nPWN::Memory.clear(force: true)\n"}]}
1236
+ {"messages":[{"role":"user","content":"PWN::Memory.forget Usage"},{"role":"assistant","content":"`PWN::Memory.forget`: Supported Method Parameters\n\nPWN::Memory.forget(\n\nkey: :some_key,\nforce: 'optional - Boolean bypass protect policy (default false)'\n\n)\n"}]}
1225
1237
  {"messages":[{"role":"user","content":"PWN::Memory.help Usage"},{"role":"assistant","content":"`PWN::Memory.help`: "}]}
1238
+ {"messages":[{"role":"user","content":"PWN::Memory.lean! Usage"},{"role":"assistant","content":"`PWN::Memory.lean!`: Supported Method Parameters\n\nresult = PWN::Memory.lean!(\n\ndry_run: 'optional - Boolean plan only (default false)',\nvalue_max_chars: 'optional - truncate values (default VALUE_MAX_CHARS)',\nephemeral_ttl_secs: 'optional - drop expired session_* keys'\n\n)\n"}]}
1226
1239
  {"messages":[{"role":"user","content":"PWN::Memory.load Usage"},{"role":"assistant","content":"`PWN::Memory.load`: Supported Method Parameters\n\nmemory = PWN::Memory.load\n"}]}
1227
1240
  {"messages":[{"role":"user","content":"PWN::Memory.load_raw_or_empty Usage"},{"role":"assistant","content":"`PWN::Memory.load_raw_or_empty`: "}]}
1241
+ {"messages":[{"role":"user","content":"PWN::Memory.protected_entry? Usage"},{"role":"assistant","content":"`PWN::Memory.protected_entry?`: "}]}
1228
1242
  {"messages":[{"role":"user","content":"PWN::Memory.recall Usage"},{"role":"assistant","content":"`PWN::Memory.recall`: Supported Method Parameters\n\nresults = PWN::Memory.recall(\n\nquery: 'optional - string to search keys/values/categories (simple match)',\ncategory: 'optional - filter by category',\nlimit: 'optional - max results (default 50)'\n\n)\n"}]}
1229
1243
  {"messages":[{"role":"user","content":"PWN::Memory.recall_semantic Usage"},{"role":"assistant","content":"`PWN::Memory.recall_semantic`: Supported Method Parameters\n\nhits = PWN::Memory.recall_semantic(query: ‘nmap sweep’, limit: 6)\n"}]}
1230
1244
  {"messages":[{"role":"user","content":"PWN::Memory.remember Usage"},{"role":"assistant","content":"`PWN::Memory.remember`: Supported Method Parameters\n\nPWN::Memory.remember(\n\nkey: 'required - Symbol or String key for the memory fact',\nvalue: 'required - The value (any JSON serializable)',\ncategory: 'optional - e.g. :fact, :preference, :lesson, :env (default: :fact)',\nsource: 'optional - :human | :reflect | :heuristic | :resolve | :consolidate (M3 provenance)',\nconfidence: 'optional - 0.0..1.0 how sure the writer was (M3)',\nimportance: 'optional - 0.0..1.0 retrieval/eviction weight (M2/M3)',\nttl: 'optional - seconds until stale (M3; consolidate evicts stale low-conf first)'\n\n)\n"}]}
@@ -2378,13 +2392,17 @@
2378
2392
  {"messages":[{"role":"user","content":"PWN::SDR::SonMicroRFID.write_tag Usage"},{"role":"assistant","content":"`PWN::SDR::SonMicroRFID.write_tag`: Supported Method Parameters\n\nPWN::SDR::SonMicroRFID.write_tag(\n\nson_micro_rfid_obj: 'required - son_micro_rfid_obj returned from #connect method',\nrfid_data: 'required - RFID data to write (see #read_tag for structure)',\nauthn: 'optional - authentication flag (default: false)',\nkey: 'optional - key for authentication (default: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])'\n\n)\n"}]}
2379
2393
  {"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"}]}
2380
2394
  {"messages":[{"role":"user","content":"PWN::Sessions.authors Usage"},{"role":"assistant","content":"`PWN::Sessions.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
2395
+ {"messages":[{"role":"user","content":"PWN::Sessions.compact_transcript! Usage"},{"role":"assistant","content":"`PWN::Sessions.compact_transcript!`: "}]}
2381
2396
  {"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-repl'\n\n)\n"}]}
2382
- {"messages":[{"role":"user","content":"PWN::Sessions.delete Usage"},{"role":"assistant","content":"`PWN::Sessions.delete`: Supported Method Parameters\n\nPWN::Sessions.delete(session_id:)\n"}]}
2397
+ {"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"}]}
2383
2398
  {"messages":[{"role":"user","content":"PWN::Sessions.help Usage"},{"role":"assistant","content":"`PWN::Sessions.help`: "}]}
2399
+ {"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"}]}
2384
2400
  {"messages":[{"role":"user","content":"PWN::Sessions.list Usage"},{"role":"assistant","content":"`PWN::Sessions.list`: Supported Method Parameters\n\nsessions = PWN::Sessions.list\n"}]}
2385
2401
  {"messages":[{"role":"user","content":"PWN::Sessions.load Usage"},{"role":"assistant","content":"`PWN::Sessions.load`: Supported Method Parameters\n\ntranscript = PWN::Sessions.load(session_id: ‘required’)\n"}]}
2402
+ {"messages":[{"role":"user","content":"PWN::Sessions.protected_session_ids Usage"},{"role":"assistant","content":"`PWN::Sessions.protected_session_ids`: "}]}
2386
2403
  {"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"}]}
2387
2404
  {"messages":[{"role":"user","content":"PWN::Sessions.stats Usage"},{"role":"assistant","content":"`PWN::Sessions.stats`: Supported Method Parameters\n\nstats = PWN::Sessions.stats\n"}]}
2405
+ {"messages":[{"role":"user","content":"PWN::Sessions.stub_session? Usage"},{"role":"assistant","content":"`PWN::Sessions.stub_session?`: "}]}
2388
2406
  {"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"}]}
2389
2407
  {"messages":[{"role":"user","content":"PWN::Setup.ai_active_engine Usage"},{"role":"assistant","content":"`PWN::Setup.ai_active_engine`: "}]}
2390
2408
  {"messages":[{"role":"user","content":"PWN::Setup.ai_key_configured? Usage"},{"role":"assistant","content":"`PWN::Setup.ai_key_configured?`: "}]}
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.663
4
+ version: 0.5.665
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
@@ -2309,6 +2309,7 @@ files:
2309
2309
  - spec/lib/pwn/ai/agent/extrospection_spec.rb
2310
2310
  - spec/lib/pwn/ai/agent/gqrx_spec.rb
2311
2311
  - spec/lib/pwn/ai/agent/hacker_one_spec.rb
2312
+ - spec/lib/pwn/ai/agent/lean_stores_spec.rb
2312
2313
  - spec/lib/pwn/ai/agent/learning_spec.rb
2313
2314
  - spec/lib/pwn/ai/agent/loop_spec.rb
2314
2315
  - spec/lib/pwn/ai/agent/metrics_spec.rb