brichan 0.5.0__py3-none-any.whl

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 (42) hide show
  1. brichan-0.5.0.dist-info/METADATA +193 -0
  2. brichan-0.5.0.dist-info/RECORD +42 -0
  3. brichan-0.5.0.dist-info/WHEEL +5 -0
  4. brichan-0.5.0.dist-info/entry_points.txt +6 -0
  5. brichan-0.5.0.dist-info/licenses/LICENSE +21 -0
  6. brichan-0.5.0.dist-info/top_level.txt +1 -0
  7. brida/__init__.py +3 -0
  8. brida/cli/__init__.py +1 -0
  9. brida/cli/_root.py +23 -0
  10. brida/cli/claude.py +58 -0
  11. brida/cli/codex.py +118 -0
  12. brida/cli/provider_commands.py +404 -0
  13. brida/cli/runtime.py +197 -0
  14. brida/contracts/__init__.py +1 -0
  15. brida/contracts/receipts/__init__.py +13 -0
  16. brida/contracts/receipts/discovery.py +5 -0
  17. brida/contracts/receipts/parser.py +5 -0
  18. brida/contracts/receipts/schema.py +35 -0
  19. brida/contracts/receipts/validation.py +1177 -0
  20. brida/lifecycle.py +334 -0
  21. brida/orchestration/__init__.py +23 -0
  22. brida/orchestration/herdr_client.py +8 -0
  23. brida/orchestration/layout.py +5 -0
  24. brida/orchestration/model_routing.py +283 -0
  25. brida/orchestration/worker_launch.py +479 -0
  26. brida/project.py +64 -0
  27. brida/resources/__init__.py +1 -0
  28. brida/resources/dogfood_v1/__init__.py +1 -0
  29. brida/resources/dogfood_v1/config/model-routing.json +38 -0
  30. brida/resources/dogfood_v1/policy/bootstrap.md +23 -0
  31. brida/resources/dogfood_v1/policy/identity.md +18 -0
  32. brida/resources/dogfood_v1/policy/memory-policy.md +14 -0
  33. brida/resources/dogfood_v1/policy/operating-principles.md +13 -0
  34. brida/resources/dogfood_v1/project-memory/index.md +6 -0
  35. brida/resources/dogfood_v1/project-memory/main/current-state.md +9 -0
  36. brida/resources/dogfood_v1/project-memory/main/decisions.md +3 -0
  37. brida/resources/dogfood_v1/project-memory/main/overview.md +8 -0
  38. brida/resources/dogfood_v1/project-memory/main/references.md +3 -0
  39. brida/resources/dogfood_v1/project-memory/main/tasks.md +11 -0
  40. brida/resources/dogfood_v1/skills/herdr-orchestration/SKILL.md +25 -0
  41. brida/resources/dogfood_v1/skills/herdr-orchestration/references/commands.md +24 -0
  42. brida/resources/dogfood_v1/skills/herdr-orchestration/references/task-packet.md +39 -0
