pwn 0.5.682 → 0.5.684

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -10
  3. data/documentation/Agent-Tool-Registry.md +13 -9
  4. data/documentation/CLI-Drivers.md +27 -28
  5. data/documentation/Configuration.md +7 -5
  6. data/documentation/Contributing.md +2 -2
  7. data/documentation/Cron.md +11 -7
  8. data/documentation/Diagrams.md +2 -2
  9. data/documentation/General-PWN-Usage.md +1 -1
  10. data/documentation/Home.md +7 -6
  11. data/documentation/How-PWN-Works.md +9 -9
  12. data/documentation/Installation.md +1 -1
  13. data/documentation/Persistence.md +2 -1
  14. data/documentation/Plugins.md +3 -3
  15. data/documentation/Reinforcement-Learning.md +103 -101
  16. data/documentation/SAST.md +1 -1
  17. data/documentation/Session-Workflow.md +152 -0
  18. data/documentation/Sessions.md +2 -1
  19. data/documentation/Troubleshooting.md +2 -2
  20. data/documentation/What-is-PWN.md +3 -3
  21. data/documentation/diagrams/agent-tool-registry.svg +152 -152
  22. data/documentation/diagrams/cron-scheduling.svg +141 -121
  23. data/documentation/diagrams/dot/agent-tool-registry.dot +4 -4
  24. data/documentation/diagrams/dot/cron-scheduling.dot +10 -7
  25. data/documentation/diagrams/dot/driver-framework.dot +1 -1
  26. data/documentation/diagrams/dot/overall-pwn-architecture.dot +4 -4
  27. data/documentation/diagrams/dot/persistence-filesystem.dot +1 -1
  28. data/documentation/diagrams/dot/plugin-ecosystem.dot +2 -2
  29. data/documentation/diagrams/dot/task-summarizer.dot +18 -16
  30. data/documentation/diagrams/driver-framework.svg +1 -1
  31. data/documentation/diagrams/overall-pwn-architecture.svg +93 -93
  32. data/documentation/diagrams/persistence-filesystem.svg +4 -4
  33. data/documentation/diagrams/plugin-ecosystem.svg +101 -100
  34. data/documentation/diagrams/task-summarizer.svg +166 -156
  35. data/documentation/pwn-ai-Agent.md +9 -4
  36. data/lib/pwn/ai/agent/dispatch.rb +52 -1
  37. data/lib/pwn/ai/agent/loop.rb +198 -159
  38. data/lib/pwn/ai/agent/open_goal.rb +83 -0
  39. data/lib/pwn/ai/agent/policy.rb +2 -3
  40. data/lib/pwn/ai/agent/prompt_builder.rb +16 -13
  41. data/lib/pwn/ai/agent/registry.rb +6 -9
  42. data/lib/pwn/ai/agent/tools/sessions.rb +32 -0
  43. data/lib/pwn/ai/agent/tools/skills.rb +56 -0
  44. data/lib/pwn/ai/agent.rb +1 -0
  45. data/lib/pwn/ai/anthropic.rb +0 -1
  46. data/lib/pwn/ai/gemini.rb +0 -1
  47. data/lib/pwn/ai/grok.rb +0 -1
  48. data/lib/pwn/ai/ollama.rb +0 -1
  49. data/lib/pwn/ai/open_ai.rb +0 -1
  50. data/lib/pwn/ai/open_web_ui.rb +0 -1
  51. data/lib/pwn/config.rb +2 -2
  52. data/lib/pwn/cron.rb +18 -5
  53. data/lib/pwn/plugins/repl.rb +43 -1
  54. data/lib/pwn/plugins/tty_spinner.rb +109 -13
  55. data/lib/pwn/sessions.rb +82 -0
  56. data/lib/pwn/version.rb +1 -1
  57. data/spec/integration/persistence_roundtrip_spec.rb +2 -1
  58. data/spec/integration/prompt_builder_spec.rb +3 -3
  59. data/spec/integration/reinforced_feedback_loop_spec.rb +6 -11
  60. data/spec/lib/pwn/ai/agent/dispatch_spec.rb +38 -82
  61. data/spec/lib/pwn/ai/agent/loop_spec.rb +284 -11
  62. data/spec/lib/pwn/ai/agent/open_goal_spec.rb +37 -0
  63. data/spec/lib/pwn/ai/agent/prompt_builder_spec.rb +7 -3
  64. data/spec/lib/pwn/ai/agent/registry_spec.rb +16 -9
  65. data/spec/lib/pwn/ai/agent/tools/sessions_spec.rb +5 -0
  66. data/spec/lib/pwn/ai/agent/tools/skills_spec.rb +16 -0
  67. data/spec/lib/pwn/ai/red_team/test_case_engine_spec.rb +20 -0
  68. data/spec/lib/pwn/cron_spec.rb +13 -3
  69. data/spec/lib/pwn/plugins/repl_spec.rb +26 -0
  70. data/spec/lib/pwn/plugins/tty_spinner_spec.rb +44 -0
  71. data/spec/lib/pwn/sessions_spec.rb +29 -0
  72. data/spec/spec_helper.rb +6 -0
  73. data/third_party/pwn_rdoc.jsonl +28 -1
  74. metadata +4 -1
@@ -4,268 +4,288 @@
4
4
  <!-- Generated by graphviz version 14.1.2 (0)
5
5
  -->
6
6
  <!-- Title: PWN_Cron Pages: 1 -->
7
- <svg width="1605pt" height="617pt"
8
- viewBox="0.00 0.00 1605.00 617.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 574.2)">
7
+ <svg width="1489pt" height="667pt"
8
+ viewBox="0.00 0.00 1489.00 667.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 624.2)">
10
10
  <title>PWN_Cron</title>
11
- <polygon fill="#0f172a" stroke="none" points="-43.2,43.2 -43.2,-574.2 1561.7,-574.2 1561.7,43.2 -43.2,43.2"/>
12
- <text xml:space="preserve" text-anchor="start" x="557.88" y="-509" font-family="sans-Serif" font-weight="bold" font-size="20.00" fill="#e2e8f0">PWN::Cron &#45; Scheduled Autonomous Jobs</text>
13
- <text xml:space="preserve" text-anchor="start" x="532.75" y="-497.55" font-family="sans-Serif" font-size="11.00" fill="#94a3b8">prompt · ruby · script → jobs.yml → worker → pwn&#45;ai &#160;· &#160;seeded self&#45;improvement (Curriculum)</text>
11
+ <polygon fill="#0f172a" stroke="none" points="-43.2,43.2 -43.2,-624.2 1446.2,-624.2 1446.2,43.2 -43.2,43.2"/>
12
+ <text xml:space="preserve" text-anchor="start" x="500.12" y="-559" font-family="sans-Serif" font-weight="bold" font-size="20.00" fill="#e2e8f0">PWN::Cron &#45; Scheduled Autonomous Jobs</text>
13
+ <text xml:space="preserve" text-anchor="start" x="496.38" y="-547.55" font-family="sans-Serif" font-size="11.00" fill="#94a3b8">prompt · ruby · script → jobs.yml → worker → pwn&#45;ai &#160;· &#160;hygiene on · curriculum opt&#45;in</text>
14
14
  <g id="clust2" class="cluster">
15
15
  <title>cluster_kinds</title>
