methodproof 0.7.23__tar.gz → 0.7.25__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 (86) hide show
  1. {methodproof-0.7.23 → methodproof-0.7.25}/CHANGELOG.md +12 -0
  2. {methodproof-0.7.23 → methodproof-0.7.25}/PKG-INFO +1 -1
  3. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/store.py +21 -0
  4. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/tui/start.py +27 -15
  5. {methodproof-0.7.23 → methodproof-0.7.25}/pyproject.toml +1 -1
  6. {methodproof-0.7.23 → methodproof-0.7.25}/.github/workflows/ci.yml +0 -0
  7. {methodproof-0.7.23 → methodproof-0.7.25}/.gitignore +0 -0
  8. {methodproof-0.7.23 → methodproof-0.7.25}/LICENSE +0 -0
  9. {methodproof-0.7.23 → methodproof-0.7.25}/README.md +0 -0
  10. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/__init__.py +0 -0
  11. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/__main__.py +0 -0
  12. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/_daemon.py +0 -0
  13. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/agents/__init__.py +0 -0
  14. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/agents/base.py +0 -0
  15. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/agents/music.py +0 -0
  16. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/agents/terminal.py +0 -0
  17. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/agents/watcher.py +0 -0
  18. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/analysis.py +0 -0
  19. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/binding.py +0 -0
  20. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/bip39.py +0 -0
  21. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/bridge.py +0 -0
  22. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/cli.py +0 -0
  23. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/config.py +0 -0
  24. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/crypto.py +0 -0
  25. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/e2e.py +0 -0
  26. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/graph.py +0 -0
  27. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hook.py +0 -0
  28. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/__init__.py +0 -0
  29. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/claude_code.py +0 -0
  30. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/claude_code.sh +0 -0
  31. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/cline_hook.sh +0 -0
  32. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/codex_hook.sh +0 -0
  33. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/gemini_hook.sh +0 -0
  34. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/install.py +0 -0
  35. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/kiro_hook.sh +0 -0
  36. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/mcp_register.py +0 -0
  37. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/openclaw/HOOK.md +0 -0
  38. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/openclaw/handler.ts +0 -0
  39. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/openclaw_install.py +0 -0
  40. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/opencode_plugin.js +0 -0
  41. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/hooks/wrappers.py +0 -0
  42. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/integrity.py +0 -0
  43. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/kdf.py +0 -0
  44. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/keychain.py +0 -0
  45. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/live.py +0 -0
  46. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/lock.py +0 -0
  47. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/mcp.py +0 -0
  48. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/migrate_db.py +0 -0
  49. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/proxy.py +0 -0
  50. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/proxy_daemon.py +0 -0
  51. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/repos.py +0 -0
  52. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/skills/methodproof/SKILL.md +0 -0
  53. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/sync.py +0 -0
  54. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/tui/__init__.py +0 -0
  55. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/tui/consent.py +0 -0
  56. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/tui/init.py +0 -0
  57. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/tui/log.py +0 -0
  58. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/tui/login_success.py +0 -0
  59. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/tui/review.py +0 -0
  60. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/tui/status.py +0 -0
  61. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/tui/theme.py +0 -0
  62. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/viewer.py +0 -0
  63. {methodproof-0.7.23 → methodproof-0.7.25}/methodproof/wordlist.py +0 -0
  64. {methodproof-0.7.23 → methodproof-0.7.25}/test_windows_compat.py +0 -0
  65. {methodproof-0.7.23 → methodproof-0.7.25}/tests/__init__.py +0 -0
  66. {methodproof-0.7.23 → methodproof-0.7.25}/tests/conftest.py +0 -0
  67. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_analysis.py +0 -0
  68. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_cli_auth.py +0 -0
  69. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_cli_config.py +0 -0
  70. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_cli_helpers.py +0 -0
  71. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_cli_session.py +0 -0
  72. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_cli_share.py +0 -0
  73. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_cli_start.py +0 -0
  74. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_cli_update.py +0 -0
  75. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_e2e_integration.py +0 -0
  76. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_graph.py +0 -0
  77. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_hooks.py +0 -0
  78. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_live.py +0 -0
  79. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_openclaw_hooks.py +0 -0
  80. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_profiles.py +0 -0
  81. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_security.py +0 -0
  82. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_store.py +0 -0
  83. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_sync.py +0 -0
  84. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_viewer.py +0 -0
  85. {methodproof-0.7.23 → methodproof-0.7.25}/tests/test_wrappers.py +0 -0
  86. {methodproof-0.7.23 → methodproof-0.7.25}/uv.lock +0 -0
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.25] — 2026-04-12
4
+
5
+ ### Fixed
6
+ - **TUI event metadata never rendered** — `_fmt_meta` read fields like `path`, `command`, `message` from the top-level event dict, but they live inside the `metadata` sub-dict. All event-type formatters now read from `ev["metadata"]`.
7
+ - **Tier hardcoded as "Pro" in session bar** — decoded from JWT on mount; now shows actual account type (Free / Basic / Pro / Team).
8
+ - **Unused `Worker`/`WorkerState` imports** removed from `tui/start.py`.
9
+
10
+ ## [0.7.24] — 2026-04-12
11
+
12
+ ### Fixed
13
+ - **TUI event feed was always empty** — `_poll_events` called `store.get_session_events` which did not exist; `except Exception: return` silently swallowed the `AttributeError`. Added `get_session_events(session_id, after_id="")` to store — uses SQLite `rowid` for monotonic pagination so the TUI feed populates in real time. Also surfaced poll errors to the Textual log instead of swallowing them.
14
+
3
15
  ## [0.7.23] — 2026-04-12
