@ikieaneh/opencode-kit 0.5.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.
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "opencode-kit",
3
+ "description": "Standardized orchestration framework — contract-based, rules-enforced, zero-touch agent workflow",
4
+ "version": "0.4.0",
5
+ "author": {
6
+ "name": "Rizki Rachman",
7
+ "url": "https://github.com/RizkiRachman"
8
+ },
9
+ "homepage": "https://github.com/RizkiRachman/opencode-kit",
10
+ "repository": "https://github.com/RizkiRachman/opencode-kit",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "opencode",
14
+ "opencode-plugin",
15
+ "orchestration",
16
+ "workflow",
17
+ "agents",
18
+ "enforcement",
19
+ "contract",
20
+ "scoring",
21
+ "adr"
22
+ ]
23
+ }
@@ -0,0 +1,201 @@
1
+ /**
2
+ * opencode-kit plugin for OpenCode.ai
3
+ *
4
+ * Injects contract + rules enforcement into every session.
5
+ * Auto-registers skills directory. Auto-initializes contract if missing.
6
+ * Contract keys are unique per project (hashed from git remote).
7
+ */
8
+
9
+ import path from 'path';
10
+ import fs from 'fs';
11
+ import os from 'os';
12
+ import crypto from 'crypto';
13
+ import { fileURLToPath } from 'url';
14
+
15
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
16
+ const PLUGIN_ROOT = path.resolve(__dirname, '../..');
17
+ const SKILLS_DIR = path.resolve(PLUGIN_ROOT, 'skills');
18
+ const TEMPLATES_DIR = path.resolve(PLUGIN_ROOT, 'templates');
19
+
20
+ let _bootstrapCache = undefined;
21
+ let _pluginLogger = undefined;
22
+
23
+ // --- Minimal logger (avoids console.log — uses client api if available) ---
24
+ const log = (level, msg) => {
25
+ const prefix = `[opencode-kit]`;
26
+ if (_pluginLogger && typeof _pluginLogger[level] === 'function') {
27
+ _pluginLogger[level](`${prefix} ${msg}`);
28
+ } else if (typeof process !== 'undefined' && process.stderr) {
29
+ process.stderr.write(`${prefix} ${msg}\n`);
30
+ }
31
+ };
32
+
33
+ // --- Generate unique contract key per project ---
34
+ const getProjectHash = (projectDir) => {
35
+ // Try git remote first
36
+ const gitConfigPath = path.join(projectDir, '.git', 'config');
37
+ if (fs.existsSync(gitConfigPath)) {
38
+ const config = fs.readFileSync(gitConfigPath, 'utf8');
39
+ const remoteMatch = config.match(/\[remote "origin"\][\s\S]*?url\s*=\s*(.+)/);
40
+ if (remoteMatch) {
41
+ const hash = crypto.createHash('sha256').update(remoteMatch[1].trim()).digest('hex').slice(0, 12);
42
+ return `orchestration-contract:${hash}`;
43
+ }
44
+ }
45
+ // Fallback: hash the absolute path
46
+ const hash = crypto.createHash('sha256').update(projectDir).digest('hex').slice(0, 12);
47
+ return `orchestration-contract:${hash}`;
48
+ };
49
+
50
+ // --- Resolve config: project → global → plugin default ---
51
+ const resolveConfigPath = (projectDir, relPath) => {
52
+ const homeDir = os.homedir();
53
+ const globalDir = path.join(homeDir, '.config/opencode-kit');
54
+
55
+ // 1. Project override
56
+ const projectPath = path.join(projectDir, '.opencode', relPath);
57
+ if (fs.existsSync(projectPath)) return projectPath;
58
+
59
+ // 2. Global defaults
60
+ const globalPath = path.join(globalDir, relPath);
61
+ if (fs.existsSync(globalPath)) return globalPath;
62
+
63
+ // 3. Plugin templates
64
+ const pluginPath = path.join(TEMPLATES_DIR, relPath);
65
+ if (fs.existsSync(pluginPath)) return pluginPath;
66
+
67
+ // 4. Plugin root
68
+ const rootPath = path.join(PLUGIN_ROOT, relPath);
69
+ if (fs.existsSync(rootPath)) return rootPath;
70
+
71
+ return null;
72
+ };
73
+
74
+ // --- Auto-init contract.json if missing ---
75
+ const ensureContract = (projectDir) => {
76
+ const homeDir = os.homedir();
77
+ const globalDir = path.join(homeDir, '.config/opencode-kit');
78
+ const contractPath = path.join(projectDir, '.opencode', 'orchestration', 'contract.json');
79
+
80
+ // Already exists — nothing to do
81
+ if (fs.existsSync(contractPath)) return contractPath;
82
+
83
+ // Check global config first
84
+ const globalContract = path.join(globalDir, 'orchestration', 'contract.json');
85
+ if (fs.existsSync(globalContract)) {
86
+ fs.mkdirSync(path.dirname(contractPath), { recursive: true });
87
+ fs.copyFileSync(globalContract, contractPath);
88
+ log('info', `Auto-initialized contract from global config: ${contractPath}`);
89
+ return contractPath;
90
+ }
91
+
92
+ // Scaffold from plugin template
93
+ const templatePath = path.join(TEMPLATES_DIR, 'contract.json');
94
+ if (fs.existsSync(templatePath)) {
95
+ fs.mkdirSync(path.dirname(contractPath), { recursive: true });
96
+ fs.copyFileSync(templatePath, contractPath);
97
+ log('info', `Auto-initialized contract from plugin template: ${contractPath}`);
98
+ return contractPath;
99
+ }
100
+
101
+ log('warn', 'Could not auto-initialize contract — no template found');
102
+ return null;
103
+ };
104
+
105
+ // --- Load bootstrap content (cached) ---
106
+ const getBootstrapContent = () => {
107
+ if (_bootstrapCache !== undefined) return _bootstrapCache;
108
+
109
+ const skillPath = path.join(SKILLS_DIR, 'orchestration-template', 'SKILL.md');
110
+ if (!fs.existsSync(skillPath)) {
111
+ log('warn', 'orchestration-template skill not found');
112
+ _bootstrapCache = null;
113
+ return null;
114
+ }
115
+
116
+ const fullContent = fs.readFileSync(skillPath, 'utf8');
117
+ const match = fullContent.match(/^---\n[\s\S]*?\n---\n([\s\S]*)$/);
118
+ const content = match ? match[1] : fullContent;
119
+
120
+ _bootstrapCache = `<EXTREMELY_IMPORTANT>
121
+ You have opencode-kit — a standardized orchestration framework.
122
+
123
+ **Contract Protocol (MANDATORY):**
124
+ Before any tool call, you MUST load the orchestration contract:
125
+ lean-ctx ctx_knowledge recall --query "orchestration-contract"
126
+
127
+ If not found in lean-ctx, check:
128
+ 1. .opencode/orchestration/contract.json (project override)
129
+ 2. ~/.config/opencode-kit/contract.json (global defaults)
130
+
131
+ If neither exists, run: npx opencode-kit init
132
+
133
+ **Pre-flight checklist (CRITICAL):**
134
+ - [ ] Loaded contract from lean-ctx or file?
135
+ - [ ] Not on main/master branch?
136
+ - [ ] contract.state allows current action?
137
+ - [ ] rules.json loaded?
138
+
139
+ **Rules enforcement:**
140
+ CRITICAL rules → BLOCK. HIGH rules → FLAG. Never skip.
141
+
142
+ ${content}
143
+ </EXTREMELY_IMPORTANT>`;
144
+
145
+ return _bootstrapCache;
146
+ };
147
+
148
+ export const OpencodeKitPlugin = async ({ client, directory }) => {
149
+ const homeDir = os.homedir();
150
+ const projectDir = directory || process.cwd();
151
+ const globalConfigDir = path.join(homeDir, '.config/opencode-kit');
152
+ const contractKey = getProjectHash(projectDir);
153
+
154
+ // Wire up logger
155
+ _pluginLogger = client?.log || null;
156
+
157
+ log('info', `Plugin loaded (project: ${path.basename(projectDir)}, key: ${contractKey})`);
158
+
159
+ // Auto-init contract on first run
160
+ ensureContract(projectDir);
161
+
162
+ // Ensure global config directory exists
163
+ fs.mkdirSync(path.join(globalConfigDir, 'orchestration'), { recursive: true });
164
+ fs.mkdirSync(path.join(globalConfigDir, 'rules'), { recursive: true });
165
+
166
+ return {
167
+ config: async (config) => {
168
+ config.skills = config.skills || {};
169
+ config.skills.paths = config.skills.paths || [];
170
+
171
+ if (!config.skills.paths.includes(SKILLS_DIR)) {
172
+ config.skills.paths.push(SKILLS_DIR);
173
+ log('info', `Registered skills: ${SKILLS_DIR}`);
174
+ }
175
+
176
+ // Register global config skills path
177
+ if (!config.skills.paths.includes(globalConfigDir)) {
178
+ if (fs.existsSync(globalConfigDir)) {
179
+ config.skills.paths.push(globalConfigDir);
180
+ }
181
+ }
182
+
183
+ // Provide default contract key hint for agents
184
+ config.contractKey = contractKey;
185
+ },
186
+
187
+ 'experimental.chat.messages.transform': async (_input, output) => {
188
+ const bootstrap = getBootstrapContent();
189
+ if (!bootstrap || !output.messages.length) return;
190
+
191
+ const firstUser = output.messages.find(m => m.info.role === 'user');
192
+ if (!firstUser || !firstUser.parts.length) return;
193
+
194
+ // Guard: skip if already injected
195
+ if (firstUser.parts.some(p => p.type === 'text' && p.text.includes('opencode-kit'))) return;
196
+
197
+ const ref = firstUser.parts[0];
198
+ firstUser.parts.unshift({ ...ref, type: 'text', text: bootstrap });
199
+ }
200
+ };
201
+ };
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rizki Rachman
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,417 @@
1
+ <!-- Improved compatibility of back to top link: See: https://github.com/othneildrew/Best-README-Template/pull/73 -->
2
+ <a id="readme-top"></a>
3
+
4
+ <!-- PROJECT SHIELDS -->
5
+ [![Contributors][contributors-shield]][contributors-url]
6
+ [![Forks][forks-shield]][forks-url]
7
+ [![Stargazers][stars-shield]][stars-url]
8
+ [![Issues][issues-shield]][issues-url]
9
+ [![MIT License][license-shield]][license-url]
10
+
11
+ <br />
12
+ <div align="center">
13
+ <a href="https://github.com/RizkiRachman/opencode-kit">
14
+ <img src="docs/images/logo.png" alt="Logo" width="80" height="80">
15
+ </a>
16
+
17
+ <h3 align="center">opencode-kit</h3>
18
+
19
+ <p align="center">
20
+ Standardized OpenCode orchestration framework — contract-based, rules-enforced, zero-touch agent workflow
21
+ <br />
22
+ <a href="https://github.com/RizkiRachman/opencode-kit"><strong>Explore the docs »</strong></a>
23
+ <br />
24
+ <br />
25
+ <a href="https://github.com/RizkiRachman/opencode-kit/issues/new?labels=bug">Report Bug</a>
26
+ &middot;
27
+ <a href="https://github.com/RizkiRachman/opencode-kit/issues/new?labels=enhancement">Request Feature</a>
28
+ </p>
29
+
30
+ <p>
31
+ <b>macOS M-Series</b> — Apple Silicon (arm64)
32
+ </p>
33
+ </div>
34
+
35
+ <!-- TABLE OF CONTENTS -->
36
+ <details>
37
+ <summary>Table of Contents</summary>
38
+ <ol>
39
+ <li><a href="#about-the-project">About The Project</a></li>
40
+ <li><a href="#philosophy">Philosophy</a></li>
41
+ <li>
42
+ <a href="#getting-started">Getting Started</a>
43
+ <ul>
44
+ <li><a href="#prerequisites">Prerequisites</a></li>
45
+ <li><a href="#installation">Installation</a></li>
46
+ </ul>
47
+ </li>
48
+ <li><a href="#usage">Usage</a></li>
49
+ <li><a href="#structure">Structure</a></li>
50
+ <li><a href="#the-6-pillars">The 6 Pillars</a></li>
51
+ <li><a href="#roadmap">Roadmap</a></li>
52
+ <li><a href="#contributing">Contributing</a></li>
53
+ <li><a href="#license">License</a></li>
54
+ <li><a href="#contact">Contact</a></li>
55
+ </ol>
56
+ </details>
57
+
58
+ <!-- ABOUT THE PROJECT -->
59
+ ## About The Project
60
+
61
+ `opencode-kit` is a portable orchestration framework for OpenCode-based AI agents. It solves one core problem:
62
+
63
+ **Agents skip the workflow and jump straight to implementation.**
64
+
65
+ Traditional agent frameworks use conventions (".md files say to load state first") but agents routinely bypass them because there's no enforcement. `opencode-kit` makes the workflow **machine-enforced**, not convention-based.
66
+
67
+ ### How it works (v0.4 — Plugin Mode)
68
+
69
+ With `opencode-kit` installed as an OpenCode plugin, enforcement is **global**. No per-project scaffolding needed.
70
+
71
+ 1. **Plugin injects enforcement** — every session auto-loads the orchestration contract before any work
72
+ 2. **`contract.json`** — shared state machine every agent MUST read/write (local or global)
73
+ 3. **`rules.json`** — machine-readable rules with CRITICAL/HIGH severity
74
+ 4. **3 auto-registered skills** — `orchestration-template`, `scoring-pipeline`, `adr-generator`
75
+ 5. **Config resolution** — `.opencode/` → `~/.config/opencode-kit/` → plugin defaults
76
+
77
+ ### Built for macOS M-Series
78
+
79
+ Developed and tested on Apple Silicon (M1/M2/M3/M4). All scripts use portable POSIX shell with zero Linux-specific dependencies.
80
+
81
+ <p align="right">(<a href="#readme-top">back to top</a>)</p>
82
+
83
+ <!-- PHILOSOPHY -->
84
+ ## Philosophy
85
+
86
+ ### Data-driven enforcement, not convention
87
+
88
+ Most agent frameworks say "please load the envelope first" in prose. Agents ignore prose. `opencode-kit` stores rules as JSON and validates them with shell scripts — the agent can't work around a failing `preflight.sh`.
89
+
90
+ ### Contract over envelope
91
+
92
+ The shared state is called a **contract**, not an envelope. A contract is legally binding — every agent agrees to its terms. Breaking the contract is a governance violation, not a suggestion.
93
+
94
+ ### Score or fail
95
+
96
+ Every subagent output is scored on a 0-100 scale:
97
+ - **≥70** → PASS, advance to next phase
98
+ - **50-69** → RETRY (up to 3 attempts)
99
+ - **<50** → BLOCKED (escalate to user)
100
+
101
+ This creates a quality floor that cheap models can meet through architecture, not raw intelligence.
102
+
103
+ <p align="right">(<a href="#readme-top">back to top</a>)</p>
104
+
105
+ <!-- GETTING STARTED -->
106
+ ## Getting Started
107
+
108
+ ### Prerequisites
109
+
110
+ - **macOS** on Apple Silicon (M1, M2, M3, or M4)
111
+ - **Node.js** ≥ 18 (for `npx` support)
112
+ - **Git** (for version control)
113
+ - **OpenCode** with the following MCPs configured:
114
+ - `lean-ctx` (context persistence)
115
+ - `gitnexus` (code intelligence)
116
+ - `graphify` (knowledge graph)
117
+
118
+ ```sh
119
+ # Verify prerequisites
120
+ node --version # ≥ 18
121
+ git --version # any recent version
122
+ ```
123
+
124
+ ### Installation
125
+
126
+ #### Option 1: Install as plugin (recommended v0.4+)
127
+
128
+ Add to your project's `opencode.json`:
129
+
130
+ ```json
131
+ {
132
+ "plugin": [
133
+ "opencode-kit", ← MUST be first
134
+ "other-plugins..."
135
+ ]
136
+ }
137
+ ```
138
+
139
+ Then install:
140
+
141
+ ```sh
142
+ npm install opencode-kit
143
+ ```
144
+
145
+ The plugin auto-loads on next session. Skills `orchestration-template`, `scoring-pipeline`, `adr-generator` become available. The orchestration contract is injected into every session automatically.
146
+
147
+ > **Plugin ordering**: opencode-kit MUST be first in the plugin array. Its system prompt transform is foundational — other plugins may add behavior, but opencode-kit enforces the workflow.
148
+
149
+ #### Option 2: Quick scaffold (pre-v0.4 style)
150
+
151
+ ```sh
152
+ npx opencode-kit init
153
+ ```
154
+
155
+ This scaffolds the full framework into your current project directory. Compatible with plugin mode — use both for maximum control.
156
+
157
+ #### Option 3: From source
158
+
159
+ ```sh
160
+ git clone https://github.com/RizkiRachman/opencode-kit.git
161
+ cd your-project
162
+ /path/to/opencode-kit/src/init.sh
163
+ ```
164
+
165
+ ### Post-install verification
166
+
167
+ ```sh
168
+ .opencode/src/verify.sh
169
+ ```
170
+
171
+ Expected output:
172
+ ```
173
+ ✅ contract.json
174
+ ✅ rules.json
175
+ ✅ agents/orchestrator.md (has pre-flight gate)
176
+ ✅ agents/planner.md (has pre-flight gate)
177
+ ...
178
+ ✅ All checks passed
179
+ ```
180
+
181
+ <p align="right">(<a href="#readme-top">back to top</a>)</p>
182
+
183
+ <!-- USAGE -->
184
+ ## Usage
185
+
186
+ ### 1. Set a goal
187
+
188
+ Edit `.opencode/orchestration/contract.json`:
189
+
190
+ ```json
191
+ {
192
+ "state": "INIT",
193
+ "requirements": {
194
+ "goal": "Add user authentication with JWT",
195
+ "acceptance_criteria": [
196
+ "Users can register with email + password",
197
+ "Users can login and receive a JWT token",
198
+ "Tokens expire after 24 hours"
199
+ ],
200
+ "constraints": ["No new dependencies", "Follow hexagonal architecture"]
201
+ }
202
+ }
203
+ ```
204
+
205
+ ### 2. Start working
206
+
207
+ Every agent session automatically:
208
+
209
+ 1. **Loads the contract** (BLOCKED if missing)
210
+ 2. **Validates branch** (BLOCKED if on main)
211
+ 3. **Validates state** (BLOCKED if wrong phase)
212
+ 4. **Checks rules** (CRITICAL violations = BLOCK)
213
+
214
+ ### 3. The workflow runs itself
215
+
216
+ ```
217
+ INIT → PLAN → PLAN_SCORED → EXECUTE → EXECUTE_SCORED → REVIEW → REVIEW_SCORED → COMPLETE
218
+
219
+ BLOCKED ← user intervention → retry
220
+ ```
221
+
222
+ Each phase transition requires a score ≥70 to proceed.
223
+
224
+ <p align="right">(<a href="#readme-top">back to top</a>)</p>
225
+
226
+ <!-- STRUCTURE -->
227
+ ## Structure
228
+
229
+ ```
230
+ opencode-kit/
231
+ ├── rules/
232
+ │ ├── rules.json ← Machine-enforceable rules (CRITICAL/HIGH/state machine)
233
+ │ └── validation.sh ← Validates agent actions against rules (future)
234
+ ├── src/
235
+ │ ├── init.sh ← Scaffold into target project
236
+ │ ├── preflight.sh ← Envelope load gate (zero deps, fails if rules violated)
237
+ │ ├── postflight.sh ← Auto-persist + scoring pipeline
238
+ │ └── verify.sh ← Installation health check
239
+ ├── templates/
240
+ │ ├── contract.json ← Shared state contract (renamed from "envelope")
241
+ │ ├── superpowers-contract.json
242
+ │ └── agents/
243
+ │ ├── orchestrator.md
244
+ │ ├── planner.md
245
+ │ ├── task-manager.md
246
+ │ ├── code-reviewer.md
247
+ │ ├── learner.md
248
+ │ └── fixer.md
249
+ ├── package.json ← npm publish for `npx opencode-kit init`
250
+ └── README.md ← You are here
251
+ ```
252
+
253
+ <p align="right">(<a href="#readme-top">back to top</a>)</p>
254
+
255
+ <!-- THE 6 PILLARS -->
256
+ ## The 6 Pillars
257
+
258
+ ### 1. GitNexus — Code Intelligence
259
+
260
+ **Rule**: `IMPACT_001` — CRITICAL. Agent MUST run `gitnexus_impact` before editing any symbol.
261
+
262
+ ```sh
263
+ # Before touching any code:
264
+ gitnexus_impact({target: "symbolName", direction: "upstream"})
265
+ # If HIGH/CRITICAL risk → BLOCK, report to user
266
+ ```
267
+
268
+ ### 2. Graphify — Knowledge Graph
269
+
270
+ **Rule**: Agents MUST explore unfamiliar code via graph queries, not linear file reads.
271
+
272
+ ```sh
273
+ graphify query "<question>" # Scoped subgraph exploration
274
+ ```
275
+
276
+ ### 3. Lean Ctx — Context Persistence
277
+
278
+ **Rule**: `PERSIST_001` — HIGH. Contract MUST be persisted after every delegation/phase change.
279
+
280
+ ```sh
281
+ lean-ctx ctx_knowledge remember key orchestration-contract value <updated JSON>
282
+ ```
283
+
284
+ ### 4. Workflow State — State Machine
285
+
286
+ **Rule**: `STATE_001` — CRITICAL. Agents can only act in correct state.
287
+
288
+ ```json
289
+ {
290
+ "transitions": [
291
+ { "from": "INIT", "to": "PLAN" },
292
+ { "from": "PLAN", "to": "PLAN_SCORED" },
293
+ { "from": "PLAN_SCORED", "to": "EXECUTE", "require_score": 70 },
294
+ ...
295
+ { "from": "*", "to": "BLOCKED", "condition": "score < 50 OR attempts >= 3" }
296
+ ]
297
+ }
298
+ ```
299
+
300
+ ### 5. ADR — Architecture Decision Records
301
+
302
+ Every decision is logged in `contract.json.decisions.adr_log[]` with structured format:
303
+
304
+ ```json
305
+ {
306
+ "decisions": {
307
+ "adr_log": [
308
+ { "id": "ADR-001", "date": "2026-06-11", "title": "Orchestration framework",
309
+ "context": "Agents bypassed envelope protocol", "decision": "Switch to contract + rules.json",
310
+ "alternatives": ["Keep envelope", "Use script enforcement"],
311
+ "consequences": "Stronger enforcement, more scaffolding on init" }
312
+ ]
313
+ }
314
+ }
315
+ ```
316
+
317
+ ### 6. Scoring — Quality Pipeline
318
+
319
+ After every subagent delegation, scoring runs automatically:
320
+ 1. **Tier 1** — Rule-based checks (schema valid, permissions OK, blast radius safe)
321
+ 2. **Tier 2** — LLM judge (fulfills requirements? follows governance? complete?)
322
+ 3. **Tier 3** — Combined verdict (PASS/RETRY/BLOCKED)
323
+
324
+ <p align="right">(<a href="#readme-top">back to top</a>)</p>
325
+
326
+ <!-- ROADMAP -->
327
+ ## Roadmap
328
+
329
+ ### v0.1 (current POC)
330
+ - [x] GitHub repo structure
331
+ - [x] `contract.json` — shared state machine
332
+ - [x] `rules.json` — 8 enforcement rules
333
+ - [x] `preflight.sh` — load contract, validate branch, check state
334
+ - [x] `postflight.sh` — persist contract, run scoring
335
+ - [x] `init.sh` — scaffold into target project
336
+ - [x] `verify.sh` — installation health check
337
+ - [x] 6 agent .md templates with embedded pre-flight gates
338
+ - [x] npm package.json for `npx opencode-kit init`
339
+
340
+ ### v0.2 — Hardening ✅
341
+ - [x] Auto-detect MCP availability (lean-ctx, gitnexus, graphify)
342
+ - [x] `rules/validation.sh` — validate agent actions against rules
343
+ - [ ] Test on clean macOS M-series machine (manual — see notes)
344
+ - [x] Edge cases: re-init over existing `.opencode/` with --force + backup
345
+ - [x] ADR auto-generate on decision (`src/adr.sh`)
346
+
347
+ ### v0.3 — Production ✅
348
+ - [x] Cross-platform (Linux via `src/platform.sh` + `$PYTHON_CMD`)
349
+ - [x] GitHub Actions CI (ShellCheck + scaffold test + syntax check)
350
+ - [x] `opencode-kit update` — `src/update.sh` (pull latest from GitHub, preserve state)
351
+ - [x] Scoring Tier 2 — `templates/judge-prompt.md` + SCORE_002 rule
352
+ - [x] Telemetry — `src/telemetry.sh` (phases.jsonl, elapsed time, summary)
353
+
354
+ ### v0.4 — Plugin Architecture ✅
355
+ - [x] Plugin entry point (`.opencode/plugins/opencode-kit.js`)
356
+ - [x] 3 auto-registered skills (orchestration-template, scoring-pipeline, adr-generator)
357
+ - [x] Global config resolution (local → ~/.config/opencode-kit/ → plugin defaults)
358
+ - [x] Plugin schema (templates/opencode-kit.schema.json)
359
+ - [x] Plugin-aware init.sh (detects plugin, skips redundant scaffolding)
360
+ - [x] Plugin metadata (.claude-plugin/plugin.json)
361
+
362
+ ### v0.5 — Gap Analysis ✅
363
+ - [x] 5 new skills (qa-expert, system-analyst, token-optimize, verification-before-completion, learner)
364
+ - [x] Auto-init contract on first run
365
+ - [x] Contract uniqueness per project (hashed lean-ctx key)
366
+ - [x] Proper plugin logging
367
+ - [x] CLI version/help command
368
+ - [x] Logo placeholder
369
+ - [x] STATE.md auto-sync
370
+ - [x] Integration tests (7/7 passing)
371
+ - [x] CI integration test job
372
+
373
+ ### v0.6 — Publish & Polish (next)
374
+ - [ ] npm publish
375
+ - [ ] Test plugin end-to-end on clean macOS M-series machine
376
+ - [ ] Web UI for contract overview
377
+
378
+ See the [open issues](https://github.com/RizkiRachman/opencode-kit/issues) for full list.
379
+
380
+ <p align="right">(<a href="#readme-top">back to top</a>)</p>
381
+
382
+ <!-- CONTRIBUTING -->
383
+ ## Contributing
384
+
385
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for full guidelines.
386
+
387
+ TL;DR: Fork → Feature branch → Commit → PR. Follow the 6-pillar architecture. All rules enforcements must be tested.
388
+
389
+ <p align="right">(<a href="#readme-top">back to top</a>)</p>
390
+
391
+ <!-- LICENSE -->
392
+ ## License
393
+
394
+ Distributed under the MIT License. See `LICENSE` for more information.
395
+
396
+ <p align="right">(<a href="#readme-top">back to top</a>)</p>
397
+
398
+ <!-- CONTACT -->
399
+ ## Contact
400
+
401
+ Rizki Rachman — [GitHub](https://github.com/RizkiRachman)
402
+
403
+ Project Link: [https://github.com/RizkiRachman/opencode-kit](https://github.com/RizkiRachman/opencode-kit)
404
+
405
+ <p align="right">(<a href="#readme-top">back to top</a>)</p>
406
+
407
+ <!-- MARKDOWN LINKS & IMAGES -->
408
+ [contributors-shield]: https://img.shields.io/github/contributors/RizkiRachman/opencode-kit.svg?style=for-the-badge
409
+ [contributors-url]: https://github.com/RizkiRachman/opencode-kit/graphs/contributors
410
+ [forks-shield]: https://img.shields.io/github/forks/RizkiRachman/opencode-kit.svg?style=for-the-badge
411
+ [forks-url]: https://github.com/RizkiRachman/opencode-kit/network/members
412
+ [stars-shield]: https://img.shields.io/github/stars/RizkiRachman/opencode-kit.svg?style=for-the-badge
413
+ [stars-url]: https://github.com/RizkiRachman/opencode-kit/stargazers
414
+ [issues-shield]: https://img.shields.io/github/issues/RizkiRachman/opencode-kit.svg?style=for-the-badge
415
+ [issues-url]: https://github.com/RizkiRachman/opencode-kit/issues
416
+ [license-shield]: https://img.shields.io/github/license/RizkiRachman/opencode-kit.svg?style=for-the-badge
417
+ [license-url]: https://github.com/RizkiRachman/opencode-kit/blob/main/LICENSE