emux 0.4.0__tar.gz

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 (46) hide show
  1. emux-0.4.0/.claude-plugin/plugin.json +51 -0
  2. emux-0.4.0/.codex-plugin/plugin.json +45 -0
  3. emux-0.4.0/.converge/README.md +12 -0
  4. emux-0.4.0/.converge/closeout.json +55 -0
  5. emux-0.4.0/.converge/closeout.md +23 -0
  6. emux-0.4.0/.converge/converge-rows.json +232 -0
  7. emux-0.4.0/.converge/emux-web-monitor-steer-fleet-ui.md +29 -0
  8. emux-0.4.0/.converge/history.jsonl +12 -0
  9. emux-0.4.0/.converge/last-summary.json +4369 -0
  10. emux-0.4.0/.converge/manifest.json +26 -0
  11. emux-0.4.0/.converge/pytest-rows.json +863 -0
  12. emux-0.4.0/.converge/real-surface-rows.json +144 -0
  13. emux-0.4.0/.converge/real_surface_probe.py +242 -0
  14. emux-0.4.0/.converge/synthetic-user.md +34 -0
  15. emux-0.4.0/.eidos-plugin.json +17 -0
  16. emux-0.4.0/.github/workflows/ci.yml +23 -0
  17. emux-0.4.0/.github/workflows/publish.yml +32 -0
  18. emux-0.4.0/.gitignore +10 -0
  19. emux-0.4.0/.governor/adr/ADR-001-autonomous-goal-mode-is-part-of-emux-s-purpose.md +9 -0
  20. emux-0.4.0/.governor/config.yaml +3 -0
  21. emux-0.4.0/.governor/guardrails/GUARD-001-emux-drives-existing-sessions-only-never-spawn-nev.md +9 -0
  22. emux-0.4.0/.governor/sops/SOP-001-goal-decomposition.md +36 -0
  23. emux-0.4.0/.governor/sops/SOP-002-completion-feedback.md +32 -0
  24. emux-0.4.0/.governor/sops/SOP-003-blocked-task-escalation.md +37 -0
  25. emux-0.4.0/.mcp.json +16 -0
  26. emux-0.4.0/.telos/config.yaml +3 -0
  27. emux-0.4.0/.telos/north_stars/ns_1271c383bf3e/ticks.jsonl +2 -0
  28. emux-0.4.0/.telos/north_stars/ns_1271c383bf3e.yaml +11 -0
  29. emux-0.4.0/CHANGELOG.md +19 -0
  30. emux-0.4.0/CODE_OF_CONDUCT.md +7 -0
  31. emux-0.4.0/CONTRIBUTING.md +29 -0
  32. emux-0.4.0/LICENSE +21 -0
  33. emux-0.4.0/PKG-INFO +359 -0
  34. emux-0.4.0/README.md +327 -0
  35. emux-0.4.0/SECURITY.md +19 -0
  36. emux-0.4.0/docs/decisions/0001-autonomous-goal-mode.md +53 -0
  37. emux-0.4.0/docs/north-star.md +51 -0
  38. emux-0.4.0/pyproject.toml +62 -0
  39. emux-0.4.0/src/emux/__init__.py +3 -0
  40. emux-0.4.0/src/emux/cli.py +751 -0
  41. emux-0.4.0/src/emux/server.py +1189 -0
  42. emux-0.4.0/src/emux/tui.py +537 -0
  43. emux-0.4.0/src/emux/web.py +1284 -0
  44. emux-0.4.0/tests/test_basic.py +717 -0
  45. emux-0.4.0/tests/test_converse.py +419 -0
  46. emux-0.4.0/tests/test_web.py +391 -0
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "emux",
3
+ "version": "0.1.0",
4
+ "description": "Eidos mux: TUI picker and MCP server for named tmux sessions.",
5
+ "author": {
6
+ "name": "Eidos AGI",
7
+ "url": "https://github.com/eidos-agi"
8
+ },
9
+ "homepage": "https://github.com/eidos-agi/emux",
10
+ "repository": "https://github.com/eidos-agi/emux",
11
+ "license": "MIT",
12
+ "category": "agent-tools",
13
+ "keywords": [
14
+ "mcp",
15
+ "tmux",
16
+ "claude-code",
17
+ "terminal",
18
+ "session-control",
19
+ "automation"
20
+ ],
21
+ "mcpServers": {
22
+ "emux": {
23
+ "command": "uv",
24
+ "args": [
25
+ "run",
26
+ "--directory",
27
+ "${CLAUDE_PLUGIN_ROOT}",
28
+ "emux",
29
+ "mcp"
30
+ ]
31
+ }
32
+ },
33
+ "x-eidos": {
34
+ "site": {
35
+ "slug": "emux",
36
+ "icon": "MX",
37
+ "tagline": "Pick up where you left off in tmux.",
38
+ "shape": "Session registry + MCP",
39
+ "status": "ready",
40
+ "hosts": ["codex", "claude-code"],
41
+ "codex": "codex-package",
42
+ "claude": "claude-marketplace",
43
+ "install": {
44
+ "codex": "Install from the Eidos plugin store.",
45
+ "claude": "claude plugins install emux@eidos-marketplace"
46
+ },
47
+ "start": "Register a tmux session, then drive it with send/run/capture.",
48
+ "requires": ["tmux", "Python 3.11+"]
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "emux",
3
+ "version": "0.1.0",
4
+ "description": "Eidos mux: TUI picker and MCP server for named tmux sessions.",
5
+ "author": {
6
+ "name": "Eidos AGI",
7
+ "email": "daniel@eidosagi.com",
8
+ "url": "https://github.com/eidos-agi"
9
+ },
10
+ "homepage": "https://github.com/eidos-agi/emux",
11
+ "repository": "https://github.com/eidos-agi/emux",
12
+ "license": "MIT",
13
+ "keywords": [
14
+ "mcp",
15
+ "tmux",
16
+ "codex",
17
+ "claude-code",
18
+ "terminal",
19
+ "session-control",
20
+ "automation"
21
+ ],
22
+ "mcpServers": "./.mcp.json",
23
+ "interface": {
24
+ "displayName": "Emux",
25
+ "shortDescription": "Control named tmux sessions from agents.",
26
+ "longDescription": "Emux gives Codex and Claude Code a shared registry for existing tmux sessions plus MCP tools to list sessions, register friendly names, send keys, capture panes, and run command-plus-capture loops. It never spawns or kills tmux sessions; it only observes and drives sessions the user already owns.",
27
+ "developerName": "Eidos AGI",
28
+ "category": "Developer Tools",
29
+ "capabilities": [
30
+ "MCP",
31
+ "Terminal Control",
32
+ "Session Registry",
33
+ "Automation"
34
+ ],
35
+ "websiteURL": "https://github.com/eidos-agi/emux",
36
+ "privacyPolicyURL": "https://github.com/eidos-agi/emux/blob/main/SECURITY.md",
37
+ "termsOfServiceURL": "https://github.com/eidos-agi/emux",
38
+ "defaultPrompt": [
39
+ "Use Emux to list my tmux sessions.",
40
+ "Register this Claude Code tmux session with Emux.",
41
+ "Capture the latest output from a named tmux session."
42
+ ],
43
+ "brandColor": "#0F766E"
44
+ }
45
+ }
@@ -0,0 +1,12 @@
1
+ # Converge Evidence
2
+
3
+ This directory is the repo-local entry point for Converge target rows, proof
4
+ envelopes, and repair gaps.
5
+
6
+ Current active loop:
7
+
8
+ - [emux web — monitor + steer fleet UI](emux-web-monitor-steer-fleet-ui.md)
9
+
10
+ Canonical contract files may live in domain-owned directories such as
11
+ `security/`, `contracts/`, or `docs/`. This directory exists so future engineers
12
+ can discover the Converge history before reading every artifact.
@@ -0,0 +1,55 @@
1
+ {
2
+ "ok": true,
3
+ "state": "in_progress",
4
+ "captured_at": "2026-06-15T21:08:04Z",
5
+ "repo": "/Users/dshanklinbv/repos-eidos-agi/emux",
6
+ "score": 0.15384615384615385,
7
+ "qualified_score": 0.9615384615384616,
8
+ "class_counts": {
9
+ "match": 2,
10
+ "rounding": 0,
11
+ "pass": 0,
12
+ "pass_real_surface": 9,
13
+ "pass_controlled_harness": 43,
14
+ "pass_with_bypass": 1,
15
+ "miss_small": 0,
16
+ "miss_large": 0,
17
+ "fail": 1,
18
+ "missing": 6,
19
+ "blocked": 0,
20
+ "drift": 0,
21
+ "regression": 0,
22
+ "skip": 0
23
+ },
24
+ "regression_count": 0,
25
+ "drift_count": 0,
26
+ "generated_gap_count": 12,
27
+ "doctor": {
28
+ "ok": true,
29
+ "repo": "/Users/dshanklinbv/repos-eidos-agi/emux",
30
+ "failures": [],
31
+ "warnings": []
32
+ },
33
+ "next_target": {
34
+ "target_id": "emux-web:ux01-status-means-state",
35
+ "class": "fail",
36
+ "target": "A session's status signal answers 'which one needs me?' \u2014 distinct states for working / idle / waiting-on-input / crashed, not just alive.",
37
+ "probe": "Synthetic user 'Riley' triage run 2026-06-15.",
38
+ "delta": "Every sidebar dot is green = 'tmux session exists'. Idle, stuck, and crashed sessions all look identical, so triage (the whole job) fails at a glance.",
39
+ "evidence": ".converge/synthetic-user.md report: 'every session looks green/active; it tells me THAT things are running, not WHICH one needs me'",
40
+ "next_action": "Derive a real state per session (output flowing -> working; quiet -> idle; pane matches an input/(y/n) prompt or traceback -> needs-attention; gone -> dead) and color the dot/border by it.",
41
+ "adapter": "synthetic-user:riley",
42
+ "source_file": ".converge/converge-rows.json",
43
+ "weight": 1.0,
44
+ "proof_envelope": {},
45
+ "fails_to_test": [],
46
+ "bypassed_controls": [],
47
+ "side_effects": []
48
+ },
49
+ "next_command": "Derive a real state per session (output flowing -> working; quiet -> idle; pane matches an input/(y/n) prompt or traceback -> needs-attention; gone -> dead) and color the dot/border by it.",
50
+ "row_files": [
51
+ ".converge/converge-rows.json",
52
+ ".converge/pytest-rows.json",
53
+ ".converge/real-surface-rows.json"
54
+ ]
55
+ }
@@ -0,0 +1,23 @@
1
+ # Converge Closeout
2
+
3
+ Captured: 2026-06-15T21:08:04Z
4
+ State: in_progress
5
+
6
+ ## Score
7
+
8
+ - score: 0.15384615384615385
9
+ - qualified_score: 0.9615384615384616
10
+ - regression_count: 0
11
+ - drift_count: 0
12
+ - doctor_ok: True
13
+
14
+ ## Next Target
15
+
16
+ - target_id: `emux-web:ux01-status-means-state`
17
+ - command: `Derive a real state per session (output flowing -> working; quiet -> idle; pane matches an input/(y/n) prompt or traceback -> needs-attention; gone -> dead) and color the dot/border by it.`
18
+
19
+ ## Files
20
+
21
+ - `.converge/last-summary.json`
22
+ - `.converge/history.jsonl`
23
+ - `.converge/closeout.json`
@@ -0,0 +1,232 @@
1
+ [
2
+ {
3
+ "target_id": "emux-web:000-north-star",
4
+ "target": "Watch and steer several local agent/tmux sessions from one screen, with a manages-hierarchy flow of live panes and click-to-zoom steering.",
5
+ "probe": "docs/north-star.md committed: job, target user, success signal, explicit non-goals.",
6
+ "delta": "Closed \u2014 intent now lives in the repo, not only in chat.",
7
+ "class": "match",
8
+ "evidence": "docs/north-star.md",
9
+ "next_action": "Hold; revise if scope changes (e.g. mobile or hosted-fleet stops being a non-goal).",
10
+ "adapter": "human",
11
+ "convergence_style": "exploratory_narrowing",
12
+ "required": true,
13
+ "why": "A demo can dazzle while the actual job stays undocumented; the next session re-derives intent from chat."
14
+ },
15
+ {
16
+ "target_id": "emux-web:010-pytest-suite",
17
+ "target": "The Python surface (session listing, capture/send payloads, change detection, agent detection, HTTP routing + guards, grid cache/eviction, cycle data) is covered by automated tests.",
18
+ "probe": "uv run pytest -q --junitxml -> 41 passed.",
19
+ "delta": "All green, but every tmux call is monkeypatched \u2014 these prove logic, not real tmux behavior or any browser rendering.",
20
+ "class": "pass_controlled_harness",
21
+ "evidence": ".converge/pytest-rows.json (41 rows); /tmp/emux-junit.xml",
22
+ "next_action": "Keep green; do not let this stand in for real-surface proof of capture/send/render.",
23
+ "adapter": "converge:pytest",
24
+ "convergence_style": "regression_hardening",
25
+ "required": true,
26
+ "proof_envelope": {
27
+ "environment": "ci/local-unit",
28
+ "surface": "pytest with mocked _run_tmux/_live_sessions/_pane_command",
29
+ "captured_at": "2026-06-15",
30
+ "bypassed_controls": [
31
+ "real tmux server",
32
+ "real pane content",
33
+ "real browser DOM/JS"
34
+ ],
35
+ "fails_to_test": [
36
+ "flow view renders without hanging in a real browser",
37
+ "send-keys actually reaches a live pane",
38
+ "agent detection against a real pane_current_command",
39
+ "mobile / accessibility / error-recovery UX"
40
+ ]
41
+ }
42
+ },
43
+ {
44
+ "target_id": "emux-web:020-flow-live-panes",
45
+ "target": "The flow view renders each session as a LIVE mini tmux pane in the manages hierarchy, streaming in place without flicker.",
46
+ "probe": "Loaded FLOW at http://127.0.0.1:8689 with a real boss->{lead-a,lead-b}->{worker,worker2} tree; panes updated in place.",
47
+ "delta": "Proven once, by eye, in this session \u2014 no repeatable artifact or assertion.",
48
+ "class": "pass_real_surface",
49
+ "evidence": "browser screenshots ss_92733pc9e, ss_5610kw1rz (2026-06-15)",
50
+ "next_action": "Capture a re-runnable browser proof (Playwright/claude-in-chrome script) that asserts N .fbox elements with non-empty live content and no console errors.",
51
+ "adapter": "human:browser",
52
+ "convergence_style": "consensus_evidence",
53
+ "required": true,
54
+ "proof_envelope": {
55
+ "environment": "local-daemon",
56
+ "surface": "browser flow view",
57
+ "base_origin": "http://127.0.0.1:8689",
58
+ "captured_at": "2026-06-15",
59
+ "freshness_days": 7,
60
+ "fails_to_test": [
61
+ "repeatable assertion",
62
+ "behavior under many sessions",
63
+ "behavior when a pane dies mid-view"
64
+ ]
65
+ }
66
+ },
67
+ {
68
+ "target_id": "emux-web:040b-error-recovery-ui",
69
+ "target": "On daemon failure the modal keeps the user's unsent draft, shows a clear failure state, and auto-reconnects when the daemon returns.",
70
+ "probe": "Opened the steer modal, typed a draft, killed the daemon, clicked SEND, then restarted the daemon.",
71
+ "delta": "Fixed an optimistic-clear bug that dropped the draft on send-failure; now the draft is restored if the send does not land.",
72
+ "class": "pass_real_surface",
73
+ "evidence": "browser JS read 2026-06-15: after failed send input='print(...)' (kept), status='unreachable'; after daemon restart status auto-returned to 'live' with the draft intact",
74
+ "next_action": "Hold; re-verify if the send/poll flow changes. Server half is covered by the real-surface probe (emux-web:040-error-recovery).",
75
+ "adapter": "human:browser",
76
+ "convergence_style": "graceful_degradation",
77
+ "required": true,
78
+ "why": "Failure handling is most of perceived quality for an always-on cockpit instrument.",
79
+ "proof_envelope": {
80
+ "environment": "local-daemon, daemon killed and restarted under a live modal",
81
+ "surface": "browser steer modal (#modalinput / #modalstatus)",
82
+ "base_origin": "http://127.0.0.1:8689",
83
+ "captured_at": "2026-06-15",
84
+ "freshness_days": 7,
85
+ "fails_to_test": [
86
+ "draft preservation in the chat-view composer (now unreachable via clicks)"
87
+ ]
88
+ }
89
+ },
90
+ {
91
+ "target_id": "emux-web:ux01-status-means-state",
92
+ "target": "A session's status signal answers 'which one needs me?' — distinct states for working / idle / waiting-on-input / crashed, not just alive.",
93
+ "probe": "Synthetic user 'Riley' triage run 2026-06-15.",
94
+ "delta": "Every sidebar dot is green = 'tmux session exists'. Idle, stuck, and crashed sessions all look identical, so triage (the whole job) fails at a glance.",
95
+ "class": "fail",
96
+ "evidence": ".converge/synthetic-user.md report: 'every session looks green/active; it tells me THAT things are running, not WHICH one needs me'",
97
+ "next_action": "Derive a real state per session (output flowing -> working; quiet -> idle; pane matches an input/(y/n) prompt or traceback -> needs-attention; gone -> dead) and color the dot/border by it.",
98
+ "adapter": "synthetic-user:riley",
99
+ "convergence_style": "exploratory_narrowing",
100
+ "required": true,
101
+ "why": "This is the question the cockpit exists to answer; decorative status defeats its purpose."
102
+ },
103
+ {
104
+ "target_id": "emux-web:ux02-needs-attention-surfacing",
105
+ "target": "Sessions blocked on input, on a (y/n) prompt, or showing a traceback bubble to the top with a badge.",
106
+ "probe": "Synthetic user run: scraper blocked on input(), tokut-8766 had a ConnectionResetError traceback — both 'needs a human'.",
107
+ "delta": "Neither is flagged anywhere; only caught by reading raw pane text.",
108
+ "class": "missing",
109
+ "evidence": ".converge/synthetic-user.md friction log #7",
110
+ "next_action": "Detect attention-needed patterns in pane tails and surface them (sort-to-top + badge) across grid/flow/activity.",
111
+ "adapter": "synthetic-user:riley",
112
+ "convergence_style": "consensus_evidence",
113
+ "required": true
114
+ },
115
+ {
116
+ "target_id": "emux-web:ux03-triage-in-sidebar",
117
+ "target": "The primary triage signal (recent-activity + idle-for-N) is visible where the user first looks — the sidebar — not only in the ACTIVITY tab.",
118
+ "probe": "Riley found the ACTIVITY sparkline view last; the sidebar dots carried no triage signal.",
119
+ "delta": "Real signal is buried one nav-tab away; 'active —' vs 'active 3s ago' is too subtle and everything reads 'active'.",
120
+ "class": "missing",
121
+ "evidence": ".converge/synthetic-user.md friction log #4,#5",
122
+ "next_action": "Put a tiny activity sparkline / 'idle N' on each sidebar card; reserve the word 'active' for sessions actually emitting.",
123
+ "adapter": "synthetic-user:riley",
124
+ "convergence_style": "regression_hardening",
125
+ "required": false
126
+ },
127
+ {
128
+ "target_id": "emux-web:ux04-click-affordance",
129
+ "target": "Clicking anywhere on a flow box opens its steer modal; the click target is obvious.",
130
+ "probe": "Riley's first click on a pane body was a no-op; only the title bar worked (needs reproduction — body click may have landed on empty canvas).",
131
+ "delta": "Either a real dead-zone or an unclear affordance; cost the user a step.",
132
+ "class": "missing",
133
+ "evidence": ".converge/synthetic-user.md friction log #2",
134
+ "next_action": "Reproduce a body-click; ensure the whole .fbox is the hit target and add a hover affordance (cursor/overlay 'click to steer').",
135
+ "adapter": "synthetic-user:riley",
136
+ "convergence_style": "exact_match",
137
+ "required": false
138
+ },
139
+ {
140
+ "target_id": "emux-web:ux05-agent-current-task",
141
+ "target": "A detected agent box shows a one-line 'currently: <task / idle at prompt>' instead of only the raw pane.",
142
+ "probe": "claude-refactor showed only the Claude Code welcome splash; no sense of what it had done.",
143
+ "delta": "Raw pane only; no task/recent-activity summary for detected agents.",
144
+ "class": "missing",
145
+ "evidence": ".converge/synthetic-user.md goal 3",
146
+ "next_action": "Heuristic 'currently' line from the pane tail for known agents (idle-at-prompt vs working vs awaiting-approval).",
147
+ "adapter": "synthetic-user:riley",
148
+ "convergence_style": "tolerance_band",
149
+ "required": false
150
+ },
151
+ {
152
+ "target_id": "emux-web:041-empty-edge-inputs",
153
+ "target": "Empty, huge, multiline, pasted, and control-bearing inputs behave predictably in the steer input and modal.",
154
+ "probe": "Not tested. Empty send is guarded (if(!text)); other edges unknown.",
155
+ "delta": "No edge-input proof.",
156
+ "class": "missing",
157
+ "evidence": "none",
158
+ "next_action": "Exercise empty/huge/multiline/paste in the modal input; confirm send behavior and that send-keys -l handles them.",
159
+ "adapter": "human:browser",
160
+ "convergence_style": "exact_match",
161
+ "required": false
162
+ },
163
+ {
164
+ "target_id": "emux-web:042-accessibility",
165
+ "target": "The UI is usable by keyboard, screen reader, visible focus, and sufficient contrast; the modal traps focus and Esc closes it.",
166
+ "probe": "Esc closes modal and number keys switch views (verified). No screen-reader semantics, focus-trap, or contrast audit.",
167
+ "delta": "Keyboard partially proven; assistive-tech and contrast unproven.",
168
+ "class": "missing",
169
+ "evidence": "keyboard handlers present in code; no a11y audit",
170
+ "next_action": "Run an automated a11y check on the page; add aria roles to modal/dialog and verify focus trap.",
171
+ "adapter": "human:browser",
172
+ "convergence_style": "regression_hardening",
173
+ "required": false
174
+ },
175
+ {
176
+ "target_id": "emux-web:043-mobile-layout",
177
+ "target": "The cockpit remains usable on a narrow viewport (or explicitly declares desktop-only as a non-goal).",
178
+ "probe": "docs/north-star.md declares desktop-first; mobile is an explicit non-goal.",
179
+ "delta": "Closed by scoping decision (not a responsive build).",
180
+ "class": "match",
181
+ "evidence": "docs/north-star.md (Non-goals: Desktop-first)",
182
+ "next_action": "Revisit only if mobile stops being a non-goal.",
183
+ "adapter": "human",
184
+ "convergence_style": "graceful_degradation",
185
+ "required": false
186
+ },
187
+ {
188
+ "target_id": "emux-web:050-daemon-as-service",
189
+ "target": "`emux web` survives logout/reboot as a real service (launchd), matching the README's persistence claim.",
190
+ "probe": "`emux web --print-launchd` emits a RunAtLoad/KeepAlive plist (test asserts it is well-formed). Never actually installed or reboot-tested.",
191
+ "delta": "The plist is generated and shaped right, but 'persistent daemon' is unproven on a real machine.",
192
+ "class": "pass_with_bypass",
193
+ "evidence": "test_launchd_plist_is_well_formed; README install steps",
194
+ "next_action": "Install the plist, launchctl load, kill the process, confirm KeepAlive restarts it; optionally a reboot check.",
195
+ "adapter": "human",
196
+ "convergence_style": "consensus_evidence",
197
+ "required": false,
198
+ "proof_envelope": {
199
+ "environment": "string-generation only",
200
+ "surface": "launchd plist text",
201
+ "captured_at": "2026-06-15",
202
+ "bypassed_controls": [
203
+ "never loaded into launchd",
204
+ "never reboot-tested"
205
+ ],
206
+ "fails_to_test": [
207
+ "RunAtLoad on real login",
208
+ "KeepAlive restart on crash"
209
+ ]
210
+ }
211
+ },
212
+ {
213
+ "target_id": "emux-web:060-flow-recursion-guard",
214
+ "target": "A cyclic manages relationship (A->B->A) renders without hanging the browser.",
215
+ "probe": "Live-demoed a 3-node cycle earlier; harness test pins that grid_payload carries both loop edges.",
216
+ "delta": "Real-surface (no hang) verified by eye; only the data layer is automated.",
217
+ "class": "pass_controlled_harness",
218
+ "evidence": "test_flow_handles_recursive_manages_cycle; browser cycle demo 2026-06-12",
219
+ "next_action": "Optional: scripted browser proof that a cyclic registry renders and the JS guard terminates.",
220
+ "adapter": "converge:pytest",
221
+ "convergence_style": "regression_hardening",
222
+ "required": false,
223
+ "proof_envelope": {
224
+ "environment": "local-unit + manual browser",
225
+ "surface": "grid_payload data + manual flow render",
226
+ "captured_at": "2026-06-15",
227
+ "fails_to_test": [
228
+ "automated assertion that the JS BFS guard terminates"
229
+ ]
230
+ }
231
+ }
232
+ ]
@@ -0,0 +1,29 @@
1
+ # emux web — monitor + steer fleet UI
2
+
3
+ Generated: 2026-06-15T18:52:27Z
4
+ Scope: Record the target, proof envelope, known gaps, and next repair command.
5
+
6
+ ## Canonical Contracts
7
+
8
+ - none recorded yet
9
+
10
+ ## Proof Artifacts
11
+
12
+ - none recorded yet
13
+
14
+ ## Current Status
15
+
16
+ Record the current pass, partial, blocked, and gap rows here. Do not mark a
17
+ browser/API full loop as real-surface pass unless its proof envelope records the
18
+ actual surface or `base_origin` exercised.
19
+
20
+ ## Next Command
21
+
22
+ ```bash
23
+ uv run pytest -q && emux web (manual real-surface checks at http://127.0.0.1:8689)
24
+ ```
25
+
26
+ ## Secret Hygiene
27
+
28
+ Do not commit raw recovery links, token hashes, access tokens, refresh tokens,
29
+ passwords, TOTP secrets, TOTP codes, otpauth URIs, JWTs, or provider secrets.
@@ -0,0 +1,12 @@
1
+ {"captured_at": "2026-06-15T18:54:32Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 1, "match": 0, "miss_large": 0, "miss_small": 0, "missing": 4, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 4, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 0.9574468085106383, "regression_count": 0, "score": 0.06382978723404255}
2
+ {"captured_at": "2026-06-15T18:54:49Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 1, "match": 0, "miss_large": 0, "miss_small": 0, "missing": 4, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 4, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 0.9574468085106383, "regression_count": 0, "score": 0.06382978723404255}
3
+ {"captured_at": "2026-06-15T18:58:51Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 1, "match": 0, "miss_large": 0, "miss_small": 0, "missing": 4, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 7, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 0.9591836734693877, "regression_count": 0, "score": 0.10204081632653061}
4
+ {"captured_at": "2026-06-15T18:59:11Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 1, "match": 0, "miss_large": 0, "miss_small": 0, "missing": 4, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 7, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 0.9591836734693877, "regression_count": 0, "score": 0.10204081632653061}
5
+ {"captured_at": "2026-06-15T19:11:51Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 0, "match": 0, "miss_large": 0, "miss_small": 0, "missing": 4, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 9, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 0.98, "regression_count": 0, "score": 0.14}
6
+ {"captured_at": "2026-06-15T19:11:51Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 0, "match": 0, "miss_large": 0, "miss_small": 0, "missing": 4, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 9, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 0.98, "regression_count": 0, "score": 0.14}
7
+ {"captured_at": "2026-06-15T19:12:50Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 0, "match": 1, "miss_large": 0, "miss_small": 0, "missing": 3, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 9, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 1.0, "regression_count": 0, "score": 0.16}
8
+ {"captured_at": "2026-06-15T19:12:51Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 0, "match": 1, "miss_large": 0, "miss_small": 0, "missing": 3, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 9, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 1.0, "regression_count": 0, "score": 0.16}
9
+ {"captured_at": "2026-06-15T19:13:14Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 0, "match": 2, "miss_large": 0, "miss_small": 0, "missing": 2, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 9, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 1.0, "regression_count": 0, "score": 0.16}
10
+ {"captured_at": "2026-06-15T19:13:15Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 0, "match": 2, "miss_large": 0, "miss_small": 0, "missing": 2, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 9, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 1.0, "regression_count": 0, "score": 0.16}
11
+ {"captured_at": "2026-06-15T21:08:03Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 1, "match": 2, "miss_large": 0, "miss_small": 0, "missing": 6, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 9, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 0.9615384615384616, "regression_count": 0, "score": 0.15384615384615385}
12
+ {"captured_at": "2026-06-15T21:08:04Z", "class_counts": {"blocked": 0, "drift": 0, "fail": 1, "match": 2, "miss_large": 0, "miss_small": 0, "missing": 6, "pass": 0, "pass_controlled_harness": 43, "pass_real_surface": 9, "pass_with_bypass": 1, "regression": 0, "rounding": 0, "skip": 0}, "drift_count": 0, "qualified_score": 0.9615384615384616, "regression_count": 0, "score": 0.15384615384615385}