4
16
 
5
17
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: methodproof
3
- Version: 0.7.23
3
+ Version: 0.7.25
4
4
  Summary: See how you code. Capture and visualize your engineering process.
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -247,6 +247,27 @@ def get_events(session_id: str) -> list[dict[str, Any]]:
247
247
  return result
248
248
 
249
249
 
250
+ def get_session_events(session_id: str, after_id: str = "") -> list[dict[str, Any]]:
251
+ """Return events for session, optionally after a given event ID (for TUI polling)."""
252
+ db = _db()
253
+ if after_id:
254
+ row = db.execute("SELECT rowid FROM events WHERE id = ?", (after_id,)).fetchone()
255
+ after_rowid = row[0] if row else 0
256
+ else:
257
+ after_rowid = 0
258
+ rows = db.execute(
259
+ "SELECT rowid, * FROM events WHERE session_id = ? AND rowid > ? ORDER BY rowid",
260
+ (session_id, after_rowid),
261
+ ).fetchall()
262
+ result = []
263
+ for r in rows:
264
+ d = dict(r)
265
+ d["ts"] = d.pop("timestamp", 0)
266
+ d["metadata"] = _decompress_meta(d["metadata"])
267
+ result.append(d)
268
+ return result
269
+
270
+
250
271
  def get_graph(session_id: str) -> dict[str, Any]:
251
272
  """Build GraphResponse-compatible dict from SQLite."""
252
273
  events = get_events(session_id)
@@ -1,6 +1,7 @@
1
1
  """Textual TUI for mp start — live session event feed."""
2
2
  from __future__ import annotations
3
3
 
4
+ import json
4
5
  import time
5
6
  from datetime import datetime, UTC
6
7
 
@@ -9,9 +10,7 @@ from textual.binding import Binding
9
10
  from textual.containers import Horizontal, Vertical
10
11
  from textual.reactive import reactive
11
12
  from textual.widgets import Footer, Header, RichLog, Static
12
- from textual.worker import Worker, WorkerState
13
-
14
- from methodproof import store
13
+ from methodproof import config, store
15
14
  from methodproof.tui.theme import BASE_CSS, BORDER, DIM, GOLD, GREEN, PURPLE, RED, TEXT
16
15
 
