methodproof 0.7.28__tar.gz → 0.7.30__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.28 → methodproof-0.7.30}/CHANGELOG.md +10 -0
  2. {methodproof-0.7.28 → methodproof-0.7.30}/PKG-INFO +1 -1
  3. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/cli.py +45 -25
  4. {methodproof-0.7.28 → methodproof-0.7.30}/pyproject.toml +1 -1
  5. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_cli_start.py +3 -2
  6. {methodproof-0.7.28 → methodproof-0.7.30}/.github/workflows/ci.yml +0 -0
  7. {methodproof-0.7.28 → methodproof-0.7.30}/.gitignore +0 -0
  8. {methodproof-0.7.28 → methodproof-0.7.30}/LICENSE +0 -0
  9. {methodproof-0.7.28 → methodproof-0.7.30}/README.md +0 -0
  10. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/__init__.py +0 -0
  11. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/__main__.py +0 -0
  12. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/_daemon.py +0 -0
  13. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/agents/__init__.py +0 -0
  14. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/agents/base.py +0 -0
  15. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/agents/music.py +0 -0
  16. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/agents/terminal.py +0 -0
  17. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/agents/watcher.py +0 -0
  18. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/analysis.py +0 -0
  19. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/binding.py +0 -0
  20. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/bip39.py +0 -0
  21. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/bridge.py +0 -0
  22. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/config.py +0 -0
  23. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/crypto.py +0 -0
  24. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/e2e.py +0 -0
  25. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/graph.py +0 -0
  26. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hook.py +0 -0
  27. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/__init__.py +0 -0
  28. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/claude_code.py +0 -0
  29. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/claude_code.sh +0 -0
  30. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/cline_hook.sh +0 -0
  31. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/codex_hook.sh +0 -0
  32. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/gemini_hook.sh +0 -0
  33. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/install.py +0 -0
  34. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/kiro_hook.sh +0 -0
  35. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/mcp_register.py +0 -0
  36. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/openclaw/HOOK.md +0 -0
  37. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/openclaw/handler.ts +0 -0
  38. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/openclaw_install.py +0 -0
  39. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/opencode_plugin.js +0 -0
  40. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/hooks/wrappers.py +0 -0
  41. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/integrity.py +0 -0
  42. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/kdf.py +0 -0
  43. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/keychain.py +0 -0
  44. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/live.py +0 -0
  45. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/lock.py +0 -0
  46. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/mcp.py +0 -0
  47. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/migrate_db.py +0 -0
  48. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/proxy.py +0 -0
  49. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/proxy_daemon.py +0 -0
  50. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/repos.py +0 -0
  51. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/skills/methodproof/SKILL.md +0 -0
  52. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/store.py +0 -0
  53. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/sync.py +0 -0
  54. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/tui/__init__.py +0 -0
  55. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/tui/consent.py +0 -0
  56. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/tui/init.py +0 -0
  57. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/tui/log.py +0 -0
  58. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/tui/login_success.py +0 -0
  59. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/tui/review.py +0 -0
  60. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/tui/start.py +0 -0
  61. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/tui/status.py +0 -0
  62. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/tui/theme.py +0 -0
  63. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/viewer.py +0 -0
  64. {methodproof-0.7.28 → methodproof-0.7.30}/methodproof/wordlist.py +0 -0
  65. {methodproof-0.7.28 → methodproof-0.7.30}/test_windows_compat.py +0 -0
  66. {methodproof-0.7.28 → methodproof-0.7.30}/tests/__init__.py +0 -0
  67. {methodproof-0.7.28 → methodproof-0.7.30}/tests/conftest.py +0 -0
  68. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_analysis.py +0 -0
  69. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_cli_auth.py +0 -0
  70. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_cli_config.py +0 -0
  71. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_cli_helpers.py +0 -0
  72. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_cli_session.py +0 -0
  73. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_cli_share.py +0 -0
  74. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_cli_update.py +0 -0
  75. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_e2e_integration.py +0 -0
  76. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_graph.py +0 -0
  77. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_hooks.py +0 -0
  78. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_live.py +0 -0
  79. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_openclaw_hooks.py +0 -0
  80. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_profiles.py +0 -0
  81. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_security.py +0 -0
  82. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_store.py +0 -0
  83. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_sync.py +0 -0
  84. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_viewer.py +0 -0
  85. {methodproof-0.7.28 → methodproof-0.7.30}/tests/test_wrappers.py +0 -0
  86. {methodproof-0.7.28 → methodproof-0.7.30}/uv.lock +0 -0
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.30] — 2026-04-12
4
+
5
+ ### Changed
6
+ - **Removed Basic tier from journal entitlement** — tiers are Free and Pro+ only. Dropped the server-side credit fetch for Basic; `_journal_entitlement` now returns `"unlimited"` for Pro+ and local credit count for Free.
7
+
8
+ ## [0.7.29] — 2026-04-12
9
+
10
+ ### Changed
11
+ - **Journal mode output is now tier-aware** — Pro/Team/Admin/Superadmin users see "Unlimited journal entries (Pro plan)" everywhere journal credits are displayed (`mp journal on`, `mp journal status`, `mp start --journal`, session mode line, consent flow). Basic users get a live credit count fetched from `GET /auth/me` (falls back to local cache if offline). Free users see their local credit count as before. Credit deduction on `--journal` is skipped for unlimited tiers.
12
+
3
13
  ## [0.7.28] — 2026-04-12
