pwn 0.5.779 → 0.5.781

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -3
  3. data/documentation/AI-Integration.md +4 -4
  4. data/documentation/AWS.md +10 -9
  5. data/documentation/Agent-Tool-Registry.md +20 -17
  6. data/documentation/Blockchain.md +3 -2
  7. data/documentation/Bounty.md +8 -6
  8. data/documentation/BurpSuite.md +6 -10
  9. data/documentation/CLI-Drivers.md +7 -4
  10. data/documentation/Capability-Broker-Sandbox.md +1 -1
  11. data/documentation/Configuration.md +23 -15
  12. data/documentation/Contributing.md +3 -3
  13. data/documentation/Cron.md +3 -2
  14. data/documentation/Diagrams.md +9 -3
  15. data/documentation/Drivers.md +12 -6
  16. data/documentation/Extrospection.md +25 -5
  17. data/documentation/FFI.md +15 -25
  18. data/documentation/Fuzzing.md +13 -13
  19. data/documentation/General-PWN-Usage.md +7 -4
  20. data/documentation/Harness-Evaluation.md +90 -3
  21. data/documentation/Home.md +6 -5
  22. data/documentation/How-PWN-Works.md +9 -10
  23. data/documentation/Installation.md +12 -11
  24. data/documentation/Metasploit.md +13 -19
  25. data/documentation/Mistakes.md +2 -2
  26. data/documentation/NmapIt.md +6 -3
  27. data/documentation/Operability.md +99 -0
  28. data/documentation/Persistence.md +3 -2
  29. data/documentation/Plugin-Degradation.md +4 -2
  30. data/documentation/Plugins.md +4 -11
  31. data/documentation/Policy-Benchmark.md +4 -0
  32. data/documentation/Reinforcement-Learning.md +19 -3
  33. data/documentation/Reporting.md +6 -5
  34. data/documentation/SAST.md +15 -10
  35. data/documentation/SDR-Decoder-Coverage.md +10 -4
  36. data/documentation/SDR.md +28 -40
  37. data/documentation/Session-Workflow.md +25 -12
  38. data/documentation/Sessions.md +7 -0
  39. data/documentation/Skills-Memory-Learning.md +11 -4
  40. data/documentation/Swarm.md +6 -0
  41. data/documentation/Transparent-Browser.md +1 -1
  42. data/documentation/Troubleshooting.md +6 -3
  43. data/documentation/What-is-PWN.md +4 -4
  44. data/documentation/Why-PWN.md +1 -1
  45. data/documentation/diagrams/agent-tool-registry.svg +219 -180
  46. data/documentation/diagrams/ai-integration-tool-calling.svg +35 -34
  47. data/documentation/diagrams/code-scanning-sast.svg +78 -78
  48. data/documentation/diagrams/cron-scheduling.svg +165 -145
  49. data/documentation/diagrams/dot/_THEME.md +6 -4
  50. data/documentation/diagrams/dot/agent-tool-registry.dot +6 -2
  51. data/documentation/diagrams/dot/ai-integration-tool-calling.dot +1 -1
  52. data/documentation/diagrams/dot/code-scanning-sast.dot +8 -8
  53. data/documentation/diagrams/dot/cron-scheduling.dot +2 -0
  54. data/documentation/diagrams/dot/driver-framework.dot +1 -1
  55. data/documentation/diagrams/dot/extrospection-world-awareness.dot +2 -2
  56. data/documentation/diagrams/dot/fuzzing-workflow.dot +3 -3
  57. data/documentation/diagrams/dot/history-to-drivers.dot +1 -1
  58. data/documentation/diagrams/dot/memory-skills-detailed.dot +3 -3
  59. data/documentation/diagrams/dot/mistakes-negative-feedback.dot +2 -2
  60. data/documentation/diagrams/dot/overall-pwn-architecture.dot +33 -121
  61. data/documentation/diagrams/dot/persistence-filesystem.dot +2 -2
  62. data/documentation/diagrams/dot/plugin-ecosystem.dot +2 -2
  63. data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +31 -167
  64. data/documentation/diagrams/dot/pwn-repl-prototyping.dot +1 -1
  65. data/documentation/diagrams/dot/reinforcement-learning.dot +15 -7
  66. data/documentation/diagrams/dot/reporting-pipeline.dot +5 -3
  67. data/documentation/diagrams/dot/reverse-engineering-flow.dot +3 -3
  68. data/documentation/diagrams/dot/sdr-radio-flow.dot +5 -5
  69. data/documentation/diagrams/dot/sessions-cron-automation.dot +1 -1
  70. data/documentation/diagrams/dot/swarm-multi-agent.dot +3 -3
  71. data/documentation/diagrams/dot/task-summarizer.dot +2 -2
  72. data/documentation/diagrams/dot/web-application-testing.dot +4 -3
  73. data/documentation/diagrams/dot/zero-day-research-flow.dot +4 -3
  74. data/documentation/diagrams/driver-framework.svg +1 -1
  75. data/documentation/diagrams/extrospection-world-awareness.svg +178 -178
  76. data/documentation/diagrams/fuzzing-workflow.svg +58 -58
  77. data/documentation/diagrams/history-to-drivers.svg +42 -42
  78. data/documentation/diagrams/memory-skills-detailed.svg +210 -210
  79. data/documentation/diagrams/mistakes-negative-feedback.svg +116 -116
  80. data/documentation/diagrams/overall-pwn-architecture.svg +248 -404
  81. data/documentation/diagrams/persistence-filesystem.svg +143 -143
  82. data/documentation/diagrams/plugin-ecosystem.svg +100 -100
  83. data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +233 -752
  84. data/documentation/diagrams/pwn-repl-prototyping.svg +27 -27
  85. data/documentation/diagrams/reinforcement-learning.svg +295 -221
  86. data/documentation/diagrams/reporting-pipeline.svg +94 -80
  87. data/documentation/diagrams/reverse-engineering-flow.svg +31 -31
  88. data/documentation/diagrams/sdr-radio-flow.svg +157 -155
  89. data/documentation/diagrams/sessions-cron-automation.svg +13 -13
  90. data/documentation/diagrams/swarm-multi-agent.svg +86 -86
  91. data/documentation/diagrams/task-summarizer.svg +57 -57
  92. data/documentation/diagrams/web-application-testing.svg +81 -75
  93. data/documentation/diagrams/zero-day-research-flow.svg +101 -92
  94. data/documentation/pwn-REPL.md +5 -3
  95. data/documentation/pwn-ai-Agent.md +18 -14
  96. data/documentation/pwn_silent_help_learn_demo.gif +0 -0
  97. data/etc/default_skills/pwn/ai/agent/learning/SKILL.md +1 -0
  98. data/lib/pwn/ai/agent/learning.rb +46 -1
  99. data/lib/pwn/ai/agent/loop.rb +6 -3
  100. data/lib/pwn/ai/agent/policy_evaluation.rb +5 -1
  101. data/lib/pwn/ai/agent/reward.rb +9 -0
  102. data/lib/pwn/version.rb +1 -1
  103. data/spec/fixtures/harness/completion_regressions.json +10 -0
  104. data/spec/fixtures/harness/completion_regressions.json.sha256 +1 -0
  105. data/spec/integration/harness_evaluation_spec.rb +13 -0
  106. data/spec/lib/pwn/ai/agent/learning_spec.rb +22 -0
  107. data/spec/lib/pwn/ai/agent/loop_spec.rb +39 -0
  108. data/spec/lib/pwn/ai/agent/policy_evaluation_spec.rb +6 -1
  109. data/spec/lib/pwn/ai/agent/reward_spec.rb +21 -0
  110. data/spec/support/harness/evaluate.rb +1 -1
  111. data/third_party/pwn_rdoc.jsonl +2 -1
  112. metadata +10 -7
@@ -4,185 +4,194 @@
4
4
  <!-- Generated by graphviz version 14.1.2 (0)