16
- <path fill="#022c22" stroke="#047857" stroke-width="2" d="M874,-257C874,-257 1028.25,-257 1028.25,-257 1034.25,-257 1040.25,-263 1040.25,-269 1040.25,-269 1040.25,-472 1040.25,-472 1040.25,-478 1034.25,-484 1028.25,-484 1028.25,-484 874,-484 874,-484 868,-484 862,-478 862,-472 862,-472 862,-269 862,-269 862,-263 868,-257 874,-257"/>
17
- <text xml:space="preserve" text-anchor="middle" x="951.12" y="-461" font-family="sans-Serif" font-size="20.00" fill="#a7f3d0">Job Kinds</text>
16
+ <path fill="#022c22" stroke="#047857" stroke-width="2" d="M874,-307C874,-307 1028.25,-307 1028.25,-307 1034.25,-307 1040.25,-313 1040.25,-319 1040.25,-319 1040.25,-522 1040.25,-522 1040.25,-528 1034.25,-534 1028.25,-534 1028.25,-534 874,-534 874,-534 868,-534 862,-528 862,-522 862,-522 862,-319 862,-319 862,-313 868,-307 874,-307"/>
17
+ <text xml:space="preserve" text-anchor="middle" x="951.12" y="-511" font-family="sans-Serif" font-size="20.00" fill="#a7f3d0">Job Kinds</text>
18
18
  </g>
19
19
  <g id="clust4" class="cluster">
20
20
  <title>cluster_seed</title>
21
- <path fill="#2e1065" stroke="#6d28d9" stroke-width="2" d="M1131.25,-8C1131.25,-8 1506.5,-8 1506.5,-8 1512.5,-8 1518.5,-14 1518.5,-20 1518.5,-20 1518.5,-359 1518.5,-359 1518.5,-365 1512.5,-371 1506.5,-371 1506.5,-371 1131.25,-371 1131.25,-371 1125.25,-371 1119.25,-365 1119.25,-359 1119.25,-359 1119.25,-20 1119.25,-20 1119.25,-14 1125.25,-8 1131.25,-8"/>
22
- <text xml:space="preserve" text-anchor="middle" x="1318.88" y="-348" font-family="sans-Serif" font-size="20.00" fill="#ddd6fe">Seeded Self&#45;Improvement (install_defaults)</text>
21
+ <path fill="#2e1065" stroke="#6d28d9" stroke-width="2" d="M1131.25,-8C1131.25,-8 1391,-8 1391,-8 1397,-8 1403,-14 1403,-20 1403,-20 1403,-444 1403,-444 1403,-450 1397,-456 1391,-456 1391,-456 1131.25,-456 1131.25,-456 1125.25,-456 1119.25,-450 1119.25,-444 1119.25,-444 1119.25,-20 1119.25,-20 1119.25,-14 1125.25,-8 1131.25,-8"/>
22
+ <text xml:space="preserve" text-anchor="middle" x="1261.12" y="-433" font-family="sans-Serif" font-size="20.00" fill="#ddd6fe">Seeded Jobs (install_defaults)</text>
23
23
  </g>
24
24
  <!-- Create -->
25
25
  <g id="node1" class="node">
26
26
  <title>Create</title>
27
- <path fill="#7dd3fc" stroke="#334155" stroke-width="1.4" d="M118,-440.25C118,-440.25 27.75,-440.25 27.75,-440.25 21.75,-440.25 15.75,-434.25 15.75,-428.25 15.75,-428.25 15.75,-403.75 15.75,-403.75 15.75,-397.75 21.75,-391.75 27.75,-391.75 27.75,-391.75 118,-391.75 118,-391.75 124,-391.75 130,-397.75 130,-403.75 130,-403.75 130,-428.25 130,-428.25 130,-434.25 124,-440.25 118,-440.25"/>
28
- <text xml:space="preserve" text-anchor="middle" x="72.88" y="-425.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">cron_create</text>
29
- <text xml:space="preserve" text-anchor="middle" x="72.88" y="-412.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">name · schedule</text>
30
- <text xml:space="preserve" text-anchor="middle" x="72.88" y="-398.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">prompt | ruby | script</text>
27
+ <path fill="#7dd3fc" stroke="#334155" stroke-width="1.4" d="M118,-490.25C118,-490.25 27.75,-490.25 27.75,-490.25 21.75,-490.25 15.75,-484.25 15.75,-478.25 15.75,-478.25 15.75,-453.75 15.75,-453.75 15.75,-447.75 21.75,-441.75 27.75,-441.75 27.75,-441.75 118,-441.75 118,-441.75 124,-441.75 130,-447.75 130,-453.75 130,-453.75 130,-478.25 130,-478.25 130,-484.25 124,-490.25 118,-490.25"/>
28
+ <text xml:space="preserve" text-anchor="middle" x="72.88" y="-475.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">cron_create</text>
29
+ <text xml:space="preserve" text-anchor="middle" x="72.88" y="-462.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">name · schedule</text>
30
+ <text xml:space="preserve" text-anchor="middle" x="72.88" y="-448.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">prompt | ruby | script</text>
31
31
  </g>
32
32
  <!-- Jobs -->
33
33
  <g id="node3" class="node">
34
34
  <title>Jobs</title>
35
- <path fill="#fcd34d" stroke="#334155" stroke-width="1.4" d="M439.12,-392.73C439.12,-394.53 413.35,-396 381.62,-396 349.9,-396 324.12,-394.53 324.12,-392.73 324.12,-392.73 324.12,-363.27 324.12,-363.27 324.12,-361.47 349.9,-360 381.62,-360 413.35,-360 439.12,-361.47 439.12,-363.27 439.12,-363.27 439.12,-392.73 439.12,-392.73"/>
36
- <path fill="none" stroke="#334155" stroke-width="1.4" d="M439.12,-392.73C439.12,-390.92 413.35,-389.45 381.62,-389.45 349.9,-389.45 324.12,-390.92 324.12,-392.73"/>
37
- <text xml:space="preserve" text-anchor="middle" x="381.62" y="-374.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">~/.pwn/cron/jobs.yml</text>
35
+ <path fill="#fcd34d" stroke="#334155" stroke-width="1.4" d="M439.12,-442.73C439.12,-444.53 413.35,-446 381.62,-446 349.9,-446 324.12,-444.53 324.12,-442.73 324.12,-442.73 324.12,-413.27 324.12,-413.27 324.12,-411.47 349.9,-410 381.62,-410 413.35,-410 439.12,-411.47 439.12,-413.27 439.12,-413.27 439.12,-442.73 439.12,-442.73"/>
36
+ <path fill="none" stroke="#334155" stroke-width="1.4" d="M439.12,-442.73C439.12,-440.92 413.35,-439.45 381.62,-439.45 349.9,-439.45 324.12,-440.92 324.12,-442.73"/>
37
+ <text xml:space="preserve" text-anchor="middle" x="381.62" y="-424.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">~/.pwn/cron/jobs.yml</text>
38
38
  </g>
39
39
  <!-- Create&#45;&gt;Jobs -->
40
40
  <g id="edge1" class="edge">
41
41
  <title>Create&#45;&gt;Jobs</title>
42
- <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M130.5,-408.99C182.35,-402.56 259.13,-393.05 313.93,-386.26"/>
43
- <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="314.01,-389.07 321.6,-385.31 313.32,-383.52 314.01,-389.07"/>
44
- <text xml:space="preserve" text-anchor="middle" x="226.88" y="-402.35" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">write</text>
42
+ <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M130.5,-458.99C182.35,-452.56 259.13,-443.05 313.93,-436.26"/>
43
+ <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="314.01,-439.07 321.6,-435.31 313.32,-433.52 314.01,-439.07"/>
44
+ <text xml:space="preserve" text-anchor="middle" x="226.88" y="-452.35" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">write</text>
45
45
  </g>
46
46
  <!-- Crontab -->
47
47
  <g id="node4" class="node">
48
48
  <title>Crontab</title>
