dotbrain 0.4.2__tar.gz → 0.4.4__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 (49) hide show
  1. {dotbrain-0.4.2 → dotbrain-0.4.4}/PKG-INFO +1 -1
  2. {dotbrain-0.4.2 → dotbrain-0.4.4}/docs/cli-reference.md +3 -2
  3. {dotbrain-0.4.2 → dotbrain-0.4.4}/docs/getting-started.md +10 -6
  4. {dotbrain-0.4.2 → dotbrain-0.4.4}/pyproject.toml +1 -1
  5. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/__init__.py +1 -1
  6. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/cli.py +24 -12
  7. dotbrain-0.4.2/src/dotbrain/updater.py +0 -117
  8. {dotbrain-0.4.2 → dotbrain-0.4.4}/.gitignore +0 -0
  9. {dotbrain-0.4.2 → dotbrain-0.4.4}/LICENSE +0 -0
  10. {dotbrain-0.4.2 → dotbrain-0.4.4}/README.md +0 -0
  11. {dotbrain-0.4.2 → dotbrain-0.4.4}/docs/README.md +0 -0
  12. {dotbrain-0.4.2 → dotbrain-0.4.4}/docs/architecture.md +0 -0
  13. {dotbrain-0.4.2 → dotbrain-0.4.4}/docs/beads-backend.md +0 -0
  14. {dotbrain-0.4.2 → dotbrain-0.4.4}/docs/configuration.md +0 -0
  15. {dotbrain-0.4.2 → dotbrain-0.4.4}/docs/glossary.md +0 -0
  16. {dotbrain-0.4.2 → dotbrain-0.4.4}/docs/skills.md +0 -0
  17. {dotbrain-0.4.2 → dotbrain-0.4.4}/docs/wiring.md +0 -0
  18. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/_cli_reference.py +0 -0
  19. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/adopter_repos.py +0 -0
  20. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/beads.py +0 -0
  21. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/bootstrap.py +0 -0
  22. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/brainspaces.py +0 -0
  23. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/config.py +0 -0
  24. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/doctor.py +0 -0
  25. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/hooks.py +0 -0
  26. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/migrate.py +0 -0
  27. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/paths.py +0 -0
  28. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resource_loader.py +0 -0
  29. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/__init__.py +0 -0
  30. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/agents/claude/implementer.md +0 -0
  31. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/agents/claude/investigator.md +0 -0
  32. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/agents/claude/reviewer.md +0 -0
  33. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/agents/claude/verifier.md +0 -0
  34. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/agents/codex/implementer.toml +0 -0
  35. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/agents/codex/investigator.toml +0 -0
  36. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/agents/codex/reviewer.toml +0 -0
  37. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/agents/codex/verifier.toml +0 -0
  38. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/config.yaml +0 -0
  39. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/core.yaml +0 -0
  40. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/templates/brain/AGENTS.md +0 -0
  41. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/templates/brain/DOTBRAIN.md +0 -0
  42. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/templates/brain/adr/README.md +0 -0
  43. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/templates/brain/designs/README.md +0 -0
  44. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/templates/brain/docs/README.md +0 -0
  45. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/templates/brain/project.yaml +0 -0
  46. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/resources/templates/gitignore +0 -0
  47. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/skills.py +0 -0
  48. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/subagents.py +0 -0
  49. {dotbrain-0.4.2 → dotbrain-0.4.4}/src/dotbrain/workflows.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: dotbrain
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: Wires project Brainspaces and skills into coding agents.
5
5
  Project-URL: Homepage, https://github.com/arminzou/dotbrain
6
6
  Project-URL: Repository, https://github.com/arminzou/dotbrain
@@ -22,7 +22,8 @@ Reference for the public `dotbrain` CLI.
22
22
  │ links. │
23
23
  │ doctor Read-only health check: machine readiness, project wiring, beads │
24
24
  │ state drift. │
25
- │ update Update this released CLI to the latest stable PyPI release. │
25
+ │ update Print the command that upgrades this CLI with the tool that │
26
+ │ installed it. │
26
27
  │ wire Create or repair a project Brainspace and wire an adopter repo. │
27
28
  │ refresh Refresh Brain/workspace files, repo links, beads state, and │
28
29
  │ project skills. │
@@ -348,7 +349,7 @@ Reference for the public `dotbrain` CLI.
348
349
 
349
350
  Usage: dotbrain update [OPTIONS]
350
351
 
351
- Update this released CLI to the latest stable PyPI release.
352
+ Print the command that upgrades this CLI with the tool that installed it.
352
353
 
353
354
  ┌─ Options ────────────────────────────────────────────────────────────────────┐
354
355
  │ --help -h Show this message and exit. │