5
5
  -->
6
6
  <!-- Title: PWN_ZeroDay Pages: 1 -->
7
- <svg width="1520pt" height="329pt"
8
- viewBox="0.00 0.00 1520.00 329.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
9
- <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(43.2 286.18)">
7
+ <svg width="1306pt" height="457pt"
8
+ viewBox="0.00 0.00 1306.00 457.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
9
+ <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(43.2 413.84)">
10
10
  <title>PWN_ZeroDay</title>
11
- <polygon fill="#0f172a" stroke="none" points="-43.2,43.2 -43.2,-286.18 1476.7,-286.18 1476.7,43.2 -43.2,43.2"/>
12
- <text xml:space="preserve" text-anchor="start" x="532.25" y="-220.98" font-family="sans-Serif" font-weight="bold" font-size="20.00" fill="#e2e8f0">Zero&#45;Day Research Lifecycle with PWN</text>
13
- <text xml:space="preserve" text-anchor="start" x="564.88" y="-209.53" font-family="sans-Serif" font-size="11.00" fill="#94a3b8">attack surface → hypothesis → prove → weaponise → disclose</text>
11
+ <polygon fill="#0f172a" stroke="none" points="-43.2,43.2 -43.2,-413.84 1262.95,-413.84 1262.95,43.2 -43.2,43.2"/>
12
+ <text xml:space="preserve" text-anchor="start" x="425.38" y="-348.64" font-family="sans-Serif" font-weight="bold" font-size="20.00" fill="#e2e8f0">Zero&#45;Day Research Lifecycle with PWN</text>
13
+ <text xml:space="preserve" text-anchor="start" x="458" y="-337.19" font-family="sans-Serif" font-size="11.00" fill="#94a3b8">attack surface → hypothesis → prove → weaponise → disclose</text>
14
14
  <g id="clust1" class="cluster">
15
15
  <title>cluster_hyp</title>
16
- <path fill="#022c22" stroke="#047857" d="M210.5,-39.98C210.5,-39.98 312,-39.98 312,-39.98 318,-39.98 324,-45.98 324,-51.98 324,-51.98 324,-178.98 324,-178.98 324,-184.98 318,-190.98 312,-190.98 312,-190.98 210.5,-190.98 210.5,-190.98 204.5,-190.98 198.5,-184.98 198.5,-178.98 198.5,-178.98 198.5,-51.98 198.5,-51.98 198.5,-45.98 204.5,-39.98 210.5,-39.98"/>
17
- <text xml:space="preserve" text-anchor="middle" x="261.25" y="-167.98" font-family="sans-Serif" font-size="20.00" fill="#a7f3d0">Hypothesise</text>
16
+ <path fill="#022c22" stroke="#047857" d="M210.5,-153.64C210.5,-153.64 312,-153.64 312,-153.64 318,-153.64 324,-159.64 324,-165.64 324,-165.64 324,-292.64 324,-292.64 324,-298.64 318,-304.64 312,-304.64 312,-304.64 210.5,-304.64 210.5,-304.64 204.5,-304.64 198.5,-298.64 198.5,-292.64 198.5,-292.64 198.5,-165.64 198.5,-165.64 198.5,-159.64 204.5,-153.64 210.5,-153.64"/>
17
+ <text xml:space="preserve" text-anchor="middle" x="261.25" y="-281.64" font-family="sans-Serif" font-size="20.00" fill="#a7f3d0">Hypothesise</text>
18
18
  </g>
19
19
  <g id="clust2" class="cluster">
20
20
  <title>cluster_prove</title>
21
- <path fill="#422006" stroke="#a16207" d="M407,-44.98C407,-44.98 1035.25,-44.98 1035.25,-44.98 1041.25,-44.98 1047.25,-50.98 1047.25,-56.98 1047.25,-56.98 1047.25,-183.98 1047.25,-183.98 1047.25,-189.98 1041.25,-195.98 1035.25,-195.98 1035.25,-195.98 407,-195.98 407,-195.98 401,-195.98 395,-189.98 395,-183.98 395,-183.98 395,-56.98 395,-56.98 395,-50.98 401,-44.98 407,-44.98"/>
22
- <text xml:space="preserve" text-anchor="middle" x="721.12" y="-172.98" font-family="sans-Serif" font-size="20.00" fill="#fde68a">Prove</text>
21
+ <path fill="#422006" stroke="#a16207" d="M407,-172.64C407,-172.64 1009,-172.64 1009,-172.64 1015,-172.64 1021,-178.64 1021,-184.64 1021,-184.64 1021,-311.64 1021,-311.64 1021,-317.64 1015,-323.64 1009,-323.64 1009,-323.64 407,-323.64 407,-323.64 401,-323.64 395,-317.64 395,-311.64 395,-311.64 395,-184.64 395,-184.64 395,-178.64 401,-172.64 407,-172.64"/>
22
+ <text xml:space="preserve" text-anchor="middle" x="708" y="-300.64" font-family="sans-Serif" font-size="20.00" fill="#fde68a">Prove</text>
23
23
  </g>
24
24
  <g id="clust3" class="cluster">
25
25
  <title>cluster_weapon</title>
26
- <path fill="#450a0a" stroke="#b91c1c" d="M1130.25,-44.98C1130.25,-44.98 1222.75,-44.98 1222.75,-44.98 1228.75,-44.98 1234.75,-50.98 1234.75,-56.98 1234.75,-56.98 1234.75,-183.98 1234.75,-183.98 1234.75,-189.98 1228.75,-195.98 1222.75,-195.98 1222.75,-195.98 1130.25,-195.98 1130.25,-195.98 1124.25,-195.98 1118.25,-189.98 1118.25,-183.98 1118.25,-183.98 1118.25,-56.98 1118.25,-56.98 1118.25,-50.98 1124.25,-44.98 1130.25,-44.98"/>
27
- <text xml:space="preserve" text-anchor="middle" x="1176.5" y="-172.98" font-family="sans-Serif" font-size="20.00" fill="#fecaca">Weaponise</text>
26
+ <path fill="#450a0a" stroke="#b91c1c" d="M907.12,-13.64C907.12,-13.64 999.62,-13.64 999.62,-13.64 1005.62,-13.64 1011.62,-19.64 1011.62,-25.64 1011.62,-25.64 1011.62,-152.64 1011.62,-152.64 1011.62,-158.64 1005.62,-164.64 999.62,-164.64 999.62,-164.64 907.12,-164.64 907.12,-164.64 901.12,-164.64 895.12,-158.64 895.12,-152.64 895.12,-152.64 895.12,-25.64 895.12,-25.64 895.12,-19.64 901.12,-13.64 907.12,-13.64"/>
27
+ <text xml:space="preserve" text-anchor="middle" x="953.38" y="-141.64" font-family="sans-Serif" font-size="20.00" fill="#fecaca">Weaponise</text>
28
28
  </g>
29
29
  <g id="clust4" class="cluster">
30
30
  <title>cluster_disc</title>
31
- <path fill="#2e1065" stroke="#6d28d9" d="M1317.75,-44.98C1317.75,-44.98 1413.5,-44.98 1413.5,-44.98 1419.5,-44.98 1425.5,-50.98 1425.5,-56.98 1425.5,-56.98 1425.5,-183.98 1425.5,-183.98 1425.5,-189.98 1419.5,-195.98 1413.5,-195.98 1413.5,-195.98 1317.75,-195.98 1317.75,-195.98 1311.75,-195.98 1305.75,-189.98 1305.75,-183.98 1305.75,-183.98 1305.75,-56.98 1305.75,-56.98 1305.75,-50.98 1311.75,-44.98 1317.75,-44.98"/>
32
- <text xml:space="preserve" text-anchor="middle" x="1365.62" y="-172.98" font-family="sans-Serif" font-size="20.00" fill="#ddd6fe">Disclose</text>
31
+ <path fill="#2e1065" stroke="#6d28d9" d="M1104,-13.64C1104,-13.64 1199.75,-13.64 1199.75,-13.64 1205.75,-13.64 1211.75,-19.64 1211.75,-25.64 1211.75,-25.64 1211.75,-152.64 1211.75,-152.64 1211.75,-158.64 1205.75,-164.64 1199.75,-164.64 1199.75,-164.64 1104,-164.64 1104,-164.64 1098,-164.64 1092,-158.64 1092,-152.64 1092,-152.64 1092,-25.64 1092,-25.64 1092,-19.64 1098,-13.64 1104,-13.64"/>
32
+ <text xml:space="preserve" text-anchor="middle" x="1151.88" y="-141.64" font-family="sans-Serif" font-size="20.00" fill="#ddd6fe">Disclose</text>
33
33
  </g>
