ctrlrelay 0.1.6__tar.gz → 0.1.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 (94) hide show
  1. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/CHANGELOG.md +27 -0
  2. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/PKG-INFO +1 -1
  3. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/pyproject.toml +1 -1
  4. ctrlrelay-0.1.7/src/ctrlrelay/__init__.py +33 -0
  5. ctrlrelay-0.1.7/tests/test_cli_version.py +49 -0
  6. ctrlrelay-0.1.6/src/ctrlrelay/__init__.py +0 -8
  7. ctrlrelay-0.1.6/tests/test_cli_version.py +0 -22
  8. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  9. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  10. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  11. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/.github/dependabot.yml +0 -0
  12. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/.github/workflows/build.yml +0 -0
  13. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/.github/workflows/cla.yml +0 -0
  14. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/.github/workflows/pages.yml +0 -0
  15. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/.github/workflows/publish.yml +0 -0
  16. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/.github/workflows/test.yml +0 -0
  17. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/.gitignore +0 -0
  18. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/CODE_OF_CONDUCT.md +0 -0
  19. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/CONTRIBUTING.md +0 -0
  20. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/LICENSE +0 -0
  21. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/README.md +0 -0
  22. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/SECURITY.md +0 -0
  23. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/config/orchestrator.yaml.example +0 -0
  24. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/docs/Gemfile +0 -0
  25. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/docs/_config.yml +0 -0
  26. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/docs/architecture.md +0 -0
  27. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/docs/bridge.md +0 -0
  28. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/docs/cli.md +0 -0
  29. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/docs/configuration.md +0 -0
  30. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/docs/development.md +0 -0
  31. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/docs/feedback-loop.md +0 -0
  32. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/docs/getting-started.md +0 -0
  33. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/docs/index.md +0 -0
  34. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/docs/operations.md +0 -0
  35. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/bridge/__init__.py +0 -0
  36. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/bridge/__main__.py +0 -0
  37. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/bridge/protocol.py +0 -0
  38. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/bridge/server.py +0 -0
  39. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/bridge/telegram_handler.py +0 -0
  40. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/cli.py +0 -0
  41. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/__init__.py +0 -0
  42. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/audit.py +0 -0
  43. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/checkpoint.py +0 -0
  44. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/config.py +0 -0
  45. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/dispatcher.py +0 -0
  46. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/github.py +0 -0
  47. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/obs.py +0 -0
  48. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/poller.py +0 -0
  49. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/pr_verifier.py +0 -0
  50. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/pr_watcher.py +0 -0
  51. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/scheduler.py +0 -0
  52. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/state.py +0 -0
  53. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/core/worktree.py +0 -0
  54. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/dashboard/__init__.py +0 -0
  55. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/dashboard/client.py +0 -0
  56. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/pipelines/__init__.py +0 -0
  57. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/pipelines/base.py +0 -0
  58. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/pipelines/dev.py +0 -0
  59. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/pipelines/post_merge.py +0 -0
  60. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/pipelines/secops.py +0 -0
  61. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/transports/__init__.py +0 -0
  62. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/transports/base.py +0 -0
  63. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/transports/file_mock.py +0 -0
  64. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/src/ctrlrelay/transports/socket_client.py +0 -0
  65. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/__init__.py +0 -0
  66. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/conftest.py +0 -0
  67. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_audit.py +0 -0
  68. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_bridge_protocol.py +0 -0
  69. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_bridge_server.py +0 -0
  70. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_checkpoint.py +0 -0
  71. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_cli_ci_wait.py +0 -0
  72. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_cli_dev.py +0 -0
  73. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_cli_secops.py +0 -0
  74. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_cli_start.py +0 -0
  75. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_config.py +0 -0
  76. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_dashboard_client.py +0 -0
  77. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_dev_integration.py +0 -0
  78. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_dev_pipeline.py +0 -0
  79. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_dispatcher.py +0 -0
  80. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_docs_site.py +0 -0
  81. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_github.py +0 -0
  82. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_obs.py +0 -0
  83. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_pipeline_base.py +0 -0
  84. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_poller.py +0 -0
  85. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_post_merge.py +0 -0
  86. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_pr_verifier.py +0 -0
  87. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_pr_watcher.py +0 -0
  88. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_scheduler.py +0 -0
  89. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_secops_integration.py +0 -0
  90. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_secops_pipeline.py +0 -0
  91. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_state.py +0 -0
  92. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_telegram_handler.py +0 -0
  93. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_transport.py +0 -0
  94. {ctrlrelay-0.1.6 → ctrlrelay-0.1.7}/tests/test_worktree.py +0 -0
@@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.1.7] - 2026-04-20
11
+
12
+ Patch release. Fixes one drift bug in how the package reports its own
13
+ version — the `__version__` string was pinned to a literal in
14
+ `__init__.py` and never got bumped alongside releases, so `ctrlrelay
15
+ version` on an installed 0.1.6 wheel still reported `0.1.4`. No API
16
+ or behavior changes.
17
+
18
+ ### Fixed
19
+
20
+ - **`__version__` now derives from installed metadata** (`closes
21
+ #94`). `ctrlrelay.__version__` resolves via
22
+ `importlib.metadata.version("ctrlrelay")` at import time so it
23
+ tracks the installed wheel's `pyproject.toml` automatically.
24
+ Source-checkout pytest runs (where no dist-info exists because
25
+ `pythonpath = ["src"]` is the only mechanism putting the package on
26
+ `sys.path`) fall back to parsing the sibling `pyproject.toml` with
27
+ `tomllib` — so the drift-catcher test
28
+ (`test_version_matches_pyproject`) still sees a real version
29
+ instead of a `0.0.0+unknown` placeholder.
30
+
31
+ ### Operator notes
32
+
33
+ - No migration or restart guidance. Upgrade via `uv tool upgrade
34
+ ctrlrelay` (or `pip install -U ctrlrelay`) and the next `ctrlrelay
35
+ version` will report `0.1.7`.
36
+
10
37
  ## [0.1.6] - 2026-04-20