@@ -179,16 +179,20 @@ codex plugin add dotbrain@dotbrain
179
179
  Then refresh the CLI to match, either by asking your agent or by re-running the install command
180
180
  from step 2 with the new tag.
181
181
 
182
- To update only the released CLI, run:
182
+ To update only the released CLI, upgrade it with the tool that installed it:
183
183
 
184
184
  ```bash
185
- dotbrain update
185
+ uv tool install dotbrain@latest # uv
186
+ pipx upgrade dotbrain # pipx
187
+ python -m pip install --upgrade dotbrain # pip, using the Python dotbrain is installed in
186
188
  ```
187
189
 
188
- It installs the latest stable release from PyPI and does not update plugins or private dotbrain
189
- data. On Windows, wait a moment for the running launcher to exit, then confirm with
190
- `dotbrain --version`. `uv tool upgrade dotbrain` (or `pipx upgrade dotbrain`) works too.
191
- Contributor checkouts remain editable: update the checkout with Git instead of using this command.
190
+ With uv, use `dotbrain@latest` rather than `uv tool upgrade dotbrain`: an install pinned to one
191
+ version, such as the plugin installer's, stays on that version under `uv tool upgrade`. Not sure
192
+ which tool you used? `dotbrain update` prints the right command for your install.
193
+
194
+ Updating the CLI does not update plugins or private dotbrain data. Contributor checkouts remain
195
+ editable: update the checkout with Git instead.
192
196
 
193
197
  ## Edit Config Only When Needed
194
198
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dotbrain"
3
- version = "0.4.2"
3
+ version = "0.4.4"
4
4
  description = "Wires project Brainspaces and skills into coding agents."
5
5
  requires-python = ">=3.11"
6
6
  license = "MIT"
@@ -4,4 +4,4 @@ A testable Python CLI for wiring repos into Brainspaces, seeding Brains, and
4
4
  managing skills. Exposes the workflow commands plus pure path/contract helpers.
