loopsmith-cli 0.1.1__tar.gz → 0.1.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: loopsmith-cli
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Self-evolving agent loops behind a deterministic verification gate. Installs the prebuilt Rust binary as `loopsmith`.
5
5
  Author-email: bitphill <bitphill@tuta.com>
6
6
  License-Expression: MIT
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
  # `loopsmith` on PyPI was already registered by an unrelated project, so the
7
7
  # distribution is `loopsmith-cli`. The installed command is `loopsmith`.
8
8
  name = "loopsmith-cli"
9
- version = "0.1.1"
9
+ version = "0.1.2"
10
10
  description = "Self-evolving agent loops behind a deterministic verification gate. Installs the prebuilt Rust binary as `loopsmith`."
11
11
  readme = "README.md"
12
12
  license = "MIT"
@@ -25,7 +25,7 @@ import urllib.request
25
25
  import zipfile
26
26
  from pathlib import Path
27
27
 
28
- __version__ = "0.1.1"
28
+ __version__ = "0.1.2"
29
29
 
30
30
  REPO = "bitphill/loopsmith"
31
31
  _RELEASE_BASE = f"https://github.com/{REPO}/releases/download/v{__version__}"
@@ -115,12 +115,14 @@ def ensure_binary() -> Path:
115
115
  if destination.exists():
116
116
  return destination
117
117
 
118
- # A `loopsmith` already on PATH beats downloading a second copy — someone who
119
- # ran `cargo install loopsmith` should not silently get two binaries.
120
- existing = shutil.which("loopsmith")
121
- if existing and Path(existing).resolve() != destination.resolve():
122
- return Path(existing)
123
-
118
+ # There is deliberately no "reuse a `loopsmith` already on PATH" shortcut
119
+ # here. pip installs *this* package's console script as `loopsmith` on PATH,
120
+ # so `shutil.which("loopsmith")` finds the very script that is running and
121
+ # `execv`ing it re-enters this function — an infinite exec loop that presents
122
+ # as the command hanging with no output. Distinguishing our own script from a
123
+ # cargo-installed binary means comparing against argv[0], the interpreter's
124
+ # script directory, and every symlink in between, to save one download that
125
+ # happens once per version. Not worth the failure mode.
124
126
  target = _target()
125
127
  asset = f"loopsmith-v{__version__}-{target}.{'zip' if windows else 'tar.gz'}"
126
128
  want = _expected_digest(asset)
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  import os
6
6
  import subprocess
7
7
  import sys
8
+ from pathlib import Path
8
9
 
9
10
  from . import ResolveError, ensure_binary
10
11
 
@@ -20,6 +21,21 @@ def main() -> int:
20
21
  print("[loopsmith] build from source instead: cargo install loopsmith", file=sys.stderr)
21
22
  return 127
22
23
 
24
+ # Never exec ourselves. This is belt-and-braces against the one failure mode
25
+ # that has no useful symptom: an exec loop looks exactly like a hang, with no
26
+ # output, no error, and no traceback to read.
27
+ try:
28
+ if Path(exe).resolve() == Path(sys.argv[0]).resolve():
29
+ print(
30
+ f"[loopsmith] refusing to run {exe}: that is this launcher, not the "
31
+ "loopsmith binary.\n"
32
+ "[loopsmith] build from source instead: cargo install loopsmith",
33
+ file=sys.stderr,
34
+ )
35
+ return 127
36
+ except OSError:
37
+ pass # An unresolvable argv[0] is not a reason to refuse to run.
38
+
23
39
  argv = [str(exe), *sys.argv[1:]]
24
40
 
25
41
  # On POSIX, replace this process rather than wrapping it. loopsmith is
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: loopsmith-cli
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Self-evolving agent loops behind a deterministic verification gate. Installs the prebuilt Rust binary as `loopsmith`.
5
5
  Author-email: bitphill <bitphill@tuta.com>
6
6
  License-Expression: MIT
File without changes
File without changes