@lyupro/codex-bridge 0.5.0 → 0.5.1
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.
- package/CHANGELOG.md +19 -0
- package/README.md +44 -19
- package/cli/rules-owners.mjs +24 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.5.1] - 2026-08-12
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Installing or uninstalling no longer fails over a rules-registry lock that is busy for one more
|
|
14
|
+
millisecond. Windows answers a taken lock with three codes, and only one of them is `EEXIST`: a
|
|
15
|
+
lock file whose delete is still pending comes back `EPERM`, and a file another process still
|
|
16
|
+
holds comes back `EBUSY` — the acquisition loop treated both as fatal instead of waiting. All
|
|
17
|
+
three now mean "not yours yet", and the decision lives in one exported check, `isLockTaken()`.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- The README's first screen names the problem the package solves, keeps the install command inside
|
|
22
|
+
the first 30 lines, adds a second badge row, and shows `doctor` output from a healthy host in
|
|
23
|
+
place of a screenshot.
|
|
24
|
+
- The reference documentation under `docs/` is English-only now (`overview.ru.md` became
|
|
25
|
+
`overview.md`), and the working folders — plans, checklists and audits — left the repository and
|
|
26
|
+
its history: a fresh clone contains the five reference documents and nothing else.
|
|
27
|
+
|
|
9
28
|
## [0.5.0] - 2026-08-11
|
|
10
29
|
|
|
11
30
|
### Added
|
package/README.md
CHANGED
|
@@ -6,29 +6,14 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/@lyupro/codex-bridge)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- **Invalid work is rejected before quota is spent.** Scope, order, retry, branch, and continuation checks run before a run folder is created.
|
|
13
|
-
- **Verdicts come from artifacts.** CLI events, git state, and the declared report decide the result, not model claims about itself.
|
|
14
|
-
- **Identical retries attach safely.** Repeating the same command joins the active run instead of starting another one.
|
|
15
|
-
- **5 host guards enforce the boundary.** `reply-guard`, `order-gate`, `worktree-lock`, `prune-guard`, and `stop-guard` cover replies, orders, edits, deletion, and stopping.
|
|
16
|
-
- **Installation is identifiable and reversible.** Writes to `settings.json` are merged and backed up; uninstall removes recorded package files only.
|
|
17
|
-
- **Every run leaves an audit folder.** The verbatim task, scope, before/after git state, events, report, verdict, and reason remain together.
|
|
18
|
-
- **Zero runtime dependencies and zero build steps.** The package is plain `.mjs` on the Node.js standard library.
|
|
9
|
+
[](https://www.npmjs.com/package/@lyupro/codex-bridge)
|
|
10
|
+
[](https://www.npmjs.com/package/@lyupro/codex-bridge)
|
|
11
|
+
[](package.json)
|
|
19
12
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
## Requirements
|
|
23
|
-
|
|
24
|
-
- Node.js >= 24
|
|
25
|
-
- An authenticated [Codex CLI](https://developers.openai.com/codex/cli): `codex --version` and `codex login`
|
|
26
|
-
- Claude Code, which hosts the agents, commands, and guards
|
|
13
|
+
Agentic coding spends one model subscription on everything, and implementation is the expensive part. codex-bridge moves that work to a separate [Codex CLI](https://developers.openai.com/codex/cli) subscription: Claude Code plans, dispatches and accepts, Codex executes — and every delegated run is guarded, verified and audited on disk.
|
|
27
14
|
|
|
28
15
|
## Install
|
|
29
16
|
|
|
30
|
-
For a one-off user installation, global access, or a clone entry point:
|
|
31
|
-
|
|
32
17
|
```bash
|
|
33
18
|
npm i -g @lyupro/codex-bridge # puts both command names on PATH
|
|
34
19
|
codex-bridge install # into ~/.claude and ~/.lyupro/.codex-bridge/
|
|
@@ -50,12 +35,52 @@ If a global install and a clone coexist, you have two package copies. `codex-bri
|
|
|
50
35
|
|
|
51
36
|
`codex-runs/` contains operator data. Uninstall never removes it.
|
|
52
37
|
|
|
38
|
+
## Requirements
|
|
39
|
+
|
|
40
|
+
- Node.js >= 24
|
|
41
|
+
- An authenticated [Codex CLI](https://developers.openai.com/codex/cli): `codex --version` and `codex login`
|
|
42
|
+
- Claude Code, which hosts the agents, commands, and guards
|
|
43
|
+
|
|
44
|
+
## What it gives you
|
|
45
|
+
|
|
46
|
+
- **Runs survive the caller.** A detached worker keeps the run and its artifacts alive after the dispatcher exits.
|
|
47
|
+
- **Invalid work is rejected before quota is spent.** Scope, order, retry, branch, and continuation checks run before a run folder is created.
|
|
48
|
+
- **Verdicts come from artifacts.** CLI events, git state, and the declared report decide the result, not model claims about itself.
|
|
49
|
+
- **Identical retries attach safely.** Repeating the same command joins the active run instead of starting another one.
|
|
50
|
+
- **5 host guards enforce the boundary.** `reply-guard`, `order-gate`, `worktree-lock`, `prune-guard`, and `stop-guard` cover replies, orders, edits, deletion, and stopping.
|
|
51
|
+
- **Installation is identifiable and reversible.** Writes to `settings.json` are merged and backed up; uninstall removes recorded package files only.
|
|
52
|
+
- **Every run leaves an audit folder.** The verbatim task, scope, before/after git state, events, report, verdict, and reason remain together.
|
|
53
|
+
- **Zero runtime dependencies and zero build steps.** The package is plain `.mjs` on the Node.js standard library.
|
|
54
|
+
|
|
55
|
+
The current suite contains **604 automated tests: 603 passing and 1 skipped**.
|
|
56
|
+
|
|
53
57
|
## Verify
|
|
54
58
|
|
|
55
59
|
```bash
|
|
56
60
|
codex-bridge doctor
|
|
57
61
|
```
|
|
58
62
|
|
|
63
|
+
Output on a healthy host (trimmed):
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
[ok] host: ~/.claude (user, exists)
|
|
67
|
+
[ok] installation: @lyupro/codex-bridge@0.5.1 (matches package)
|
|
68
|
+
[ok] files: 53 installed file(s) present
|
|
69
|
+
[ok] rules: ~/.codex/rules/codex-bridge.rules (matches record)
|
|
70
|
+
[ok] permissions: installed (24/24 own strings in allow/deny)
|
|
71
|
+
[ok] hook:SubagentStop: matcher * -> ~/.lyupro/.codex-bridge/hooks/reply-guard.mjs
|
|
72
|
+
[ok] hook:PreToolUse: matcher Agent|Task -> ~/.lyupro/.codex-bridge/hooks/order-gate.mjs
|
|
73
|
+
[ok] hook:PreToolUse: matcher Write|Edit|MultiEdit|NotebookEdit -> ~/.lyupro/.codex-bridge/hooks/worktree-lock.mjs
|
|
74
|
+
[ok] hook:PreToolUse: matcher Bash|PowerShell -> ~/.lyupro/.codex-bridge/hooks/prune-guard.mjs
|
|
75
|
+
[ok] hook:PreToolUse: matcher TaskStop -> ~/.lyupro/.codex-bridge/hooks/stop-guard.mjs
|
|
76
|
+
[warn] retention: Automatic cleanup is ON — run transport older than 30 days is removed to reclaim disk space.
|
|
77
|
+
[ok] conventions: ~/.lyupro/.codex-bridge/conventions.md (found)
|
|
78
|
+
[ok] codex: codex-cli 0.146.1
|
|
79
|
+
[ok] node: 24.18.0 (requires >=24)
|
|
80
|
+
[ok] runsRoot: ~/.claude/codex-runs
|
|
81
|
+
[ok] liveRuns: 0 runs working right now
|
|
82
|
+
```
|
|
83
|
+
|
|
59
84
|
`doctor` reports the selected host, package source, installed files and guards, Codex availability, retention policy, permissions, live runs, and the current repository's run folder.
|
|
60
85
|
|
|
61
86
|
## Update
|
package/cli/rules-owners.mjs
CHANGED
|
@@ -99,19 +99,41 @@ async function dropStaleLock(lockPath) {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Windows answers a taken lock with three different codes, and only one of them is EEXIST. A file
|
|
104
|
+
* whose last handle closed while a delete was pending stays visible but refuses to be opened:
|
|
105
|
+
* `open(..., 'wx')` comes back EPERM, and a file another process still holds comes back EBUSY.
|
|
106
|
+
* Treating those as fatal is what made `tests/cli/rules-owners.test.mjs` fail twice on 2026-08-11
|
|
107
|
+
* with EPERM on the lock file — the suite went red over a lock that was simply busy for one more
|
|
108
|
+
* millisecond. All three mean the same thing to a caller waiting for a lock: not yours yet.
|
|
109
|
+
*/
|
|
110
|
+
const LOCK_TAKEN_CODES = new Set(['EEXIST', 'EPERM', 'EBUSY']);
|
|
111
|
+
|
|
112
|
+
/** Exported so the retry contract is asserted directly; the race itself reproduces only by luck. */
|
|
113
|
+
export function isLockTaken(err) {
|
|
114
|
+
return LOCK_TAKEN_CODES.has(err?.code);
|
|
115
|
+
}
|
|
116
|
+
|
|
102
117
|
async function acquireRegistryLock(host) {
|
|
103
118
|
await fs.mkdir(host.codexRulesDir, { recursive: true });
|
|
104
119
|
const lockPath = registryLockPath(host);
|
|
120
|
+
let lastTaken;
|
|
105
121
|
for (let attempt = 0; attempt < REGISTRY_LOCK_RETRIES; attempt += 1) {
|
|
106
122
|
try {
|
|
107
123
|
const handle = await fs.open(lockPath, 'wx');
|
|
108
124
|
return { handle, lockPath };
|
|
109
125
|
} catch (err) {
|
|
110
|
-
if (err
|
|
126
|
+
if (!isLockTaken(err)) throw err;
|
|
127
|
+
lastTaken = err;
|
|
111
128
|
if (!(await dropStaleLock(lockPath))) await waitForRegistryLock();
|
|
112
129
|
}
|
|
113
130
|
}
|
|
114
|
-
|
|
131
|
+
// The code is part of the message: a timeout on EPERM points at a delete that never completed,
|
|
132
|
+
// a timeout on EEXIST at an owner that never released.
|
|
133
|
+
throw new Error(
|
|
134
|
+
`timed out waiting for rules ownership registry lock: ${lockPath} (last attempt: ${lastTaken.code})`,
|
|
135
|
+
{ cause: lastTaken },
|
|
136
|
+
);
|
|
115
137
|
}
|
|
116
138
|
|
|
117
139
|
async function withRegistryLock(host, action) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lyupro/codex-bridge",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "Claude Code-to-Codex delegation with 5 guards,
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"description": "Claude Code-to-Codex delegation with 5 guards, 604 tests, zero runtime dependencies, and zero build steps.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
7
7
|
"codex",
|