34
34
  <!-- Surface -->
35
35
  <g id="node1" class="node">
36
36
  <title>Surface</title>
37
- <path fill="#7dd3fc" stroke="#334155" stroke-width="1.3" d="M107.5,-116.98C107.5,-116.98 12,-116.98 12,-116.98 6,-116.98 0,-110.98 0,-104.98 0,-104.98 0,-92.98 0,-92.98 0,-86.98 6,-80.98 12,-80.98 12,-80.98 107.5,-80.98 107.5,-80.98 113.5,-80.98 119.5,-86.98 119.5,-92.98 119.5,-92.98 119.5,-104.98 119.5,-104.98 119.5,-110.98 113.5,-116.98 107.5,-116.98"/>
38
- <text xml:space="preserve" text-anchor="middle" x="59.75" y="-101.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Attack Surface</text>
39
- <text xml:space="preserve" text-anchor="middle" x="59.75" y="-89.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">OpenAPI · Shodan · Git</text>
37
+ <path fill="#7dd3fc" stroke="#334155" stroke-width="1.3" d="M107.5,-230.64C107.5,-230.64 12,-230.64 12,-230.64 6,-230.64 0,-224.64 0,-218.64 0,-218.64 0,-206.64 0,-206.64 0,-200.64 6,-194.64 12,-194.64 12,-194.64 107.5,-194.64 107.5,-194.64 113.5,-194.64 119.5,-200.64 119.5,-206.64 119.5,-206.64 119.5,-218.64 119.5,-218.64 119.5,-224.64 113.5,-230.64 107.5,-230.64"/>
38
+ <text xml:space="preserve" text-anchor="middle" x="59.75" y="-215.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Attack Surface</text>
39
+ <text xml:space="preserve" text-anchor="middle" x="59.75" y="-203.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">OpenAPI · Shodan · Git</text>
40
40
  </g>
41
41
  <!-- SAST -->
42
42
  <g id="node2" class="node">
43
43
  <title>SAST</title>
44
- <path fill="#6ee7b7" stroke="#334155" stroke-width="1.3" d="M285.25,-151.98C285.25,-151.98 236.25,-151.98 236.25,-151.98 230.25,-151.98 224.25,-145.98 224.25,-139.98 224.25,-139.98 224.25,-127.98 224.25,-127.98 224.25,-121.98 230.25,-115.98 236.25,-115.98 236.25,-115.98 285.25,-115.98 285.25,-115.98 291.25,-115.98 297.25,-121.98 297.25,-127.98 297.25,-127.98 297.25,-139.98 297.25,-139.98 297.25,-145.98 291.25,-151.98 285.25,-151.98"/>
45
- <text xml:space="preserve" text-anchor="middle" x="260.75" y="-136.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">PWN::SAST</text>
46
- <text xml:space="preserve" text-anchor="middle" x="260.75" y="-124.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">taint patterns</text>
44
+ <path fill="#6ee7b7" stroke="#334155" stroke-width="1.3" d="M285.25,-265.64C285.25,-265.64 236.25,-265.64 236.25,-265.64 230.25,-265.64 224.25,-259.64 224.25,-253.64 224.25,-253.64 224.25,-241.64 224.25,-241.64 224.25,-235.64 230.25,-229.64 236.25,-229.64 236.25,-229.64 285.25,-229.64 285.25,-229.64 291.25,-229.64 297.25,-235.64 297.25,-241.64 297.25,-241.64 297.25,-253.64 297.25,-253.64 297.25,-259.64 291.25,-265.64 285.25,-265.64"/>
45
+ <text xml:space="preserve" text-anchor="middle" x="260.75" y="-250.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">PWN::SAST</text>
46
+ <text xml:space="preserve" text-anchor="middle" x="260.75" y="-238.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">taint patterns</text>
47
47
  </g>
48
48
  <!-- Surface&#45;&gt;SAST -->
49
49
  <g id="edge1" class="edge">
50
50
  <title>Surface&#45;&gt;SAST</title>
51
- <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M119.92,-109.38C150.05,-114.68 186.12,-121.03 214.08,-125.94"/>
52
- <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="213.3,-128.65 221.67,-127.28 214.27,-123.14 213.3,-128.65"/>
51
+ <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M119.92,-223.05C150.05,-228.35 186.12,-234.69 214.08,-239.61"/>
52
+ <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="213.3,-242.32 221.67,-240.94 214.27,-236.8 213.3,-242.32"/>
53
53
  </g>
54
54
  <!-- AI -->
55
55
  <g id="node3" class="node">
56
56
  <title>AI</title>
57
- <path fill="#6ee7b7" stroke="#334155" stroke-width="1.3" d="M291.25,-83.98C291.25,-83.98 230.25,-83.98 230.25,-83.98 224.25,-83.98 218.25,-77.98 218.25,-71.98 218.25,-71.98 218.25,-59.98 218.25,-59.98 218.25,-53.98 224.25,-47.98 230.25,-47.98 230.25,-47.98 291.25,-47.98 291.25,-47.98 297.25,-47.98 303.25,-53.98 303.25,-59.98 303.25,-59.98 303.25,-71.98 303.25,-71.98 303.25,-77.98 297.25,-83.98 291.25,-83.98"/>
58
- <text xml:space="preserve" text-anchor="middle" x="260.75" y="-68.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">pwn&#45;ai</text>
59
- <text xml:space="preserve" text-anchor="middle" x="260.75" y="-56.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Agent::VulnGen</text>
57
+ <path fill="#6ee7b7" stroke="#334155" stroke-width="1.3" d="M291.25,-197.64C291.25,-197.64 230.25,-197.64 230.25,-197.64 224.25,-197.64 218.25,-191.64 218.25,-185.64 218.25,-185.64 218.25,-173.64 218.25,-173.64 218.25,-167.64 224.25,-161.64 230.25,-161.64 230.25,-161.64 291.25,-161.64 291.25,-161.64 297.25,-161.64 303.25,-167.64 303.25,-173.64 303.25,-173.64 303.25,-185.64 303.25,-185.64 303.25,-191.64 297.25,-197.64 291.25,-197.64"/>
58
+ <text xml:space="preserve" text-anchor="middle" x="260.75" y="-182.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">pwn&#45;ai</text>
59
+ <text xml:space="preserve" text-anchor="middle" x="260.75" y="-170.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Agent::VulnGen</text>
60
60
  </g>
61
61
  <!-- Surface&#45;&gt;AI -->
62
62
  <g id="edge2" class="edge">
63
63
  <title>Surface&#45;&gt;AI</title>
64
- <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M119.92,-89.17C147.98,-84.51 181.19,-79 208.2,-74.52"/>
65
- <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="208.48,-77.32 215.91,-73.25 207.56,-71.79 208.48,-77.32"/>
64
+ <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M119.92,-202.83C147.98,-198.18 181.19,-192.67 208.2,-188.19"/>
65
+ <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="208.48,-190.98 215.91,-186.91 207.56,-185.46 208.48,-190.98"/>
66
66
  </g>
67
67
  <!-- Obs -->
