logics-manager 2.3.0__tar.gz → 2.3.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.
- {logics_manager-2.3.0 → logics_manager-2.3.2}/PKG-INFO +1 -1
- {logics_manager-2.3.0 → logics_manager-2.3.2}/README.md +42 -1
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/cli.py +128 -6
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager.egg-info/PKG-INFO +1 -1
- {logics_manager-2.3.0 → logics_manager-2.3.2}/pyproject.toml +1 -1
- {logics_manager-2.3.0 → logics_manager-2.3.2}/LICENSE +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/__init__.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/__main__.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/assist.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/assist_handoff.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/assist_surface.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/audit.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/bootstrap.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/cli_output.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/config.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/doctor.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/flow.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/flow_evidence.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/index.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/insights.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/lint.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/mcp.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/path_utils.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/sync.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/termstyle.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/update_check.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager/viewer.py +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager.egg-info/SOURCES.txt +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager.egg-info/dependency_links.txt +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager.egg-info/entry_points.txt +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/logics_manager.egg-info/top_level.txt +0 -0
- {logics_manager-2.3.0 → logics_manager-2.3.2}/setup.cfg +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/AlexAgo83/logics-manager/actions/workflows/ci.yml)
|
|
4
4
|
[](LICENSE)
|
|
5
|
-

|
|
6
6
|

|
|
7
7
|

|
|
8
8
|

