methodproof 0.7.21__tar.gz → 0.7.23__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.
- {methodproof-0.7.21 → methodproof-0.7.23}/CHANGELOG.md +13 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/PKG-INFO +1 -1
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/cli.py +41 -7
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/config.py +2 -1
- {methodproof-0.7.21 → methodproof-0.7.23}/pyproject.toml +1 -1
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/conftest.py +1 -1
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_cli_start.py +7 -5
- methodproof-0.7.21/.code-review-graph/.gitignore +0 -3
- methodproof-0.7.21/.code-review-graph/graph.db +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/.github/workflows/ci.yml +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/.gitignore +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/LICENSE +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/README.md +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/__init__.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/__main__.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/_daemon.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/agents/__init__.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/agents/base.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/agents/music.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/agents/terminal.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/agents/watcher.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/analysis.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/binding.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/bip39.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/bridge.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/crypto.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/e2e.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/graph.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hook.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/__init__.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/claude_code.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/claude_code.sh +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/cline_hook.sh +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/codex_hook.sh +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/gemini_hook.sh +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/install.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/kiro_hook.sh +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/mcp_register.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/openclaw/HOOK.md +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/openclaw/handler.ts +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/openclaw_install.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/opencode_plugin.js +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/hooks/wrappers.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/integrity.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/kdf.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/keychain.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/live.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/lock.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/mcp.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/migrate_db.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/proxy.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/proxy_daemon.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/repos.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/skills/methodproof/SKILL.md +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/store.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/sync.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/tui/__init__.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/tui/consent.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/tui/init.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/tui/log.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/tui/login_success.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/tui/review.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/tui/start.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/tui/status.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/tui/theme.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/viewer.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/methodproof/wordlist.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/test_windows_compat.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/__init__.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_analysis.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_cli_auth.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_cli_config.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_cli_helpers.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_cli_session.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_cli_share.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_cli_update.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_e2e_integration.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_graph.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_hooks.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_live.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_openclaw_hooks.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_profiles.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_security.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_store.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_sync.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_viewer.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/tests/test_wrappers.py +0 -0
- {methodproof-0.7.21 → methodproof-0.7.23}/uv.lock +0 -0
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.7.23] — 2026-04-12
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- **`mp` alias works immediately after `init`** — `_install_alias` now creates a real symlink (`mp → methodproof`) in the same bin directory instead of writing an rc alias. No shell restart or eval needed. Falls back to rc alias if symlinking fails (e.g. read-only bin dir).
|
|
7
|
+
|
|
8
|
+
## [0.7.22] — 2026-04-11
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Username in session output** — `mp start` banner shows `Account: @username` (falls back to email). `mp stop` summary shows the same. Username fetched from `/auth/me` on login and stored in config profile.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- **`eval "$(methodproof shell-hook)"` missing `mp` alias** — `shell-hook` now emits both the command-logging hooks and `alias mp="methodproof"`, so eval fully activates the CLI without a shell restart.
|
|
15
|
+
|
|
3
16
|
## [0.7.20] — 2026-04-11
|
|
4
17
|
|
|
5
18
|
### Fixed
|
|
@@ -131,7 +131,21 @@ _ALIAS_MARKER = "# methodproof-alias"
|
|
|
131
131
|
|
|
132
132
|
|
|
133
133
|
def _install_alias() -> None:
|
|
134
|
-
"""
|
|
134
|
+
"""Install `mp` as an executable symlink next to `methodproof` in PATH.
|
|
135
|
+
Falls back to writing an alias in the shell rc if symlinking fails."""
|
|
136
|
+
import shutil
|
|
137
|
+
mp_exe = shutil.which("mp")
|
|
138
|
+
methodproof_exe = shutil.which("methodproof")
|
|
139
|
+
if mp_exe:
|
|
140
|
+
return # already exists
|
|
141
|
+
if methodproof_exe and sys.platform != "win32":
|
|
142
|
+
mp_path = Path(methodproof_exe).parent / "mp"
|
|
143
|
+
try:
|
|
144
|
+
mp_path.symlink_to(methodproof_exe)
|
|
145
|
+
return
|
|
146
|
+
except OSError:
|
|
147
|
+
pass # fall through to rc alias
|
|
148
|
+
# Fallback: write alias to shell rc (requires shell restart / eval)
|
|
135
149
|
rc, _ = hook.get_shell_rc()
|
|
136
150
|
if rc.exists() and _ALIAS_MARKER in rc.read_text():
|
|
137
151
|
return
|
|
@@ -484,14 +498,19 @@ def cmd_init(args: argparse.Namespace) -> None:
|
|
|
484
498
|
print("Signing key: exists")
|
|
485
499
|
|
|
486
500
|
_print_intro()
|
|
487
|
-
|
|
488
|
-
|
|
501
|
+
import shutil
|
|
502
|
+
if shutil.which("mp"):
|
|
503
|
+
print(" Run `mp start` to begin recording.\n")
|
|
504
|
+
else:
|
|
505
|
+
print(" Restart your shell or run this to activate `mp`:\n")
|
|
506
|
+
print(" eval \"$(methodproof shell-hook)\"\n")
|
|
489
507
|
|
|
490
508
|
|
|
491
509
|
def cmd_shell_hook(_args: argparse.Namespace) -> None:
|
|
492
510
|
"""Print the shell hook text for the current shell (for eval)."""
|
|
493
511
|
_, hook_text = hook.get_shell_rc()
|
|
494
|
-
|
|
512
|
+
alias = 'Set-Alias mp methodproof' if sys.platform == "win32" else 'alias mp="methodproof"'
|
|
513
|
+
print(hook_text.strip() + "\n" + alias)
|
|
495
514
|
|
|
496
515
|
|
|
497
516
|
# ── TUI mode helpers ──────────────────────────────────────────────────────────
|
|
@@ -1203,8 +1222,11 @@ def cmd_start(args: argparse.Namespace) -> None:
|
|
|
1203
1222
|
config.save(cfg)
|
|
1204
1223
|
|
|
1205
1224
|
active = [k for k, v in capture.items() if v]
|
|
1225
|
+
username = cfg.get("username")
|
|
1226
|
+
account_label = f"@{username}" if username else (cfg.get("email") or cfg.get("account_id", "")[:8])
|
|
1206
1227
|
print(f"\n{_banner()}")
|
|
1207
1228
|
print(f"Recording: {sid[:8]}")
|
|
1229
|
+
print(f"Account: {account_label}")
|
|
1208
1230
|
print(f"Watching: {watch_dir}")
|
|
1209
1231
|
if repo_url:
|
|
1210
1232
|
print(f"Repo: {repo_url}")
|
|
@@ -1397,7 +1419,7 @@ def cmd_stop(args: argparse.Namespace) -> None:
|
|
|
1397
1419
|
session = store.get_session(sid)
|
|
1398
1420
|
cfg["active_session"] = None
|
|
1399
1421
|
config.save(cfg)
|
|
1400
|
-
_print_summary(session, stats)
|
|
1422
|
+
_print_summary(session, stats, cfg)
|
|
1401
1423
|
|
|
1402
1424
|
|
|
1403
1425
|
def cmd_view(args: argparse.Namespace) -> None:
|
|
@@ -1705,6 +1727,13 @@ def cmd_login(args: argparse.Namespace) -> None:
|
|
|
1705
1727
|
cfg["account_id"] = claims.get("user_id", "")
|
|
1706
1728
|
cfg["last_auth_at"] = time.time()
|
|
1707
1729
|
cfg["master_key_fingerprint"] = "" # clear stale fingerprint from previous account
|
|
1730
|
+
# Fetch profile to store email and username
|
|
1731
|
+
try:
|
|
1732
|
+
profile = _request("GET", "/auth/me", api, poll["token"])
|
|
1733
|
+
cfg["email"] = profile.get("email", "")
|
|
1734
|
+
cfg["username"] = profile.get("username") or ""
|
|
1735
|
+
except Exception as exc:
|
|
1736
|
+
_log_debug("auth.profile_fetch_failed", error=str(exc))
|
|
1708
1737
|
config.save(cfg)
|
|
1709
1738
|
config.save_active_profile(cfg)
|
|
1710
1739
|
print(" done.\n")
|
|
@@ -1714,7 +1743,7 @@ def cmd_login(args: argparse.Namespace) -> None:
|
|
|
1714
1743
|
sync_research_consent(cfg["token"], cfg["api_url"])
|
|
1715
1744
|
from methodproof.tui.login_success import run as show_success
|
|
1716
1745
|
show_success(
|
|
1717
|
-
display_name=cfg.get("email") or cfg.get("account_id", "")[:8],
|
|
1746
|
+
display_name=cfg.get("username") or cfg.get("email") or cfg.get("account_id", "")[:8],
|
|
1718
1747
|
email=cfg.get("email", ""),
|
|
1719
1748
|
account_count=len(cfg.get("profiles", {})),
|
|
1720
1749
|
added=getattr(args, "add", False),
|
|
@@ -2011,11 +2040,16 @@ def _duration(s: dict) -> str:
|
|
|
2011
2040
|
return f"{secs // 60}:{secs % 60:02d}"
|
|
2012
2041
|
|
|
2013
2042
|
|
|
2014
|
-
def _print_summary(session: dict | None, stats: dict) -> None:
|
|
2043
|
+
def _print_summary(session: dict | None, stats: dict, cfg: dict | None = None) -> None:
|
|
2015
2044
|
if not session:
|
|
2016
2045
|
return
|
|
2046
|
+
cfg = cfg or {}
|
|
2047
|
+
username = cfg.get("username")
|
|
2048
|
+
account_label = f"@{username}" if username else (cfg.get("email") or cfg.get("account_id", "")[:8])
|
|
2017
2049
|
print(f"\n{_banner()}")
|
|
2018
2050
|
print(f"Session: {session['id'][:8]}")
|
|
2051
|
+
if account_label:
|
|
2052
|
+
print(f" Account: {account_label}")
|
|
2019
2053
|
print(f" Events: {session['total_events']}")
|
|
2020
2054
|
print(f" Duration: {_duration(session)}")
|
|
2021
2055
|
print(f" Graph: {stats['next']} links, {stats['causal']} causal")
|
|
@@ -42,6 +42,7 @@ _DEFAULTS: dict[str, Any] = {
|
|
|
42
42
|
"e2e_fingerprint": "",
|
|
43
43
|
"auto_update": False,
|
|
44
44
|
"account_id": "",
|
|
45
|
+
"username": "",
|
|
45
46
|
"last_auth_at": 0,
|
|
46
47
|
"local_ai_ports": [], # user-configured localhost ports for local LLM capture
|
|
47
48
|
"publish_redact": {
|
|
@@ -161,7 +162,7 @@ def save(cfg: dict[str, Any]) -> None:
|
|
|
161
162
|
# --- Multi-account profiles ---
|
|
162
163
|
|
|
163
164
|
_PROFILE_KEYS = [
|
|
164
|
-
"token", "refresh_token", "email", "account_id",
|
|
165
|
+
"token", "refresh_token", "email", "account_id", "username",
|
|
165
166
|
"last_auth_at", "master_key_fingerprint",
|
|
166
167
|
"e2e_mode", "e2e_fingerprint",
|
|
167
168
|
"journal_mode", "journal_credits",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "methodproof"
|
|
3
|
-
version = "0.7.
|
|
3
|
+
version = "0.7.23"
|
|
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"]
|
|
@@ -125,7 +125,7 @@ def cli_args():
|
|
|
125
125
|
"verbose": False, "streaming": False, "force": False,
|
|
126
126
|
"local": False, "api_url": None, "no_key": False, "auto": None,
|
|
127
127
|
"account": None, "purge": False, "keep_sessions": False,
|
|
128
|
-
"anonymous": False,
|
|
128
|
+
"anonymous": False, "yes": False,
|
|
129
129
|
}
|
|
130
130
|
defaults.update(kwargs)
|
|
131
131
|
return argparse.Namespace(**defaults)
|
|
@@ -427,11 +427,13 @@ def test_consent_detailed_redaction_toggle():
|
|
|
427
427
|
# ── cmd_init ──
|
|
428
428
|
|
|
429
429
|
|
|
430
|
-
@patch("methodproof.
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
430
|
+
@patch("methodproof.hook.install", return_value="hook installed")
|
|
431
|
+
@patch("methodproof.integrity.has_keypair", return_value=True)
|
|
432
|
+
def test_init_first_run(mock_keypair, mock_hook, cli_args, capsys):
|
|
433
|
+
# First run with --yes: all prompts auto-accepted, no stdin required
|
|
434
|
+
cli.cmd_init(cli_args(yes=True))
|
|
435
|
+
out = capsys.readouterr().out
|
|
436
|
+
assert "METHODPROOF" in out or "Recording" in out or "mp start" in out
|
|
435
437
|
|
|
436
438
|
|
|
437
439
|
@patch("methodproof.integrity.has_keypair", return_value=True)
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|