68
68
  <g id="node6" class="node">
69
69
  <title>Obs</title>
70
- <path fill="#fcd34d" stroke="#334155" stroke-width="1.3" d="M480.5,-108.98C480.5,-108.98 415,-108.98 415,-108.98 409,-108.98 403,-102.98 403,-96.98 403,-96.98 403,-76.98 403,-76.98 403,-70.98 409,-64.98 415,-64.98 415,-64.98 480.5,-64.98 480.5,-64.98 486.5,-64.98 492.5,-70.98 492.5,-76.98 492.5,-76.98 492.5,-96.98 492.5,-96.98 492.5,-102.98 486.5,-108.98 480.5,-108.98"/>
71
- <text xml:space="preserve" text-anchor="middle" x="447.75" y="-95.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Recon.observe</text>
72
- <text xml:space="preserve" text-anchor="middle" x="447.75" y="-83.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">host port product</text>
73
- <text xml:space="preserve" text-anchor="middle" x="447.75" y="-71.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">version evidence</text>
70
+ <path fill="#fcd34d" stroke="#334155" stroke-width="1.3" d="M480.5,-250.64C480.5,-250.64 415,-250.64 415,-250.64 409,-250.64 403,-244.64 403,-238.64 403,-238.64 403,-218.64 403,-218.64 403,-212.64 409,-206.64 415,-206.64 415,-206.64 480.5,-206.64 480.5,-206.64 486.5,-206.64 492.5,-212.64 492.5,-218.64 492.5,-218.64 492.5,-238.64 492.5,-238.64 492.5,-244.64 486.5,-250.64 480.5,-250.64"/>
71
+ <text xml:space="preserve" text-anchor="middle" x="447.75" y="-237.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Recon.observe</text>
72
+ <text xml:space="preserve" text-anchor="middle" x="447.75" y="-225.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">host port product</text>
73
+ <text xml:space="preserve" text-anchor="middle" x="447.75" y="-213.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">version evidence</text>
74
74
  </g>
75
75
  <!-- SAST&#45;&gt;Obs -->
76
76
  <g id="edge3" class="edge">
77
77
  <title>SAST&#45;&gt;Obs</title>
78
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M297.86,-124.8C325.02,-117.9 362.67,-108.34 393.31,-100.55"/>
79
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="393.6,-103.37 400.67,-98.68 392.22,-97.94 393.6,-103.37"/>
78
+ <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M297.86,-243.93C324.9,-241.16 362.34,-237.31 392.91,-234.17"/>
79
+ <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="392.94,-236.98 400.62,-233.38 392.37,-231.41 392.94,-236.98"/>
80
80
  </g>
81
81
  <!-- AI&#45;&gt;Obs -->
82
82
  <g id="edge4" class="edge">
83
83
  <title>AI&#45;&gt;Obs</title>
84
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M303.73,-70.74C330.05,-73.73 364.24,-77.61 392.59,-80.83"/>
85
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="392.14,-83.6 400.4,-81.72 392.77,-78.03 392.14,-83.6"/>
84
+ <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M303.73,-190.76C330.16,-197.76 364.54,-206.87 392.97,-214.4"/>
85
+ <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="392,-217.04 400.45,-216.38 393.44,-211.63 392,-217.04"/>
86
86
  </g>
87
87
  <!-- Fuzz -->
88
88
  <g id="node4" class="node">
89
89
  <title>Fuzz</title>
90
- <path fill="#fcd34d" stroke="#334155" stroke-width="1.3" d="M1010,-156.98C1010,-156.98 964.75,-156.98 964.75,-156.98 958.75,-156.98 952.75,-150.98 952.75,-144.98 952.75,-144.98 952.75,-132.98 952.75,-132.98 952.75,-126.98 958.75,-120.98 964.75,-120.98 964.75,-120.98 1010,-120.98 1010,-120.98 1016,-120.98 1022,-126.98 1022,-132.98 1022,-132.98 1022,-144.98 1022,-144.98 1022,-150.98 1016,-156.98 1010,-156.98"/>
91
- <text xml:space="preserve" text-anchor="middle" x="987.38" y="-141.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Fuzz · Sock</text>
92
- <text xml:space="preserve" text-anchor="middle" x="987.38" y="-129.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Packet</text>
90
+ <path fill="#fcd34d" stroke="#334155" stroke-width="1.3" d="M725.75,-284.64C725.75,-284.64 680.5,-284.64 680.5,-284.64 674.5,-284.64 668.5,-278.64 668.5,-272.64 668.5,-272.64 668.5,-260.64 668.5,-260.64 668.5,-254.64 674.5,-248.64 680.5,-248.64 680.5,-248.64 725.75,-248.64 725.75,-248.64 731.75,-248.64 737.75,-254.64 737.75,-260.64 737.75,-260.64 737.75,-272.64 737.75,-272.64 737.75,-278.64 731.75,-284.64 725.75,-284.64"/>
91
+ <text xml:space="preserve" text-anchor="middle" x="703.12" y="-269.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Fuzz · Sock</text>
92
+ <text xml:space="preserve" text-anchor="middle" x="703.12" y="-257.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Packet</text>
93
+ </g>
94
+ <!-- Ver -->
95
+ <g id="node7" class="node">
96
+ <title>Ver</title>
97
+ <path fill="#fcd34d" stroke="#334155" stroke-width="1.3" d="M1001,-260.64C1001,-260.64 904.75,-260.64 904.75,-260.64 898.75,-260.64 892.75,-254.64 892.75,-248.64 892.75,-248.64 892.75,-228.64 892.75,-228.64 892.75,-222.64 898.75,-216.64 904.75,-216.64 904.75,-216.64 1001,-216.64 1001,-216.64 1007,-216.64 1013,-222.64 1013,-228.64 1013,-228.64 1013,-248.64 1013,-248.64 1013,-254.64 1007,-260.64 1001,-260.64"/>
98
+ <text xml:space="preserve" text-anchor="middle" x="952.88" y="-247.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Findings.verify</text>
99
+ <text xml:space="preserve" text-anchor="middle" x="952.88" y="-235.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">transcript shows impact</text>
100
+ <text xml:space="preserve" text-anchor="middle" x="952.88" y="-223.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">or severity stays info</text>
101
+ </g>
102
+ <!-- Fuzz&#45;&gt;Ver -->
103
+ <g id="edge7" class="edge">
104
+ <title>Fuzz&#45;&gt;Ver</title>
105
+ <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M738.31,-262.78C775.37,-258.59 835.5,-251.79 882.53,-246.48"/>
106
+ <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="882.76,-249.27 890.4,-245.59 882.13,-243.71 882.76,-249.27"/>
107
+ <text xml:space="preserve" text-anchor="middle" x="823.88" y="-257.92" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">stored PoC</text>
93
108
  </g>
94
109
  <!-- Asm -->
95
110
  <g id="node8" class="node">
96
111
  <title>Asm</title>
97
- <path fill="#fda4af" stroke="#334155" stroke-width="1.3" d="M1214,-156.98C1214,-156.98 1138,-156.98 1138,-156.98 1132,-156.98 1126,-150.98 1126,-144.98 1126,-144.98 1126,-132.98 1126,-132.98 1126,-126.98 1132,-120.98 1138,-120.98 1138,-120.98 1214,-120.98 1214,-120.98 1220,-120.98 1226,-126.98 1226,-132.98 1226,-132.98 1226,-144.98 1226,-144.98 1226,-150.98 1220,-156.98 1214,-156.98"/>
98
- <text xml:space="preserve" text-anchor="middle" x="1176" y="-141.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Assembly</text>
99
- <text xml:space="preserve" text-anchor="middle" x="1176" y="-129.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">pwn&#45;asm shellcode</text>
112
+ <path fill="#fda4af" stroke="#334155" stroke-width="1.3" d="M990.88,-125.64C990.88,-125.64 914.88,-125.64 914.88,-125.64 908.88,-125.64 902.88,-119.64 902.88,-113.64 902.88,-113.64 902.88,-101.64 902.88,-101.64 902.88,-95.64 908.88,-89.64 914.88,-89.64 914.88,-89.64 990.88,-89.64 990.88,-89.64 996.88,-89.64 1002.88,-95.64 1002.88,-101.64 1002.88,-101.64 1002.88,-113.64 1002.88,-113.64 1002.88,-119.64 996.88,-125.64 990.88,-125.64"/>
113
+ <text xml:space="preserve" text-anchor="middle" x="952.88" y="-110.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Assembly</text>
114
+ <text xml:space="preserve" text-anchor="middle" x="952.88" y="-98.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">pwn&#45;asm shellcode</text>
100
115
  </g>