4
14
 
5
15
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: methodproof
3
- Version: 0.7.28
3
+ Version: 0.7.30
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
@@ -156,13 +156,34 @@ def _install_alias() -> None:
156
156
  f.write(alias)
157
157
 
158
158
 
159
- def _print_journal_intro(credits: int) -> None:
160
- """Show journal mode introduction with remaining credits."""
159
+ _PRO_TIERS = {"pro", "team", "admin", "superadmin"}
160
+
161
+
162
+ def _journal_entitlement(cfg: dict) -> str | int:
163
+ """Return 'unlimited' for Pro+ users, or an int credit count for free users."""
164
+ token = cfg.get("token", "")
165
+ claims = _decode_jwt_claims(token) if token else {}
166
+ account_type = claims.get("account_type", "free").lower()
167
+ if account_type in _PRO_TIERS:
168
+ return "unlimited"
169
+ return int(cfg.get("journal_credits", 0))
170
+
171
+
172
+ def _journal_credits_line(entitlement: str | int) -> str:
173
+ if entitlement == "unlimited":
174
+ return "Unlimited journal entries (Pro plan)"
175
+ n = int(entitlement)
176
+ label = f"{n} free journal credit{'s' if n != 1 else ''}"
177
+ return f"{label} (up to {config.FREE_JOURNAL_MAX_HOURS}h per session)"
178
+
179
+
180
+ def _print_journal_intro(cfg: dict) -> None:
181
+ """Show journal mode introduction with tier-aware credit status."""
182
+ entitlement = _journal_entitlement(cfg)
161
183
  print(" ┌─────────────────────────────────────────────────────┐")
162
184
  print(" │ Journal Mode — full content capture │")
163
185
  print(" └─────────────────────────────────────────────────────┘")
164
- print(f" You have {credits} free journal credit{'s' if credits != 1 else ''} "
165
- f"(sessions up to {config.FREE_JOURNAL_MAX_HOURS}h each).")
186
+ print(f" {_journal_credits_line(entitlement)}")
166
187
  print()
167
188
  print(" By default, MethodProof captures structural metadata only —")
168
189
  print(" file paths, line counts, timing, tool names. Journal mode")
@@ -199,9 +220,8 @@ def _run_consent(cfg: dict) -> dict:
199
220
  cfg["research_consent"] = False
200
221
  cfg["publish_redact"] = dict(config._DEFAULTS["publish_redact"])
201
222
  cfg["consent_acknowledged"] = True
202
- credits = cfg.get("journal_credits", config._DEFAULTS["journal_credits"])
203
223
  print("\n Minimal capture enabled (file changes + git commits).\n")
204
- _print_journal_intro(credits)
224
+ _print_journal_intro(cfg)
205
225
  print(" Customize anytime: `methodproof consent`\n")
206
226
  return cfg
207
227
 
@@ -210,9 +230,8 @@ def _run_consent(cfg: dict) -> dict:
210
230
  cfg["research_consent"] = False
211
231
  cfg["publish_redact"] = dict(config._DEFAULTS["publish_redact"])
212
232
  cfg["consent_acknowledged"] = True
213
- credits = cfg.get("journal_credits", config._DEFAULTS["journal_credits"])
214
233
  print(f"\n {_rainbow('Full Spectrum')} enabled — free live streaming unlocked.\n")
215
- _print_journal_intro(credits)
234
+ _print_journal_intro(cfg)
216
235
  print(" Customize anytime: `methodproof consent`\n")
217
236
  return cfg
218
237
 
@@ -873,7 +892,8 @@ def cmd_journal(args: argparse.Namespace) -> None:
873
892
  """Journal mode — full content capture."""
874
893
  subcmd = getattr(args, "journal_cmd", None)
875
894
  cfg = config.load()
876
- credits = cfg.get("journal_credits", 0)
895
+ entitlement = _journal_entitlement(cfg)
896
+ is_unlimited = entitlement == "unlimited"
877
897
 
878
898
  if subcmd == "on":
879
899
  print("Journal Mode — Full Content Capture\n")
@@ -884,12 +904,9 @@ def cmd_journal(args: argparse.Namespace) -> None:
884
904
  print(" • Terminal output (not just commands)")
