tycho-cli 0.0.6__tar.gz → 0.0.7__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 (68) hide show
  1. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/PKG-INFO +1 -1
  2. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_update.py +14 -4
  3. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/__init__.py +1 -1
  4. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/cli.py +16 -9
  5. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/.github/workflows/ci.yml +0 -0
  6. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/.github/workflows/release.yml +0 -0
  7. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/.gitignore +0 -0
  8. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/.tycho.toml +0 -0
  9. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/CONTRIBUTING.md +0 -0
  10. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/LICENSE +0 -0
  11. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/README.md +0 -0
  12. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/docs/bundler-spike.md +0 -0
  13. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/docs/harness-support.md +0 -0
  14. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/docs/hooks.md +0 -0
  15. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/docs/transcript-structures.md +0 -0
  16. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/docs/tycho-web.md +0 -0
  17. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/packaging/homebrew/tycho.rb +0 -0
  18. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/packaging/npm/bin/tycho.js +0 -0
  19. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/packaging/npm/package.json +0 -0
  20. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/pyproject.toml +0 -0
  21. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/conftest.py +0 -0
  22. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/codex_transcript_sample.jsonl +0 -0
  23. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/cursor_stop_payload.json +0 -0
  24. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/cursor_transcript_sample.jsonl +0 -0
  25. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/eval/claude_masked_red_suite.jsonl +0 -0
  26. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/eval/codex_masked_red_suite.jsonl +0 -0
  27. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/eval/cursor_masked_red_suite.jsonl +0 -0
  28. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/eval/opencode_masked_red_suite.json +0 -0
  29. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/opencode_transcript_sample.json +0 -0
  30. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/transcript_multiturn.jsonl +0 -0
  31. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/transcript_sample.jsonl +0 -0
  32. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_count.py +0 -0
  33. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_doctor.py +0 -0
  34. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_e2e_install.py +0 -0
  35. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_eval.py +0 -0
  36. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_init_safety.py +0 -0
  37. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m1.py +0 -0
  38. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m2.py +0 -0
  39. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m3.py +0 -0
  40. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m4.py +0 -0
  41. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m5.py +0 -0
  42. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m6.py +0 -0
  43. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_relay.py +0 -0
  44. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_scope.py +0 -0
  45. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_smoke.py +0 -0
  46. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_status.py +0 -0
  47. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_turn_scope.py +0 -0
  48. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/__main__.py +0 -0
  49. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/astdiff.py +0 -0
  50. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/checks.py +0 -0
  51. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/config.py +0 -0
  52. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/doctor.py +0 -0
  53. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/events.py +0 -0
  54. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/fsstate.py +0 -0
  55. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/gitstate.py +0 -0
  56. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/harness.py +0 -0
  57. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/hook.py +0 -0
  58. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/init.py +0 -0
  59. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/model.py +0 -0
  60. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/opencode.py +0 -0
  61. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/report.py +0 -0
  62. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/runlog.py +0 -0
  63. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/state.py +0 -0
  64. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/status.py +0 -0
  65. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/verify.py +0 -0
  66. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/version.py +0 -0
  67. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho-target.ps1.example +0 -0
  68. {tycho_cli-0.0.6 → tycho_cli-0.0.7}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tycho-cli
3
- Version: 0.0.6
3
+ Version: 0.0.7
4
4
  Summary: Tycho — a free, offline, open-source local verifier that proves an AI agent actually did what it claims, from git, the filesystem, process exit codes, and the harness event stream. No account, no LLM in the trust path.
5
5
  Project-URL: Homepage, https://swail.dev/tycho
6
6
  Project-URL: Repository, https://github.com/swail-labs/tycho