101
116
  <!-- Fuzz&#45;&gt;Asm -->
102
- <g id="edge8" class="edge">
117
+ <g id="edge9" class="edge">
103
118
  <title>Fuzz&#45;&gt;Asm</title>
104
- <path fill="none" stroke="#fb7185" stroke-width="1.3" d="M1022.6,-138.98C1048.62,-138.98 1085.05,-138.98 1115.76,-138.98"/>
105
- <polygon fill="#fb7185" stroke="#fb7185" stroke-width="1.3" points="1115.55,-141.78 1123.55,-138.98 1115.55,-136.18 1115.55,-141.78"/>
119
+ <path fill="none" stroke="#fb7185" stroke-width="1.3" d="M732.43,-248.16C751.03,-236.03 775.93,-219.84 798,-205.64 837.56,-180.19 883.02,-151.28 914.21,-131.5"/>
120
+ <polygon fill="#fb7185" stroke="#fb7185" stroke-width="1.3" points="915.69,-133.87 920.95,-127.22 912.69,-129.14 915.69,-133.87"/>
106
121
  </g>
107
122
  <!-- TB -->
108
123
  <g id="node5" class="node">
109
124
  <title>TB</title>
110
- <path fill="#fcd34d" stroke="#334155" stroke-width="1.3" d="M1027.25,-88.98C1027.25,-88.98 947.5,-88.98 947.5,-88.98 941.5,-88.98 935.5,-82.98 935.5,-76.98 935.5,-76.98 935.5,-64.98 935.5,-64.98 935.5,-58.98 941.5,-52.98 947.5,-52.98 947.5,-52.98 1027.25,-52.98 1027.25,-52.98 1033.25,-52.98 1039.25,-58.98 1039.25,-64.98 1039.25,-64.98 1039.25,-76.98 1039.25,-76.98 1039.25,-82.98 1033.25,-88.98 1027.25,-88.98"/>
111
- <text xml:space="preserve" text-anchor="middle" x="987.38" y="-73.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">TransparentBrowser</text>
112
- <text xml:space="preserve" text-anchor="middle" x="987.38" y="-61.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Burp replay</text>
125
+ <path fill="#fcd34d" stroke="#334155" stroke-width="1.3" d="M743,-216.64C743,-216.64 663.25,-216.64 663.25,-216.64 657.25,-216.64 651.25,-210.64 651.25,-204.64 651.25,-204.64 651.25,-192.64 651.25,-192.64 651.25,-186.64 657.25,-180.64 663.25,-180.64 663.25,-180.64 743,-180.64 743,-180.64 749,-180.64 755,-186.64 755,-192.64 755,-192.64 755,-204.64 755,-204.64 755,-210.64 749,-216.64 743,-216.64"/>
126
+ <text xml:space="preserve" text-anchor="middle" x="703.12" y="-201.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">TransparentBrowser</text>
127
+ <text xml:space="preserve" text-anchor="middle" x="703.12" y="-189.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Burp replay</text>
128
+ </g>
129
+ <!-- TB&#45;&gt;Ver -->
130
+ <g id="edge8" class="edge">
131
+ <title>TB&#45;&gt;Ver</title>
132
+ <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M755.46,-206.93C792.25,-212.87 842.23,-220.94 882.56,-227.45"/>
133
+ <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="882.04,-230.2 890.39,-228.71 882.93,-224.67 882.04,-230.2"/>
134
+ <text xml:space="preserve" text-anchor="middle" x="823.88" y="-222.99" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">reproduction</text>
113
135
  </g>
114
136
  <!-- MSF -->
115
137
  <g id="node9" class="node">
116
138
  <title>MSF</title>
117
- <path fill="#fda4af" stroke="#334155" stroke-width="1.3" d="M1194.5,-88.98C1194.5,-88.98 1157.5,-88.98 1157.5,-88.98 1151.5,-88.98 1145.5,-82.98 1145.5,-76.98 1145.5,-76.98 1145.5,-64.98 1145.5,-64.98 1145.5,-58.98 1151.5,-52.98 1157.5,-52.98 1157.5,-52.98 1194.5,-52.98 1194.5,-52.98 1200.5,-52.98 1206.5,-58.98 1206.5,-64.98 1206.5,-64.98 1206.5,-76.98 1206.5,-76.98 1206.5,-82.98 1200.5,-88.98 1194.5,-88.98"/>
118
- <text xml:space="preserve" text-anchor="middle" x="1176" y="-73.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Metasploit</text>
119
- <text xml:space="preserve" text-anchor="middle" x="1176" y="-61.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">module</text>
139
+ <path fill="#fda4af" stroke="#334155" stroke-width="1.3" d="M971.38,-57.64C971.38,-57.64 934.38,-57.64 934.38,-57.64 928.38,-57.64 922.38,-51.64 922.38,-45.64 922.38,-45.64 922.38,-33.64 922.38,-33.64 922.38,-27.64 928.38,-21.64 934.38,-21.64 934.38,-21.64 971.38,-21.64 971.38,-21.64 977.38,-21.64 983.38,-27.64 983.38,-33.64 983.38,-33.64 983.38,-45.64 983.38,-45.64 983.38,-51.64 977.38,-57.64 971.38,-57.64"/>
140
+ <text xml:space="preserve" text-anchor="middle" x="952.88" y="-42.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Metasploit</text>
141
+ <text xml:space="preserve" text-anchor="middle" x="952.88" y="-30.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">module</text>
120
142
  </g>
121
143
  <!-- TB&#45;&gt;MSF -->
122
- <g id="edge9" class="edge">
144
+ <g id="edge10" class="edge">
123
145
  <title>TB&#45;&gt;MSF</title>
124
- <path fill="none" stroke="#fb7185" stroke-width="1.3" d="M1039.87,-70.98C1069.94,-70.98 1107.33,-70.98 1135.15,-70.98"/>
125
- <polygon fill="#fb7185" stroke="#fb7185" stroke-width="1.3" points="1134.96,-73.78 1142.96,-70.98 1134.96,-68.18 1134.96,-73.78"/>
146
+ <path fill="none" stroke="#fb7185" stroke-width="1.3" d="M730.95,-180.09C767.22,-155.18 834.1,-109.89 892.75,-73.64 899.34,-69.57 906.42,-65.36 913.31,-61.35"/>
147
+ <polygon fill="#fb7185" stroke="#fb7185" stroke-width="1.3" points="914.65,-63.81 920.18,-57.38 911.85,-58.96 914.65,-63.81"/>
126
148
  </g>
