pwn 0.5.781 → 0.5.783

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/Installation.md +33 -9
  3. data/documentation/diagrams/dot/extrospection-world-awareness.dot +37 -92
  4. data/documentation/diagrams/dot/memory-skills-detailed.dot +33 -98
  5. data/documentation/diagrams/dot/overall-pwn-architecture.dot +54 -32
  6. data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +53 -30
  7. data/documentation/diagrams/dot/reinforcement-learning.dot +46 -111
  8. data/documentation/diagrams/dot/swarm-multi-agent.dot +36 -61
  9. data/documentation/diagrams/extrospection-world-awareness.svg +139 -510
  10. data/documentation/diagrams/memory-skills-detailed.svg +126 -475
  11. data/documentation/diagrams/overall-pwn-architecture.svg +116 -266
  12. data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +158 -244
  13. data/documentation/diagrams/reinforcement-learning.svg +238 -529
  14. data/documentation/diagrams/swarm-multi-agent.svg +104 -233
  15. data/documentation/pwn-REPL.md +31 -3
  16. data/documentation/pwn-ai-Agent.md +62 -2
  17. data/etc/default_cron/session_cleanup.rb +335 -42
  18. data/lib/pwn/ai/agent/curriculum.rb +2 -2
  19. data/lib/pwn/ai/agent/learning.rb +11 -4
  20. data/lib/pwn/ai/agent/mistakes.rb +22 -3
  21. data/lib/pwn/ai/agent/tools/sessions.rb +6 -6
  22. data/lib/pwn/ai/http_retry.rb +3 -0
  23. data/lib/pwn/ai/router.rb +3 -1
  24. data/lib/pwn/cron.rb +1 -1
  25. data/lib/pwn/memory.rb +62 -6
  26. data/lib/pwn/plugins/repl/ai.rb +13 -3
  27. data/lib/pwn/plugins/repl/ai_console.rb +37 -21
  28. data/lib/pwn/session_trace.rb +1 -1
  29. data/lib/pwn/sessions.rb +305 -80
  30. data/lib/pwn/version.rb +1 -1
  31. data/spec/lib/pwn/ai/agent/learning_spec.rb +65 -2
  32. data/spec/lib/pwn/ai/agent/swarm_spec.rb +3 -3
  33. data/spec/lib/pwn/memory_spec.rb +58 -1
  34. data/spec/lib/pwn/plugins/repl/ai_console_spec.rb +191 -6
  35. data/spec/lib/pwn/plugins/repl/ai_result_chronology_spec.rb +2 -2
  36. data/spec/lib/pwn/plugins/repl/ai_spec.rb +28 -11
  37. data/spec/lib/pwn/session_cleanup_default_spec.rb +2 -2
  38. data/spec/lib/pwn/session_cleanup_payload_spec.rb +467 -36
  39. data/spec/lib/pwn/sessions_spec.rb +116 -16
  40. data/third_party/pwn_rdoc.jsonl +12 -0
  41. metadata +1 -1
@@ -4,259 +4,130 @@
4
4
  <!-- Generated by graphviz version 14.1.2 (0)
5
5
  -->
6
6
  <!-- Title: PWN_Swarm Pages: 1 -->
7
- <svg width="1094pt" height="604pt"
8
- viewBox="0.00 0.00 1094.00 604.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 560.58)">
7
+ <svg width="819pt" height="545pt"
8
+ viewBox="0.00 0.00 819.00 545.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(28.8 516.67)">
10
10
  <title>PWN_Swarm</title>
11
- <polygon fill="#0f172a" stroke="none" points="-43.2,43.2 -43.2,-560.58 1050.67,-560.58 1050.67,43.2 -43.2,43.2"/>
12
- <text xml:space="preserve" text-anchor="start" x="225.86" y="-495.38" font-family="sans-Serif" font-weight="bold" font-size="20.00" fill="#e2e8f0">PWN::AI::Agent::Swarm &#45; Native Multi&#45;Agent Orchestration</text>
13
- <text xml:space="preserve" text-anchor="start" x="356.36" y="-483.93" font-family="sans-Serif" font-size="11.00" fill="#94a3b8">personas · ask · debate · broadcast · shared bus (no daemon)</text>
11
+ <polygon fill="#0f172a" stroke="none" points="-28.8,28.8 -28.8,-516.67 789.8,-516.67 789.8,28.8 -28.8,28.8"/>
12
+ <text xml:space="preserve" text-anchor="start" x="102.62" y="-465.87" font-family="sans-Serif" font-weight="bold" font-size="20.00" fill="#e2e8f0">PWN::AI::Agent::Swarm &#45; Native Multi&#45;Agent Orchestration</text>
13
+ <text xml:space="preserve" text-anchor="start" x="233.12" y="-454.42" font-family="sans-Serif" font-size="11.00" fill="#94a3b8">personas · ask / debate / broadcast · shared bus (no daemon)</text>
14
+ <g id="clust1" class="cluster">
15
+ <title>cluster_explicit</title>
16
+ <path fill="#1e293b" stroke="#334155" d="M20,-325.58C20,-325.58 336,-325.58 336,-325.58 342,-325.58 348,-331.58 348,-337.58 348,-337.58 348,-428.87 348,-428.87 348,-434.87 342,-440.87 336,-440.87 336,-440.87 20,-440.87 20,-440.87 14,-440.87 8,-434.87 8,-428.87 8,-428.87 8,-337.58 8,-337.58 8,-331.58 14,-325.58 20,-325.58"/>
17
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-425.47" font-family="sans-Serif" font-size="12.00" fill="#e2e8f0">EXPLICIT DELEGATION &#160;· &#160;operator / calling agent</text>
18
+ </g>
14
19
  <g id="clust2" class="cluster">
15
- <title>cluster_verbs</title>
16
- <path fill="#2e1065" stroke="#6d28d9" stroke-width="2" d="M20,-292.12C20,-292.12 739,-292.12 739,-292.12 745,-292.12 751,-298.12 751,-304.12 751,-304.12 751,-375.88 751,-375.88 751,-381.88 745,-387.88 739,-387.88 739,-387.88 20,-387.88 20,-387.88 14,-387.88 8,-381.88 8,-375.88 8,-375.88 8,-304.12 8,-304.12 8,-298.12 14,-292.12 20,-292.12"/>
17
- <text xml:space="preserve" text-anchor="middle" x="379.5" y="-364.88" font-family="sans-Serif" font-size="20.00" fill="#ddd6fe">Swarm Verbs &#160;(toolset: swarm)</text>
20
+ <title>cluster_escalation</title>
21
+ <path fill="#1e293b" stroke="#94a3b8" stroke-dasharray="5,2" d="M380,-325.58C380,-325.58 696,-325.58 696,-325.58 702,-325.58 708,-331.58 708,-337.58 708,-337.58 708,-428.87 708,-428.87 708,-434.87 702,-440.87 696,-440.87 696,-440.87 380,-440.87 380,-440.87 374,-440.87 368,-434.87 368,-428.87 368,-428.87 368,-337.58 368,-337.58 368,-331.58 374,-325.58 380,-325.58"/>
22
+ <text xml:space="preserve" text-anchor="middle" x="538" y="-425.47" font-family="sans-Serif" font-size="12.00" fill="#e2e8f0">CONDITIONAL ESCALATION &#160;· &#160;private Loop path</text>
18
23
  </g>
19
24
  <g id="clust4" class="cluster">