17
16
  _CSS = BASE_CSS + f"""
@@ -94,7 +93,7 @@ class StartApp(App[None]):
94
93
  watch_dir = self._session.get("watch_dir", "?")
95
94
  sid = self._session_id[:8]
96
95
  yield Static(
97
- f" session: [{GOLD}]{sid}[/{GOLD}] · {watch_dir} · [{GREEN}]●[/{GREEN}] 00:00:00 · [{PURPLE}]Pro[/{PURPLE}]",
96
+ f" session: [{GOLD}]{sid}[/{GOLD}] · {watch_dir} · [{GREEN}]●[/{GREEN}] 00:00:00",
98
97
  id="session-bar",
99
98
  markup=True,
100
99
  )
@@ -108,6 +107,15 @@ class StartApp(App[None]):
108
107
  yield Footer()
109
108
 
110
109
  def on_mount(self) -> None:
110
+ import base64
111
+ cfg = config.load()
112
+ token = cfg.get("token", "")
113
+ try:
114
+ payload = token.split(".")[1] + "=="
115
+ claims = json.loads(base64.urlsafe_b64decode(payload))
116
+ except Exception:
117
+ claims = {}
118
+ self._account_type = (claims.get("account_type") or "free").capitalize()
111
119
  self.set_interval(_POLL_INTERVAL, self._poll_events)
112
120
  self.set_interval(1.0, self._tick_timer)
113
121
 
@@ -120,7 +128,7 @@ class StartApp(App[None]):
120
128
  watch_dir = self._session.get("watch_dir", "?")
121
129
  self.query_one("#session-bar", Static).update(
122
130
  f" session: [{GOLD}]{sid}[/{GOLD}] · {watch_dir} · [{GREEN}]●[/{GREEN}]"
123
- f" {h:02d}:{m:02d}:{s:02d} · [{PURPLE}]Pro[/{PURPLE}]"
131
+ f" {h:02d}:{m:02d}:{s:02d} · [{PURPLE}]{self._account_type}[/{PURPLE}]"
124
132
  )
125
133
 
126
134
  def _poll_events(self) -> None:
@@ -128,7 +136,8 @@ class StartApp(App[None]):
128
136
  return
129
137
  try:
130
138
  events = store.get_session_events(self._session_id, after_id=self._last_seen_id)
131
- except Exception:
139
+ except Exception as exc:
140
+ self.log.warning(f"poll_events failed: {exc}")
132
141
  return
133
142
 
134
143
  feed = self.query_one(RichLog)
@@ -172,25 +181,28 @@ class StartApp(App[None]):
172
181
 
173
182
  def _fmt_meta(ev: dict) -> str:
174
183
  etype = ev.get("type", "")
184
+ meta = ev.get("metadata") or {}
185
+ if not isinstance(meta, dict):
186
+ meta = {}
175
187
  if etype in ("file_edit", "file_create", "file_delete"):
176
- path = ev.get("path") or ev.get("file_path", "")
177
- delta = ev.get("line_delta") or ev.get("lines_added", "")
178
- return f"{path} {f'+{delta}' if delta else ''}"
188
+ path = meta.get("path") or meta.get("file_path", "")
189
+ delta = meta.get("line_delta") or meta.get("lines_added", "")
190
+ return f"{path} {f'+{delta}' if delta else ''}".strip()
179
191
  if etype == "terminal_cmd":
180
- cmd = ev.get("command", "")[:40]
181
- ec = ev.get("exit_code", 0)
192
+ cmd = (meta.get("command") or "")[:40]
193
+ ec = meta.get("exit_code", 0)
182
194
  return f"{cmd} {'✓' if ec == 0 else f'✗{ec}'}"
183
195
  if etype == "git_commit":
184
- return (ev.get("message") or "")[:40]
196
+ return (meta.get("message") or "")[:40]
185
197
  if etype in ("llm_prompt", "agent_prompt"):
186
- tokens = ev.get("prompt_tokens") or ev.get("input_length", "")
198
+ tokens = meta.get("prompt_tokens") or meta.get("input_length", "")
187
199
  return f"{tokens} tokens" if tokens else ""
188
200
  if etype in ("llm_completion", "agent_completion"):
189
- tokens = ev.get("completion_tokens") or ev.get("output_length", "")
201
+ tokens = meta.get("completion_tokens") or meta.get("output_length", "")
190
202
  dur = ev.get("duration_ms", "")
191
203
  return f"{tokens} tokens {dur}ms" if tokens else ""
192
204
  if etype == "test_run":
193
- p, f = ev.get("passed", 0), ev.get("failed", 0)
205
+ p, f = meta.get("passed", 0), meta.get("failed", 0)
194
206
  return f"{p} passed {f} failed" if f else f"{p} passed"
195
207
  return ""
196
208
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "methodproof"
3
- version = "0.7.23"
3
+ version = "0.7.25"
4
4
  description = "See how you code. Capture and visualize your engineering process."
5
5
  requires-python = ">=3.11"
6
6
  dependencies = ["watchdog>=4.0", "websocket-client>=1.7", "cryptography>=43.0", "keyring>=25.0", "textual>=0.59", "rich>=13.7"]
File without changes
File without changes
File without changes
File without changes