127
- <!-- Ver -->
128
- <g id="node7" class="node">
129
- <title>Ver</title>
130
- <path fill="#fcd34d" stroke="#334155" stroke-width="1.3" d="M759.5,-108.98C759.5,-108.98 663.25,-108.98 663.25,-108.98 657.25,-108.98 651.25,-102.98 651.25,-96.98 651.25,-96.98 651.25,-76.98 651.25,-76.98 651.25,-70.98 657.25,-64.98 663.25,-64.98 663.25,-64.98 759.5,-64.98 759.5,-64.98 765.5,-64.98 771.5,-70.98 771.5,-76.98 771.5,-76.98 771.5,-96.98 771.5,-96.98 771.5,-102.98 765.5,-108.98 759.5,-108.98"/>
131
- <text xml:space="preserve" text-anchor="middle" x="711.38" y="-95.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Findings.verify</text>
132
- <text xml:space="preserve" text-anchor="middle" x="711.38" y="-83.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">transcript shows impact</text>
133
- <text xml:space="preserve" text-anchor="middle" x="711.38" y="-71.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">or severity stays info</text>
134
- </g>
135
- <!-- Obs&#45;&gt;Ver -->
149
+ <!-- Obs&#45;&gt;Fuzz -->
136
150
  <g id="edge5" class="edge">
137
- <title>Obs&#45;&gt;Ver</title>
138
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M493.13,-86.98C533.69,-86.98 594.32,-86.98 641.22,-86.98"/>
139
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="641.05,-89.78 649.05,-86.98 641.05,-84.18 641.05,-89.78"/>
140
- <text xml:space="preserve" text-anchor="middle" x="571.88" y="-88.93" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">lead, not a finding</text>
151
+ <title>Obs&#45;&gt;Fuzz</title>
152
+ <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M492.88,-235.26C539.38,-242.23 612.15,-253.15 658.47,-260.09"/>
153
+ <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="657.94,-262.85 666.27,-261.26 658.77,-257.31 657.94,-262.85"/>
154
+ <text xml:space="preserve" text-anchor="middle" x="571.88" y="-254.11" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">lead, not a finding</text>
141
155
  </g>
142
- <!-- Ver&#45;&gt;Fuzz -->
156
+ <!-- Obs&#45;&gt;TB -->
143
157
  <g id="edge6" class="edge">
144
- <title>Ver&#45;&gt;Fuzz</title>
145
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M771.83,-98.26C823.3,-108.03 896.54,-121.93 942.75,-130.7"/>
146
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="942.15,-133.43 950.53,-132.17 943.19,-127.93 942.15,-133.43"/>
147
- </g>
148
- <!-- Ver&#45;&gt;TB -->
149
- <g id="edge7" class="edge">
150
- <title>Ver&#45;&gt;TB</title>
151
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M771.83,-83.5C817.14,-80.86 879.32,-77.23 925.08,-74.56"/>
152
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="925.09,-77.36 932.91,-74.1 924.76,-71.77 925.09,-77.36"/>
158
+ <title>Obs&#45;&gt;TB</title>
159
+ <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M492.81,-221.3C506.47,-219.15 521.59,-216.91 535.5,-215.14 570.39,-210.7 609.52,-206.77 641.08,-203.87"/>
160
+ <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="640.95,-206.69 648.66,-203.17 640.44,-201.11 640.95,-206.69"/>
161
+ <text xml:space="preserve" text-anchor="middle" x="571.88" y="-217.09" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">lead</text>
153
162
  </g>
154
163
  <!-- H1 -->
155
164
  <g id="node10" class="node">
156
165
  <title>H1</title>
157
- <path fill="#c4b5fd" stroke="#334155" stroke-width="1.3" d="M1405.5,-156.98C1405.5,-156.98 1325.75,-156.98 1325.75,-156.98 1319.75,-156.98 1313.75,-150.98 1313.75,-144.98 1313.75,-144.98 1313.75,-132.98 1313.75,-132.98 1313.75,-126.98 1319.75,-120.98 1325.75,-120.98 1325.75,-120.98 1405.5,-120.98 1405.5,-120.98 1411.5,-120.98 1417.5,-126.98 1417.5,-132.98 1417.5,-132.98 1417.5,-144.98 1417.5,-144.98 1417.5,-150.98 1411.5,-156.98 1405.5,-156.98"/>
158
- <text xml:space="preserve" text-anchor="middle" x="1365.62" y="-141.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">HackerOne</text>
159
- <text xml:space="preserve" text-anchor="middle" x="1365.62" y="-129.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">BugCrowd · Synack</text>
166
+ <path fill="#c4b5fd" stroke="#334155" stroke-width="1.3" d="M1191.75,-125.64C1191.75,-125.64 1112,-125.64 1112,-125.64 1106,-125.64 1100,-119.64 1100,-113.64 1100,-113.64 1100,-101.64 1100,-101.64 1100,-95.64 1106,-89.64 1112,-89.64 1112,-89.64 1191.75,-89.64 1191.75,-89.64 1197.75,-89.64 1203.75,-95.64 1203.75,-101.64 1203.75,-101.64 1203.75,-113.64 1203.75,-113.64 1203.75,-119.64 1197.75,-125.64 1191.75,-125.64"/>
167
+ <text xml:space="preserve" text-anchor="middle" x="1151.88" y="-110.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">HackerOne</text>
168
+ <text xml:space="preserve" text-anchor="middle" x="1151.88" y="-98.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">BugCrowd · Synack</text>
160
169
  </g>
161
170
  <!-- Asm&#45;&gt;H1 -->
162
- <g id="edge10" class="edge">
171
+ <g id="edge11" class="edge">
163
172
  <title>Asm&#45;&gt;H1</title>
164
- <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M1226.3,-138.98C1249.97,-138.98 1278.57,-138.98 1303.61,-138.98"/>
165
- <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1303.4,-141.78 1311.4,-138.98 1303.4,-136.18 1303.4,-141.78"/>
173
+ <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M1003.33,-107.64C1029.64,-107.64 1062.21,-107.64 1090.05,-107.64"/>
174
+ <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1089.71,-110.44 1097.71,-107.64 1089.71,-104.84 1089.71,-110.44"/>
166
175
  </g>
167
176
  <!-- Rep -->
168
177
  <g id="node11" class="node">
169
178
  <title>Rep</title>
170
- <path fill="#c4b5fd" stroke="#334155" stroke-width="1.3" d="M1395.38,-88.98C1395.38,-88.98 1335.88,-88.98 1335.88,-88.98 1329.88,-88.98 1323.88,-82.98 1323.88,-76.98 1323.88,-76.98 1323.88,-64.98 1323.88,-64.98 1323.88,-58.98 1329.88,-52.98 1335.88,-52.98 1335.88,-52.98 1395.38,-52.98 1395.38,-52.98 1401.38,-52.98 1407.38,-58.98 1407.38,-64.98 1407.38,-64.98 1407.38,-76.98 1407.38,-76.98 1407.38,-82.98 1401.38,-88.98 1395.38,-88.98"/>
171
- <text xml:space="preserve" text-anchor="middle" x="1365.62" y="-73.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Reports · Skills</text>
172
- <text xml:space="preserve" text-anchor="middle" x="1365.62" y="-61.48" font-family="sans-Serif" font-size="10.00" fill="#0f172a">distill_skill</text>
179
+ <path fill="#c4b5fd" stroke="#334155" stroke-width="1.3" d="M1181.62,-57.64C1181.62,-57.64 1122.12,-57.64 1122.12,-57.64 1116.12,-57.64 1110.12,-51.64 1110.12,-45.64 1110.12,-45.64 1110.12,-33.64 1110.12,-33.64 1110.12,-27.64 1116.12,-21.64 1122.12,-21.64 1122.12,-21.64 1181.62,-21.64 1181.62,-21.64 1187.62,-21.64 1193.62,-27.64 1193.62,-33.64 1193.62,-33.64 1193.62,-45.64 1193.62,-45.64 1193.62,-51.64 1187.62,-57.64 1181.62,-57.64"/>
180
+ <text xml:space="preserve" text-anchor="middle" x="1151.88" y="-42.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">Reports · Skills</text>
181
+ <text xml:space="preserve" text-anchor="middle" x="1151.88" y="-30.14" font-family="sans-Serif" font-size="10.00" fill="#0f172a">distill_skill</text>
173
182
  </g>
174
183
  <!-- MSF&#45;&gt;Rep -->
