@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.
- package/.claude-plugin/plugin.json +23 -0
- package/.opencode/plugins/opencode-kit.js +201 -0
- package/LICENSE +21 -0
- package/README.md +417 -0
- package/package.json +47 -0
- package/rules/rules.json +123 -0
- package/rules/validation.sh +145 -0
- package/skills/adr-generator/SKILL.md +42 -0
- package/skills/learner/SKILL.md +44 -0
- package/skills/orchestration-template/SKILL.md +41 -0
- package/skills/qa-expert/SKILL.md +26 -0
- package/skills/scoring-pipeline/SKILL.md +43 -0
- package/skills/system-analyst/SKILL.md +28 -0
- package/skills/token-optimize/SKILL.md +32 -0
- package/skills/verification-before-completion/SKILL.md +60 -0
- package/src/adr.sh +139 -0
- package/src/cli.js +47 -0
- package/src/global-config.sh +81 -0
- package/src/init.sh +165 -0
- package/src/platform.sh +34 -0
- package/src/postflight.sh +132 -0
- package/src/preflight.sh +121 -0
- package/src/telemetry.sh +66 -0
- package/src/update.sh +180 -0
- package/src/verify.sh +67 -0
- package/templates/agents/code-reviewer.md +88 -0
- package/templates/agents/fixer.md +56 -0
- package/templates/agents/learner.md +87 -0
- package/templates/agents/orchestrator.md +110 -0
- package/templates/agents/planner.md +89 -0
- package/templates/agents/task-manager.md +97 -0
- package/templates/contract.json +86 -0
- package/templates/judge-prompt.md +55 -0
- package/templates/opencode-kit.schema.json +83 -0
- package/templates/superpowers-contract.json +8 -0
|
@@ -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
|
+
·
|
|
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
|