methodproof 0.7.24__tar.gz → 0.7.26__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.24 → methodproof-0.7.26}/CHANGELOG.md +12 -0
  2. {methodproof-0.7.24 → methodproof-0.7.26}/PKG-INFO +1 -1
  3. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/config.py +4 -0
  4. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/claude_code.py +21 -3
  5. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/tui/start.py +25 -14
  6. {methodproof-0.7.24 → methodproof-0.7.26}/pyproject.toml +1 -1
  7. {methodproof-0.7.24 → methodproof-0.7.26}/.github/workflows/ci.yml +0 -0
  8. {methodproof-0.7.24 → methodproof-0.7.26}/.gitignore +0 -0
  9. {methodproof-0.7.24 → methodproof-0.7.26}/LICENSE +0 -0
  10. {methodproof-0.7.24 → methodproof-0.7.26}/README.md +0 -0
  11. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/__init__.py +0 -0
  12. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/__main__.py +0 -0
  13. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/_daemon.py +0 -0
  14. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/agents/__init__.py +0 -0
  15. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/agents/base.py +0 -0
  16. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/agents/music.py +0 -0
  17. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/agents/terminal.py +0 -0
  18. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/agents/watcher.py +0 -0
  19. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/analysis.py +0 -0
  20. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/binding.py +0 -0
  21. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/bip39.py +0 -0
  22. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/bridge.py +0 -0
  23. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/cli.py +0 -0
  24. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/crypto.py +0 -0
  25. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/e2e.py +0 -0
  26. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/graph.py +0 -0
  27. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hook.py +0 -0
  28. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/__init__.py +0 -0
  29. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/claude_code.sh +0 -0
  30. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/cline_hook.sh +0 -0
  31. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/codex_hook.sh +0 -0
  32. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/gemini_hook.sh +0 -0
  33. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/install.py +0 -0
  34. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/kiro_hook.sh +0 -0
  35. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/mcp_register.py +0 -0
  36. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/openclaw/HOOK.md +0 -0
  37. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/openclaw/handler.ts +0 -0
  38. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/openclaw_install.py +0 -0
  39. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/opencode_plugin.js +0 -0
  40. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/hooks/wrappers.py +0 -0
  41. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/integrity.py +0 -0
  42. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/kdf.py +0 -0
  43. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/keychain.py +0 -0
  44. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/live.py +0 -0
  45. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/lock.py +0 -0
  46. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/mcp.py +0 -0
  47. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/migrate_db.py +0 -0
  48. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/proxy.py +0 -0
  49. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/proxy_daemon.py +0 -0
  50. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/repos.py +0 -0
  51. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/skills/methodproof/SKILL.md +0 -0
  52. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/store.py +0 -0
  53. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/sync.py +0 -0
  54. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/tui/__init__.py +0 -0
  55. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/tui/consent.py +0 -0
  56. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/tui/init.py +0 -0
  57. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/tui/log.py +0 -0
  58. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/tui/login_success.py +0 -0
  59. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/tui/review.py +0 -0
  60. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/tui/status.py +0 -0
  61. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/tui/theme.py +0 -0
  62. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/viewer.py +0 -0
  63. {methodproof-0.7.24 → methodproof-0.7.26}/methodproof/wordlist.py +0 -0
  64. {methodproof-0.7.24 → methodproof-0.7.26}/test_windows_compat.py +0 -0
  65. {methodproof-0.7.24 → methodproof-0.7.26}/tests/__init__.py +0 -0
  66. {methodproof-0.7.24 → methodproof-0.7.26}/tests/conftest.py +0 -0
  67. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_analysis.py +0 -0
  68. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_cli_auth.py +0 -0
  69. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_cli_config.py +0 -0
  70. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_cli_helpers.py +0 -0
  71. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_cli_session.py +0 -0
  72. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_cli_share.py +0 -0
  73. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_cli_start.py +0 -0
  74. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_cli_update.py +0 -0
  75. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_e2e_integration.py +0 -0
  76. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_graph.py +0 -0
  77. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_hooks.py +0 -0
  78. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_live.py +0 -0
  79. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_openclaw_hooks.py +0 -0
  80. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_profiles.py +0 -0
  81. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_security.py +0 -0
  82. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_store.py +0 -0
  83. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_sync.py +0 -0
  84. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_viewer.py +0 -0
  85. {methodproof-0.7.24 → methodproof-0.7.26}/tests/test_wrappers.py +0 -0
  86. {methodproof-0.7.24 → methodproof-0.7.26}/uv.lock +0 -0
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.26] — 2026-04-12
4
+
5
+ ### Fixed
6
+ - **Journal mode missing tool and prompt content** — `tool_call`, `tool_result`, and `user_prompt` hook events never captured content even with journal mode on; the extractors never included it. `tool_call` now captures `tool_input_preview` (command/path/query smartly extracted), `tool_result` captures `result_preview` (500 char cap), `user_prompt` captures `prompt_text`. All three fields are added to `JOURNAL_CONTENT_FIELDS` so they're stripped when journal is off.
7
+
8
+ ## [0.7.25] — 2026-04-12
9
+
10
+ ### Fixed
11
+ - **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"]`.
12
+ - **Tier hardcoded as "Pro" in session bar** — decoded from JWT on mount; now shows actual account type (Free / Basic / Pro / Team).
13
+ - **Unused `Worker`/`WorkerState` imports** removed from `tui/start.py`.
14
+
3
15
  ## [0.7.24] — 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.24