175
- <g id="edge11" class="edge">
184
+ <g id="edge12" class="edge">
176
185
  <title>MSF&#45;&gt;Rep</title>
177
- <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M1207.15,-70.98C1235.81,-70.98 1279.48,-70.98 1313.57,-70.98"/>
178
- <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1313.4,-73.78 1321.4,-70.98 1313.4,-68.18 1313.4,-73.78"/>
186
+ <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M983.8,-39.64C1014.62,-39.64 1063.24,-39.64 1100.1,-39.64"/>
187
+ <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1099.71,-42.44 1107.71,-39.64 1099.71,-36.84 1099.71,-42.44"/>
179
188
  </g>
180
189
  <!-- Rep&#45;&gt;AI -->
181
- <g id="edge12" class="edge">
190
+ <g id="edge13" class="edge">
182
191
  <title>Rep&#45;&gt;AI</title>
183
- <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1323.29,-57.61C1298.02,-50.07 1264.85,-41.32 1234.75,-36.98 865.36,16.34 765.55,7.58 395,-36.98 367.71,-40.26 337.77,-46.53 313.2,-52.4"/>
184
- <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="312.73,-49.63 305.62,-54.24 314.06,-55.07 312.73,-49.63"/>
185
- <text xml:space="preserve" text-anchor="middle" x="853.5" y="-3.18" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">lesson → next hunt</text>
192
+ <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1109.59,-25.94C1084.33,-18.28 1051.17,-9.53 1021,-5.64 964.47,1.64 949.23,2 892.75,-5.64 671.94,-35.53 419.2,-121.71 312.98,-160.42"/>
193
+ <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="312.17,-157.74 305.62,-163.12 314.09,-162.99 312.17,-157.74"/>
194
+ <text xml:space="preserve" text-anchor="middle" x="703.12" y="-55.77" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">lesson → next hunt</text>
186
195
  </g>
187
196
  </g>
188
197
  </svg>
@@ -66,7 +66,7 @@ the LLM to manufacture provenance.
66
66
  | `pwn-ai-sessions` | `PWN::Sessions` | List/view/delete transcripts |
67
67
  | `pwn-ai-cron` | `PWN::Cron` | List/run/toggle scheduled jobs |
68
68
  | `pwn-ai-delegate` | `Agent::Swarm` | Send one request to a persona |
69
- | `toggle-debug` | `Agent::Loop` / `Plugins::Log` | Stage log per operator request to `/tmp/pwn-ai-DEBUG-<SESSION_ID>-RN.log` |
69
+ | `toggle-debug` | `Agent::Loop` / `Plugins::Log` | Stage log per operator request to `~/.pwn/logs/pwn-ai-DEBUG-<SESSION_ID>-R<N>.log` |
70
70
  | `toggle-trace` | `Agent::Loop` / `Plugins::Log` | Turns `toggle-debug` on with TracePoint; ENTER after each engine/tool step. Pry.config, not Env. Off turns both off. |
71
71
  | `toggle-pwn-ai-speaks` | `Plugins::Voice` | TTS every final answer on/off |
72
72
  | `welcome-banner` | `PWN::Banner` | Redraw a random banner |
@@ -158,7 +158,9 @@ switch to serial, Bluetooth, or TCP and use `/msg` to retry.
158
158
 
159
159
  ## Multi-line input
160
160
 
161
- `pwn-ai` and `pwn-asm` use a custom `PWNMultiLineInput` reader. Plain
161
+ `pwn-asm` and the legacy line-mode AI console use `PWNMultiLineInput`. The
162
+ default pwn-ai curses console owns its own input/render loop; see its
163
+ [current key table](pwn-ai-Agent.md). In the line reader, plain
162
164
  **ENTER** submits; insert a newline (keep composing) with **any** of:
163
165
 
164
166
  | Keystroke | Works on | Notes |
@@ -193,7 +195,7 @@ emulator's config on its own.
193
195
 
194
196
  ## History → Driver
195
197
 
196
- `~/.pwn_history` captures every line you type. When a sequence works, turn it
198
+ `~/.pwn/pwn_history` captures every line you type. When a sequence works, turn it
197
199
  into a shipped `bin/pwn_*` driver - see
198
200
  [From REPL History to Driver](Drivers.md).
199
201
 
@@ -4,8 +4,8 @@
4
4
  the goal; the agent plans a sequence of tool calls (`pwn_eval`, `shell`,
5
5
  `memory_*`, `skill_*`, `mistakes_*`, `reward_*`, `curriculum_*`, `extro_*`,
6
6
  `agent_*`, ...), executes them against the live process, observes the results,
7
- and loops until it can give you a final answer - **learning from every failure
8
- so it doesn't repeat it**.
7
+ and checks completion against the original request and available host evidence.
8
+ Learning records failures and corrections; it cannot guarantee nonrecurrence.
9
9
 
10
10
  ## Two ways to run it
11
11
 
@@ -149,7 +149,9 @@ resets also use white holds/wipes. Ordinary locking never changes color or shape
149
149
  Colored falling blocks, Pac-Man, Galaga and Frogger support interiors up to 64 cells; the other artwork retains
150
150
  its 16-cell limit. Above the applicable limit, art is centered and padded rather
151
151
  than clipped or stretched.
152
- One `PWN::Banner.mini_names` animation is randomly
152
+ At startup the pane shows the centered WhiteRabbit miniature; games activate
153
+ only after the pane first receives focus. After that, one
154
+ `PWN::Banner.mini_names` animation is randomly
153
155
  selected for the session and retained across redraws, model changes and resize;
154
156
  changing the active session selects again. Frames advance at the banner API's