5
5
  """
6
6
 
7
- __version__ = "0.4.2"
7
+ __version__ = "0.4.4"
@@ -2,13 +2,16 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import json
6
+ import subprocess
5
7
  import sys
8
+ from importlib import metadata
6
9
  from pathlib import Path
7
10
  from typing import Optional
8
11
 
9
12
  import typer
10
13
 
11
- from dotbrain import __version__, updater
14
+ from dotbrain import __version__
12
15
  from dotbrain import doctor as doctor_mod
13
16
  from dotbrain import adopter_repos, beads as beads_mod, bootstrap as bootstrap_mod, config, brainspaces, hooks, migrate, paths, resource_loader, skills, subagents, workflows
14
17
 
@@ -167,18 +170,27 @@ def doctor() -> None:
167
170
 
168
171
  @app.command()
169
172
  def update() -> None:
170
- """Update this released CLI to the latest stable PyPI release."""
173
+ """Print the command that upgrades this CLI with the tool that installed it."""
174
+ typer.echo(_upgrade_hint())
175
+
176
+
177
+ def _upgrade_hint() -> str:
171
178
  try:
172
- target = updater.update_cli(__version__)
173
- except updater.UpdateError as exc:
174
- typer.echo(f"dotbrain update: {exc}", err=True)
175
- raise typer.Exit(1) from exc
176
- if target is None:
177
- typer.echo(f"dotbrain {__version__} is already current")
178
- elif sys.platform == "win32":
179
- typer.echo(f"dotbrain update to {target} is starting; run 'dotbrain --version' in a moment to verify")
180
- else:
181
- typer.echo(f"dotbrain updated from {__version__} to {target}; run 'dotbrain --version' to verify")
179
+ files = metadata.distribution("dotbrain").files or ()
180
+ record = next((f for f in files if f.name == "direct_url.json"), None)
181
+ direct_url = json.loads(record.read_text(encoding="utf-8")) if record else {}
182
+ except (metadata.PackageNotFoundError, OSError, ValueError):
183
+ direct_url = {}
184
+ if direct_url.get("dir_info", {}).get("editable"):
185
+ return "dotbrain is an editable install; update its checkout with git pull"
186
+ prefix = Path(sys.prefix)
187
+ if (prefix / "uv-receipt.toml").exists():
188
+ # @latest also clears the exact-version pin that `uv tool upgrade` would honor.
189
+ return "To update dotbrain, run: uv tool install dotbrain@latest"
190
+ if (prefix / "pipx_metadata.json").exists():
191
+ return "To update dotbrain, run: pipx upgrade dotbrain"
192
+ pip = subprocess.list2cmdline([sys.executable, "-m", "pip", "install", "--upgrade", "dotbrain"])
193
+ return f"To update dotbrain, run: {pip}"
182
194
 
183
195
 
184
196
  @app.command()
@@ -1,117 +0,0 @@
1
- """Update released dotbrain CLI installations from PyPI."""
2
-
3
- from __future__ import annotations
4
-
5
- import json
6
- import os
7
- import re
8
- import subprocess
9
- from importlib import metadata
10
- from typing import Any, Callable
11
- from urllib.error import URLError
12
- from urllib.request import Request, urlopen
13
-
14
- PACKAGE = "dotbrain"
15
- _PYPI_URL = f"https://pypi.org/pypi/{PACKAGE}/json"
16
- _VERSION_RE = re.compile(r"^(\d+)\.(\d+)\.(\d+)$")
17
- Fetch = Callable[[str], dict[str, Any]]
18
- Run = Callable[..., subprocess.CompletedProcess[str]]
19
-
20
-
21
- class UpdateError(RuntimeError):
22
- """The CLI could not safely update itself."""
23
-
24
-
25
- def update_cli(current_version: str, *, fetch: Fetch | None = None,
26
- run: Run = subprocess.run) -> str | None:
27
- """Install the latest stable release, returning its version or ``None`` when current."""
28
- if _is_editable_install():
29
- raise UpdateError("editable installs are updated from their checkout; use git pull there")
30
-
31
- fetch = fetch or _fetch_json
32
- target_version = _latest_version(fetch(_PYPI_URL))
33
- if _version_parts(target_version) <= _version_parts(current_version):
34
- return None
35
-
36
- command = ["uv", "tool", "install", "--force", f"{PACKAGE}=={target_version}"]
37
- if _is_windows():
38
- _defer_install(command)
39
- return target_version
40
- try:
41
- result = run(command, check=False)
42
- except FileNotFoundError as exc:
43
- raise UpdateError("uv is not on PATH; install uv and retry") from exc
44
- if result.returncode:
45
- raise UpdateError(f"uv could not install {target_version}; the existing CLI was left unchanged")
46
- return target_version
47
-
48
-
49
- def _is_windows() -> bool:
50
- return os.name == "nt"
51
-
52
-
53
- def _defer_install(command: list[str]) -> None:
54
- """Run detached, after this Windows launcher releases its executable lock.
55
-
56
- The child must not share this process's console: otherwise its output and
57
- lifetime bleed into the caller's shell, and the prompt looks hung until the
58
- install finishes. It gets a hidden console rather than none: a console-less
59
- cmd makes Windows open a visible window for each console child it runs.
60
- """
61
- script = f"ping -n 2 127.0.0.1 >NUL & {subprocess.list2cmdline(command)}"
62
- subprocess.Popen(
63
- ["cmd", "/c", script],
64
- stdin=subprocess.DEVNULL,
65
- stdout=subprocess.DEVNULL,
66
- stderr=subprocess.DEVNULL,
67
- creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0)
68
- | getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0),
69
- )
70
-
71
-
72
- def _is_editable_install() -> bool:
73
- try:
74
- distribution = metadata.distribution("dotbrain")
75
- except metadata.PackageNotFoundError:
76
- return False
77
- raw = next(
78
- (
79
- distribution.locate_file(path).read_text(encoding="utf-8")
80
- for path in distribution.files or ()
81
- if path.name == "direct_url.json"
82
- ),
83
- None,
84
- )
85
- if not raw:
86
- return False
87
- try:
88
- return bool(json.loads(raw).get("dir_info", {}).get("editable"))
89
- except (ValueError, AttributeError):
90
- return False
91
-
92
-
93
- def _fetch_json(url: str) -> dict[str, Any]:
94
- request = Request(url, headers={"Accept": "application/json", "User-Agent": "dotbrain"})
95
- try:
96
- with urlopen(request, timeout=10) as response: # noqa: S310 - fixed PyPI URL
97
- data = json.load(response)
98
- except (OSError, URLError, ValueError) as exc:
99
- raise UpdateError("could not reach PyPI to check for updates") from exc
100
- if not isinstance(data, dict):
101
- raise UpdateError("PyPI returned an invalid update response")
102
- return data
103
-
104
-
105
- def _latest_version(release: dict[str, Any]) -> str:
106
- info = release.get("info", {}) if isinstance(release.get("info"), dict) else {}
107
- version = str(info.get("version", ""))
108
- if not _VERSION_RE.fullmatch(version):
109
- raise UpdateError("PyPI did not return a stable dotbrain release")
110
- return version
111
-
112
-
113
- def _version_parts(version: str) -> tuple[int, int, int]:
114
- match = _VERSION_RE.fullmatch(version)
115
- if not match:
116
- raise UpdateError(f"unsupported installed version: {version}")
117
- return tuple(int(part) for part in match.groups())
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