3
+ Version: 0.7.26
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
@@ -114,6 +114,10 @@ JOURNAL_CONTENT_FIELDS: list[tuple[str, str]] = [
114
114
  ("browser_ai_chat", "url"),
115
115
  # Tasks — subject reveals intent
116
116
  ("task_created", "subject"),
117
+ # Claude Code hooks — tool input/output and raw user prompt
118
+ ("user_prompt", "prompt_text"),
119
+ ("tool_call", "tool_input_preview"),
120
+ ("tool_result", "result_preview"),
117
121
  ]
118
122
 
119
123
 
@@ -58,13 +58,31 @@ _TYPE_MAP = {
58
58
 
59
59
  _TOOL = "claude_code"
60
60
 
61
+ def _tool_input_preview(d: dict) -> str:
62
+ """Compact one-line summary of tool input for journal mode."""
63
+ inp = d.get("tool_input") or {}
64
+ # Flatten the most useful field per tool rather than dumping the whole dict
65
+ for key in ("command", "file_path", "path", "query", "url", "description"):
66
+ if key in inp:
67
+ return str(inp[key])[:300]
68
+ return json.dumps(inp)[:300] if inp else ""
69
+
70
+
61
71
  _META_EXTRACTORS = {
62
72
  "UserPromptSubmit": lambda d: {
63
- "tool": _TOOL, "prompt_preview": _build_prompt_meta(d.get("prompt") or "").get("prompt_summary", ""),
73
+ "tool": _TOOL,
74
+ "prompt_text": d.get("prompt") or "",
75
+ "prompt_preview": _build_prompt_meta(d.get("prompt") or "").get("prompt_summary", ""),
64
76
  "prompt_length": len(d.get("prompt") or ""),
65
77
  },
66
- "PreToolUse": lambda d: {"tool": _TOOL, "tool_name": d.get("tool_name", "unknown")},
67
- "PostToolUse": lambda d: {"tool": _TOOL, "tool_name": d.get("tool_name", "unknown"), "success": True},
78
+ "PreToolUse": lambda d: {
79
+ "tool": _TOOL, "tool_name": d.get("tool_name", "unknown"),
80
+ "tool_input_preview": _tool_input_preview(d),
81
+ },
82
+ "PostToolUse": lambda d: {
83
+ "tool": _TOOL, "tool_name": d.get("tool_name", "unknown"), "success": True,
84
+ "result_preview": str(d.get("tool_response") or "")[:500],
85
+ },
68
86
  "PostToolUseFailure": lambda d: {
69
87
  "tool": _TOOL, "tool_name": d.get("tool_name", "unknown"),
70
88
  "success": False, "is_interrupt": d.get("is_interrupt", False),
@@ -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:
@@ -173,25 +181,28 @@ class StartApp(App[None]):
173
181
 
174
182
  def _fmt_meta(ev: dict) -> str:
175
183
  etype = ev.get("type", "")
184
+ meta = ev.get("metadata") or {}
185
+ if not isinstance(meta, dict):
186
+ meta = {}
176
187
  if etype in ("file_edit", "file_create", "file_delete"):
177
- path = ev.get("path") or ev.get("file_path", "")
178
- delta = ev.get("line_delta") or ev.get("lines_added", "")
179
- 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()
180
191
  if etype == "terminal_cmd":
181
- cmd = ev.get("command", "")[:40]
182
- ec = ev.get("exit_code", 0)
192
+ cmd = (meta.get("command") or "")[:40]
193
+ ec = meta.get("exit_code", 0)
183
194
  return f"{cmd} {'✓' if ec == 0 else f'✗{ec}'}"
184
195
  if etype == "git_commit":
185
- return (ev.get("message") or "")[:40]
196
+ return (meta.get("message") or "")[:40]
186
197
  if etype in ("llm_prompt", "agent_prompt"):
187
- tokens = ev.get("prompt_tokens") or ev.get("input_length", "")
198
+ tokens = meta.get("prompt_tokens") or meta.get("input_length", "")
188
199
  return f"{tokens} tokens" if tokens else ""
189
200
  if etype in ("llm_completion", "agent_completion"):
190
- tokens = ev.get("completion_tokens") or ev.get("output_length", "")
201
+ tokens = meta.get("completion_tokens") or meta.get("output_length", "")
191
202
  dur = ev.get("duration_ms", "")
192
203
  return f"{tokens} tokens {dur}ms" if tokens else ""
193
204
  if etype == "test_run":
194
- p, f = ev.get("passed", 0), ev.get("failed", 0)
205
+ p, f = meta.get("passed", 0), meta.get("failed", 0)
195
206
  return f"{p} passed {f} failed" if f else f"{p} passed"
196
207
  return ""
197
208
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "methodproof"
3
- version = "0.7.24"
3
+ version = "0.7.26"
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