155
157
  `mini_frame_seconds(name:)` cadence (0.05 seconds for Asteroids/Galaga, 0.1 for
@@ -460,11 +462,10 @@ prints usage; at an idle prompt it reports that there is no active request.
460
462
  conversation and tool evidence stay available. The latest explicit user
461
463
  instruction takes precedence over conflicting earlier instructions; tool
462
464
  output cannot submit steering.
463
- * A steer starts a fresh completion scope from the latest instruction, not a
464
- keyword-edited reconstruction of the original goal. Include all still-required
465
- deliverables in that instruction. Old artifact requirements and a supplied
466
- old verification contract are not silently imposed on the revised task.
467
- Previously completed work is retained as evidence, not claimed to be undone.
465
+ * Steering is additive by default: original obligations and authored verification
466
+ checks remain. Explicit `replace:` changes scope; CLI objective replacement uses
467
+ `--replace-session` with `--approve-replacement` and a new contract. Previously
468
+ completed work is retained, not undone. See [Harness Evaluation](Harness-Evaluation.md#request-lifetime-integration-boundary).
468
469
 
469
470
  In curses, **only the main event thread draws and reads terminal keys**. One
470
471
  request-owned worker runs the real `Loop.run`, inheriting PWN request thread
@@ -511,8 +512,9 @@ after upgrading these files.
511
512
  it reads like *"no, that's wrong"* the previous outcome is flipped to
512
513
  `success:false`, fingerprinted, **and recorded as a `(prompt, rejected,
513
514
  chosen)` DPO preference pair** in `~/.pwn/preferences.jsonl`.
514
- 3. **Registry** hands Loop the tool schemas - the full set for frontier
515
- engines, or `CORE_TOOLS` + top-K keyword-relevant when
515
+ 3. **Registry** hands Loop the tool schemas. Normal Loop requests core-only
516
+ schemas (with request-relevant MCP exposure); explicit broader callers can use
517
+ `CORE_TOOLS` + top-K keyword-relevant when
516
518
  `ai.agent.tool_router` is on (default on for `ollama` / `openwebui`). Rank
517
519
  can include a Q-advantage term from `Policy` after a pair has been visited
518
520
  at least twice, plus `ai.agent.tool_preference` as a smaller tie-break.
@@ -555,14 +557,16 @@ after upgrading these files.
555
557
  outside world; a `:refuted` verify is itself recorded as a Mistakes
556
558
  `assumption` fingerprint.
557
559
  7. Results are appended to the message list; go to 5.
558
- 8. When the reply has *no* tool_calls it's the **final answer**. With
560
+ 8. A reply with no tool calls is a **candidate final**, not completion evidence.
561
+ RequestRuntime, artifact readback and any host-authored verification contract
562
+ must permit finalization; failed or incomplete work remains distinct. With
559
563
  `defer_introspect` on (default), the user-visible reply returns first and
560
564
  `Learning.auto_introspect` runs on a background thread. Specs and cron stay
561
565
  inline. Then *(local)*
562
566
  `fact_check_local_final` auto-`extro_verify`s every CVE / version-shaped
563
567
  claim in the answer; **`Reward.judge`** scores (request, final) with a cheap LLM ORM →
564
568
  `{score, verdict, rationale, source}` (heuristic overlap only if the engine is unavailable); **`Policy.finish`** applies that judge score as
565
- the terminal reward and updates Q / REINFORCE; **`Reward.prm`** back-labels each transcript
569
+ a resolved outcome; only independently linked actions receive positive training credit; **`Reward.prm`** back-labels each transcript
566
570
  step with `step_reward:+1/0/-1`; failed goals are optionally HER-relabeled
567
571
  by `Curriculum.hindsight`; `Reflect.on` writes durable lessons via
568
572
  `ai.reflect_engine` (teacher-student - a frontier engine may author the
@@ -585,8 +589,8 @@ The two that matter most:
585
589
 
586
590
  | Tool | Reach |
587
591
  |---|---|
588
- | `pwn_eval` | **Any** Ruby in-process - the whole `PWN::` namespace, `require`, monkey-patch, everything |
589
- | `shell` | **Any** OS command on the host. Runs through `PWN::AI::Agent::ToolGuard` first (placeholder, schema, bash-only syntax). |
592
+ | `pwn_eval` | Ruby over the PWN namespace, subject to runtime permissions, confirmation and configured sandbox policy; strict/permissive sandbox paths use isolated workers |
593
+ | `shell` | OS commands subject to runtime permissions, confirmation and sandbox policy. Runs through `PWN::AI::Agent::ToolGuard` first (placeholder, schema, bash-only syntax). |
590
594
 
591
595
  Everything else (memory, skills, learning, **mistakes**, **reward**,
592
596
  **curriculum**, **policy**, extrospection, cron, swarm, sessions, metrics) is a
@@ -43,6 +43,7 @@ PWN::AI::Agent::Learning.evidence_transcript(opts)
43
43
  - `consistency_check`
44
44
  - `disputed_save`
45
45
  - `outcomes`
46
+ - `regression_task`
46
47
  - `stats`
47
48
  - `to_context`
48
49
  - `exemplars_for`
@@ -456,7 +456,7 @@ module PWN
456
456
  }
457
457
  entry[:score] = score if decision || opts.key?(:score)
458
458
  if decision
459
- %i[verdict confidence training_score decision_version verification verifier_verdict grounded critic_pass judge_score quality_score rationale].each do |key|
459
+ %i[verdict confidence training_score decision_version verification verifier_verdict grounded critic_pass judge_score quality_score rationale claimed_completion verified_completion false_completion].each do |key|
460
460
  entry[key] = decision[key] if decision.key?(key)
461
461
  end
462
462
  entry[:status] = 'unverified' if decision[:training_score].nil?
@@ -542,9 +542,42 @@ module PWN
542
542
  # Supported Method Parameters::
543
543
  # stats = PWN::AI::Agent::Learning.stats
544
544
 
545
+ # Export an operator-authored, inert file-check recipe from a real failure.
546
+ # Never mine executable commands or gold answers from model prose.
547
+ public_class_method def self.regression_task(opts = {})
548
+ row = outcomes(limit: 10_000).find { |entry| entry[:id] == opts[:outcome_id] }
549
+ verification = row && row[:verification]
550
+ raise ArgumentError, 'persisted verified failure required' unless verification.is_a?(Hash) && Reward.resolve_outcome(outcome: row)[:verifier_verdict] == :fail
551
+
552
+ request = opts[:request].to_s
553
+ raise ArgumentError, 'original request digest mismatch' if request.empty? || verification[:request_digest] != Digest::SHA256.hexdigest(request)
554
+
555
+ requirements = Array(verification[:requirements])
556
+ checks = opts[:checks]
557
+ raise ArgumentError, 'exact original requirement coverage required' unless checks.is_a?(Array) && !requirements.empty? && checks.all?(Hash) && checks.map { |check| check[:requirement] }.uniq.sort == requirements.sort
558
+ raise ArgumentError, 'original requirement spans required' unless requirements.all? { |requirement| request.include?(requirement) }
559
+
560
+ checks.each do |check|
561
+ path = check[:path].to_s
562
+ raise ArgumentError, 'only relative in-root artifact paths allowed' if path.empty? || path.start_with?('/') || path.split('/').include?('..') || path.include?("\0")
563
+ raise ArgumentError, 'authored file/json expected content required' unless %w[file json].include?(check[:kind].to_s) && check.key?(:expected)
564
+ end
565
+ contract = { request: request, requirements: requirements, checks: checks.map { |check| check.slice(:requirement, :kind, :path, :expected) } }
566
+ # Detach returned recipes from caller and ledger objects; JSON is the
567
+ # portable fixture format used by the existing RSpec harness.
568
+ contract = JSON.parse(JSON.generate(contract), symbolize_names: true)
569
+ { schema: 'pwn-failure-regression-v1', split: 'regression', source_outcome_id: row[:id],
570
+ source_verification_sha256: Digest::SHA256.hexdigest(JSON.generate(verification)),
571
+ contract_sha256: Digest::SHA256.hexdigest(JSON.generate(contract)), contract: contract }
572
+ end
573
+
545
574
  public_class_method def self.stats
546
575
  rows = outcomes(limit: 10_000)
547
576
  total = rows.length
577
+ claims = rows.count { |row| row[:claimed_completion] == true }
578
+ false_completions = rows.count { |row| row[:false_completion] == true }
579
+ verified_completions = rows.count { |row| row[:verified_completion] == true }
580
+ checked_claims = rows.count { |row| row[:claimed_completion] == true && !row[:verified_completion].nil? }
548
581
  rows = rows.reject { |r| (r[:decision_version] && r[:training_score].nil?) || r[:success].nil? }
549
582
  evaluated = rows.length
550
583
  ok = rows.count { |r| r[:success] == true }
@@ -562,6 +595,11 @@ module PWN
562
595
  heur_ok = heur.count { |r| r[:success] == true }
563
596
  {
564
597
  total_outcomes: total,
598
+ completion_claims: claims,
599
+ checked_completion_claims: checked_claims,
600
+ false_completions: false_completions,
601
+ verified_completions: verified_completions,
602
+ false_completion_rate: checked_claims.positive? ? false_completions.to_f / checked_claims : nil,
565
603
  unknown_outcomes: total - evaluated,
566
604
  successes: ok,
567
605
  failures: rows.count { |r| r[:success] == false },
@@ -2398,6 +2436,13 @@ module PWN
2398
2436
  max_baks: 'optional - newest bak files to keep (defaults to 5)'
2399
2437
  )
2400
2438
 
2439
+ # Export an inert regression contract from a persisted verified failure.
2440
+ #{self}.regression_task(
2441
+ outcome_id: 'required - exact id in the recent learning ledger',
2442
+ request: 'required - complete original request matching the verifier digest',
2443
+ checks: 'required - independently authored file/json checks with relative paths and literal expected content'
2444
+ )
2445
+
2401
2446
  # Run outcomes and return its result
2402
2447
  #{self}.outcomes(
2403
2448
  limit: 'optional - max entries returned newest-first (default 50)',