@@ -0,0 +1,193 @@
1
+ Metadata-Version: 2.4
2
+ Name: brichan
3
+ Version: 0.5.0
4
+ Summary: Repository-native AI Chief of Staff orchestration
5
+ Author: Minh Tran
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Minh Tran
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Keywords: ai,orchestration,codex,claude-code,chief-of-staff
29
+ Classifier: Development Status :: 3 - Alpha
30
+ Classifier: Environment :: Console
31
+ Classifier: Intended Audience :: Developers
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Operating System :: POSIX
34
+ Classifier: Programming Language :: Python :: 3
35
+ Classifier: Programming Language :: Python :: 3.10
36
+ Classifier: Programming Language :: Python :: 3.11
37
+ Classifier: Programming Language :: Python :: 3.12
38
+ Classifier: Programming Language :: Python :: 3.13
39
+ Classifier: Topic :: Software Development :: Build Tools
40
+ Requires-Python: >=3.10
41
+ Description-Content-Type: text/markdown
42
+ License-File: LICENSE
43
+ Dynamic: license-file
44
+
45
+ # Brichan
46
+
47
+ ![Brichan coordinating a team of AI workers](assets/brida-hero.png)
48
+
49
+ Brichan is an AI Chief of Staff for Codex and Claude Code. Give it a project
50
+ goal; it keeps the necessary context, coordinates independent workers through
51
+ Herdr, checks their evidence, and records useful project state outside chat.
52
+ Its existing runtime package and console commands remain `brida` and
53
+ `brida-*` for compatibility.
54
+
55
+ ## Current dogfood scope
56
+
57
+ The primary one-user dogfood path is now an installed Python package running
58
+ inside an existing top-level Git repository. Installed-project mode currently
59
+ supports Codex on POSIX-compatible systems with Python 3.10+. Herdr is needed
60
+ only when Brida coordinates independent worker sessions.
61
+
62
+ Brida is not published to a package registry yet; the planned PyPI
63
+ distribution name is `brichan` (`pip install brichan`), while the importable
64
+ package stays `brida` and every console command keeps its existing name.
65
+ Until it is published, build the wheel locally from this repository with the
66
+ installer. It can be invoked from any directory and does not activate or
67
+ modify the target project's virtual environment:
68
+
69
+ ```bash
70
+ /absolute/path/to/brida/scripts/install-brida
71
+ ```
72
+
73
+ By default, the script creates a dedicated environment at
74
+ `$HOME/.local/share/brida/venv` and command symlinks in `$HOME/.local/bin`.
75
+ It automatically selects an available Python 3.10+ interpreter with `pip`,
76
+ `setuptools`, `venv`, and `wheel`, builds from a temporary source snapshot,
77
+ and installs all Brida console commands. No virtualenv activation is
78
+ required. If the command directory is not on `PATH`, the installer prints
79
+ the exact export to add to the shell profile.
80
+
81
+ ## Initialize a project
82
+
83
+ Preview the complete footprint before writing:
84
+
85
+ ```bash
86
+ brida init --project /absolute/path/to/repository
87
+ brida init --apply --project /absolute/path/to/repository
88
+ ```
89
+
90
+ `init` defaults to dry-run and performs zero writes. `--apply` creates only a
91
+ versioned `.brida/` directory containing managed policy, model routing, Herdr
92
+ skill resources, and mutable project memory. Repeating it against healthy
93
+ state is idempotent.
94
+
95
+ Diagnose and launch from any directory with an explicit target:
96
+
97
+ ```bash
98
+ brida status --project /absolute/path/to/repository
99
+ brida doctor --project /absolute/path/to/repository
100
+ brida run --project /absolute/path/to/repository -- <codex arguments>
101
+ ```
102
+
103
+ From inside a healthy initialized repository, bare `brida` also launches
104
+ Codex. The installed entrypoint:
105
+
106
+ - leaves `AGENTS.md`, `CLAUDE.md`, `.codex/`, and provider configuration
107
+ untouched;
108
+ - launches external `codex` directly at the target root and never executes
109
+ target-owned `bin/brida-*` wrappers;
110
+ - injects package-owned Brida policy and Herdr skill discovery;
111
+ - rejects native delegation, permission bypasses, cwd/scope widening, profiles,
112
+ remote execution, and arbitrary Codex configuration before `--`;
113
+ - treats option-looking text after `--` as literal prompt content.
114
+
115
+ State diagnostics reject malformed, dangling, symlinked, inaccessible, or
116
+ incompatible `.brida/` state without silently repairing it. Schema v1 has no
117
+ automatic migration: package-version changes require deliberate backup and
118
+ reinitialization. See the
119
+ [installed Codex dogfood guide](docs/guides/installable-dogfood.md) for the
120
+ exact footprint, exit codes, safeguards, and compatibility boundary.
121
+
122
+ ## Checkout compatibility and development
123
+
124
+ The original checkout workflow remains available for development and for
125
+ Claude Code:
126
+
127
+ ```bash
128
+ bin/brida
129
+ bin/brida --runtime claude
130
+ ```
131
+
132
+ Checkout mode uses package-owned `bin/brida-*` wrappers. Installed-project mode
133
+ does not. Coordinator defaults and worker routes are settings-driven, so the
134
+ coordinator and implementation, review, planning, or scan workers may use
135
+ different runtimes. See the [model-routing guide](docs/guides/model-routing.md)
136
+ to change defaults, select a named route, or use a one-off override.
137
+
138
+ The `brida-codex` and `brida-claude` console commands installed by `brichan`
139
+ remain checkout-oriented: `brida-codex` resolves coordinator routing from a
140
+ Brida source checkout (or `BRIDA_ROOT`) or from an already-initialized
141
+ project's `.brida/` state, while `brida-claude` resolves only from a checkout
142
+ or `BRIDA_ROOT`. Both are for development and checkout use, not standalone
143
+ installed-project launches. `--help`/`--version` work from any directory; the
144
+ [installed Codex dogfood guide](docs/guides/installable-dogfood.md) has the
145
+ exact boundary.
146
+
147
+ ## How it works
148
+
149
+ 1. You describe the outcome and constraints.
150
+ 2. Brida reads only the project context needed for that work.
151
+ 3. Brida gives bounded tasks to independent workers through Herdr.
152
+ 4. Brida verifies results, records decisions and status, then reports back.
153
+
154
+ Herdr is the worker control plane. Native runtime delegation stays disabled so
155
+ worker ownership, evidence, and cleanup remain visible.
156
+
157
+ Project context lives in `projects/<project-slug>/` as a small set of Markdown
158
+ files for overview, current state, tasks, decisions, and references. Read the
159
+ [project memory policy](docs/policy/memory-policy.md) for the contract.
160
+
161
+ ## Development
162
+
163
+ Run the complete local validation suite before sharing a change:
164
+
165
+ ```bash
166
+ make check
167
+ ```
168
+
169
+ You can also run individual layers while iterating:
170
+
171
+ ```bash
172
+ make test-unit
173
+ make test-contract
174
+ make test-integration
175
+ make package-check
176
+ ```
177
+
178
+ The importable implementation is in `src/brida/`; stable command wrappers are
179
+ in `bin/` and `scripts/`. See [CONTRIBUTING.md](CONTRIBUTING.md) for the change
180
+ workflow and [the repository layout](docs/architecture/repository-layout.md)
181
+ for module boundaries.
182
+
183
+ ## Learn more
184
+
185
+ - [Model routing and worker launch settings](docs/guides/model-routing.md)
186
+ - [Installed Codex dogfood](docs/guides/installable-dogfood.md)
187
+ - [Documentation index](docs/index.md)
188
+ - [Operating principles](docs/policy/operating-principles.md)
189
+ - [Security policy](SECURITY.md)
190
+
191
+ ## License
192
+
193
+ Brida is available under the [MIT License](LICENSE).
@@ -0,0 +1,42 @@
1
+ brichan-0.5.0.dist-info/licenses/LICENSE,sha256=9XdXK_INnKeX43x8WI6sIBknvaELPBF64IjF39Hkaas,1066
2
+ brida/__init__.py,sha256=6TP3n7y8nk_HGMjPKHLpja53qNufdyO8a92fHnEscCk,68
3
+ brida/lifecycle.py,sha256=A7XBRW6GuWtFKzTFqpiu0Eff4n6JhlUMvz4_8uphyjI,10932
4
+ brida/project.py,sha256=Zi4tH0_V69VQJNNovB_--rDqVRAQEmI6ZBifx6glf0Y,1816
5
+ brida/cli/__init__.py,sha256=-WeS-o4ivaNlUCWmEkRbq-qmyMGGWImHkpsSMGGfKBg,45
6
+ brida/cli/_root.py,sha256=1MpUoMCJK51DieyE68-3Rq45wCIiQmGHWgmS1P4Zm84,708
7
+ brida/cli/claude.py,sha256=rFkrKaLp5IXNk9GqbISs2YnVtq3szrInnFFHuZ9zHTA,1786
8
+ brida/cli/codex.py,sha256=UGWzeE6CCtTT1x0B_sc0wqKDqTOPUDNx0RhSxjbSvzE,3903
9
+ brida/cli/provider_commands.py,sha256=nvWFbFKR9dx9QixUt4BaRZF-kF6xqsVfGOhAAW0Nut4,14067
10
+ brida/cli/runtime.py,sha256=_FVI1U5iWMwXEovWAD9BsUvrVxYkRtSCpBlHmyMpGbc,6129
11
+ brida/contracts/__init__.py,sha256=Va71T-aZ4_6gsWQ1f2-MK11_cWUK-HlU2OJ5WW4wG8M,31
12
+ brida/contracts/receipts/__init__.py,sha256=XLX3G9j2XSyo14tFLCxm_t6B0zFqCZyHkRHlBoFJH8M,340
13
+ brida/contracts/receipts/discovery.py,sha256=LOvvHwv7JF3ARpUtKWzkdzRROlV8balNedsHqArsFwY,115
14
+ brida/contracts/receipts/parser.py,sha256=ef8mCjPhyGpn7BYzPwhICHp3sPdKbakDkfwbcIsIlOs,127
15
+ brida/contracts/receipts/schema.py,sha256=OXSBHmxvddvVZn0nuVKRHS_WQ3REMbJWfwzYj69RSf8,807
16
+ brida/contracts/receipts/validation.py,sha256=Vt3AM1OwMDJ-BU25Xihxnf3Xp55QMD4AJod9hd7BiNM,35492
17
+ brida/orchestration/__init__.py,sha256=zJ29vdNooU0vdsm39em21taAAqdXvAa_b4bmuw_wpEs,453
18
+ brida/orchestration/herdr_client.py,sha256=x0aOSOZ3WZtxiH1beciztcYh5PK67F795VXJjxd4aJM,207
19
+ brida/orchestration/layout.py,sha256=QJF6sdfj6P4pMtdCGrdD0AH52lErxlVVC66KqJAEUxE,154
20
+ brida/orchestration/model_routing.py,sha256=ifdlYgtyZ_DEaOu5p1ILlvBODR5FxDij5ny6HMm0ljA,9092
21
+ brida/orchestration/worker_launch.py,sha256=yk6l_jRcEOzYpF9-v_2LXMotLYvnDE13FoRdulu-qBU,15620
22
+ brida/resources/__init__.py,sha256=7GEpLlpkVEZme8RnxNlCnLzD_uLikBA_88GEXx4spx8,40
23
+ brida/resources/dogfood_v1/__init__.py,sha256=L78bUjJrs4arq1LDoO59UdiVY4xQ5jTbekraVBFs0A4,45
24
+ brida/resources/dogfood_v1/config/model-routing.json,sha256=FiWJdemnKZVEu83WN4qX0B-w2I0BlJm17zJlSPiROag,710
25
+ brida/resources/dogfood_v1/policy/bootstrap.md,sha256=_w8q-EIlZco5QeMNj_Ec0xZNfBKykaxMPhn2OJuG7OA,1094
26
+ brida/resources/dogfood_v1/policy/identity.md,sha256=s9ITrFrsTJ4EAR8KXN_bWZi_2UbZ1sYX0XEnSQusRo0,846
27
+ brida/resources/dogfood_v1/policy/memory-policy.md,sha256=T2aWpntloiiCNK962JNPhBMGRxjCgbb4XFaxJ-YLffA,647
28
+ brida/resources/dogfood_v1/policy/operating-principles.md,sha256=9mgsHhpW_AWI3-bunGNnvkFJphkefzZs5O-6Frza_70,779
29
+ brida/resources/dogfood_v1/project-memory/index.md,sha256=PhLkcqvVkfOeTTaKkDqkgpQHmvEmKY2efKE7z_F-L_k,149
30
+ brida/resources/dogfood_v1/project-memory/main/current-state.md,sha256=edsLUKxloOFEsXmxx1XN8HlMwpPto7TOS4BUiOvi1HQ,163
31
+ brida/resources/dogfood_v1/project-memory/main/decisions.md,sha256=7YFB4XErRSqtn8G_DkYLvDRVMET12PWyDZJWokjtJvI,91
32
+ brida/resources/dogfood_v1/project-memory/main/overview.md,sha256=0ZSZvrBXixQucghtnPIHFzrUXBAQ8mGe6donHGDqtSA,182
33
+ brida/resources/dogfood_v1/project-memory/main/references.md,sha256=QK-QLajcACshlEHGhDsAH_7BKX2PeTQ5eoABQ4Pd4LE,68
34
+ brida/resources/dogfood_v1/project-memory/main/tasks.md,sha256=bTnFf-vkOb6hfbqtaNeYWwn0yhL5gQEz7DVH48fcDFk,196
35
+ brida/resources/dogfood_v1/skills/herdr-orchestration/SKILL.md,sha256=Wn1R5chYYO8oZ2lABsOY7fX9TV7_u2Qiy-DStnQbIMs,1064
36
+ brida/resources/dogfood_v1/skills/herdr-orchestration/references/commands.md,sha256=-aD6JS8M6aGl64fMm-m9VzOh3bMRLDDG_4m7xyVZ6Is,678
37
+ brida/resources/dogfood_v1/skills/herdr-orchestration/references/task-packet.md,sha256=7nmPVPIveATBeqVuOYo0rPFmZzIvPKd3BUaSLwHmvo4,616
38
+ brichan-0.5.0.dist-info/METADATA,sha256=cfqYf5K8eg59GUOszobjhBTGZkobaHOjULCkHKr7NIA,8026
39
+ brichan-0.5.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
40
+ brichan-0.5.0.dist-info/entry_points.txt,sha256=9NZhQ3yZ70QED5FHpl0d4_gO75RJUDcI_DHnj41ml6s,253
41
+ brichan-0.5.0.dist-info/top_level.txt,sha256=RJpGCwKsFy7LBiknV_FtTiR0OBrJXUR9XDDruQxH4AA,6
42
+ brichan-0.5.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,6 @@
1
+ [console_scripts]
2
+ brida = brida.cli.runtime:main
3
+ brida-claude = brida.cli.claude:main
4
+ brida-codex = brida.cli.codex:main
5
+ brida-herdr-agent-start = brida.orchestration.worker_launch:main
6
+ brida-validate-receipts = brida.contracts.receipts.validation:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Minh Tran
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ brida
brida/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """Brida's importable orchestration core."""
2
+
3
+ __version__ = "0.5.0"
brida/cli/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """Stable Brida command-line entrypoints."""
brida/cli/_root.py ADDED
@@ -0,0 +1,23 @@
1
+ """Repository-root resolution shared by source and installed CLI adapters."""
2
+
3
+ import os
4
+ from pathlib import Path
5
+
6
+
7
+ def repository_root() -> Path:
8
+ override = os.environ.get("BRIDA_ROOT")
9
+ if override:
10
+ return Path(override).resolve()
11
+
12
+ current = Path.cwd().resolve()
13
+ for candidate in (current, *current.parents):
14
+ if (candidate / "AGENTS.md").is_file() and (candidate / "bin").is_dir():
15
+ return candidate
16
+
17
+ source_root = Path(__file__).resolve().parents[3]
18
+ if (source_root / "AGENTS.md").is_file():
19
+ return source_root
20
+ raise RuntimeError(
21
+ "cannot locate the Brida repository root; run inside the repository "
22
+ "or set BRIDA_ROOT"
23
+ )
brida/cli/claude.py ADDED
@@ -0,0 +1,58 @@
1
+ """Claude Code runtime adapter."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import sys
7
+
8
+ from ._root import repository_root
9
+ from brida import __version__
10
+ from brida.orchestration.model_routing import (
11
+ RoutingError,
12
+ load_settings,
13
+ resolve_coordinator,
14
+ )
15
+ from .provider_commands import claude_command
16
+
17
+
18
+ def command(argv: list[str], environment: dict[str, str]) -> list[str]:
19
+ root = repository_root()
20
+ settings = load_settings(repository=root, environment=environment)
21
+ compatibility_model = environment.get("BRIDA_CLAUDE_COORDINATOR_MODEL") or None
22
+ route = resolve_coordinator(
23
+ settings,
24
+ "claude",
25
+ model=compatibility_model,
26
+ )
27
+ return claude_command(route, argv)
28
+
29
+
30
+ def main(argv: list[str] | None = None) -> int:
31
+ arguments = sys.argv[1:] if argv is None else argv
32
+ try:
33
+ os.chdir(repository_root())
34
+ resolved_command = command(arguments, os.environ)
35
+ except RoutingError as exc:
36
+ print(f"brida-claude: {exc}", file=sys.stderr)
37
+ return 2
38
+ except RuntimeError as exc:
39
+ if arguments[:1] in (["--help"], ["-h"]):
40
+ print("usage: brida-claude [claude arguments...]")
41
+ print()
42
+ print(
43
+ "brida-claude is checkout-oriented: run it from within the "
44
+ "Brida source checkout, or with BRIDA_ROOT set. It is not "
45
+ "part of the Codex-first installed-project workflow."
46
+ )
47
+ return 0
48
+ if arguments[:1] in (["--version"], ["-V"]):
49
+ print(f"brida-claude {__version__}")
50
+ return 0
51
+ print(f"brida-claude: {exc}", file=sys.stderr)
52
+ return 2
53
+ os.execvp("claude", resolved_command)
54
+ return 0
55
+
56
+
57
+ if __name__ == "__main__":
58
+ raise SystemExit(main())
brida/cli/codex.py ADDED
@@ -0,0 +1,118 @@
1
+ """Codex runtime adapter."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import sys
7
+
8
+ from ._root import repository_root
9
+ from brida import __version__
10
+ from brida.lifecycle import StateKind, inspect_project
11
+ from brida.orchestration.model_routing import (
12
+ RoutingError,
13
+ load_settings,
14
+ resolve_coordinator,
15
+ )
16
+ from brida.project import ProjectPaths, ProjectError, project_paths
17
+ from .provider_commands import codex_command, codex_project_command
18
+
19
+
20
+ def command(
21
+ argv: list[str],
22
+ environment: dict[str, str] | None = None,
23
+ ) -> list[str]:
24
+ env = os.environ if environment is None else environment
25
+ root = repository_root()
26
+ settings = load_settings(repository=root, environment=env)
27
+ route = resolve_coordinator(settings, "codex")
28
+ return codex_command(route, argv, cwd=root)
29
+
30
+
31
+ def project_command(
32
+ paths: ProjectPaths,
33
+ argv: list[str],
34
+ environment: dict[str, str] | None = None,
35
+ ) -> list[str]:
36
+ """Resolve a package-owned command for one initialized Git project."""
37
+
38
+ env = os.environ if environment is None else environment
39
+ inspection = inspect_project(paths)
40
+ if inspection.kind is not StateKind.HEALTHY:
41
+ raise RoutingError(
42
+ f"project state is {inspection.kind.value}: {inspection.detail}"
43
+ )
44
+ settings = load_settings(
45
+ paths.state_root / "config" / "model-routing.json",
46
+ environment=env,
47
+ )
48
+ route = resolve_coordinator(settings, "codex")
49
+ bootstrap_path = paths.state_root / "policy" / "bootstrap.md"
50
+ try:
51
+ bootstrap = bootstrap_path.read_text(encoding="utf-8")
52
+ except OSError as exc:
53
+ raise RoutingError(f"cannot read Brida bootstrap policy: {exc}") from exc
54
+ developer_instructions = (
55
+ f"{bootstrap.rstrip()}\n\n"
56
+ f"Target project root: {paths.project_root}\n"
57
+ f"Mutable Brida state root: {paths.state_root}\n"
58
+ "Use only package-owned Brida launchers; never execute target-repository "
59
+ "bin/brida-* wrappers."
60
+ )
61
+ return codex_project_command(
62
+ route,
63
+ argv,
64
+ cwd=paths.project_root,
65
+ developer_instructions=developer_instructions,
66
+ skill_path=paths.state_root / "skills" / "herdr-orchestration",
67
+ )
68
+
69
+
70
+ def run_project(
71
+ paths: ProjectPaths,
72
+ argv: list[str],
73
+ environment: dict[str, str] | None = None,
74
+ ) -> int:
75
+ resolved_command = project_command(paths, argv, environment)
76
+ os.chdir(paths.project_root)
77
+ os.execvp("codex", resolved_command)
78
+ return 0
79
+
80
+
81
+ def main(argv: list[str] | None = None) -> int:
82
+ arguments = sys.argv[1:] if argv is None else argv
83
+ try:
84
+ paths = project_paths()
85
+ if paths.state_root.exists():
86
+ return run_project(paths, arguments, os.environ)
87
+ except (ProjectError, RoutingError) as exc:
88
+ if not isinstance(exc, ProjectError):
89
+ print(f"brida-codex: {exc}", file=sys.stderr)
90
+ return 2
91
+ pass
92
+ try:
93
+ resolved_command = command(arguments, os.environ)
94
+ except RoutingError as exc:
95
+ print(f"brida-codex: {exc}", file=sys.stderr)
96
+ return 2
97
+ except RuntimeError as exc:
98
+ if arguments[:1] in (["--help"], ["-h"]):
99
+ print("usage: brida-codex [codex arguments...]")
100
+ print()
101
+ print(
102
+ "brida-codex is checkout-oriented: run it from within the "
103
+ "Brida source checkout (or with BRIDA_ROOT set), or inside a "
104
+ "Git project initialized with 'brida init --apply' for the "
105
+ "installed-project workflow."
106
+ )
107
+ return 0
108
+ if arguments[:1] in (["--version"], ["-V"]):
109
+ print(f"brida-codex {__version__}")
110
+ return 0
111
+ print(f"brida-codex: {exc}", file=sys.stderr)
112
+ return 2
113
+ os.execvp("codex", resolved_command)
114
+ return 0
115
+
116
+
117
+ if __name__ == "__main__":
118
+ raise SystemExit(main())