@@ -153,7 +153,7 @@ def test_update_prints_the_upgrade_command_then_runs_it(_online, monkeypatch, ca
153
153
 
154
154
  monkeypatch.setattr(cli.sys, "platform", "linux") # POSIX runs the upgrade in place
155
155
  _fetches(monkeypatch, "9.9.9")
156
- monkeypatch.setattr(cli, "_upgrade_command", lambda: ["echo", "upgrading"])
156
+ monkeypatch.setattr(cli, "_upgrade_command", lambda force=False: ["echo", "upgrading"])
157
157
  ran = {}
158
158
 
159
159
  class _Done:
@@ -173,7 +173,7 @@ def test_update_on_windows_defers_the_upgrade_past_process_exit(_online, monkeyp
173
173
 
174
174
  monkeypatch.setattr(cli.sys, "platform", "win32")
175
175
  _fetches(monkeypatch, "9.9.9")
176
- monkeypatch.setattr(cli, "_upgrade_command", lambda: ["uv", "tool", "upgrade", "tycho-cli"])
176
+ monkeypatch.setattr(cli, "_upgrade_command", lambda force=False: ["uv", "tool", "upgrade", "tycho-cli"])
177
177
  monkeypatch.setattr(subprocess, "run", lambda *a, **k: pytest.fail("must not upgrade in-process on Windows"))
178
178
  spawned = {}
179
179
  monkeypatch.setattr(cli, "_spawn_deferred_upgrade", lambda cmd: spawned.setdefault("cmd", list(cmd)))
@@ -192,8 +192,18 @@ def test_upgrade_command_names_the_distribution_not_the_taken_tycho(monkeypatch,
192
192
  # the installed tool (TYCHO-96).
193
193
  monkeypatch.setattr(cli.sys, "prefix", prefix)
194
194
  cmd = cli._upgrade_command()
195
- assert "tycho-cli" in cmd
196
- assert "tycho" not in cmd # the plain command name must never be the upgrade target
195
+ assert "tycho-cli" in " ".join(cmd)
196
+ assert "tycho" not in cmd # the bare command name must never be a standalone upgrade target
197
+
198
+
199
+ @pytest.mark.parametrize("prefix", ["/home/u/.local/pipx/venvs/tycho-cli",
200
+ "/home/u/.local/share/uv/tools/tycho-cli"]) # pip has no persisted pin
201
+ def test_force_crosses_a_version_pin_plain_respects_it(monkeypatch, prefix):
202
+ # A user who installed `tycho-cli==X` on purpose: plain `update` must stay within that pin
203
+ # (`upgrade`), and only `--force` reinstalls the latest across it (`install …@latest`/`--force`).
204
+ monkeypatch.setattr(cli.sys, "prefix", prefix)
205
+ assert "upgrade" in cli._upgrade_command(force=False)
206
+ assert "install" in cli._upgrade_command(force=True)
197
207
 
198
208
 
199
209
  def test_update_skip_dismisses_and_counts(_online, monkeypatch, capsys):
@@ -6,4 +6,4 @@ trust path. Free, open source (Apache 2.0), offline, no account needed.
6
6
  """
7
7
 
8
8
  # Alpha. Bumped to 0.1.0 for the first public release (TYCHO-10).
9
- __version__ = "0.0.6"
9
+ __version__ = "0.0.7"
@@ -157,6 +157,7 @@ def main(argv: Sequence[str] | None = None) -> int:
157
157
  )
158
158
  up = sub.add_parser("update", help=_COMMANDS["update"])
159
159
  up.add_argument("--skip", action="store_true", help="dismiss the current update notice (records the dismissal)")
160
+ up.add_argument("--force", action="store_true", help="reinstall the latest even across a pinned version (uv/pipx)")
160
161
  sub.add_parser("help", help=_COMMANDS["help"])
161
162
 
162
163
  args = parser.parse_args(argv)
@@ -169,7 +170,7 @@ def main(argv: Sequence[str] | None = None) -> int:
169
170
  if args.command == "scope":
170
171
  return _scope(Path.cwd(), args.action, args.paths, args.exclude)
171
172
  if args.command == "update":
172
- return _update(skip=args.skip)
173
+ return _update(skip=args.skip, force=args.force)
173
174
  if args.command == "relay":
174
175
  return _relay(Path.cwd(), on=args.on, off=args.off)
175
176
  if args.command in ("statusline", "status"):
@@ -363,7 +364,7 @@ def _print_update_notice() -> None:
363
364
  pass
364
365
 
365
366
 
366
- def _upgrade_command() -> list[str]:
367
+ def _upgrade_command(force: bool = False) -> list[str]:
367
368
  """The upgrade command for however Tycho was installed — best-effort from the install
368
369
  path. Falls back to pip, which works for a plain `pip install` (TYCHO-10).
369
370
 
@@ -371,21 +372,26 @@ def _upgrade_command() -> list[str]:
371
372
  `tycho` on PyPI is an unrelated project, so `pip install --upgrade tycho` would pull that,
372
373
  and `pipx/uv upgrade tycho` wouldn't find the tool (installed as `tycho-cli`) — TYCHO-96.
373
374
  Single-sourced from the same constant the update check queries, so the two can't drift.
375
+
376
+ `force` reinstalls the latest even across a version pin set at install time (`uv tool
377
+ install tycho-cli==X` / `pipx install tycho-cli==X`). Without it, `uv tool upgrade` /
378
+ `pipx upgrade` only move within that pin — respecting a version the user chose on purpose.
374
379
  """
375
380
  from . import version as version_mod
376
381
 
377
382
  pkg = version_mod._DIST_NAME or "tycho-cli"
378
383
  prefix = sys.prefix.replace("\\", "/").lower()
379
384
  if "pipx" in prefix:
380
- return ["pipx", "upgrade", pkg]
385
+ return ["pipx", "install", "--force", pkg] if force else ["pipx", "upgrade", pkg]
381
386
  if "/uv/tools/" in prefix or "/uv/" in prefix:
382
- return ["uv", "tool", "upgrade", pkg]
387
+ return ["uv", "tool", "install", f"{pkg}@latest"] if force else ["uv", "tool", "upgrade", pkg]
383
388
  return [sys.executable, "-m", "pip", "install", "--upgrade", pkg]
384
389
 
385
390
 
386
- def _update(skip: bool) -> int:
391
+ def _update(skip: bool, force: bool = False) -> int:
387
392
  """`tycho update` — check the index and upgrade in place, or `--skip` to dismiss the
388
- notice for this version. Offline/failure is reported, never fatal (TYCHO-10/53)."""
393
+ notice for this version. `--force` reinstalls the latest across a pinned version (uv/pipx);
394
+ plain update respects the pin. Offline/failure is reported, never fatal (TYCHO-10/53)."""
389
395
  from . import state
390
396
  from . import version as version_mod
391
397
 
@@ -406,7 +412,8 @@ def _update(skip: bool) -> int:
406
412
  if not behind:
407
413
  print(f"tycho {__version__} is up to date.")
408
414
  return ExitCode.OK
409
- cmd = _upgrade_command()
415
+ cmd = _upgrade_command(force=force)
416
+ hint = "" if force else " (if it's pinned and doesn't move, `tycho update --force`)"
410
417
  if sys.platform == "win32":
411
418
  # A running .exe can't have its own launcher shim replaced on Windows — an in-process
412
419
  # `uv tool upgrade` fails to copy `…\.local\bin\tycho.exe` with os error 32 ("being used
@@ -415,13 +422,13 @@ def _update(skip: bool) -> int:
415
422
  try:
416
423
  _spawn_deferred_upgrade(cmd)
417
424
  print(f"Updating tycho {__version__} → {newest}. The upgrade runs once this process "
418
- f"exits; re-open your shell and run `tycho --version` to confirm.")
425
+ f"exits; re-open your shell and run `tycho --version` to confirm.{hint}")
419
426
  return ExitCode.OK
420
427
  except Exception as exc:
421
428
  print(f"tycho: couldn't schedule the upgrade ({type(exc).__name__}). Run it yourself:\n {' '.join(cmd)}",
422
429
  file=sys.stderr)
423
430
  return ExitCode.OK
424
- print(f"Updating tycho {__version__} → {newest}: {' '.join(cmd)}")
431
+ print(f"Updating tycho {__version__} → {newest}: {' '.join(cmd)}{hint}")
425
432
  try:
426
433
  import subprocess
427
434
 
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