|
|
@@ -58,6 +58,15 @@ python3.11 -m pip install .
|
|
|
58
58
|
logics-manager --help
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
On Debian, Ubuntu, or WSL environments where Python is externally managed, use `pipx` instead of installing into the system Python:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
sudo apt update
|
|
65
|
+
sudo apt install pipx python3-venv
|
|
66
|
+
pipx ensurepath
|
|
67
|
+
pipx install logics-manager
|
|
68
|
+
```
|
|
69
|
+
|
|
61
70
|
Or install the npm package:
|
|
62
71
|
|
|
63
72
|
```bash
|
|
@@ -197,6 +206,38 @@ To update the installed CLI later:
|
|
|
197
206
|
logics-manager self-update
|
|
198
207
|
```
|
|
199
208
|
|
|
209
|
+
If `self-update` reports an externally managed Python environment, migrate the Python install through `pipx`:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
sudo apt update
|
|
213
|
+
sudo apt install pipx python3-venv
|
|
214
|
+
pipx ensurepath
|
|
215
|
+
pipx install --force logics-manager
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
If `logics-manager` is already installed through `pipx`, update that managed environment directly:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
pipx upgrade logics-manager
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
For npm installs, update with:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
npm install -g @grifhinz/logics-manager@latest
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
If npm reports a successful update but `logics-manager --version` still shows an older version, another installation is earlier on `PATH`. Diagnose it with:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
command -v -a logics-manager
|
|
234
|
+
npm prefix -g
|
|
235
|
+
npm list -g @grifhinz/logics-manager --depth=0
|
|
236
|
+
"$(npm prefix -g)/bin/logics-manager" --version
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
If the direct npm binary shows the expected version, remove the older Python install or move the npm global `bin` directory earlier on `PATH`.
|
|
240
|
+
|
|
200
241
|
## VS Code Extension
|
|
201
242
|
|
|
202
243
|
The VS Code extension is the human cockpit around the same runtime. It helps you:
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
4
6
|
from importlib import metadata
|
|
5
7
|
import subprocess
|
|
6
8
|
import sys
|
|
9
|
+
import sysconfig
|
|
7
10
|
from shutil import which
|
|
8
11
|
from pathlib import Path
|
|
9
12
|
|
|
@@ -133,6 +136,104 @@ def get_cli_version() -> str:
|
|
|
133
136
|
return "0.0.0"
|
|
134
137
|
|
|
135
138
|
|
|
139
|
+
def _is_running_inside_venv() -> bool:
|
|
140
|
+
return sys.prefix != getattr(sys, "base_prefix", sys.prefix)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _is_externally_managed_python() -> bool:
|
|
144
|
+
if _is_running_inside_venv():
|
|
145
|
+
return False
|
|
146
|
+
stdlib = sysconfig.get_path("stdlib")
|
|
147
|
+
return bool(stdlib and (Path(stdlib) / "EXTERNALLY-MANAGED").exists())
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _is_running_from_pipx(package_name: str = DEFAULT_SELF_UPDATE_PY_PACKAGE) -> bool:
|
|
151
|
+
expected = package_name.replace("_", "-").lower()
|
|
152
|
+
candidates = [Path(sys.prefix), Path(sys.executable)]
|
|
153
|
+
for candidate in candidates:
|
|
154
|
+
parts = [part.lower() for part in candidate.parts]
|
|
155
|
+
for index, part in enumerate(parts[:-2]):
|
|
156
|
+
if part == "pipx" and parts[index + 1] == "venvs" and parts[index + 2] == expected:
|
|
157
|
+
return True
|
|
158
|
+
return False
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _is_running_from_npm_package() -> bool:
|
|
162
|
+
package_json = Path(__file__).resolve().parents[1] / "package.json"
|
|
163
|
+
try:
|
|
164
|
+
payload = json.loads(package_json.read_text(encoding="utf-8"))
|
|
165
|
+
except (OSError, json.JSONDecodeError):
|
|
166
|
+
return False
|
|
167
|
+
return payload.get("name") == DEFAULT_SELF_UPDATE_PACKAGE
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _find_executable_paths(command: str) -> list[str]:
|
|
171
|
+
paths: list[str] = []
|
|
172
|
+
seen: set[str] = set()
|
|
173
|
+
names = [command]
|
|
174
|
+
if sys.platform == "win32":
|
|
175
|
+
extensions = [suffix.lower() for suffix in os.environ.get("PATHEXT", ".COM;.EXE;.BAT;.CMD").split(";") if suffix]
|
|
176
|
+
if Path(command).suffix.lower() not in extensions:
|
|
177
|
+
names = [command + extension for extension in extensions]
|
|
178
|
+
for directory in os.environ.get("PATH", "").split(os.pathsep):
|
|
179
|
+
if not directory:
|
|
180
|
+
continue
|
|
181
|
+
for name in names:
|
|
182
|
+
candidate = Path(directory) / name
|
|
183
|
+
try:
|
|
184
|
+
resolved = str(candidate.resolve())
|
|
185
|
+
except OSError:
|
|
186
|
+
resolved = str(candidate)
|
|
187
|
+
if resolved in seen:
|
|
188
|
+
continue
|
|
189
|
+
if candidate.exists() and os.access(candidate, os.X_OK):
|
|
190
|
+
seen.add(resolved)
|
|
191
|
+
paths.append(str(candidate))
|
|
192
|
+
return paths
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _print_path_conflict_guidance(paths: list[str]) -> None:
|
|
196
|
+
if len(paths) <= 1:
|
|
197
|
+
return
|
|
198
|
+
print(
|
|
199
|
+
"\n".join(
|
|
200
|
+
[
|
|
201
|
+
"",
|
|
202
|
+
"Multiple logics-manager executables are on PATH. If --version still shows an older release, an earlier install is taking precedence.",
|
|
203
|
+
"Diagnose with:",
|
|
204
|
+
" command -v -a logics-manager",
|
|
205
|
+
" pipx list",
|
|
206
|
+
" npm list -g @grifhinz/logics-manager --depth=0",
|
|
207
|
+
]
|
|
208
|
+
)
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _print_externally_managed_update_guidance(package_name: str) -> None:
|
|
213
|
+
print(
|
|
214
|
+
"\n".join(
|
|
215
|
+
[
|
|
216
|
+
"This Python installation is externally managed, so pip cannot safely update logics-manager in the system environment.",
|
|
217
|
+
"",
|
|
218
|
+
"If this command was installed with pipx, update it with:",
|
|
219
|
+
f" pipx upgrade {package_name}",
|
|
220
|
+
"",
|
|
221
|
+
"Otherwise migrate the Python install through pipx:",
|
|
222
|
+
" sudo apt update",
|
|
223
|
+
" sudo apt install pipx python3-venv",
|
|
224
|
+
" pipx ensurepath",
|
|
225
|
+
f" pipx install --force {package_name}",
|
|
226
|
+
"",
|
|
227
|
+
"If you installed the npm package instead, run:",
|
|
228
|
+
f" npm install -g {DEFAULT_SELF_UPDATE_PACKAGE}@latest",
|
|
229
|
+
"",
|
|
230
|
+
"Advanced override, at your own risk:",
|
|
231
|
+
f" logics-manager self-update --manager pip --break-system-packages",
|
|
232
|
+
]
|
|
233
|
+
)
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
|
|
136
237
|
def _is_json_mode(argv: list[str]) -> bool:
|
|
137
238
|
return "--json" in argv or any(argv[index] == "--format" and index + 1 < len(argv) and argv[index + 1] == "json" for index in range(len(argv)))
|
|
138
239
|
|
|
@@ -205,23 +306,40 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
205
306
|
return 0 if payload["ok"] else 1
|
|
206
307
|
if command == "self-update":
|
|
207
308
|
parser = argparse.ArgumentParser(prog="logics-manager self-update", add_help=False)
|
|
208
|
-
parser.add_argument("--manager", choices=("auto", "pip", "npm"), default="auto")
|
|
309
|
+
parser.add_argument("--manager", choices=("auto", "pip", "pipx", "npm"), default="auto")
|
|
209
310
|
parser.add_argument("--package", default=DEFAULT_SELF_UPDATE_PACKAGE)
|
|
210
311
|
parser.add_argument("--python-package", default=DEFAULT_SELF_UPDATE_PY_PACKAGE)
|
|
312
|
+
parser.add_argument("--break-system-packages", action="store_true")
|
|
211
313
|
parser.add_argument("--dry-run", action="store_true")
|
|
212
314
|
parsed = parser.parse_args(rest)
|
|
213
315
|
|
|
214
316
|
manager = parsed.manager
|
|
215
317
|
if manager == "auto":
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
manager = "
|
|
318
|
+
if _is_running_from_npm_package() and which("npm"):
|
|
319
|
+
manager = "npm"
|
|
320
|
+
elif _is_running_from_pipx(parsed.python_package) and which("pipx"):
|
|
321
|
+
manager = "pipx"
|
|
220
322
|
else:
|
|
221
|
-
|
|
323
|
+
try:
|
|
324
|
+
metadata.version(parsed.python_package)
|
|
325
|
+
except metadata.PackageNotFoundError:
|
|
326
|
+
manager = "npm" if which("npm") else "pip"
|
|
327
|
+
else:
|
|
328
|
+
manager = "pip"
|
|
222
329
|
|
|
223
330
|
if manager == "pip":
|
|
331
|
+
if _is_externally_managed_python() and not parsed.break_system_packages:
|
|
332
|
+
_print_externally_managed_update_guidance(parsed.python_package)
|
|
333
|
+
return 1
|
|
224
334
|
command = [sys.executable, "-m", "pip", "install", "--upgrade", parsed.python_package]
|
|
335
|
+
if parsed.break_system_packages:
|
|
336
|
+
command.append("--break-system-packages")
|
|
337
|
+
elif manager == "pipx":
|
|
338
|
+
pipx = which("pipx")
|
|
339
|
+
if not pipx:
|
|
340
|
+
print("pipx was not found on PATH. Install pipx or update with --manager pip/npm.")
|
|
341
|
+
return 1
|
|
342
|
+
command = [pipx, "upgrade", parsed.python_package]
|
|
225
343
|
else:
|
|
226
344
|
npm = which("npm")
|
|
227
345
|
if not npm:
|
|
@@ -236,7 +354,11 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
236
354
|
result = subprocess.run(command, check=False)
|
|
237
355
|
if result.returncode == 0:
|
|
238
356
|
target = parsed.python_package if manager == "pip" else parsed.package
|
|
357
|
+
if manager == "pipx":
|
|
358
|
+
target = parsed.python_package
|
|
239
359
|
print(f"Updated {target} via {manager}.")
|
|
360
|
+
if manager == "npm":
|
|
361
|
+
_print_path_conflict_guidance(_find_executable_paths("logics-manager"))
|
|
240
362
|
return result.returncode
|
|
241
363
|
if command == "flow" and (rest[:1] in (["new"], ["list"], ["companion"], ["deliver"], ["validate-closeout"], ["repair"], ["closeout"], ["promote"], ["split"], ["close"], ["finish"]) or rest[:1] in HELP_ARGV):
|
|
242
364
|
from .flow import main as flow_main
|
|
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
|