885
905
  print(" • Tool call parameters and results\n")
886
906
  print("All content is encrypted (AES-256-GCM) and subject to your consent settings.\n")
887
- if credits > 0:
888
- print(f"You have {credits} free journal credit{'s' if credits != 1 else ''} "
889
- f"(sessions up to {config.FREE_JOURNAL_MAX_HOURS}h each).")
890
- print("After credits are used, journal mode requires a Pro plan.\n")
891
- else:
892
- print("Journal mode requires a Pro plan (or free credits if available).\n")
907
+ print(f" {_journal_credits_line(entitlement)}\n")
908
+ if not is_unlimited and int(entitlement) == 0:
909
+ print("You have no credits remaining. Upgrade to Pro for unlimited journal entries.\n")
893
910
  answer = input("Enable journal mode? [y/N] ").strip().lower()
894
911
  if answer != "y":
895
912
  print("Journal mode not enabled.")
@@ -913,9 +930,7 @@ def cmd_journal(args: argparse.Namespace) -> None:
913
930
  print("Journal mode: OFF (structural only)")
914
931
  print(" Only metadata captured: lengths, types, timing, file paths.")
915
932
  print(" Enable with: methodproof journal on")
916
- if credits > 0:
917
- print(f" Free journal credits: {credits} "
918
- f"(up to {config.FREE_JOURNAL_MAX_HOURS}h per session)")
933
+ print(f" {_journal_credits_line(entitlement)}")
919
934
 
920
935
  else:
921
936
  print("Usage: methodproof journal [on|off|status]")
@@ -1196,12 +1211,17 @@ def cmd_start(args: argparse.Namespace) -> None:
1196
1211
  # Journal mode
1197
1212
  if getattr(args, "journal", False):
1198
1213
  cfg["journal_mode"] = True
1199
- credits = cfg.get("journal_credits", 0)
1200
- if credits > 0:
1201
- cfg["journal_credits"] = credits - 1
1202
- print(f"Journal mode ON (free credit used — {credits - 1} remaining, {config.FREE_JOURNAL_MAX_HOURS}h cap).")
1214
+ entitlement = _journal_entitlement(cfg)
1215
+ if entitlement == "unlimited":
1216
+ print("Journal mode ON (full content capture).")
1203
1217
  else:
1204
- print("Journal mode ON for this session (full content capture).")
1218
+ credits = int(entitlement)
1219
+ if credits > 0:
1220
+ cfg["journal_credits"] = credits - 1
1221
+ remaining = credits - 1
1222
+ print(f"Journal mode ON (free credit used — {remaining} remaining, {config.FREE_JOURNAL_MAX_HOURS}h cap).")
1223
+ else:
1224
+ print("Journal mode ON for this session (full content capture).")
1205
1225
  config.save(cfg)
1206
1226
 
1207
1227
  # E2E mode
@@ -1558,8 +1578,8 @@ def cmd_status(args: argparse.Namespace) -> None:
1558
1578
  # Modes
1559
1579
  modes = []
1560
1580
  if cfg.get("journal_mode"):
1561
- credits = cfg.get("journal_credits", 0)
1562
- modes.append(f"journal ({credits} credits)")
1581
+ ent = _journal_entitlement(cfg)
1582
+ modes.append("journal (unlimited)" if ent == "unlimited" else f"journal ({ent} credits)")
1563
1583
  if cfg.get("e2e_mode"):
1564
1584
  fp = cfg.get("e2e_fingerprint", "")
1565
1585
  modes.append(f"e2e ({fp[:8]})" if fp else "e2e")
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "methodproof"
3
- version = "0.7.28"
3
+ version = "0.7.30"
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"]
@@ -118,9 +118,10 @@ def test_start_creates_session_and_spawns_daemon(mock_sleep, mock_popen, mock_re
118
118
  @patch("subprocess.Popen")
119
119
  @patch("time.sleep")
120
120
  def test_start_journal_decrements_credits(mock_sleep, mock_popen, mock_req, mock_repo, mock_update, mock_auth,
121
- mock_hook, mock_alive, logged_in_cfg, cli_args,
121
+ mock_hook, mock_alive, logged_in_cfg, fake_jwt, cli_args,
122
122
  monkeypatch, capsys):
123
- cfg = logged_in_cfg(account_id="acct-1")
123
+ # Use free-tier JWT — pro/team skips credit deduction (unlimited)
124
+ cfg = logged_in_cfg(account_id="acct-1", token=fake_jwt(user_id="acct-1", account_type="free"))
124
125
  cfg["journal_credits"] = 2
125
126
  config.save(cfg)
126
127
  pidfile = config.DIR / "methodproof.pid"
File without changes
File without changes
File without changes
File without changes