49
- <path fill="#fda4af" stroke="#334155" stroke-width="1.4" d="M428.25,-468C428.25,-468 335,-468 335,-468 329,-468 323,-462 323,-456 323,-456 323,-444 323,-444 323,-438 329,-432 335,-432 335,-432 428.25,-432 428.25,-432 434.25,-432 440.25,-438 440.25,-444 440.25,-444 440.25,-456 440.25,-456 440.25,-462 434.25,-468 428.25,-468"/>
50
- <text xml:space="preserve" text-anchor="middle" x="381.62" y="-453.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">per&#45;job crontab</text>
51
- <text xml:space="preserve" text-anchor="middle" x="381.62" y="-439.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">(install_crontab: true)</text>
49
+ <path fill="#fda4af" stroke="#334155" stroke-width="1.4" d="M428.25,-518C428.25,-518 335,-518 335,-518 329,-518 323,-512 323,-506 323,-506 323,-494 323,-494 323,-488 329,-482 335,-482 335,-482 428.25,-482 428.25,-482 434.25,-482 440.25,-488 440.25,-494 440.25,-494 440.25,-506 440.25,-506 440.25,-512 434.25,-518 428.25,-518"/>
50
+ <text xml:space="preserve" text-anchor="middle" x="381.62" y="-503.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">per&#45;job crontab</text>
51
+ <text xml:space="preserve" text-anchor="middle" x="381.62" y="-489.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">(install_crontab: true)</text>
52
52
  </g>
53
53
  <!-- Create&#45;&gt;Crontab -->
54
54
  <g id="edge3" class="edge">
55
55
  <title>Create&#45;&gt;Crontab</title>
56
- <path fill="none" stroke="#fb7185" stroke-width="1.3" d="M130.5,-422.28C182.02,-427.99 258.16,-436.43 312.89,-442.49"/>
57
- <polygon fill="#fb7185" stroke="#fb7185" stroke-width="1.3" points="312.3,-445.24 320.56,-443.34 312.91,-439.68 312.3,-445.24"/>
58
- <text xml:space="preserve" text-anchor="middle" x="226.88" y="-438" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">optional per&#45;job</text>
56
+ <path fill="none" stroke="#fb7185" stroke-width="1.3" d="M130.5,-472.28C182.02,-477.99 258.16,-486.43 312.89,-492.49"/>
57
+ <polygon fill="#fb7185" stroke="#fb7185" stroke-width="1.3" points="312.3,-495.24 320.56,-493.34 312.91,-489.68 312.3,-495.24"/>
58
+ <text xml:space="preserve" text-anchor="middle" x="226.88" y="-488" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">optional per&#45;job</text>
59
59
  </g>
60
60
  <!-- Seed -->
61
61
  <g id="node2" class="node">
62
62
  <title>Seed</title>