20
- <title>cluster_personas</title>
21
- <path fill="#022c22" stroke="#047857" stroke-width="2" d="M107,-149.88C107,-149.88 749,-149.88 749,-149.88 755,-149.88 761,-155.88 761,-161.88 761,-161.88 761,-233.62 761,-233.62 761,-239.62 755,-245.62 749,-245.62 749,-245.62 107,-245.62 107,-245.62 101,-245.62 95,-239.62 95,-233.62 95,-233.62 95,-161.88 95,-161.88 95,-155.88 101,-149.88 107,-149.88"/>
22
- <text xml:space="preserve" text-anchor="middle" x="428" y="-222.62" font-family="sans-Serif" font-size="20.00" fill="#a7f3d0">Illustrative personas (each = nested Loop; not completion proof)</text>
25
+ <title>cluster_runtime</title>
26
+ <path fill="#1e293b" stroke="#334155" d="M20,-166.79C20,-166.79 336,-166.79 336,-166.79 342,-166.79 348,-172.79 348,-178.79 348,-178.79 348,-283.58 348,-283.58 348,-289.58 342,-295.58 336,-295.58 336,-295.58 20,-295.58 20,-295.58 14,-295.58 8,-289.58 8,-283.58 8,-283.58 8,-178.79 8,-178.79 8,-172.79 14,-166.79 20,-166.79"/>
27
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-280.18" font-family="sans-Serif" font-size="12.00" fill="#e2e8f0">EXECUTION OWNER &#160;· &#160;Swarm.ask → nested Loop</text>
23
28
  </g>
24
29
  <g id="clust6" class="cluster">
30
+ <title>cluster_handoff</title>
31
+ <path fill="#1e293b" stroke="#334155" d="M20,-8C20,-8 336,-8 336,-8 342,-8 348,-14 348,-20 348,-20 348,-124.79 348,-124.79 348,-130.79 342,-136.79 336,-136.79 336,-136.79 20,-136.79 20,-136.79 14,-136.79 8,-130.79 8,-124.79 8,-124.79 8,-20 8,-20 8,-14 14,-8 20,-8"/>
32
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-121.39" font-family="sans-Serif" font-size="12.00" fill="#e2e8f0">RESULT BOUNDARY &#160;· &#160;calling runtime retains responsibility</text>
33
+ </g>
34
+ <g id="clust7" class="cluster">
25
35
  <title>cluster_state</title>
26
- <path fill="#422006" stroke="#a16207" stroke-width="2" d="M120,-8C120,-8 729,-8 729,-8 735,-8 741,-14 741,-20 741,-20 741,-91.38 741,-91.38 741,-97.38 735,-103.38 729,-103.38 729,-103.38 120,-103.38 120,-103.38 114,-103.38 108,-97.38 108,-91.38 108,-91.38 108,-20 108,-20 108,-14 114,-8 120,-8"/>
27
- <text xml:space="preserve" text-anchor="middle" x="424.5" y="-80.38" font-family="sans-Serif" font-size="20.00" fill="#fde68a">Shared State &#160;~/.pwn/</text>
36
+ <path fill="#1e293b" stroke="#334155" d="M380,-8C380,-8 696,-8 696,-8 702,-8 708,-14 708,-20 708,-20 708,-124.79 708,-124.79 708,-130.79 702,-136.79 696,-136.79 696,-136.79 380,-136.79 380,-136.79 374,-136.79 368,-130.79 368,-124.79 368,-124.79 368,-20 368,-20 368,-14 374,-8 380,-8"/>
37
+ <text xml:space="preserve" text-anchor="middle" x="538" y="-121.39" font-family="sans-Serif" font-size="12.00" fill="#e2e8f0">CONTINUITY &#160;· &#160;~/.pwn/</text>
28
38
  </g>
29
- <!-- Orchestrator -->
39
+ <!-- Entry -->
30
40
  <g id="node1" class="node">
