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.
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/PKG-INFO +1 -1
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_update.py +14 -4
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/__init__.py +1 -1
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/cli.py +16 -9
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/.github/workflows/ci.yml +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/.github/workflows/release.yml +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/.gitignore +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/.tycho.toml +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/CONTRIBUTING.md +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/LICENSE +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/README.md +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/docs/bundler-spike.md +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/docs/harness-support.md +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/docs/hooks.md +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/docs/transcript-structures.md +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/docs/tycho-web.md +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/packaging/homebrew/tycho.rb +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/packaging/npm/bin/tycho.js +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/packaging/npm/package.json +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/pyproject.toml +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/conftest.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/codex_transcript_sample.jsonl +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/cursor_stop_payload.json +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/cursor_transcript_sample.jsonl +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/eval/claude_masked_red_suite.jsonl +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/eval/codex_masked_red_suite.jsonl +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/eval/cursor_masked_red_suite.jsonl +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/eval/opencode_masked_red_suite.json +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/opencode_transcript_sample.json +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/transcript_multiturn.jsonl +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/fixtures/transcript_sample.jsonl +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_count.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_doctor.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_e2e_install.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_eval.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_init_safety.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m1.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m2.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m3.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m4.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m5.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_m6.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_relay.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_scope.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_smoke.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_status.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tests/test_turn_scope.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/__main__.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/astdiff.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/checks.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/config.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/doctor.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/events.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/fsstate.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/gitstate.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/harness.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/hook.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/init.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/model.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/opencode.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/report.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/runlog.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/state.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/status.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/verify.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho/version.py +0 -0
- {tycho_cli-0.0.6 → tycho_cli-0.0.7}/tycho-target.ps1.example +0 -0
- {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.
|
|
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
|
|
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):
|
|
@@ -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.
|
|
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
|
|
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
|