63
- <path fill="#7dd3fc" stroke="#334155" stroke-width="1.4" d="M133.75,-343C133.75,-343 12,-343 12,-343 6,-343 0,-337 0,-331 0,-331 0,-319 0,-319 0,-313 6,-307 12,-307 12,-307 133.75,-307 133.75,-307 139.75,-307 145.75,-313 145.75,-319 145.75,-319 145.75,-331 145.75,-331 145.75,-337 139.75,-343 133.75,-343"/>
64
- <text xml:space="preserve" text-anchor="middle" x="72.88" y="-328.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">PWN::Cron.install_defaults</text>
65
- <text xml:space="preserve" text-anchor="middle" x="72.88" y="-314.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">(pwn setup &#45;&#45;migrate)</text>
63
+ <path fill="#7dd3fc" stroke="#334155" stroke-width="1.4" d="M133.75,-393C133.75,-393 12,-393 12,-393 6,-393 0,-387 0,-381 0,-381 0,-369 0,-369 0,-363 6,-357 12,-357 12,-357 133.75,-357 133.75,-357 139.75,-357 145.75,-363 145.75,-369 145.75,-369 145.75,-381 145.75,-381 145.75,-387 139.75,-393 133.75,-393"/>
64
+ <text xml:space="preserve" text-anchor="middle" x="72.88" y="-378.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">PWN::Cron.install_defaults</text>
65
+ <text xml:space="preserve" text-anchor="middle" x="72.88" y="-364.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">(pwn setup &#45;&#45;migrate)</text>
66
66
  </g>
67
67
  <!-- Seed&#45;&gt;Jobs -->
68
68
  <g id="edge2" class="edge">
69
69
  <title>Seed&#45;&gt;Jobs</title>
70
- <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M146.18,-337.49C197,-346.27 264.47,-357.93 313.98,-366.48"/>
71
- <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="313.33,-369.21 321.69,-367.82 314.29,-363.7 313.33,-369.21"/>
72
- <text xml:space="preserve" text-anchor="middle" x="226.88" y="-358.2" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">idempotent seed</text>
70
+ <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M146.18,-387.49C197,-396.27 264.47,-407.93 313.98,-416.48"/>
71
+ <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="313.33,-419.21 321.69,-417.82 314.29,-413.7 313.33,-419.21"/>
72
+ <text xml:space="preserve" text-anchor="middle" x="226.88" y="-408.2" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">idempotent seed</text>
73
73
  </g>
74
74
  <!-- Worker -->
75
75
  <g id="node5" class="node">
76
76
  <title>Worker</title>
77
- <path fill="#fda4af" stroke="#334155" stroke-width="1.4" d="M443.25,-324C443.25,-324 320,-324 320,-324 314,-324 308,-318 308,-312 308,-312 308,-274 308,-274 308,-268 314,-262 320,-262 320,-262 443.25,-262 443.25,-262 449.25,-262 455.25,-268 455.25,-274 455.25,-274 455.25,-312 455.25,-312 455.25,-318 449.25,-324 443.25,-324"/>
78
- <text xml:space="preserve" text-anchor="middle" x="381.62" y="-309.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">background worker</text>
79
- <text xml:space="preserve" text-anchor="middle" x="381.62" y="-296.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">pwn setup keep&#45;alive</text>
80
- <text xml:space="preserve" text-anchor="middle" x="381.62" y="-282.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">systemd &#45;&#45;user / launchd</text>
81
- <text xml:space="preserve" text-anchor="middle" x="381.62" y="-269.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">schtasks / crontab @reboot</text>
77
+ <path fill="#fda4af" stroke="#334155" stroke-width="1.4" d="M443.25,-374C443.25,-374 320,-374 320,-374 314,-374 308,-368 308,-362 308,-362 308,-324 308,-324 308,-318 314,-312 320,-312 320,-312 443.25,-312 443.25,-312 449.25,-312 455.25,-318 455.25,-324 455.25,-324 455.25,-362 455.25,-362 455.25,-368 449.25,-374 443.25,-374"/>
78
+ <text xml:space="preserve" text-anchor="middle" x="381.62" y="-359.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">background worker</text>
79
+ <text xml:space="preserve" text-anchor="middle" x="381.62" y="-346.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">pwn setup keep&#45;alive</text>
80
+ <text xml:space="preserve" text-anchor="middle" x="381.62" y="-332.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">systemd &#45;&#45;user / launchd</text>
81
+ <text xml:space="preserve" text-anchor="middle" x="381.62" y="-319.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">schtasks / crontab @reboot</text>
82
82
  </g>
83
83
  <!-- Seed&#45;&gt;Worker -->
84
84
  <g id="edge4" class="edge">
85
85
  <title>Seed&#45;&gt;Worker</title>
86
- <path fill="none" stroke="#fb7185" stroke-width="1.3" d="M130.08,-306.33C149.68,-300.71 171.97,-295.29 192.75,-292.5 227.03,-287.9 265.14,-287.19 298.03,-287.95"/>
87
- <polygon fill="#fb7185" stroke="#fb7185" stroke-width="1.3" points="297.57,-290.74 305.64,-288.16 297.72,-285.14 297.57,-290.74"/>
88
- <text xml:space="preserve" text-anchor="middle" x="226.88" y="-294.45" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">pwn setup</text>
86
+ <path fill="none" stroke="#fb7185" stroke-width="1.3" d="M130.08,-356.33C149.68,-350.71 171.97,-345.29 192.75,-342.5 227.03,-337.9 265.14,-337.19 298.03,-337.95"/>
87
+ <polygon fill="#fb7185" stroke="#fb7185" stroke-width="1.3" points="297.57,-340.74 305.64,-338.16 297.72,-335.14 297.57,-340.74"/>
88
+ <text xml:space="preserve" text-anchor="middle" x="226.88" y="-344.45" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">pwn setup</text>
89
89
  </g>
90
90
  <!-- Runner -->
91
91
  <g id="node6" class="node">
92
92
  <title>Runner</title>
93
- <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M709.25,-373C709.25,-373 626.5,-373 626.5,-373 620.5,-373 614.5,-367 614.5,-361 614.5,-361 614.5,-349 614.5,-349 614.5,-343 620.5,-337 626.5,-337 626.5,-337 709.25,-337 709.25,-337 715.25,-337 721.25,-343 721.25,-349 721.25,-349 721.25,-361 721.25,-361 721.25,-367 715.25,-373 709.25,-373"/>
94
- <text xml:space="preserve" text-anchor="middle" x="667.88" y="-351.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">PWN::Cron.run(id)</text>
93
+ <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M709.25,-423C709.25,-423 626.5,-423 626.5,-423 620.5,-423 614.5,-417 614.5,-411 614.5,-411 614.5,-399 614.5,-399 614.5,-393 620.5,-387 626.5,-387 626.5,-387 709.25,-387 709.25,-387 715.25,-387 721.25,-393 721.25,-399 721.25,-399 721.25,-411 721.25,-411 721.25,-417 715.25,-423 709.25,-423"/>
94
+ <text xml:space="preserve" text-anchor="middle" x="667.88" y="-401.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">PWN::Cron.run(id)</text>
95
95
  </g>
96
96
  <!-- Jobs&#45;&gt;Runner -->
97
97
  <g id="edge7" class="edge">
98
98
  <title>Jobs&#45;&gt;Runner</title>
99
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M439.81,-373.37C487.43,-369.52 555.15,-364.04 604.24,-360.07"/>
100
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="604.39,-362.86 612.14,-359.43 603.94,-357.28 604.39,-362.86"/>
101
- <text xml:space="preserve" text-anchor="middle" x="534.88" y="-369.83" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">load job</text>
99
+ <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M439.81,-423.37C487.43,-419.52 555.15,-414.04 604.24,-410.07"/>
100
+ <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="604.39,-412.86 612.14,-409.43 603.94,-407.28 604.39,-412.86"/>
101
+ <text xml:space="preserve" text-anchor="middle" x="534.88" y="-419.83" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">load job</text>
102
102
  </g>
103
103
  <!-- Crontab&#45;&gt;Runner -->
104
104
  <g id="edge5" class="edge">
105
105
  <title>Crontab&#45;&gt;Runner</title>
106
- <path fill="none" stroke="#fb7185" stroke-width="2" d="M440.92,-441.88C477.95,-435.63 526.46,-425.41 567.5,-410 589.04,-401.91 611.58,-389.77 629.74,-378.96"/>
107
- <polygon fill="#fb7185" stroke="#fb7185" stroke-width="2" points="630.84,-381.56 636.23,-375.02 627.93,-376.78 630.84,-381.56"/>
108
- <text xml:space="preserve" text-anchor="middle" x="534.88" y="-431.28" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">fire on schedule</text>
106
+ <path fill="none" stroke="#fb7185" stroke-width="2" d="M440.92,-491.88C477.95,-485.63 526.46,-475.41 567.5,-460 589.04,-451.91 611.58,-439.77 629.74,-428.96"/>
107
+ <polygon fill="#fb7185" stroke="#fb7185" stroke-width="2" points="630.84,-431.56 636.23,-425.02 627.93,-426.78 630.84,-431.56"/>
108
+ <text xml:space="preserve" text-anchor="middle" x="534.88" y="-481.28" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">fire on schedule</text>
109
109
  </g>
110
110
  <!-- Worker&#45;&gt;Runner -->
111
111
  <g id="edge6" class="edge">
112
112
  <title>Worker&#45;&gt;Runner</title>
113
- <path fill="none" stroke="#fb7185" stroke-width="2" d="M455.83,-308.97C501.57,-318.94 559.88,-331.66 603.61,-341.2"/>
114
- <polygon fill="#fb7185" stroke="#fb7185" stroke-width="2" points="602.74,-343.88 611.16,-342.85 603.94,-338.41 602.74,-343.88"/>
115
- <text xml:space="preserve" text-anchor="middle" x="534.88" y="-335.13" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">poll jobs.yml</text>
113
+ <path fill="none" stroke="#fb7185" stroke-width="2" d="M455.83,-358.97C501.57,-368.94 559.88,-381.66 603.61,-391.2"/>
114
+ <polygon fill="#fb7185" stroke="#fb7185" stroke-width="2" points="602.74,-393.88 611.16,-392.85 603.94,-388.41 602.74,-393.88"/>
115
+ <text xml:space="preserve" text-anchor="middle" x="534.88" y="-385.13" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">poll jobs.yml</text>
116
116
  </g>
117
117
  <!-- Prompt -->
118
118
  <g id="node7" class="node">
119
119
  <title>Prompt</title>
120
- <path fill="#6ee7b7" stroke="#334155" stroke-width="1.4" d="M992.88,-373C992.88,-373 909.38,-373 909.38,-373 903.38,-373 897.38,-367 897.38,-361 897.38,-361 897.38,-349 897.38,-349 897.38,-343 903.38,-337 909.38,-337 909.38,-337 992.88,-337 992.88,-337 998.88,-337 1004.88,-343 1004.88,-349 1004.88,-349 1004.88,-361 1004.88,-361 1004.88,-367 998.88,-373 992.88,-373"/>
121
- <text xml:space="preserve" text-anchor="middle" x="951.12" y="-358.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">:prompt</text>
122
- <text xml:space="preserve" text-anchor="middle" x="951.12" y="-344.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">→ pwn&#45;ai one&#45;shot</text>
120
+ <path fill="#6ee7b7" stroke="#334155" stroke-width="1.4" d="M992.88,-423C992.88,-423 909.38,-423 909.38,-423 903.38,-423 897.38,-417 897.38,-411 897.38,-411 897.38,-399 897.38,-399 897.38,-393 903.38,-387 909.38,-387 909.38,-387 992.88,-387 992.88,-387 998.88,-387 1004.88,-393 1004.88,-399 1004.88,-399 1004.88,-411 1004.88,-411 1004.88,-417 998.88,-423 992.88,-423"/>
121
+ <text xml:space="preserve" text-anchor="middle" x="951.12" y="-408.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">:prompt</text>
122
+ <text xml:space="preserve" text-anchor="middle" x="951.12" y="-394.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">→ pwn&#45;ai one&#45;shot</text>
123
123
  </g>
124
124
  <!-- Runner&#45;&gt;Prompt -->
125
125
  <g id="edge8" class="edge">
126
126
  <title>Runner&#45;&gt;Prompt</title>
127
- <path fill="none" stroke="#34d399" stroke-width="1.3" d="M721.78,-355C768.77,-355 837.52,-355 887.29,-355"/>
128
- <polygon fill="#34d399" stroke="#34d399" stroke-width="1.3" points="887.02,-357.8 895.02,-355 887.02,-352.2 887.02,-357.8"/>
127
+ <path fill="none" stroke="#34d399" stroke-width="1.3" d="M721.78,-405C768.77,-405 837.52,-405 887.29,-405"/>
128
+ <polygon fill="#34d399" stroke="#34d399" stroke-width="1.3" points="887.02,-407.8 895.02,-405 887.02,-402.2 887.02,-407.8"/>
129
129
  </g>
130
130
  <!-- Ruby -->
131
131
  <g id="node8" class="node">
132
132
  <title>Ruby</title>
133
- <path fill="#6ee7b7" stroke="#334155" stroke-width="1.4" d="M1020.25,-301C1020.25,-301 882,-301 882,-301 876,-301 870,-295 870,-289 870,-289 870,-277 870,-277 870,-271 876,-265 882,-265 882,-265 1020.25,-265 1020.25,-265 1026.25,-265 1032.25,-271 1032.25,-277 1032.25,-277 1032.25,-289 1032.25,-289 1032.25,-295 1026.25,-301 1020.25,-301"/>
134
- <text xml:space="preserve" text-anchor="middle" x="951.12" y="-286.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">:ruby</text>
135
- <text xml:space="preserve" text-anchor="middle" x="951.12" y="-272.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">→ TOPLEVEL_BINDING.eval</text>
133
+ <path fill="#6ee7b7" stroke="#334155" stroke-width="1.4" d="M1020.25,-351C1020.25,-351 882,-351 882,-351 876,-351 870,-345 870,-339 870,-339 870,-327 870,-327 870,-321 876,-315 882,-315 882,-315 1020.25,-315 1020.25,-315 1026.25,-315 1032.25,-321 1032.25,-327 1032.25,-327 1032.25,-339 1032.25,-339 1032.25,-345 1026.25,-351 1020.25,-351"/>
134
+ <text xml:space="preserve" text-anchor="middle" x="951.12" y="-336.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">:ruby</text>
135
+ <text xml:space="preserve" text-anchor="middle" x="951.12" y="-322.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">→ TOPLEVEL_BINDING.eval</text>
136
136
  </g>
137
137
  <!-- Runner&#45;&gt;Ruby -->
138
138
  <g id="edge9" class="edge">
139
139
  <title>Runner&#45;&gt;Ruby</title>
140
- <path fill="none" stroke="#34d399" stroke-width="1.3" d="M721.78,-341.46C762.86,-330.94 820.59,-316.16 867.72,-304.1"/>
141
- <polygon fill="#34d399" stroke="#34d399" stroke-width="1.3" points="868.33,-306.83 875.39,-302.13 866.95,-301.4 868.33,-306.83"/>
140
+ <path fill="none" stroke="#34d399" stroke-width="1.3" d="M721.78,-391.46C762.86,-380.94 820.59,-366.16 867.72,-354.1"/>
141
+ <polygon fill="#34d399" stroke="#34d399" stroke-width="1.3" points="868.33,-356.83 875.39,-352.13 866.95,-351.4 868.33,-356.83"/>
142
142
  </g>
143
143
  <!-- Script -->
144
144
  <g id="node9" class="node">
145
145
  <title>Script</title>
146
- <path fill="#6ee7b7" stroke="#334155" stroke-width="1.4" d="M994.38,-445C994.38,-445 907.88,-445 907.88,-445 901.88,-445 895.88,-439 895.88,-433 895.88,-433 895.88,-421 895.88,-421 895.88,-415 901.88,-409 907.88,-409 907.88,-409 994.38,-409 994.38,-409 1000.38,-409 1006.38,-415 1006.38,-421 1006.38,-421 1006.38,-433 1006.38,-433 1006.38,-439 1000.38,-445 994.38,-445"/>
147
- <text xml:space="preserve" text-anchor="middle" x="951.12" y="-430.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">:script</text>
148
- <text xml:space="preserve" text-anchor="middle" x="951.12" y="-416.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">→ exec external file</text>
146
+ <path fill="#6ee7b7" stroke="#334155" stroke-width="1.4" d="M994.38,-495C994.38,-495 907.88,-495 907.88,-495 901.88,-495 895.88,-489 895.88,-483 895.88,-483 895.88,-471 895.88,-471 895.88,-465 901.88,-459 907.88,-459 907.88,-459 994.38,-459 994.38,-459 1000.38,-459 1006.38,-465 1006.38,-471 1006.38,-471 1006.38,-483 1006.38,-483 1006.38,-489 1000.38,-495 994.38,-495"/>
147
+ <text xml:space="preserve" text-anchor="middle" x="951.12" y="-480.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">:script</text>
148
+ <text xml:space="preserve" text-anchor="middle" x="951.12" y="-466.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">→ exec external file</text>
149
149
  </g>
150
150
  <!-- Runner&#45;&gt;Script -->
151
151
  <g id="edge10" class="edge">
152
152
  <title>Runner&#45;&gt;Script</title>
153
- <path fill="none" stroke="#34d399" stroke-width="1.3" d="M721.9,-370.33C736.85,-374.55 753.16,-379.05 768.25,-383 807.17,-393.19 851.01,-403.82 885.89,-412.08"/>
154
- <polygon fill="#34d399" stroke="#34d399" stroke-width="1.3" points="885.13,-414.77 893.56,-413.89 886.42,-409.32 885.13,-414.77"/>
153
+ <path fill="none" stroke="#34d399" stroke-width="1.3" d="M721.9,-420.33C736.85,-424.55 753.16,-429.05 768.25,-433 807.17,-443.19 851.01,-453.82 885.89,-462.08"/>
154
+ <polygon fill="#34d399" stroke="#34d399" stroke-width="1.3" points="885.13,-464.77 893.56,-463.89 886.42,-459.32 885.13,-464.77"/>
155
155
  </g>
156
156
  <!-- Log -->
157
- <g id="node14" class="node">
157
+ <g id="node15" class="node">
158
158
  <title>Log</title>
159
- <path fill="#fcd34d" stroke="#334155" stroke-width="1.4" d="M1384.5,-446.69C1384.5,-449.1 1354.86,-451.06 1318.38,-451.06 1281.89,-451.06 1252.25,-449.1 1252.25,-446.69 1252.25,-446.69 1252.25,-407.31 1252.25,-407.31 1252.25,-404.9 1281.89,-402.94 1318.38,-402.94 1354.86,-402.94 1384.5,-404.9 1384.5,-407.31 1384.5,-407.31 1384.5,-446.69 1384.5,-446.69"/>
160
- <path fill="none" stroke="#334155" stroke-width="1.4" d="M1384.5,-446.69C1384.5,-444.27 1354.86,-442.31 1318.38,-442.31 1281.89,-442.31 1252.25,-444.27 1252.25,-446.69"/>
161
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-430.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">~/.pwn/cron/log/&lt;id&gt;.log</text>
162
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-416.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">last_run · last_status</text>
159
+ <path fill="#fcd34d" stroke="#334155" stroke-width="1.4" d="M1326.75,-531.69C1326.75,-534.1 1297.11,-536.06 1260.62,-536.06 1224.14,-536.06 1194.5,-534.1 1194.5,-531.69 1194.5,-531.69 1194.5,-492.31 1194.5,-492.31 1194.5,-489.9 1224.14,-487.94 1260.62,-487.94 1297.11,-487.94 1326.75,-489.9 1326.75,-492.31 1326.75,-492.31 1326.75,-531.69 1326.75,-531.69"/>
160
+ <path fill="none" stroke="#334155" stroke-width="1.4" d="M1326.75,-531.69C1326.75,-529.27 1297.11,-527.31 1260.62,-527.31 1224.14,-527.31 1194.5,-529.27 1194.5,-531.69"/>
161
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-515.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">~/.pwn/cron/log/&lt;id&gt;.log</text>
162
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-501.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">last_run · last_status</text>
163
163
  </g>
164
164
  <!-- Prompt&#45;&gt;Log -->
165
- <g id="edge15" class="edge">
165
+ <g id="edge16" class="edge">
166
166
  <title>Prompt&#45;&gt;Log</title>
167
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M1005.24,-365.47C1067.59,-377.76 1171.46,-398.24 1242.1,-412.16"/>
168
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="1241.52,-414.9 1249.91,-413.7 1242.6,-409.41 1241.52,-414.9"/>
167
+ <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M1003.23,-423.67C1036.26,-435.66 1080.22,-451.46 1119.25,-465 1140.4,-472.34 1163.41,-480.12 1184.57,-487.2"/>
168
+ <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="1183.48,-489.79 1191.96,-489.67 1185.26,-484.48 1183.48,-489.79"/>
169
169
  </g>
170
170
  <!-- Practice -->
171
171
  <g id="node10" class="node">
172
172
  <title>Practice</title>
173
- <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M1379.25,-331.25C1379.25,-331.25 1257.5,-331.25 1257.5,-331.25 1251.5,-331.25 1245.5,-325.25 1245.5,-319.25 1245.5,-319.25 1245.5,-294.75 1245.5,-294.75 1245.5,-288.75 1251.5,-282.75 1257.5,-282.75 1257.5,-282.75 1379.25,-282.75 1379.25,-282.75 1385.25,-282.75 1391.25,-288.75 1391.25,-294.75 1391.25,-294.75 1391.25,-319.25 1391.25,-319.25 1391.25,-325.25 1385.25,-331.25 1379.25,-331.25"/>
174
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-316.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">curriculum_practice_nightly</text>
175
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-303.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">0 3 * * *</text>
176
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-289.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Curriculum.practice(limit:3)</text>
173
+ <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M1321.5,-64.25C1321.5,-64.25 1199.75,-64.25 1199.75,-64.25 1193.75,-64.25 1187.75,-58.25 1187.75,-52.25 1187.75,-52.25 1187.75,-27.75 1187.75,-27.75 1187.75,-21.75 1193.75,-15.75 1199.75,-15.75 1199.75,-15.75 1321.5,-15.75 1321.5,-15.75 1327.5,-15.75 1333.5,-21.75 1333.5,-27.75 1333.5,-27.75 1333.5,-52.25 1333.5,-52.25 1333.5,-58.25 1327.5,-64.25 1321.5,-64.25"/>
174
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-49.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">curriculum_practice_nightly</text>
175
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-36.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">0 3 * * * &#160;OFF</text>
176
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-22.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Curriculum.practice(limit:3)</text>
177
177
  </g>
178
178
  <!-- Ruby&#45;&gt;Practice -->
179
179
  <g id="edge11" class="edge">
180
180
  <title>Ruby&#45;&gt;Practice</title>
181
- <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M1032.73,-288.3C1092.83,-292.25 1174.63,-297.62 1235.12,-301.6"/>
182
- <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1234.89,-304.39 1243.06,-302.12 1235.26,-298.8 1234.89,-304.39"/>
181
+ <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M959.29,-314.45C978.13,-268.16 1033.58,-146.71 1119.25,-83 1136.45,-70.21 1157.51,-61.18 1178.03,-54.82"/>
182
+ <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1178.61,-57.57 1185.51,-52.64 1177.05,-52.19 1178.61,-57.57"/>
183
183
  </g>
184
184
  <!-- Offline -->
185
185
  <g id="node11" class="node">
186
186
  <title>Offline</title>
187
- <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M1372.5,-246.25C1372.5,-246.25 1264.25,-246.25 1264.25,-246.25 1258.25,-246.25 1252.25,-240.25 1252.25,-234.25 1252.25,-234.25 1252.25,-209.75 1252.25,-209.75 1252.25,-203.75 1258.25,-197.75 1264.25,-197.75 1264.25,-197.75 1372.5,-197.75 1372.5,-197.75 1378.5,-197.75 1384.5,-203.75 1384.5,-209.75 1384.5,-209.75 1384.5,-234.25 1384.5,-234.25 1384.5,-240.25 1378.5,-246.25 1372.5,-246.25"/>
188
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-231.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">curriculum_offline_judge</text>
189
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-218.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">30 3 * * *</text>
190
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-204.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Curriculum.offline_judge</text>
187
+ <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M1314.75,-416.25C1314.75,-416.25 1206.5,-416.25 1206.5,-416.25 1200.5,-416.25 1194.5,-410.25 1194.5,-404.25 1194.5,-404.25 1194.5,-379.75 1194.5,-379.75 1194.5,-373.75 1200.5,-367.75 1206.5,-367.75 1206.5,-367.75 1314.75,-367.75 1314.75,-367.75 1320.75,-367.75 1326.75,-373.75 1326.75,-379.75 1326.75,-379.75 1326.75,-404.25 1326.75,-404.25 1326.75,-410.25 1320.75,-416.25 1314.75,-416.25"/>
188
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-401.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">curriculum_offline_judge</text>
189
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-388.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">30 3 * * * &#160;OFF</text>
190
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-374.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Curriculum.offline_judge</text>
191
191
  </g>
192
192
  <!-- Ruby&#45;&gt;Offline -->
193
193
  <g id="edge12" class="edge">
194
194
  <title>Ruby&#45;&gt;Offline</title>
195
- <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M1032.73,-269.54C1095.15,-259.11 1180.97,-244.78 1242.02,-234.58"/>
196
- <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1242.23,-237.39 1249.66,-233.31 1241.31,-231.86 1242.23,-237.39"/>
195
+ <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M1032.92,-348.5C1079.76,-357.49 1138.38,-368.74 1184.27,-377.54"/>
196
+ <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1183.54,-380.25 1191.93,-379.01 1184.6,-374.75 1183.54,-380.25"/>
197
197
  </g>
198
198
  <!-- Train -->
199
199
  <g id="node12" class="node">
200
200
  <title>Train</title>
201
- <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M1378.12,-162C1378.12,-162 1258.62,-162 1258.62,-162 1252.62,-162 1246.62,-156 1246.62,-150 1246.62,-150 1246.62,-112 1246.62,-112 1246.62,-106 1252.62,-100 1258.62,-100 1258.62,-100 1378.12,-100 1378.12,-100 1384.12,-100 1390.12,-106 1390.12,-112 1390.12,-112 1390.12,-150 1390.12,-150 1390.12,-156 1384.12,-162 1378.12,-162"/>
202
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-147.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">curriculum_train_weekly</text>
203
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-134.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">0 4 * * 0</text>
204
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-120.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Curriculum.train_and_gate</text>
205
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-107.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">(dry_run / export_ready)</text>
201
+ <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M1320.38,-332C1320.38,-332 1200.88,-332 1200.88,-332 1194.88,-332 1188.88,-326 1188.88,-320 1188.88,-320 1188.88,-282 1188.88,-282 1188.88,-276 1194.88,-270 1200.88,-270 1200.88,-270 1320.38,-270 1320.38,-270 1326.38,-270 1332.38,-276 1332.38,-282 1332.38,-282 1332.38,-320 1332.38,-320 1332.38,-326 1326.38,-332 1320.38,-332"/>
202
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-317.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">curriculum_train_weekly</text>
203
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-304.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">0 4 * * 0 &#160;OFF</text>
204
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-290.55" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Curriculum.train_and_gate</text>
205
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-277.05" font-family="sans-Serif" font-size="11.00" fill="#0f172a">(dry_run / export_ready)</text>
206
206
  </g>
207
207
  <!-- Ruby&#45;&gt;Train -->
208
208
  <g id="edge13" class="edge">
209
209
  <title>Ruby&#45;&gt;Train</title>
210
- <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M976.84,-264.34C1008.33,-241.38 1065.2,-202.69 1119.25,-180 1156.44,-164.39 1199.73,-152.97 1236.34,-145.11"/>
211
- <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1236.8,-147.87 1244.06,-143.49 1235.65,-142.39 1236.8,-147.87"/>
210
+ <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M1032.92,-324.59C1077.84,-319.92 1133.59,-314.12 1178.56,-309.44"/>
211
+ <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1178.65,-312.24 1186.32,-308.63 1178.07,-306.67 1178.65,-312.24"/>
212
212
  </g>
213
213
  <!-- MemGC -->
214
214
  <g id="node13" class="node">
215
215
  <title>MemGC</title>
216
- <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M1381.88,-64.25C1381.88,-64.25 1254.88,-64.25 1254.88,-64.25 1248.88,-64.25 1242.88,-58.25 1242.88,-52.25 1242.88,-52.25 1242.88,-27.75 1242.88,-27.75 1242.88,-21.75 1248.88,-15.75 1254.88,-15.75 1254.88,-15.75 1381.88,-15.75 1381.88,-15.75 1387.88,-15.75 1393.88,-21.75 1393.88,-27.75 1393.88,-27.75 1393.88,-52.25 1393.88,-52.25 1393.88,-58.25 1387.88,-64.25 1381.88,-64.25"/>
217
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-49.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">learning_consolidate_nightly</text>
218
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-36.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">0 5 * * *</text>
219
- <text xml:space="preserve" text-anchor="middle" x="1318.38" y="-22.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Learning.consolidate</text>
216
+ <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M1324.12,-234.25C1324.12,-234.25 1197.12,-234.25 1197.12,-234.25 1191.12,-234.25 1185.12,-228.25 1185.12,-222.25 1185.12,-222.25 1185.12,-197.75 1185.12,-197.75 1185.12,-191.75 1191.12,-185.75 1197.12,-185.75 1197.12,-185.75 1324.12,-185.75 1324.12,-185.75 1330.12,-185.75 1336.12,-191.75 1336.12,-197.75 1336.12,-197.75 1336.12,-222.25 1336.12,-222.25 1336.12,-228.25 1330.12,-234.25 1324.12,-234.25"/>
217
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-219.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">learning_consolidate_nightly</text>
218
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-206.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">0 5 * * * &#160;ON</text>
219
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-192.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Learning.consolidate</text>
220
220
  </g>
221
221
  <!-- Ruby&#45;&gt;MemGC -->
222
222
  <g id="edge14" class="edge">
223
223
  <title>Ruby&#45;&gt;MemGC</title>
224
- <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M961.79,-264.48C983.83,-224.24 1041.93,-128.67 1119.25,-82 1153.24,-61.49 1195.79,-50.9 1232.73,-45.47"/>
225
- <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1233,-48.26 1240.54,-44.4 1232.24,-42.71 1233,-48.26"/>
224
+ <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M986.29,-314.43C1019.57,-296.83 1071.92,-270.41 1119.25,-252 1137.1,-245.06 1156.59,-238.57 1175.21,-232.86"/>
225
+ <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1175.83,-235.6 1182.68,-230.61 1174.21,-230.24 1175.83,-235.6"/>
226
+ </g>
227
+ <!-- Lean -->
228
+ <g id="node14" class="node">
229
+ <title>Lean</title>
230
+ <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M1315.88,-149.25C1315.88,-149.25 1205.38,-149.25 1205.38,-149.25 1199.38,-149.25 1193.38,-143.25 1193.38,-137.25 1193.38,-137.25 1193.38,-112.75 1193.38,-112.75 1193.38,-106.75 1199.38,-100.75 1205.38,-100.75 1205.38,-100.75 1315.88,-100.75 1315.88,-100.75 1321.88,-100.75 1327.88,-106.75 1327.88,-112.75 1327.88,-112.75 1327.88,-137.25 1327.88,-137.25 1327.88,-143.25 1321.88,-149.25 1315.88,-149.25"/>
231
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-134.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">pwn_stores_lean_nightly</text>
232
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-121.3" font-family="sans-Serif" font-size="11.00" fill="#0f172a">15 5 * * * &#160;ON</text>
233
+ <text xml:space="preserve" text-anchor="middle" x="1260.62" y="-107.8" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Learning.gc_stores!</text>
234
+ </g>
235
+ <!-- Ruby&#45;&gt;Lean -->
236
+ <g id="edge15" class="edge">
237
+ <title>Ruby&#45;&gt;Lean</title>
238
+ <path fill="none" stroke="#a78bfa" stroke-width="1.3" d="M965.84,-314.48C991.95,-280.5 1052.2,-208.02 1119.25,-168 1138.79,-156.34 1161.78,-147.58 1183.43,-141.12"/>
239
+ <polygon fill="#a78bfa" stroke="#a78bfa" stroke-width="1.3" points="1184.12,-143.83 1191.05,-138.94 1182.58,-138.45 1184.12,-143.83"/>
226
240
  </g>
227
241
  <!-- Ruby&#45;&gt;Log -->
228
- <g id="edge16" class="edge">
242
+ <g id="edge17" class="edge">
229
243
  <title>Ruby&#45;&gt;Log</title>
230
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M1004.49,-301.68C1016.54,-306.71 1029.08,-312.56 1040.25,-319 1078.69,-341.14 1079.21,-360.9 1119.25,-380 1157.78,-398.39 1204.05,-409.88 1242.18,-416.9"/>
231
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="1241.39,-419.6 1249.75,-418.25 1242.36,-414.09 1241.39,-419.6"/>
244
+ <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M1009.34,-351.53C1020.13,-356.34 1030.94,-362.14 1040.25,-369 1084.73,-401.78 1073.73,-433.68 1119.25,-465 1138.7,-478.38 1162.27,-488.22 1184.5,-495.32"/>
245
+ <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="1183.58,-497.97 1192.05,-497.62 1185.21,-492.61 1183.58,-497.97"/>
232
246
  </g>
233
247
  <!-- Script&#45;&gt;Log -->
234
- <g id="edge17" class="edge">
248
+ <g id="edge18" class="edge">
235
249
  <title>Script&#45;&gt;Log</title>
236
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M1006.81,-427C1069.34,-427 1172.09,-427 1242.14,-427"/>
237
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="1241.84,-429.8 1249.84,-427 1241.84,-424.2 1241.84,-429.8"/>
250
+ <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M1006.75,-483.22C1056.16,-488.84 1129.38,-497.18 1184.34,-503.43"/>
251
+ <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="1183.81,-506.19 1192.08,-504.31 1184.44,-500.62 1183.81,-506.19"/>
238
252
  </g>
239
253
  <!-- Practice&#45;&gt;Log -->
240
- <g id="edge19" class="edge">
254
+ <g id="edge20" class="edge">
241
255
  <title>Practice&#45;&gt;Log</title>
242
- <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1318.38,-331.84C1318.38,-352.07 1318.38,-372.31 1318.38,-392.54"/>
243
- <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="1315.58,-392.5 1318.38,-400.5 1321.18,-392.5 1315.58,-392.5"/>
256
+ <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1187.4,-43.74C1147.92,-50.07 1102.7,-65.32 1079.75,-101 1038.15,-165.67 1038.15,-382.33 1079.75,-447 1102.22,-481.93 1145.59,-498.26 1184.23,-505.82"/>
257
+ <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="1183.63,-508.55 1191.99,-507.21 1184.61,-503.04 1183.63,-508.55"/>
244
258
  </g>
245
259
  <!-- Offline&#45;&gt;Log -->
246
- <g id="edge20" class="edge">
260
+ <g id="edge21" class="edge">
247
261
  <title>Offline&#45;&gt;Log</title>
248
- <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1251.6,-216.96C1194.23,-216.83 1115.32,-227.71 1079.75,-283 1060.76,-312.53 1060.76,-332.47 1079.75,-362 1113.44,-414.38 1185.55,-428.27 1241.74,-430.47"/>
249
- <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="1241.63,-433.27 1249.71,-430.69 1241.79,-427.67 1241.63,-433.27"/>
262
+ <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1260.62,-416.84C1260.62,-437.07 1260.62,-457.31 1260.62,-477.54"/>
263
+ <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="1257.83,-477.5 1260.63,-485.5 1263.43,-477.5 1257.83,-477.5"/>
250
264
  </g>
251
265
  <!-- Train&#45;&gt;Log -->
252
- <g id="edge21" class="edge">
266
+ <g id="edge22" class="edge">
253
267
  <title>Train&#45;&gt;Log</title>
254
- <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1246.05,-128.08C1189.33,-130.27 1114.38,-144.17 1079.75,-198 1040.32,-259.3 1040.32,-300.7 1079.75,-362 1113.44,-414.38 1185.55,-428.27 1241.74,-430.47"/>
255
- <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="1241.63,-433.27 1249.71,-430.69 1241.79,-427.67 1241.63,-433.27"/>
268
+ <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1188.5,-307.28C1148.87,-314.94 1103.12,-331.67 1079.75,-368 1060.76,-397.53 1060.76,-417.47 1079.75,-447 1102.22,-481.93 1145.59,-498.26 1184.23,-505.82"/>
269
+ <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="1183.63,-508.55 1191.99,-507.21 1184.61,-503.04 1183.63,-508.55"/>
256
270
  </g>
257
271
  <!-- MemGC&#45;&gt;Log -->
258
- <g id="edge22" class="edge">
272
+ <g id="edge23" class="edge">
259
273
  <title>MemGC&#45;&gt;Log</title>
260
- <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1242.46,-34.66C1186.11,-35.45 1113.43,-47.64 1079.75,-100 1048.25,-148.97 1048.25,-313.03 1079.75,-362 1113.44,-414.38 1185.55,-428.27 1241.74,-430.47"/>
261
- <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="1241.63,-433.27 1249.71,-430.69 1241.79,-427.67 1241.63,-433.27"/>
274
+ <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1184.58,-213.73C1145.77,-220.1 1102.12,-235.22 1079.75,-270 1037.19,-336.16 1037.19,-380.84 1079.75,-447 1102.22,-481.93 1145.59,-498.26 1184.23,-505.82"/>
275
+ <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="1183.63,-508.55 1191.99,-507.21 1184.61,-503.04 1183.63,-508.55"/>
276
+ </g>
277
+ <!-- Lean&#45;&gt;Log -->
278
+ <g id="edge24" class="edge">
279
+ <title>Lean&#45;&gt;Log</title>
280
+ <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1192.91,-127.91C1152.2,-133.69 1103.77,-148.65 1079.75,-186 1048.37,-234.78 1048.37,-398.22 1079.75,-447 1102.22,-481.93 1145.59,-498.26 1184.23,-505.82"/>
281
+ <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="1183.63,-508.55 1191.99,-507.21 1184.61,-503.04 1183.63,-508.55"/>
262
282
  </g>
263
283
  <!-- Log&#45;&gt;Jobs -->
264
- <g id="edge18" class="edge">
284
+ <g id="edge19" class="edge">
265
285
  <title>Log&#45;&gt;Jobs</title>
266
- <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1251.77,-424.28C1210.35,-419.64 1157.61,-408.1 1119.25,-380 1064.09,-339.6 1099.73,-281.72 1040.25,-248 971.33,-208.93 940.45,-236.97 862,-248 748.68,-263.93 712.79,-260.4 614.5,-319 588.86,-334.29 594.67,-354.62 567.5,-367 530.84,-383.71 485.78,-386.7 449.32,-385.39"/>
267
- <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="449.85,-382.61 441.73,-385.04 449.59,-388.21 449.85,-382.61"/>
268
- <text xml:space="preserve" text-anchor="middle" x="795.62" y="-262.32" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">update status</text>
286
+ <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M1193.93,-501.51C1168.23,-494.67 1140.01,-483.43 1119.25,-465 1057.85,-410.49 1109.62,-341.93 1040.25,-298 973.32,-255.62 940.45,-286.97 862,-298 748.68,-313.93 712.79,-310.4 614.5,-369 588.86,-384.29 594.67,-404.62 567.5,-417 530.84,-433.71 485.78,-436.7 449.32,-435.39"/>
287
+ <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="449.85,-432.61 441.73,-435.04 449.59,-438.21 449.85,-432.61"/>
288
+ <text xml:space="preserve" text-anchor="middle" x="795.62" y="-312.32" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">update status</text>
269
289
  </g>
270
290
  </g>
271
291
  </svg>
@@ -1,6 +1,6 @@
1
1
  digraph "PWN_Agent_Tool_Registry" {
2
2
  graph [
3
- label=<<B>PWN::AI::Agent::Registry - Toolsets exposed to the LLM</B><BR/><FONT POINT-SIZE="11" COLOR="#94a3b8">13 toolsets · 85 callable tools · lib/pwn/ai/agent/tools/*</FONT>>,
3
+ label=<<B>PWN::AI::Agent::Registry - Toolsets exposed to the LLM</B><BR/><FONT POINT-SIZE="11" COLOR="#94a3b8">13 toolsets · 87 callable tools · lib/pwn/ai/agent/tools/*</FONT>>,
4
4
  labelloc=t, fontsize=20, fontname="Helvetica",
5
5
  rankdir=LR, splines=spline, nodesep=0.35, ranksep=1.4,
6
6
  bgcolor="#0f172a", fontcolor="#e2e8f0", pad=0.6, newrank=true
@@ -9,7 +9,7 @@ digraph "PWN_Agent_Tool_Registry" {
9
9
  shape=box, penwidth=1.3, color="#334155", fontcolor="#0f172a"];
10
10
  edge [color="#94a3b8", penwidth=1.1, arrowsize=0.7];
11
11
 
12
- Registry [label="Registry\nJSON-Schema function defs\nrank(query) · CORE_TOOLS\ntool_router → CORE + top-K\ntool_preference (memory_recall first)", fillcolor="#c4b5fd", fontsize=12, penwidth=2];
12
+ Registry [label="Registry\nJSON-Schema function defs\nrank(query) · CORE_TOOLS\ntool_router → CORE + top-K\ntool_preference (CORE_TOOLS order)", fillcolor="#c4b5fd", fontsize=12, penwidth=2];
13
13
 
14
14
  subgraph cluster_ts {
15
15
  label="Toolsets"; fontcolor="#a7f3d0"; style=rounded;
@@ -36,8 +36,8 @@ digraph "PWN_Agent_Tool_Registry" {
36
36
  t_shell [label="shell\n(ToolGuard)"];
37
37
  t_eval [label="pwn_eval\n(ToolGuard)"];
38
38
  t_mem [label="memory_remember\nrecall · forget · clear\nlean"];
39
- t_skill [label="skill_list · view · create\nadd_reference · delete\nmigrate_legacy"];
40
- t_sess [label="sessions_list · view\ncurrent · delete · stats\nlean"];
39
+ t_skill [label="skills_recall · skill_list\nview · create · add_reference\ndelete · migrate_legacy"];
40
+ t_sess [label="session_recall · sessions_list\nview · current · delete\nstats · lean"];
41
41
  t_learn [label="learning_* · mistakes_*\nreward_judge · prm · sentinel\nexport_dpo · scrub · balance\ncurriculum_practice · train\nhindsight · offline_judge\ngc_stores · lean helpers"];
42
42
  t_metric [label="metrics_summary\nmetrics_reset"];
43
43
  t_extro [label="extro_snapshot · drift\nobserve · observations · intel\nwatch · verify · rf_tune · osint\nserial · telecomm · packet\nvision · voice · correlate\nstats · reset · auto_toggle"];