31
- <title>Orchestrator</title>
32
- <path fill="#7dd3fc" stroke="#334155" stroke-width="1.4" d="M279.75,-478.38C279.75,-478.38 208.25,-478.38 208.25,-478.38 202.25,-478.38 196.25,-472.38 196.25,-466.38 196.25,-466.38 196.25,-454.38 196.25,-454.38 196.25,-448.38 202.25,-442.38 208.25,-442.38 208.25,-442.38 279.75,-442.38 279.75,-442.38 285.75,-442.38 291.75,-448.38 291.75,-454.38 291.75,-454.38 291.75,-466.38 291.75,-466.38 291.75,-472.38 285.75,-478.38 279.75,-478.38"/>
33
- <text xml:space="preserve" text-anchor="middle" x="244" y="-463.43" font-family="sans-Serif" font-size="11.00" fill="#0f172a">👤 &#160;Orchestrator</text>
34
- <text xml:space="preserve" text-anchor="middle" x="244" y="-449.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">(you, in pwn&#45;ai)</text>
35
- </g>
36
- <!-- Spawn -->
41
+ <title>Entry</title>
42
+ <path fill="#7dd3fc" stroke="#334155" stroke-width="1.3" d="M328,-410.62C328,-410.62 28,-410.62 28,-410.62 22,-410.62 16,-404.62 16,-398.62 16,-398.62 16,-345.58 16,-345.58 16,-339.58 22,-333.58 28,-333.58 28,-333.58 328,-333.58 328,-333.58 334,-333.58 340,-339.58 340,-345.58 340,-345.58 340,-398.62 340,-398.62 340,-404.62 334,-410.62 328,-410.62"/>
43
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-388.65" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Choose target persona(s) + request in pwn&#45;ai</text>
44
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-375.15" font-family="sans-Serif" font-size="11.00" fill="#0f172a">agent_ask: one turn / one persona</text>
45
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-361.65" font-family="sans-Serif" font-size="11.00" fill="#0f172a">agent_debate: ordered round&#45;robin critique</text>
46
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-348.15" font-family="sans-Serif" font-size="11.00" fill="#0f172a">agent_broadcast: parallel fan&#45;out ensemble</text>
47
+ </g>
48
+ <!-- Run -->
37
49
  <g id="node3" class="node">
38
- <title>Spawn</title>
39
- <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M91.62,-342.38C91.62,-342.38 28.38,-342.38 28.38,-342.38 22.38,-342.38 16.38,-336.38 16.38,-330.38 16.38,-330.38 16.38,-318.38 16.38,-318.38 16.38,-312.38 22.38,-306.38 28.38,-306.38 28.38,-306.38 91.62,-306.38 91.62,-306.38 97.62,-306.38 103.62,-312.38 103.62,-318.38 103.62,-318.38 103.62,-330.38 103.62,-330.38 103.62,-336.38 97.62,-342.38 91.62,-342.38"/>
40
- <text xml:space="preserve" text-anchor="middle" x="60" y="-327.43" font-family="sans-Serif" font-size="11.00" fill="#0f172a">agent_spawn</text>
41
- <text xml:space="preserve" text-anchor="middle" x="60" y="-313.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">define persona</text>
42
- </g>
43
- <!-- Orchestrator&#45;&gt;Spawn -->
50
+ <title>Run</title>
51
+ <path fill="#6ee7b7" stroke="#334155" stroke-width="1.3" d="M328,-265.33C328,-265.33 28,-265.33 28,-265.33 22,-265.33 16,-259.33 16,-253.33 16,-253.33 16,-186.79 16,-186.79 16,-180.79 22,-174.79 28,-174.79 28,-174.79 328,-174.79 328,-174.79 334,-174.79 340,-180.79 340,-186.79 340,-186.79 340,-253.33 340,-253.33 340,-259.33 334,-265.33 328,-265.33"/>
52
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-243.36" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Select persona engine / model / skills / toolsets</text>
53
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-229.86" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Per&#45;persona session + recursion&#45;depth guard</text>
54
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-216.36" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Append request; run nested Loop; append reply</text>
55
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-202.86" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Tools remain behind Dispatch / confirmation / sandbox</text>
56
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-189.36" font-family="sans-Serif" font-size="11.00" fill="#0f172a">No daemon and no fixed provider&#45;to&#45;role assignment</text>
57
+ </g>
58
+ <!-- Entry&#45;&gt;Run -->
44
59
  <g id="edge1" class="edge">
45
- <title>Orchestrator&#45;&gt;Spawn</title>
46
- <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M211.33,-441.77C187.21,-428.22 154.01,-408.39 127,-387.88 111.75,-376.29 96.03,-361.78 83.65,-349.66"/>
47
- <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="85.82,-347.87 78.17,-344.23 81.88,-351.85 85.82,-347.87"/>
60
+ <title>Entry&#45;&gt;Run</title>
61
+ <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M178,-325.58C178,-319.11 178,-312.28 178,-305.35"/>
62
+ <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="180.8,-305.55 178,-297.55 175.2,-305.55 180.8,-305.55"/>
63
+ <text xml:space="preserve" text-anchor="middle" x="230.88" y="-306.08" font-family="sans-Serif" font-size="10.00" fill="#cbd5e1">ask / debate / broadcast</text>
48
64
  </g>
49
- <!-- Ask -->
50
- <g id="node4" class="node">
51
- <title>Ask</title>
52
- <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M247.5,-342.38C247.5,-342.38 162.5,-342.38 162.5,-342.38 156.5,-342.38 150.5,-336.38 150.5,-330.38 150.5,-330.38 150.5,-318.38 150.5,-318.38 150.5,-312.38 156.5,-306.38 162.5,-306.38 162.5,-306.38 247.5,-306.38 247.5,-306.38 253.5,-306.38 259.5,-312.38 259.5,-318.38 259.5,-318.38 259.5,-330.38 259.5,-330.38 259.5,-336.38 253.5,-342.38 247.5,-342.38"/>
53
- <text xml:space="preserve" text-anchor="middle" x="205" y="-327.43" font-family="sans-Serif" font-size="11.00" fill="#0f172a">agent_ask</text>
54
- <text xml:space="preserve" text-anchor="middle" x="205" y="-313.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">1 turn → 1 persona</text>
65
+ <!-- Escalate -->
66
+ <g id="node2" class="node">
67
+ <title>Escalate</title>
68
+ <path fill="#c4b5fd" stroke="#334155" stroke-width="1.3" d="M688,-410.62C688,-410.62 388,-410.62 388,-410.62 382,-410.62 376,-404.62 376,-398.62 376,-398.62 376,-345.58 376,-345.58 376,-339.58 382,-333.58 388,-333.58 388,-333.58 688,-333.58 688,-333.58 694,-333.58 700,-339.58 700,-345.58 700,-345.58 700,-398.62 700,-398.62 700,-404.62 694,-410.62 688,-410.62"/>
69
+ <text xml:space="preserve" text-anchor="middle" x="538" y="-388.65" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Local Loop is stuck beyond failure threshold</text>
70
+ <text xml:space="preserve" text-anchor="middle" x="538" y="-375.15" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Configured escalation_persona must exist</text>
71
+ <text xml:space="preserve" text-anchor="middle" x="538" y="-361.65" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Ask for a short frontier corrective hint</text>
72
+ <text xml:space="preserve" text-anchor="middle" x="538" y="-348.15" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Local model still owns its final answer</text>
55
73
  </g>
56
- <!-- Orchestrator&#45;&gt;Ask -->
74
+ <!-- Escalate&#45;&gt;Run -->
57
75
  <g id="edge2" class="edge">
58
- <title>Orchestrator&#45;&gt;Ask</title>
59
- <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M238.9,-441.86C232.27,-419.09 220.63,-379.08 212.87,-352.41"/>
60
- <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="215.57,-351.69 210.65,-344.79 210.2,-353.25 215.57,-351.69"/>
76
+ <title>Escalate&#45;&gt;Run</title>
77
+ <path fill="none" stroke="#94a3b8" stroke-width="1.3" stroke-dasharray="5,2" d="M428.79,-325.58C406.1,-316.13 381.63,-305.93 357.18,-295.74"/>
78
+ <polygon fill="#94a3b8" stroke="#94a3b8" stroke-width="1.3" points="358.28,-293.16 349.81,-292.67 356.12,-298.33 358.28,-293.16"/>
79
+ <text xml:space="preserve" text-anchor="middle" x="451.08" y="-306.08" font-family="sans-Serif" font-size="10.00" fill="#cbd5e1">conditional hint request</text>
61
80
  </g>
62
- <!-- Debate -->
81
+ <!-- Result -->
63
82
  <g id="node5" class="node">
64
- <title>Debate</title>
65
- <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M403.5,-342.38C403.5,-342.38 318.5,-342.38 318.5,-342.38 312.5,-342.38 306.5,-336.38 306.5,-330.38 306.5,-330.38 306.5,-318.38 306.5,-318.38 306.5,-312.38 312.5,-306.38 318.5,-306.38 318.5,-306.38 403.5,-306.38 403.5,-306.38 409.5,-306.38 415.5,-312.38 415.5,-318.38 415.5,-318.38 415.5,-330.38 415.5,-330.38 415.5,-336.38 409.5,-342.38 403.5,-342.38"/>
66
- <text xml:space="preserve" text-anchor="middle" x="361" y="-327.43" font-family="sans-Serif" font-size="11.00" fill="#0f172a">agent_debate</text>
67
- <text xml:space="preserve" text-anchor="middle" x="361" y="-313.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">round&#45;robin critique</text>
68
- </g>
69
- <!-- Orchestrator&#45;&gt;Debate -->
70
- <g id="edge3" class="edge">
71
- <title>Orchestrator&#45;&gt;Debate</title>
72
- <path fill="none" stroke="#38bdf8" stroke-width="2" d="M259.3,-441.86C279.53,-418.68 315.34,-377.67 338.62,-351.01"/>
73
- <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="2" points="340.56,-353.05 343.71,-345.18 336.34,-349.36 340.56,-353.05"/>
74
- </g>
75
- <!-- Broadcast -->
76
- <g id="node6" class="node">
77
- <title>Broadcast</title>
78
- <path fill="#c4b5fd" stroke="#334155" stroke-width="1.4" d="M549.62,-342.38C549.62,-342.38 474.38,-342.38 474.38,-342.38 468.38,-342.38 462.38,-336.38 462.38,-330.38 462.38,-330.38 462.38,-318.38 462.38,-318.38 462.38,-312.38 468.38,-306.38 474.38,-306.38 474.38,-306.38 549.62,-306.38 549.62,-306.38 555.62,-306.38 561.62,-312.38 561.62,-318.38 561.62,-318.38 561.62,-330.38 561.62,-330.38 561.62,-336.38 555.62,-342.38 549.62,-342.38"/>
79
- <text xml:space="preserve" text-anchor="middle" x="512" y="-327.43" font-family="sans-Serif" font-size="11.00" fill="#0f172a">agent_broadcast</text>
80
- <text xml:space="preserve" text-anchor="middle" x="512" y="-313.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">fan&#45;out ensemble</text>
81
- </g>
82
- <!-- Orchestrator&#45;&gt;Broadcast -->
83
+ <title>Result</title>
84
+ <path fill="#c4b5fd" stroke="#334155" stroke-width="1.3" d="M328,-106.54C328,-106.54 28,-106.54 28,-106.54 22,-106.54 16,-100.54 16,-94.54 16,-94.54 16,-28 16,-28 16,-22 22,-16 28,-16 28,-16 328,-16 328,-16 334,-16 340,-22 340,-28 340,-28 340,-94.54 340,-94.54 340,-100.54 334,-106.54 328,-106.54"/>
85
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-84.57" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Return reply + session ID + child inbox / honesty data</text>
86
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-71.07" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Debate passes the prior speaker&#39;s response onward</text>
87
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-57.57" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Broadcast collects replies; escalation returns a hint</text>
88
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-44.07" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Replies, consensus and bus entries are not completion proof</text>
89
+ <text xml:space="preserve" text-anchor="middle" x="178" y="-30.57" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Parent must recheck child artifacts / evidence</text>
90
+ </g>
91
+ <!-- Run&#45;&gt;Result -->
83
92
  <g id="edge4" class="edge">
84
- <title>Orchestrator&#45;&gt;Broadcast</title>
85
- <path fill="none" stroke="#38bdf8" stroke-width="1.3" d="M292.2,-446.93C333.01,-435.19 392.17,-415.3 439,-387.88 456.86,-377.42 474.55,-362.42 488.04,-349.74"/>
86
- <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="489.83,-351.9 493.66,-344.34 485.95,-347.87 489.83,-351.9"/>
87
- </g>
88
- <!-- LocalLoop -->
89
- <g id="node2" class="node">
90
- <title>LocalLoop</title>
91
- <path fill="#7dd3fc" stroke="#334155" stroke-width="1.4" d="M717.38,-478.38C717.38,-478.38 634.62,-478.38 634.62,-478.38 628.62,-478.38 622.62,-472.38 622.62,-466.38 622.62,-466.38 622.62,-454.38 622.62,-454.38 622.62,-448.38 628.62,-442.38 634.62,-442.38 634.62,-442.38 717.38,-442.38 717.38,-442.38 723.38,-442.38 729.38,-448.38 729.38,-454.38 729.38,-454.38 729.38,-466.38 729.38,-466.38 729.38,-472.38 723.38,-478.38 717.38,-478.38"/>
92
- <text xml:space="preserve" text-anchor="middle" x="676" y="-463.43" font-family="sans-Serif" font-size="11.00" fill="#0f172a">🤖 &#160;Local Loop.run</text>
93
- <text xml:space="preserve" text-anchor="middle" x="676" y="-449.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">(ai.active = ollama)</text>
94
- </g>
95
- <!-- Escalate -->
96
- <g id="node7" class="node">
97
- <title>Escalate</title>
98
- <path fill="#c4b5fd" stroke="#334155" stroke-width="2" d="M730.88,-348.62C730.88,-348.62 621.12,-348.62 621.12,-348.62 615.12,-348.62 609.12,-342.62 609.12,-336.62 609.12,-336.62 609.12,-312.12 609.12,-312.12 609.12,-306.12 615.12,-300.12 621.12,-300.12 621.12,-300.12 730.88,-300.12 730.88,-300.12 736.88,-300.12 742.88,-306.12 742.88,-312.12 742.88,-312.12 742.88,-336.62 742.88,-336.62 742.88,-342.62 736.88,-348.62 730.88,-348.62"/>
99
- <text xml:space="preserve" text-anchor="middle" x="676" y="-334.18" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Loop escalation (private)</text>
100
- <text xml:space="preserve" text-anchor="middle" x="676" y="-320.68" font-family="sans-Serif" font-size="11.00" fill="#0f172a">(local stuck ≥N fails)</text>
101
- <text xml:space="preserve" text-anchor="middle" x="676" y="-307.18" font-family="sans-Serif" font-size="11.00" fill="#0f172a">→ frontier hint</text>
93
+ <title>Run&#45;&gt;Result</title>
94
+ <path fill="none" stroke="#94a3b8" stroke-width="1.3" d="M178,-166.79C178,-160.22 178,-153.38 178,-146.48"/>
95
+ <polygon fill="#94a3b8" stroke="#94a3b8" stroke-width="1.3" points="180.8,-146.76 178,-138.76 175.2,-146.76 180.8,-146.76"/>
96
+ <text xml:space="preserve" text-anchor="middle" x="223" y="-147.29" font-family="sans-Serif" font-size="10.00" fill="#cbd5e1">observed child result</text>
102
97
  </g>
103
- <!-- LocalLoop&#45;&gt;Escalate -->
98
+ <!-- State -->
99
+ <g id="node6" class="node">
100
+ <title>State</title>
101
+ <path fill="#fcd34d" stroke="#334155" stroke-width="1.3" d="M688,-106.54C688,-106.54 388,-106.54 388,-106.54 382,-106.54 376,-100.54 376,-94.54 376,-94.54 376,-28 376,-28 376,-22 382,-16 388,-16 388,-16 688,-16 688,-16 694,-16 700,-22 700,-28 700,-28 700,-94.54 700,-94.54 700,-100.54 694,-106.54 688,-106.54"/>
102
+ <text xml:space="preserve" text-anchor="middle" x="538" y="-84.57" font-family="sans-Serif" font-size="11.00" fill="#0f172a">swarm/&lt;id&gt;/bus.jsonl: append&#45;only conversation</text>
103
+ <text xml:space="preserve" text-anchor="middle" x="538" y="-71.07" font-family="sans-Serif" font-size="11.00" fill="#0f172a">swarm/&lt;id&gt;/personas.json: name → session_id</text>
104
+ <text xml:space="preserve" text-anchor="middle" x="538" y="-57.57" font-family="sans-Serif" font-size="11.00" fill="#0f172a">sessions/*.jsonl: per&#45;persona transcripts</text>
105
+ <text xml:space="preserve" text-anchor="middle" x="538" y="-44.07" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Use swarm_id to join existing work; swarm_bus to inspect</text>
106
+ <text xml:space="preserve" text-anchor="middle" x="538" y="-30.57" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Bus tail supplies context, not independent verification</text>
107
+ </g>
108
+ <!-- Run&#45;&gt;State -->
104
109
  <g id="edge5" class="edge">
105
- <title>LocalLoop&#45;&gt;Escalate</title>
106
- <path fill="none" stroke="#fb7185" stroke-width="2" d="M676,-441.86C676,-421.22 676,-386.42 676,-360.22"/>
107
- <polygon fill="#fb7185" stroke="#fb7185" stroke-width="2" points="678.8,-360.26 676,-352.26 673.2,-360.26 678.8,-360.26"/>
108
- <text xml:space="preserve" text-anchor="middle" x="716.5" y="-397.82" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">escalation_persona</text>
109
- </g>
110
- <!-- Red -->
111
- <g id="node8" class="node">
112
- <title>Red</title>
113
- <path fill="#6ee7b7" stroke="#334155" stroke-width="1.4" d="M211.12,-206.38C211.12,-206.38 114.88,-206.38 114.88,-206.38 108.88,-206.38 102.88,-200.38 102.88,-194.38 102.88,-194.38 102.88,-169.88 102.88,-169.88 102.88,-163.88 108.88,-157.88 114.88,-157.88 114.88,-157.88 211.12,-157.88 211.12,-157.88 217.12,-157.88 223.12,-163.88 223.12,-169.88 223.12,-169.88 223.12,-194.38 223.12,-194.38 223.12,-200.38 217.12,-206.38 211.12,-206.38"/>
114
- <text xml:space="preserve" text-anchor="middle" x="163" y="-191.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">🔴 &#160;red_team</text>
115
- <text xml:space="preserve" text-anchor="middle" x="163" y="-178.43" font-family="sans-Serif" font-size="11.00" fill="#0f172a">engine: grok</text>
116
- <text xml:space="preserve" text-anchor="middle" x="163" y="-164.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">toolsets: terminal,pwn</text>
117
- </g>
118
- <!-- Spawn&#45;&gt;Red -->
119
- <!-- Agents -->
120
- <g id="node12" class="node">
121
- <title>Agents</title>
122
- <path fill="#fcd34d" stroke="#334155" stroke-width="1.4" d="M209.62,-59.75C209.62,-62.16 188.73,-64.12 163,-64.12 137.27,-64.12 116.38,-62.16 116.38,-59.75 116.38,-59.75 116.38,-20.38 116.38,-20.38 116.38,-17.96 137.27,-16 163,-16 188.73,-16 209.62,-17.96 209.62,-20.38 209.62,-20.38 209.62,-59.75 209.62,-59.75"/>
123
- <path fill="none" stroke="#334155" stroke-width="1.4" d="M209.62,-59.75C209.62,-57.34 188.73,-55.38 163,-55.38 137.27,-55.38 116.38,-57.34 116.38,-59.75"/>
124
- <text xml:space="preserve" text-anchor="middle" x="163" y="-43.11" font-family="sans-Serif" font-size="11.00" fill="#0f172a">agents.yml</text>
125
- <text xml:space="preserve" text-anchor="middle" x="163" y="-29.61" font-family="sans-Serif" font-size="11.00" fill="#0f172a">persona registry</text>
110
+ <title>Run&#45;&gt;State</title>
111
+ <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M298.01,-166.79C317.6,-158.26 338.26,-149.26 358.9,-140.27"/>
112
+ <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="359.98,-142.86 366.2,-137.09 357.74,-137.72 359.98,-142.86"/>
113
+ <text xml:space="preserve" text-anchor="middle" x="413.21" y="-147.29" font-family="sans-Serif" font-size="10.00" fill="#cbd5e1">retain request / reply / session</text>
126
114
  </g>
127
- <!-- Spawn&#45;&gt;Agents -->
128
- <g id="edge17" class="edge">
129
- <title>Spawn&#45;&gt;Agents</title>
130
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M91.84,-305.71C102.69,-300.47 115.09,-295.28 127,-292.12 329.16,-238.53 387.28,-266.93 596,-253.62 605.77,-253 765.24,-252.7 772,-245.62 801.4,-214.86 800.77,-181.24 772,-149.88 751.72,-127.77 261.59,-115.15 234,-103.38 217.35,-96.27 201.87,-83.72 189.63,-71.73"/>
131
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="191.8,-69.94 184.2,-66.18 187.8,-73.86 191.8,-69.94"/>
132
- <text xml:space="preserve" text-anchor="middle" x="803.56" y="-178.82" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">write</text>
133
- </g>
134
- <!-- Ask&#45;&gt;Red -->
135
- <g id="edge7" class="edge">
136
- <title>Ask&#45;&gt;Red</title>
137
- <path fill="none" stroke="#34d399" stroke-width="1.3" d="M199.77,-305.9C193.08,-283.56 181.36,-244.44 172.95,-216.36"/>
138
- <polygon fill="#34d399" stroke="#34d399" stroke-width="1.3" points="175.67,-215.67 170.69,-208.81 170.31,-217.28 175.67,-215.67"/>
139
- </g>
140
- <!-- Blue -->
141
- <g id="node9" class="node">
142
- <title>Blue</title>
143
- <path fill="#6ee7b7" stroke="#334155" stroke-width="1.4" d="M589.88,-206.38C589.88,-206.38 468.12,-206.38 468.12,-206.38 462.12,-206.38 456.12,-200.38 456.12,-194.38 456.12,-194.38 456.12,-169.88 456.12,-169.88 456.12,-163.88 462.12,-157.88 468.12,-157.88 468.12,-157.88 589.88,-157.88 589.88,-157.88 595.88,-157.88 601.88,-163.88 601.88,-169.88 601.88,-169.88 601.88,-194.38 601.88,-194.38 601.88,-200.38 595.88,-206.38 589.88,-206.38"/>
144
- <text xml:space="preserve" text-anchor="middle" x="529" y="-191.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">🔵 &#160;blue_team</text>
145
- <text xml:space="preserve" text-anchor="middle" x="529" y="-178.43" font-family="sans-Serif" font-size="11.00" fill="#0f172a">engine: anthropic</text>
146
- <text xml:space="preserve" text-anchor="middle" x="529" y="-164.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">toolsets: pwn,extrospection</text>
147
- </g>
148
- <!-- Debate&#45;&gt;Blue -->
149
- <g id="edge8" class="edge">
150
- <title>Debate&#45;&gt;Blue</title>
151
- <path fill="none" stroke="#34d399" stroke-width="1.3" d="M381.94,-305.9C409.74,-282.68 459.27,-241.34 493.1,-213.1"/>
152
- <polygon fill="#34d399" stroke="#34d399" stroke-width="1.3" points="494.63,-215.47 498.98,-208.19 491.04,-211.17 494.63,-215.47"/>
153
- </g>
154
- <!-- Recon -->
155
- <g id="node10" class="node">
156
- <title>Recon</title>
157
- <path fill="#6ee7b7" stroke="#334155" stroke-width="1.4" d="M397.5,-206.38C397.5,-206.38 282.5,-206.38 282.5,-206.38 276.5,-206.38 270.5,-200.38 270.5,-194.38 270.5,-194.38 270.5,-169.88 270.5,-169.88 270.5,-163.88 276.5,-157.88 282.5,-157.88 282.5,-157.88 397.5,-157.88 397.5,-157.88 403.5,-157.88 409.5,-163.88 409.5,-169.88 409.5,-169.88 409.5,-194.38 409.5,-194.38 409.5,-200.38 403.5,-206.38 397.5,-206.38"/>
158
- <text xml:space="preserve" text-anchor="middle" x="340" y="-191.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">🛰 &#160;recon</text>
159
- <text xml:space="preserve" text-anchor="middle" x="340" y="-178.43" font-family="sans-Serif" font-size="11.00" fill="#0f172a">engine: ollama</text>
160
- <text xml:space="preserve" text-anchor="middle" x="340" y="-164.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">toolsets: terminal,memory</text>
161
- </g>
162
- <!-- Debate&#45;&gt;Recon -->
163
- <g id="edge9" class="edge">
164
- <title>Debate&#45;&gt;Recon</title>
165
- <path fill="none" stroke="#34d399" stroke-width="1.3" d="M358.38,-305.9C355.05,-283.66 349.23,-244.78 345.03,-216.73"/>
166
- <polygon fill="#34d399" stroke="#34d399" stroke-width="1.3" points="347.81,-216.37 343.86,-208.87 342.27,-217.2 347.81,-216.37"/>
167
- </g>
168
- <!-- Xpl -->
169
- <g id="node11" class="node">
170
- <title>Xpl</title>
171
- <path fill="#6ee7b7" stroke="#334155" stroke-width="1.4" d="M741.25,-206.38C741.25,-206.38 660.75,-206.38 660.75,-206.38 654.75,-206.38 648.75,-200.38 648.75,-194.38 648.75,-194.38 648.75,-169.88 648.75,-169.88 648.75,-163.88 654.75,-157.88 660.75,-157.88 660.75,-157.88 741.25,-157.88 741.25,-157.88 747.25,-157.88 753.25,-163.88 753.25,-169.88 753.25,-169.88 753.25,-194.38 753.25,-194.38 753.25,-200.38 747.25,-206.38 741.25,-206.38"/>
172
- <text xml:space="preserve" text-anchor="middle" x="701" y="-191.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">💥 &#160;exploit_dev</text>
173
- <text xml:space="preserve" text-anchor="middle" x="701" y="-178.43" font-family="sans-Serif" font-size="11.00" fill="#0f172a">engine: openai</text>
174
- <text xml:space="preserve" text-anchor="middle" x="701" y="-164.93" font-family="sans-Serif" font-size="11.00" fill="#0f172a">toolsets: pwn,skills</text>
175
- </g>
176
- <!-- Broadcast&#45;&gt;Xpl -->
177
- <g id="edge10" class="edge">
178
- <title>Broadcast&#45;&gt;Xpl</title>
179
- <path fill="none" stroke="#34d399" stroke-width="1.3" d="M528.75,-305.72C544.65,-289.92 569.95,-267.22 596,-253.62 607.85,-247.44 613.13,-251.78 625,-245.62 641.22,-237.21 657.16,-224.91 670.22,-213.44"/>
180
- <polygon fill="#34d399" stroke="#34d399" stroke-width="1.3" points="672.03,-215.58 676.1,-208.14 668.28,-211.42 672.03,-215.58"/>
181
- </g>
182
- <!-- Escalate&#45;&gt;Blue -->
183
- <g id="edge11" class="edge">
184
- <title>Escalate&#45;&gt;Blue</title>
185
- <path fill="none" stroke="#34d399" stroke-width="2" d="M650.73,-299.27C626.18,-275.84 588.78,-240.16 561.91,-214.53"/>
186
- <polygon fill="#34d399" stroke="#34d399" stroke-width="2" points="563.85,-212.51 556.13,-209.01 559.99,-216.56 563.85,-212.51"/>
187
- <text xml:space="preserve" text-anchor="middle" x="639.8" y="-255.57" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">ask 3&#45;line hint</text>
188
- </g>
189
- <!-- Red&#45;&gt;Agents -->
190
- <!-- Bus -->
191
- <g id="node13" class="node">
192
- <title>Bus</title>
193
- <path fill="#fcd34d" stroke="#334155" stroke-width="1.4" d="M375,-59.75C375,-62.16 348.56,-64.12 316,-64.12 283.44,-64.12 257,-62.16 257,-59.75 257,-59.75 257,-20.38 257,-20.38 257,-17.96 283.44,-16 316,-16 348.56,-16 375,-17.96 375,-20.38 375,-20.38 375,-59.75 375,-59.75"/>
194
- <path fill="none" stroke="#334155" stroke-width="1.4" d="M375,-59.75C375,-57.34 348.56,-55.38 316,-55.38 283.44,-55.38 257,-57.34 257,-59.75"/>
195
- <text xml:space="preserve" text-anchor="middle" x="316" y="-43.11" font-family="sans-Serif" font-size="11.00" fill="#0f172a">swarm/&lt;id&gt;/bus.jsonl</text>
196
- <text xml:space="preserve" text-anchor="middle" x="316" y="-29.61" font-family="sans-Serif" font-size="11.00" fill="#0f172a">append&#45;only chat</text>
197
- </g>
198
- <!-- Red&#45;&gt;Bus -->
199
- <g id="edge13" class="edge">
200
- <title>Red&#45;&gt;Bus</title>
201
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M188.95,-157.37C214.86,-133.65 254.76,-97.12 282.92,-71.34"/>
202
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="284.71,-73.5 288.72,-66.03 280.93,-69.37 284.71,-73.5"/>
203
- <text xml:space="preserve" text-anchor="middle" x="261.91" y="-113.33" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">append reply</text>
204
- </g>
205
- <!-- Blue&#45;&gt;LocalLoop -->
206
- <g id="edge20" class="edge">
207
- <title>Blue&#45;&gt;LocalLoop</title>
208
- <path fill="none" stroke="#fb7185" stroke-width="2" stroke-dasharray="5,2" d="M556.71,-207.05C574.84,-221.13 599.77,-237.69 625,-245.62 638.2,-249.78 864.37,-243.68 874,-253.62 938.49,-320.22 803.11,-399.31 725.45,-437.11"/>
209
- <polygon fill="#fb7185" stroke="#fb7185" stroke-width="2" points="724.55,-434.43 718.55,-440.42 726.98,-439.48 724.55,-434.43"/>
210
- <text xml:space="preserve" text-anchor="middle" x="932.8" y="-326.32" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">frontier_hint</text>
211
- <text xml:space="preserve" text-anchor="middle" x="932.8" y="-315.82" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">(synthetic tool result)</text>
212
- </g>
213
- <!-- Blue&#45;&gt;Bus -->
214
- <g id="edge14" class="edge">
215
- <title>Blue&#45;&gt;Bus</title>
216
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M486.06,-157.29C460.11,-142.48 426.63,-122.65 398,-103.38 383,-93.27 367.05,-81.42 353.25,-70.79"/>
217
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="354.98,-68.59 346.94,-65.9 351.55,-73.01 354.98,-68.59"/>
218
- </g>
219
- <!-- Pmap -->
220
- <g id="node14" class="node">
221
- <title>Pmap</title>
222
- <path fill="#fcd34d" stroke="#334155" stroke-width="1.4" d="M564.38,-59.75C564.38,-62.16 532.38,-64.12 493,-64.12 453.62,-64.12 421.62,-62.16 421.62,-59.75 421.62,-59.75 421.62,-20.38 421.62,-20.38 421.62,-17.96 453.62,-16 493,-16 532.38,-16 564.38,-17.96 564.38,-20.38 564.38,-20.38 564.38,-59.75 564.38,-59.75"/>
223
- <path fill="none" stroke="#334155" stroke-width="1.4" d="M564.38,-59.75C564.38,-57.34 532.38,-55.38 493,-55.38 453.62,-55.38 421.62,-57.34 421.62,-59.75"/>
224
- <text xml:space="preserve" text-anchor="middle" x="493" y="-43.11" font-family="sans-Serif" font-size="11.00" fill="#0f172a">swarm/&lt;id&gt;/personas.json</text>
225
- <text xml:space="preserve" text-anchor="middle" x="493" y="-29.61" font-family="sans-Serif" font-size="11.00" fill="#0f172a">name → session_id</text>
226
- </g>
227
- <!-- Recon&#45;&gt;Pmap -->
228
- <g id="edge15" class="edge">
229
- <title>Recon&#45;&gt;Pmap</title>
230
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M365.95,-157.37C391.86,-133.65 431.76,-97.12 459.92,-71.34"/>
231
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="461.71,-73.5 465.72,-66.03 457.93,-69.37 461.71,-73.5"/>
232
- </g>
233
- <!-- Sess -->
234
- <g id="node15" class="node">
235
- <title>Sess</title>
236
- <path fill="#fcd34d" stroke="#334155" stroke-width="1.4" d="M732.88,-59.75C732.88,-62.16 705.59,-64.12 672,-64.12 638.41,-64.12 611.12,-62.16 611.12,-59.75 611.12,-59.75 611.12,-20.38 611.12,-20.38 611.12,-17.96 638.41,-16 672,-16 705.59,-16 732.88,-17.96 732.88,-20.38 732.88,-20.38 732.88,-59.75 732.88,-59.75"/>
237
- <path fill="none" stroke="#334155" stroke-width="1.4" d="M732.88,-59.75C732.88,-57.34 705.59,-55.38 672,-55.38 638.41,-55.38 611.12,-57.34 611.12,-59.75"/>
238
- <text xml:space="preserve" text-anchor="middle" x="672" y="-43.11" font-family="sans-Serif" font-size="11.00" fill="#0f172a">sessions/*.jsonl</text>
239
- <text xml:space="preserve" text-anchor="middle" x="672" y="-29.61" font-family="sans-Serif" font-size="11.00" fill="#0f172a">per&#45;persona transcript</text>
240
- </g>
241
- <!-- Xpl&#45;&gt;Sess -->
242
- <g id="edge16" class="edge">
243
- <title>Xpl&#45;&gt;Sess</title>
244
- <path fill="none" stroke="#f59e0b" stroke-width="1.3" d="M696.08,-157.37C691.34,-134.49 684.14,-99.69 678.84,-74.12"/>
245
- <polygon fill="#f59e0b" stroke="#f59e0b" stroke-width="1.3" points="681.61,-73.66 677.25,-66.4 676.13,-74.8 681.61,-73.66"/>
246
- </g>
247
- <!-- Bus&#45;&gt;Orchestrator -->
248
- <g id="edge19" class="edge">
249
- <title>Bus&#45;&gt;Orchestrator</title>
250
- <path fill="none" stroke="#38bdf8" stroke-width="1.3" stroke-dasharray="5,2" d="M338.69,-64.69C353.95,-78.83 375.36,-95.54 398,-103.38 448.72,-120.93 828.77,-99.01 881,-111.38 919.4,-120.47 940,-116.47 961,-149.88 983.65,-185.9 985,-210.48 961,-245.62 928.98,-292.52 888.09,-258.96 842,-292.12 796.98,-324.51 811.23,-362.34 762,-387.88 742.8,-397.83 686.48,-393.37 665,-395.88 534.65,-411.06 382.63,-435.72 301.67,-449.42"/>
251
- <polygon fill="#38bdf8" stroke="#38bdf8" stroke-width="1.3" points="301.52,-446.6 294.1,-450.7 302.46,-452.12 301.52,-446.6"/>
252
- <text xml:space="preserve" text-anchor="middle" x="980.85" y="-255.57" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">swarm_bus()</text>
253
- </g>
254
- <!-- Bus&#45;&gt;Debate -->
255
- <g id="edge18" class="edge">
256
- <title>Bus&#45;&gt;Debate</title>
257
- <path fill="none" stroke="#fbbf24" stroke-width="1.3" stroke-dasharray="5,2" d="M338.7,-64.68C353.96,-78.81 375.37,-95.52 398,-103.38 443.88,-119.3 789.8,-93.62 835,-111.38 858.88,-120.75 867.53,-126.46 878,-149.88 895.36,-188.73 907.11,-214.58 878,-245.62 868.56,-255.7 767.73,-252.22 754,-253.62 720.52,-257.04 712.38,-259.84 679,-264.12 572.48,-277.79 543.09,-265.7 439,-292.12 428.82,-294.71 418.2,-298.31 408.2,-302.15"/>
258
- <polygon fill="#fbbf24" stroke="#fbbf24" stroke-width="1.3" points="407.43,-299.44 401.03,-305 409.5,-304.64 407.43,-299.44"/>
259
- <text xml:space="preserve" text-anchor="middle" x="923.07" y="-178.82" font-family="sans-Serif" font-size="9.00" fill="#cbd5e1">tail → context</text>
115
+ <!-- Config -->
116
+ <g id="node4" class="node">
117
+ <title>Config</title>
118
+ <path fill="#fcd34d" stroke="#334155" stroke-width="1.3" d="M749,-265.33C749,-265.33 449,-265.33 449,-265.33 443,-265.33 437,-259.33 437,-253.33 437,-253.33 437,-186.79 437,-186.79 437,-180.79 443,-174.79 449,-174.79 449,-174.79 749,-174.79 749,-174.79 755,-174.79 761,-180.79 761,-186.79 761,-186.79 761,-253.33 761,-253.33 761,-259.33 755,-265.33 749,-265.33"/>
119
+ <text xml:space="preserve" text-anchor="middle" x="599" y="-243.36" font-family="sans-Serif" font-size="11.00" fill="#0f172a">PERSONA DEFINITION &#160;· &#160;independent setup</text>
120
+ <text xml:space="preserve" text-anchor="middle" x="599" y="-229.86" font-family="sans-Serif" font-size="11.00" fill="#0f172a">agent_spawn defines a persona in ~/.pwn/agents.yml</text>
121
+ <text xml:space="preserve" text-anchor="middle" x="599" y="-216.36" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Definition alone does not execute a turn</text>
122
+ <text xml:space="preserve" text-anchor="middle" x="599" y="-202.86" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Examples: red_team / blue_team / recon / exploit_dev</text>
123
+ <text xml:space="preserve" text-anchor="middle" x="599" y="-189.36" font-family="sans-Serif" font-size="11.00" fill="#0f172a">Provider and toolsets are configurable, not role guarantees</text>
124
+ </g>
125
+ <!-- Config&#45;&gt;Run -->
126
+ <g id="edge3" class="edge">
127
+ <title>Config&#45;&gt;Run</title>
128
+ <path fill="none" stroke="#94a3b8" stroke-width="1.3" d="M436.44,-220.06C408.15,-220.06 378.64,-220.06 350.11,-220.06"/>
129
+ <polygon fill="#94a3b8" stroke="#94a3b8" stroke-width="1.3" points="357.97,-217.26 349.97,-220.06 357.97,-222.86 357.97,-217.26"/>
130
+ <text xml:space="preserve" text-anchor="middle" x="388.5" y="-225.56" font-family="sans-Serif" font-size="10.00" fill="#cbd5e1">read definition</text>
260
131
  </g>
261
132
  </g>
262
133
  </svg>
@@ -45,9 +45,37 @@ Aliases shared by multiple sessions are ambiguous too; use a stable ID.
45
45
  `dependencies` means **referenced by**: files containing defined structural
46
46
  references to that session. Transcript prose, prompts, tool results and quoted
47
47
  JSON—including previous `/sessions list` output—are not dependencies. An empty
48
- array means no known structural references; `dependency_errors` separately
49
- reports uncertainty and blocks scheduled cleanup. Dependency-backed sessions
50
- stay visible and resumable. See Installation's session-cleanup schema table.
48
+ array means no known structural references. `dependency_errors` contains only
49
+ errors attributed to this session; `unresolved_dependency_stores` reports global
50
+ uncertainty without assigning blame. Lists always include the current active
51
+ session, even while its title is provisional or summary generation failed.
52
+ Other rows require valid summary provenance or valid structural dependencies.
53
+ This display exception does not confer summary provenance or bypass cleanup:
54
+ activity leases still prevent physical deletion. Explicit resume remains available.
55
+ `/sessions list [offset] [limit]` defaults to the newest page, ordered oldest-first
56
+ within that page. An explicit offset starts at that oldest-first position.
57
+ The current session is marked `active: true` and included once even outside the
58
+ requested page (so at most limit + 1 rows). `total` counts unique visible sessions;
59
+ `offset` and `has_more` describe the base page, not the extra active row.
60
+ Global unresolved stores and specific diagnostics are reported once in the envelope.
61
+ Title workers capture the active provider/model when the request starts, summarize
62
+ only that session's persisted conversation, and retry on resume. Pending work is
63
+ coalesced per session rather than dropping another session's update. Failed or
64
+ invalid generation keeps the previous title and cursor, and reports a warning
65
+ without exposing provider payloads. It never fabricates `title_source: summary`.
66
+ `/sessions cleanup` applies the bundled cron maintenance operation; use
67
+ `/sessions cleanup --dry-run` for a read-only preview. Migration preserves full
68
+ redacted learning snapshots and their offline readers; it does not manufacture
69
+ lossless migrations for other stores. Unknown global ownership blocks apply.
70
+ Prepared/committed maintenance ledgers and recoverable backups live outside
71
+ ordinary backup pruning. Old writers must be quiesced before live deployment;
72
+ updating a helper alone does not update a running process.
73
+ Request checkpoints use a version-1, hash-bound identity adapter: their session
74
+ field is provenance because restore consumes the checkpoint itself. Unknown
75
+ versions, fields and mismatched paths remain unresolved; checkpoint bytes are
76
+ never rewritten by cleanup. Other unmigrated evidence edges remain retained.
77
+ `Sessions.list(include_hidden: true)` is the diagnostic inventory. See
78
+ Installation's session-cleanup schema table and remediation limitations.
51
79
  `title_source`, `is_summarized`, `classification` and `title_reason` expose the
52
80
  same strict provenance used by cleanup. Only persisted `summary` provenance with
53
81
  a nonblank summary/title and positive integer summary cursor counts as named.
@@ -39,8 +39,68 @@ The curses console exposes these local views through the command menu:
39
39
  Running phase checkpoints are atomically persisted before publication, including
40
40
  actual check records, uncovered requirements and repair reasons.
41
41
  Worktrees isolate edits, **not** arbitrary code execution or network access.
42
- * `/sessions cleanup` previews the same provenance/dependency policy as scheduled
43
- cleanup. Inspect the exact IDs, paths, fingerprints, retention reasons and
42
+ * `/sessions list [offset] [limit]` is a page, not a retention limit. The
43
+ envelope reports `returned`, visible `total`, `physical_sessions`,
44
+ `filtered_sessions`, `has_previous` and `has_more`, plus a disjoint root-entry
45
+ `storage` breakdown. Filtered transcripts remain physically retained and explicitly
46
+ resumable. Neither pagination nor layout migration deletes summarized sessions.
47
+ * Offline housekeeping migration is separate from ordinary cleanup. After deploying
48
+ matching source and stopping **all** launchers, workers and cron schedulers, run
49
+ from the checkout:
50
+
51
+ ```ruby
52
+ require 'pwn'
53
+ require './etc/default_cron/session_cleanup'
54
+ PWN::SessionCleanup.reorganize # metadata-only plan; no changes
55
+ PWN::SessionCleanup.reorganize(dry_run: false, writers_stopped: true)
56
+ PWN::SessionCleanup.run(dry_run: true) # inspect remaining retention categories
57
+ # Only after reviewing the ledger and approving cleanup:
58
+ PWN::SessionCleanup.run(dry_run: false)
59
+ ```
60
+
61
+ Launch Ruby with `bundle exec ruby -Ilib` so this uses matching source, not an
62
+ older installed gem. `writers_stopped` is an operator assertion, not a way to
63
+ bypass held leases or unknown legacy owners. Backups and prepared/committed
64
+ ledgers live in private `~/.pwn/session_cleanup_archive` directories. The layout
65
+ migration moves unreferenced metadata and lease inodes under `sessions/support`;
66
+ new trace support also uses that layout. Existing trace paths and dependency-backed
67
+ metadata stay at their exact locations to preserve evidence anchors and are
68
+ reported in `retained_support`. Canonical transcripts stay at the root. Abandoned numeric-PID transcript temp
69
+ files are removed only after exact recoverable backups in this offline operation.
70
+ Held own-process capability markers stay in place; other active owners block.
71
+ Readers accept legacy and compact paths, including partially completed moves.
72
+ Do not restart old binaries after applying the layout. Unknown files, mesh
73
+ mappings and request checkpoints remain untouched. Complete policy trajectories
74
+ are self-contained training provenance, not transcript-retention edges; incomplete
75
+ legacy trajectories and other unresolved evidence consumers still retain sources.
76
+ * Historical IDs are not automatically transcript dependencies. The shared index
77
+ validates self-contained Mistakes records (error/fix/counters), Memory reflection
78
+ values, Extrospection drift observations and Curriculum practice results before
79
+ treating their session IDs as provenance. These stores are not rewritten or
80
+ deleted by this classification. Incomplete records still pin their identified
81
+ source; malformed containers remain diagnostics. No summary or training label
82
+ is invented. Mistakes' previous-turn readers and Memory's session-turn reader
83
+ operate on the caller's current session, not historical occurrence IDs.
84
+ Curriculum's practice log is an audit log, not a replay/evaluation queue.
85
+ * Actual Learning transcript consumers retain full redacted, content-addressed
86
+ evidence through the existing migration before transcript deletion. Sessions.load,
87
+ Curriculum.offline_judge discovery and Reward PRM copy-on-write annotation use
88
+ the verified evidence; source hashes and complete source equality are checked
89
+ before releasing a live transcript. Overlapping provenance records no longer
90
+ prevent that preservation/re-index/deletion transaction.
91
+ * Swarm `personas.json` is different: `Swarm.ask` calls `persona_session`, which
92
+ reuses its ID and acquires a writable-session lease for `Loop.run`. `retire`
93
+ removes an agents.yml registration, not that association; an explicit persona
94
+ or later respawn can reuse it. There is no persisted association-completed or
95
+ retired-session marker. Neither old mtime, an absent registry name nor a
96
+ completed bus message proves a map obsolete. Such mappings remain protected,
97
+ even with a Learning snapshot, because a read-only training artifact is not a
98
+ writable continuation. Cleanup does not silently archive them or impose a cap.
99
+ * `/sessions cleanup` runs the same maintenance operation as bundled cron:
100
+ validate, preserve supported learning evidence, remediate attributable invalid
101
+ records with recoverable backups, re-index, and remove eligible inactive sessions.
102
+ `/sessions cleanup --dry-run` previews without changing evidence or deleting
103
+ sessions. Inspect the exact IDs, paths, fingerprints, retention reasons and
44
104
  uncertainty. `a`, then Enter confirms only the displayed candidate set.
45
105
  Newly discovered or changed records are excluded. Apply rechecks activity,
46
106
  references and source bytes under locks, backs up candidate bytes, and reports