11
38
 
12
39
  The "pipeline reliability + operator control" release. Closes three
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ctrlrelay
3
- Version: 0.1.6
3
+ Version: 0.1.7
4
4
  Summary: Local-first orchestrator for headless coding agents across multiple GitHub repos
5
5
  Project-URL: Homepage, https://github.com/AInvirion/ctrlrelay
6
6
  Project-URL: Documentation, https://ainvirion.github.io/ctrlrelay/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ctrlrelay"
3
- version = "0.1.6"
3
+ version = "0.1.7"
4
4
  description = "Local-first orchestrator for headless coding agents across multiple GitHub repos"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -0,0 +1,33 @@
1
+ """ctrlrelay: Local-first orchestrator for headless coding agents."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ from ctrlrelay.core import checkpoint
6
+
7
+
8
+ def _resolve_version() -> str:
9
+ try:
10
+ return version("ctrlrelay")
11
+ except PackageNotFoundError:
12
+ # Source checkout with no installed dist-info — e.g. a bare
13
+ # `pytest tests/` with pyproject's `pythonpath = ["src"]` as the
14
+ # only mechanism putting the package on sys.path. Fall back to
15
+ # parsing pyproject.toml so the drift-catcher test still sees a
16
+ # real version instead of a placeholder.
17
+ import tomllib
18
+ from pathlib import Path
19
+
20
+ pyproject = Path(__file__).resolve().parents[2] / "pyproject.toml"
21
+ if pyproject.is_file():
22
+ try:
23
+ with pyproject.open("rb") as f:
24
+ return tomllib.load(f)["project"]["version"]
25
+ except (OSError, KeyError, tomllib.TOMLDecodeError):
26
+ pass
27
+ return "0.0.0+unknown"
28
+
29
+
30
+ __version__ = _resolve_version()
31
+
32
+ # Public API
33
+ __all__ = ["__version__", "checkpoint"]
@@ -0,0 +1,49 @@
1
+ """Tests for the version command."""
2
+
3
+ import re
4
+ import tomllib
5
+ from pathlib import Path
6
+
7
+ from typer.testing import CliRunner
8
+
9
+ from ctrlrelay import __version__
10
+ from ctrlrelay.cli import app
11
+
12
+ runner = CliRunner()
13
+
14
+ SEMVER_RE = re.compile(r"^\d+\.\d+\.\d+([.\-+].+)?$")
15
+
16
+
17
+ class TestVersionCommand:
18
+ def test_version_command_succeeds(self) -> None:
19
+ """ctrlrelay version should exit with code 0."""
20
+ result = runner.invoke(app, ["version"])
21
+
22
+ assert result.exit_code == 0
23
+
24
+ def test_version_command_prints_version(self) -> None:
25
+ """ctrlrelay version should print the package version."""
26
+ result = runner.invoke(app, ["version"])
27
+
28
+ assert __version__ in result.output
29
+
30
+ def test_version_matches_semver_shape(self) -> None:
31
+ """__version__ should look like a real version, not a literal placeholder."""
32
+ assert SEMVER_RE.match(__version__), (
33
+ f"__version__={__version__!r} does not match semver-like shape"
34
+ )
35
+
36
+ def test_version_matches_pyproject(self) -> None:
37
+ """__version__ must match pyproject.toml so published wheels don't lie.
38
+
39
+ Catches the drift that caused issue #94: bumping pyproject.toml on each
40
+ release while forgetting to bump a hardcoded string in __init__.py.
41
+ """
42
+ pyproject_path = Path(__file__).resolve().parents[1] / "pyproject.toml"
43
+ pyproject = tomllib.loads(pyproject_path.read_text())
44
+ expected = pyproject["project"]["version"]
45
+
46
+ assert __version__ == expected, (
47
+ f"__version__={__version__!r} diverges from pyproject.toml version "
48
+ f"{expected!r} — did a release bump one but not the other?"
49
+ )
@@ -1,8 +0,0 @@
1
- """ctrlrelay: Local-first orchestrator for Claude Code."""
2
-
3
- from ctrlrelay.core import checkpoint
4
-
5
- __version__ = "0.1.3"
6
-
7
- # Public API
8
- __all__ = ["__version__", "checkpoint"]
@@ -1,22 +0,0 @@
1
- """Tests for the version command."""
2
-
3
- from typer.testing import CliRunner
4
-
5
- from ctrlrelay import __version__
6
- from ctrlrelay.cli import app
7
-
8
- runner = CliRunner()
9
-
10
-
11
- class TestVersionCommand:
12
- def test_version_command_succeeds(self) -> None:
13
- """ctrlrelay version should exit with code 0."""
14
- result = runner.invoke(app, ["version"])
15
-
16
- assert result.exit_code == 0
17
-
18
- def test_version_command_prints_version(self) -> None:
19
- """ctrlrelay version should print the package version."""
20
- result = runner.invoke(app, ["version"])
21
-
22
- assert __version__ in result.output
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