@tuel/code-oz 0.20.0-alpha.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Omer Akben (Ozzy)
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.
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # code-oz
2
+
3
+ Repo-native agentic SDLC runtime that makes AI code pass through debate, evidence, and cross-family review before it can ship.
4
+
5
+ [![Tests](https://github.com/omerakben/code-oz/actions/workflows/test.yml/badge.svg)](https://github.com/omerakben/code-oz/actions/workflows/test.yml)
6
+ [![Release](https://github.com/omerakben/code-oz/actions/workflows/release.yml/badge.svg)](https://github.com/omerakben/code-oz/actions/workflows/release.yml)
7
+ [![npm version](https://img.shields.io/npm/v/@tuel/code-oz.svg)](https://www.npmjs.com/package/@tuel/code-oz)
8
+ [![Homebrew](https://img.shields.io/badge/Homebrew-omerakben%2Fcode--oz-orange)](https://github.com/omerakben/homebrew-code-oz)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
+ [![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey)](https://github.com/omerakben/code-oz/releases)
11
+ [![Tests passing](https://img.shields.io/badge/tests-3366%20passing-brightgreen)](https://github.com/omerakben/code-oz/actions/workflows/test.yml)
12
+
13
+ > **macOS note:** code-oz binaries are not yet Apple-Developer-signed (signing + notarization deferred to v0.x stable). Gatekeeper may prompt on first launch; the install script applies `xattr -d com.apple.quarantine` as a workaround, and `brew install` handles this automatically.
14
+
15
+ ## Install
16
+
17
+ Three channels deliver the same single binary, verified against the same `checksums.txt`.
18
+
19
+ ```sh
20
+ # curl | sh
21
+ curl -fsSL https://github.com/omerakben/code-oz/releases/download/v0.20.0-alpha.0/install.sh \
22
+ | sh -s -- --version v0.20.0-alpha.0
23
+
24
+ # npm (scoped under the TUEL AI publisher; binary still runs as `code-oz`)
25
+ npm install -g @tuel/code-oz
26
+
27
+ # Homebrew
28
+ brew tap omerakben/code-oz
29
+ brew install omerakben/code-oz/code-oz
30
+ ```
31
+
32
+ Platform support: macOS arm64, macOS x64, Linux x64, Linux arm64. Windows + Scoop are deferred to v0.20.1.
33
+
34
+ ## What it is
35
+
36
+ `code-oz` is a standalone terminal CLI that runs your favorite coding agents (Claude, Codex, Gemini, OpenCode, Roo Code) through a real software delivery lifecycle. It coordinates role-specialized agents over a hybrid phase-graph + agentic sub-orchestration spine with hard gates between phases, file-based state, and cross-family adversarial review. The tool runs on the user's own Claude / Codex / Gemini CLI subscriptions (via SDKs that read CLI OAuth tokens from disk). No API keys required for the supported families.
37
+
38
+ Phases (greenfield): `DEFINE → PLAN → BUILD → VERIFY → REVIEW → SHIP`. Phases (brownfield): `AUDIT → PLAN → BUILD → VERIFY → REVIEW → SHIP`. Auto-detected on boot.
39
+
40
+ ## Demo
41
+
42
+ A 5-minute runnable end-to-end walkthrough lives in [`docs/demo/01-todo-cli/`](docs/demo/01-todo-cli/README.md). One full DEFINE → SHIP cycle on a greenfield todo CLI via `FakeProvider`, all 5 gate files, cross-family REVIEW (BUILD on Claude family, REVIEW on Codex family), `--effort` envelope captures at three levels, and the full `events.jsonl` ledger. Captured outputs at all three effort levels are committed under `docs/demo/01-todo-cli/output/` so you can read the produced artifacts without running anything.
43
+
44
+ ```sh
45
+ bun run demo:todo-cli # default (balanced)
46
+ bun run demo:todo-cli --effort lite # multiplier 0.4
47
+ bun run demo:todo-cli --effort beast # multiplier 6.0
48
+ ```
49
+
50
+ ## Try it from source
51
+
52
+ ```sh
53
+ git clone https://github.com/omerakben/code-oz.git
54
+ cd code-oz && bun install && bun test
55
+ bun run build:binary
56
+
57
+ mkdir /tmp/code-oz-smoke && cd /tmp/code-oz-smoke
58
+ ~/Projects/code-oz/dist/code-oz init
59
+ ~/Projects/code-oz/dist/code-oz doctor tools
60
+ ```
61
+
62
+ ## Status
63
+
64
+ `v0.20.0-alpha.0` — first release with official install channels (curl|sh, npm, Homebrew). 3366 tests pass offline; live xAI integration gated behind opt-in env flags.
65
+
66
+ See [`docs/ABOUT.md`](docs/ABOUT.md) for the milestone inventory, product thesis, influence library, and architecture deep-dive. The milestone plan beyond v0.20 lives in [`docs/design/ROADMAP.md`](docs/design/ROADMAP.md).
67
+
68
+ ## License
69
+
70
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,197 @@
1
+ #!/usr/bin/env node
2
+
3
+ // code-oz npm launcher. Reads the package version, resolves the platform
4
+ // binary from ~/.cache/code-oz/<version>/code-oz (downloading + verifying it
5
+ // on cache miss), then execs it with the user's argv. No bun dependency on
6
+ // the user's machine. No postinstall hook (runs on first invocation), so
7
+ // survives `npm ci --ignore-scripts`.
8
+ //
9
+ // Override hooks (test/internal only — never set in production):
10
+ // CODE_OZ_NPM_BASE_URL base URL containing tarballs + checksums.txt
11
+ // (defaults to the GitHub release for this version)
12
+ // CODE_OZ_NPM_CACHE_DIR cache root (defaults to $HOME/.cache/code-oz)
13
+
14
+ 'use strict'
15
+
16
+ const fs = require('node:fs')
17
+ const os = require('node:os')
18
+ const path = require('node:path')
19
+ const { createHash } = require('node:crypto')
20
+ const { spawn, spawnSync } = require('node:child_process')
21
+ const { Readable } = require('node:stream')
22
+ const { pipeline } = require('node:stream/promises')
23
+
24
+ const GH_OWNER = 'omerakben'
25
+ const GH_REPO = 'code-oz'
26
+
27
+ function die(message) {
28
+ process.stderr.write(`code-oz launcher: ${message}\n`)
29
+ process.exit(1)
30
+ }
31
+
32
+ function readPackageVersion() {
33
+ const pkgPath = path.join(__dirname, '..', 'package.json')
34
+ let raw
35
+ try {
36
+ raw = fs.readFileSync(pkgPath, 'utf8')
37
+ } catch (err) {
38
+ die(`cannot read ${pkgPath}: ${err.message}`)
39
+ }
40
+ let parsed
41
+ try {
42
+ parsed = JSON.parse(raw)
43
+ } catch (err) {
44
+ die(`package.json is not valid JSON: ${err.message}`)
45
+ }
46
+ if (typeof parsed.version !== 'string' || parsed.version.length === 0) {
47
+ die('package.json missing string "version"')
48
+ }
49
+ return parsed.version
50
+ }
51
+
52
+ function detectPlatform() {
53
+ if (process.platform !== 'darwin' && process.platform !== 'linux') {
54
+ die(
55
+ `unsupported platform: ${process.platform}. Supported: darwin, linux. ` +
56
+ 'Windows is deferred to v0.20.1.',
57
+ )
58
+ }
59
+ if (process.arch !== 'arm64' && process.arch !== 'x64') {
60
+ die(`unsupported architecture: ${process.arch}. Supported: arm64, x64.`)
61
+ }
62
+ return { os: process.platform, arch: process.arch }
63
+ }
64
+
65
+ async function download(url, destination) {
66
+ if (url.startsWith('file://')) {
67
+ const sourcePath = url.slice('file://'.length)
68
+ if (!fs.existsSync(sourcePath)) {
69
+ throw new Error(`source file does not exist: ${sourcePath}`)
70
+ }
71
+ await fs.promises.copyFile(sourcePath, destination)
72
+ return
73
+ }
74
+ const protocol = url.startsWith('https://') ? require('node:https') : require('node:http')
75
+ await new Promise((resolve, reject) => {
76
+ const request = protocol.get(url, (response) => {
77
+ const status = response.statusCode ?? 0
78
+ if (status >= 300 && status < 400 && response.headers.location) {
79
+ response.resume()
80
+ download(response.headers.location, destination).then(resolve, reject)
81
+ return
82
+ }
83
+ if (status < 200 || status >= 300) {
84
+ response.resume()
85
+ reject(new Error(`HTTP ${status} for ${url}`))
86
+ return
87
+ }
88
+ const fileStream = fs.createWriteStream(destination)
89
+ pipeline(Readable.from(response), fileStream).then(resolve, reject)
90
+ })
91
+ request.on('error', reject)
92
+ request.setTimeout(60_000, () => {
93
+ request.destroy(new Error(`timeout downloading ${url}`))
94
+ })
95
+ })
96
+ }
97
+
98
+ function sha256File(filePath) {
99
+ const hash = createHash('sha256')
100
+ hash.update(fs.readFileSync(filePath))
101
+ return hash.digest('hex')
102
+ }
103
+
104
+ function findChecksumEntry(text, assetName) {
105
+ const lines = text.split(/\r?\n/)
106
+ for (const line of lines) {
107
+ if (line.length === 0) continue
108
+ const match = line.match(/^([0-9a-f]+)\s+\*?(.+)$/i)
109
+ if (!match) continue
110
+ const [, sha, name] = match
111
+ if (name.trim() === assetName) return sha.toLowerCase()
112
+ }
113
+ return null
114
+ }
115
+
116
+ function extractTarball(tarballPath, destinationDir) {
117
+ const result = spawnSync('tar', ['-C', destinationDir, '-xzf', tarballPath], {
118
+ stdio: ['ignore', 'inherit', 'inherit'],
119
+ })
120
+ if (result.status !== 0) {
121
+ throw new Error(`tar exited with status ${result.status}`)
122
+ }
123
+ }
124
+
125
+ async function ensureBinary({ version, host, cacheRoot, baseUrl }) {
126
+ const cacheDir = path.join(cacheRoot, version)
127
+ const cachedBinary = path.join(cacheDir, 'code-oz')
128
+ if (fs.existsSync(cachedBinary)) return cachedBinary
129
+
130
+ await fs.promises.mkdir(cacheDir, { recursive: true })
131
+ const stageName = `code-oz-v${version}-${host.os}-${host.arch}`
132
+ const assetName = `${stageName}.tar.gz`
133
+ const tarballPath = path.join(cacheDir, assetName)
134
+ const checksumsPath = path.join(cacheDir, 'checksums.txt')
135
+
136
+ try {
137
+ await download(`${baseUrl}/${assetName}`, tarballPath)
138
+ } catch (err) {
139
+ throw new Error(`failed to download ${baseUrl}/${assetName}: ${err.message}`)
140
+ }
141
+ try {
142
+ await download(`${baseUrl}/checksums.txt`, checksumsPath)
143
+ } catch (err) {
144
+ throw new Error(`failed to download ${baseUrl}/checksums.txt: ${err.message}`)
145
+ }
146
+
147
+ const checksumsText = fs.readFileSync(checksumsPath, 'utf8')
148
+ const expectedSha = findChecksumEntry(checksumsText, assetName)
149
+ if (!expectedSha) {
150
+ throw new Error(`no checksum entry for ${assetName} in checksums.txt at ${baseUrl}`)
151
+ }
152
+ const actualSha = sha256File(tarballPath)
153
+ if (actualSha !== expectedSha) {
154
+ throw new Error(`checksum mismatch for ${assetName}: expected ${expectedSha}, got ${actualSha}`)
155
+ }
156
+
157
+ extractTarball(tarballPath, cacheDir)
158
+ const stagedBinary = path.join(cacheDir, stageName, 'code-oz')
159
+ if (!fs.existsSync(stagedBinary)) {
160
+ throw new Error(`extracted tarball missing binary at ${stagedBinary}`)
161
+ }
162
+
163
+ await fs.promises.copyFile(stagedBinary, cachedBinary)
164
+ await fs.promises.chmod(cachedBinary, 0o755)
165
+ await fs.promises.rm(path.join(cacheDir, stageName), { recursive: true, force: true })
166
+ await fs.promises.rm(tarballPath, { force: true })
167
+ await fs.promises.rm(checksumsPath, { force: true })
168
+ return cachedBinary
169
+ }
170
+
171
+ async function main() {
172
+ const version = readPackageVersion()
173
+ const host = detectPlatform()
174
+ const cacheRoot = process.env.CODE_OZ_NPM_CACHE_DIR
175
+ || path.join(os.homedir(), '.cache', 'code-oz')
176
+ const baseUrl = process.env.CODE_OZ_NPM_BASE_URL
177
+ || `https://github.com/${GH_OWNER}/${GH_REPO}/releases/download/v${version}`
178
+
179
+ let binary
180
+ try {
181
+ binary = await ensureBinary({ version, host, cacheRoot, baseUrl })
182
+ } catch (err) {
183
+ die(err.message)
184
+ }
185
+
186
+ const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit' })
187
+ child.on('error', (err) => die(`failed to exec ${binary}: ${err.message}`))
188
+ child.on('exit', (code, signal) => {
189
+ if (signal) {
190
+ process.kill(process.pid, signal)
191
+ return
192
+ }
193
+ process.exit(code ?? 0)
194
+ })
195
+ }
196
+
197
+ main().catch((err) => die(err.message))
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@tuel/code-oz",
3
+ "version": "0.20.0-alpha.0",
4
+ "description": "Multi-agent software-company simulation CLI with hard SDLC gates",
5
+ "type": "module",
6
+ "bin": {
7
+ "code-oz": "npm-wrapper/index.cjs"
8
+ },
9
+ "scripts": {
10
+ "test": "bun test",
11
+ "test:watch": "bun test --watch",
12
+ "dev": "bun run src/cli.ts",
13
+ "build:binary": "bun build --compile --target=bun src/cli.ts --outfile dist/code-oz",
14
+ "build:binaries": "bun run scripts/build-binaries.ts",
15
+ "smoke": "bun run scripts/smoke-test.ts",
16
+ "typecheck": "tsc --noEmit",
17
+ "eval:repo_context": "bun run scripts/eval-repo-context.ts",
18
+ "demo:todo-cli": "bun run scripts/demo/01-todo-cli/run-demo.ts"
19
+ },
20
+ "engines": {
21
+ "node": ">=18",
22
+ "bun": ">=1.3.0"
23
+ },
24
+ "license": "MIT",
25
+ "author": "Omer Akben (Ozzy)",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/omerakben/code-oz.git"
29
+ },
30
+ "homepage": "https://github.com/omerakben/code-oz",
31
+ "bugs": "https://github.com/omerakben/code-oz/issues",
32
+ "keywords": [
33
+ "ai",
34
+ "agents",
35
+ "claude",
36
+ "codex",
37
+ "gemini",
38
+ "sdlc",
39
+ "orchestrator",
40
+ "multi-agent",
41
+ "cli"
42
+ ],
43
+ "files": [
44
+ "npm-wrapper/",
45
+ "README.md",
46
+ "LICENSE"
47
+ ],
48
+ "devDependencies": {
49
+ "@types/bun": "^1.3.13",
50
+ "typescript": "^5.9.3"
51
+ },
52
+ "dependencies": {
53
+ "yaml": "^2.6.1"
54
+ }
55
+ }