@ikieaneh/opencode-kit 0.5.2 → 0.5.4

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.
@@ -164,13 +164,24 @@ export const OpencodeKitPlugin = async ({ client, directory }) => {
164
164
  fs.mkdirSync(path.join(globalConfigDir, 'rules'), { recursive: true });
165
165
 
166
166
  return {
167
+ // Skill resolution order (first match wins):
168
+ // 1. .opencode/skills/<name>/ (user project — highest priority)
169
+ // 2. plugin skills/<name>/ (opencode-kit defaults — fallback)
167
170
  config: async (config) => {
168
171
  config.skills = config.skills || {};
169
172
  config.skills.paths = config.skills.paths || [];
170
173
 
174
+ // Register user project skills FIRST (higher priority)
175
+ const userSkillsDir = path.join(projectDir, '.opencode/skills');
176
+ if (fs.existsSync(userSkillsDir) && !config.skills.paths.includes(userSkillsDir)) {
177
+ config.skills.paths.push(userSkillsDir);
178
+ log('info', `Registered user skills: ${userSkillsDir}`);
179
+ }
180
+
181
+ // Register plugin skills SECOND (fallback)
171
182
  if (!config.skills.paths.includes(SKILLS_DIR)) {
172
183
  config.skills.paths.push(SKILLS_DIR);
173
- log('info', `Registered skills: ${SKILLS_DIR}`);
184
+ log('info', `Registered plugin skills: ${SKILLS_DIR}`);
174
185
  }
175
186
 
176
187
  // Register global config skills path
@@ -0,0 +1,108 @@
1
+ # Extension Skill Template
2
+
3
+ Create project-specific skills in `.opencode/skills/` to extend opencode-kit.
4
+
5
+ ## Resolution Order
6
+
7
+ 1. `.opencode/skills/<name>/SKILL.md` — user project skill (highest priority)
8
+ 2. `node_modules/@ikieaneh/opencode-kit/skills/<name>/SKILL.md` — plugin skill (fallback)
9
+
10
+ If a user skill and plugin skill have the **same name**, the user's version takes priority.
11
+
12
+ ## Example: Java/Spring Conventions
13
+
14
+ Create `.opencode/skills/java-conventions/SKILL.md`:
15
+
16
+ ```markdown
17
+ ---
18
+ description: Java 21 + Spring Boot 3.4 conventions for this project.
19
+ ---
20
+
21
+ # Java Conventions
22
+
23
+ ## Build & Test
24
+
25
+ | Command | Action |
26
+ |---------|--------|
27
+ | `mvn spotless:apply` | Format (Google Java Style) |
28
+ | `mvn test` | ArchUnit + unit tests |
29
+ | `mvn verify` | SpotBugs + PMD CPD |
30
+
31
+ ## Hexagonal Architecture
32
+
33
+ ```
34
+ application/ → domain model, ports, services (no Spring/JPA)
35
+ infrastructure/ → web adapters, persistence, events
36
+ ```
37
+
38
+ ## Writing Order
39
+
40
+ Port → Service → Mapper → Adapter → Constants → Events → Tests
41
+
42
+ ## Naming Rules
43
+
44
+ | Concern | Suffix | Example |
45
+ |---------|--------|---------|
46
+ | API DTO | none | `Product` |
47
+ | Domain Model | `Domain` | `ProductDomain` |
48
+ | JPA Entity | `Entity` | `ProductEntity` |
49
+
50
+ ## ArchUnit Rules (7)
51
+
52
+ 1. domainMustNotDependOnInfrastructure
53
+ 2. domainModelsMustNotHaveJpaAnnotations
54
+ 3. portsMustNotReturnOptional
55
+ 4. entitiesMustNotUseJpaRelationshipAnnotations
56
+ 5. layeredArchitectureShouldRespectHexagonalBoundaries
57
+ 6. domainServicesMustBeAnnotatedWithService
58
+ 7. repositoryAdaptersMustBeAnnotatedWithComponent
59
+ ```
60
+
61
+ ## Example: Python/Django Conventions
62
+
63
+ Create `.opencode/skills/python-conventions/SKILL.md`:
64
+
65
+ ```markdown
66
+ ---
67
+ description: Django REST Framework conventions for this project.
68
+ ---
69
+
70
+ # Python Conventions
71
+
72
+ ## Build & Test
73
+
74
+ | Command | Action |
75
+ |---------|--------|
76
+ | `black .` | Format code |
77
+ | `ruff check .` | Lint |
78
+ | `pytest` | Run tests |
79
+ | `mypy .` | Type check |
80
+
81
+ ## Architecture
82
+
83
+ Apps follow clean architecture:
84
+ - `models/` — domain models with business logic
85
+ - `serializers/` — input/output validation
86
+ - `views/` — HTTP handlers (thin)
87
+ - `services/` — business logic layer
88
+ - `tests/` — mirrors app structure
89
+ ```
90
+
91
+ ## How to Load
92
+
93
+ In `opencode.json`, add to any agent's skills array:
94
+
95
+ ```json
96
+ {
97
+ "agent": {
98
+ "task-manager": {
99
+ "skills": [
100
+ "verification-before-completion",
101
+ "java-conventions"
102
+ ]
103
+ }
104
+ }
105
+ }
106
+ ```
107
+
108
+ Or load it ad-hoc with: `/skill java-conventions`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikieaneh/opencode-kit",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "Standardized OpenCode orchestration framework — contract-based, rules-enforced, zero-touch agent workflow. Install as plugin.",
5
5
  "license": "MIT",
6
6
  "author": "RizkiRachman",
package/rules/rules.json CHANGED
@@ -3,6 +3,26 @@
3
3
  "strict": true,
4
4
  "description": "Machine-enforceable rules for OpenCode agents. CRITICAL = BLOCK agent. HIGH = FLAG orchestrator. LOW = advisory.",
5
5
 
6
+ "required_mcps": {
7
+ "description": "MCPs required for the framework to function. Preflight.sh checks these dynamically.",
8
+ "lean-ctx": {
9
+ "description": "Context persistence — contract storage and retrieval",
10
+ "severity": "required",
11
+ "check_cli": "command -v lean-ctx",
12
+ "check_tool": "lean-ctx ctx_knowledge recall"
13
+ },
14
+ "gitnexus": {
15
+ "description": "Code intelligence — impact analysis before edits",
16
+ "severity": "required",
17
+ "check_cli": "npx --yes gitnexus --version"
18
+ },
19
+ "graphify": {
20
+ "description": "Knowledge graph — codebase exploration",
21
+ "severity": "optional",
22
+ "check_cli": "npx --yes gitnexus analyze --help"
23
+ }
24
+ },
25
+
6
26
  "state_machine": {
7
27
  "transitions": [
8
28
  { "from": "INIT", "to": "PLAN", "require_score": null },
@@ -12,36 +12,39 @@ For any code change, run in order:
12
12
 
13
13
  ### 1. Formatting
14
14
  ```bash
15
- mvn spotless:apply # or equivalent formatter
15
+ # Format code (e.g., spotless, prettier, black, gofmt)
16
16
  ```
17
+ Expected: zero files changed after formatting (idempotent).
17
18
 
18
19
  ### 2. Compilation
19
20
  ```bash
20
- mvn compile
21
- # Expected: BUILD SUCCESS
21
+ # Build/tests — check for compilation errors
22
+ # e.g., mvn compile, npm run build, cargo check, go build ./...
22
23
  ```
24
+ Expected: BUILD SUCCESS.
23
25
 
24
- ### 3. Architecture (if ArchUnit present)
26
+ ### 3. Architecture Rules (if applicable)
25
27
  ```bash
26
- mvn test -Dtest="*Architecture*"
27
- # Expected: all 7 ArchUnit rules pass
28
+ # Architecture tests — e.g., ArchUnit, layered boundary checks
28
29
  ```
30
+ Expected: all architecture rules pass.
29
31
 
30
32
  ### 4. Unit Tests
31
33
  ```bash
32
- mvn test
33
- # Expected: 0 failures, 0 errors
34
+ # Run unit tests — e.g., mvn test, npm test, pytest, cargo test
34
35
  ```
36
+ Expected: 0 failures, 0 errors.
35
37
 
36
38
  ### 5. Full Verification
37
39
  ```bash
38
- mvn verify
39
- # Expected: BUILD SUCCESS
40
+ # Full suite — e.g., mvn verify, npm test -- --all
40
41
  ```
42
+ Expected: BUILD SUCCESS.
41
43
 
42
44
  ### 6. Static Analysis (if configured)
43
45
  ```bash
44
- # SpotBugs, PMD CPD, OWASP dependency check
46
+ # Linting, security scan, duplicate detection
47
+ # e.g., SpotBugs, ESLint, Clippy, bandit
45
48
  ```
46
49
 
47
50
  ## Evidence Rules
@@ -53,7 +56,7 @@ mvn verify
53
56
 
54
57
  ## Checklist
55
58
 
56
- - [ ] Formatting passes (spotless)
59
+ - [ ] Formatting passes (idempotent)
57
60
  - [ ] Compiles without errors
58
61
  - [ ] All tests pass (0 failures, 0 errors)
59
62
  - [ ] No new warnings (or documented)
package/src/init.sh CHANGED
@@ -180,29 +180,29 @@ if [ "$SAMPLE" = true ]; then
180
180
  else
181
181
  cat > opencode.json << 'SAMPLEEOF'
182
182
  {
183
- "model": "sumopod/deepseek-v4-flash",
183
+ "model": "your-model",
184
184
  "plugin": [
185
185
  "@ikieaneh/opencode-kit",
186
186
  "superpowers"
187
187
  ],
188
188
  "agent": {
189
189
  "orchestrator": {
190
- "model": "sumopod/deepseek-v4-flash",
190
+ "model": "your-model",
191
191
  "skills": ["orchestration-template", "scoring-pipeline", "verification-before-completion"],
192
192
  "steps": 50
193
193
  },
194
194
  "planner": {
195
- "model": "sumopod/deepseek-v4-flash",
195
+ "model": "your-model",
196
196
  "skills": ["brainstorming", "writing-plans", "system-analyst"],
197
197
  "steps": 80
198
198
  },
199
199
  "task-manager": {
200
- "model": "sumopod/deepseek-v4-flash",
200
+ "model": "your-model",
201
201
  "skills": ["subagent-driven-development", "executing-plans", "test-driven-development"],
202
202
  "steps": 100
203
203
  },
204
204
  "code-reviewer": {
205
- "model": "sumopod/deepseek-v4-flash",
205
+ "model": "your-model",
206
206
  "skills": ["qa-expert", "security-expert"],
207
207
  "steps": 80
208
208
  }
package/src/postflight.sh CHANGED
@@ -11,6 +11,9 @@ CONTRACT_FILE=".opencode/orchestration/contract.json"
11
11
  STATE_FILE="STATE.md"
12
12
  TELEMETRY_DIR=".opencode/telemetry"
13
13
  START_TIME_FILE=".opencode/telemetry/.phase_start"
14
+ STATE_BACKUP_DIR=".opencode/state"
15
+
16
+ mkdir -p "$TELEMETRY_DIR" "$STATE_BACKUP_DIR"
14
17
 
15
18
  echo "[opencode-kit] Post-flight: persisting state..."
16
19
 
@@ -34,16 +37,28 @@ print(d.get('state','UNKNOWN'))
34
37
  rm -f "$START_TIME_FILE"
35
38
  fi
36
39
 
37
- # --- Step 1: Re-read contract from lean-ctx (the source of truth) ---
38
- CURRENT_CONTRACT=$(lean-ctx ctx_knowledge recall --query "$CONTRACT_KEY" 2>/dev/null || cat "$CONTRACT_FILE")
40
+ # --- Step 1: Read contract (try lean-ctx first, fall back to file) ---
41
+ CURRENT_CONTRACT=$(lean-ctx ctx_knowledge recall --query "$CONTRACT_KEY" 2>/dev/null || cat "$CONTRACT_FILE" 2>/dev/null || echo "")
42
+ if [ -z "$CURRENT_CONTRACT" ]; then
43
+ echo " ⚠️ No contract found in lean-ctx or file. Creating new from template..."
44
+ if [ -f "$TEMPLATE_FILE" ]; then
45
+ CURRENT_CONTRACT=$(cat "$TEMPLATE_FILE")
46
+ fi
47
+ fi
39
48
 
40
- # --- Step 2: Write back to lean-ctx ---
41
- lean-ctx ctx_knowledge remember \
49
+ # --- Step 2: Persist (try lean-ctx first, fall back to file) ---
50
+ PERSISTED=false
51
+ if lean-ctx ctx_knowledge remember \
42
52
  category architecture \
43
53
  key "$CONTRACT_KEY" \
44
- value "$CURRENT_CONTRACT" 2>/dev/null && \
45
- echo " ✅ Contract persisted to lean-ctx" || \
46
- echo " ⚠️ lean-ctx persist failed"
54
+ value "$CURRENT_CONTRACT" 2>/dev/null; then
55
+ echo " ✅ Contract persisted to lean-ctx"
56
+ PERSISTED=true
57
+ fi
58
+
59
+ # File fallback: write to .opencode/state/contract.json
60
+ echo "$CURRENT_CONTRACT" > "$STATE_BACKUP_DIR/contract.json"
61
+ echo " ✅ Contract persisted to file: $STATE_BACKUP_DIR/contract.json"
47
62
 
48
63
  # --- Step 3: Sync STATE.md ---
49
64
  mkdir -p "$(dirname "$STATE_FILE")"
package/src/preflight.sh CHANGED
@@ -33,55 +33,71 @@ if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
33
33
  fi
34
34
  echo " ✅ Branch: $BRANCH (safe)"
35
35
 
36
- # --- Check 3: MCP Availability ---
36
+ # --- Check 3: MCP Availability (from rules.json) ---
37
37
  echo ""
38
- echo " Checking MCP availability..."
38
+ echo " Checking MCP availability from rules.json..."
39
39
 
40
40
  MCP_FAIL=0
41
41
 
42
- # 3a. lean-ctx
43
- LEAN_CTX_AVAILABLE=false
44
- if command -v lean-ctx &>/dev/null; then
45
- echo " ✅ lean-ctx MCP: available (cli)"
46
- LEAN_CTX_AVAILABLE=true
47
- elif lean-ctx ctx_knowledge recall --query "$CONTRACT_KEY" &>/dev/null; then
48
- echo " ✅ lean-ctx MCP: available (tool)"
49
- LEAN_CTX_AVAILABLE=true
50
- else
51
- echo -e "${YELLOW} ⚠️ lean-ctx MCP: NOT DETECTED contract persistence will fail${NC}"
52
- echo -e "${YELLOW} → Ensure lean-ctx is configured in opencode.json MCP servers${NC}"
53
- MCP_FAIL=1
54
- fi
55
-
56
- # 3b. gitnexus
57
- if npx --yes gitnexus --version &>/dev/null; then
58
- echo " ✅ gitnexus MCP: available"
59
- elif npx --yes gitnexus list-repos &>/dev/null; then
60
- echo " ✅ gitnexus MCP: available"
61
- else
62
- echo -e "${YELLOW} ⚠️ gitnexus MCP: NOT DETECTED — impact analysis will fail${NC}"
63
- echo -e "${YELLOW} → Ensure gitnexus is configured in opencode.json MCP servers${NC}"
64
- MCP_FAIL=1
65
- fi
66
-
67
- # 3c. graphify (check via gitnexus index since graphify consumes gitnexus data)
68
- GRAPHIFY_AVAILABLE=false
69
- if npx --yes gitnexus analyze --help &>/dev/null; then
70
- # gitnexus is available check if index exists
71
- GITNEXUS_DIR=$(find . -name "gitnexus-out" -type d 2>/dev/null | head -1)
72
- if [ -n "$GITNEXUS_DIR" ]; then
73
- echo " ✅ graphify: available (gitnexus index found)"
74
- GRAPHIFY_AVAILABLE=true
75
- else
76
- echo -e "${YELLOW} ⚠️ graphify: gitnexus index not built yet. Run: npx gitnexus analyze${NC}"
77
- fi
78
- else
79
- echo -e "${YELLOW} ⚠️ graphify: gitnexus not available — graphify depends on gitnexus index${NC}"
80
- fi
81
-
82
- # 3d. context7 (library docs — soft check, non-blocking)
83
- if command -v curl &>/dev/null; then
84
- echo " ✅ context7 MCP: curl available (http transport)"
42
+ if [ -n "$PYTHON_CMD" ] && [ -f "$RULES_FILE" ]; then
43
+ # Parse required_mcps from rules.json
44
+ $PYTHON_CMD -c "
45
+ import json, sys, subprocess, os
46
+
47
+ with open('$RULES_FILE') as f:
48
+ rules = json.load(f)
49
+
50
+ mcps = rules.get('required_mcps', {})
51
+ if not isinstance(mcps, dict) or 'description' in mcps:
52
+ # Skip the meta-description field
53
+ mcps = {k: v for k, v in mcps.items() if k != 'description' and isinstance(v, dict)}
54
+
55
+ if not mcps:
56
+ print(' ℹ️ No required_mcps defined in rules.json — skipping MCP checks')
57
+ sys.exit(0)
58
+
59
+ failures = []
60
+ for name, cfg in mcps.items():
61
+ cli_check = cfg.get('check_cli', '')
62
+ tool_check = cfg.get('check_tool', '')
63
+ severity = cfg.get('severity', 'optional')
64
+ desc = cfg.get('description', name)
65
+
66
+ available = False
67
+ # Try CLI check first
68
+ if cli_check:
69
+ try:
70
+ result = subprocess.run(cli_check, shell=True, capture_output=True, timeout=5)
71
+ if result.returncode == 0:
72
+ available = True
73
+ except:
74
+ pass
75
+
76
+ # Try tool check as fallback
77
+ if not available and tool_check:
78
+ try:
79
+ result = subprocess.run(tool_check, shell=True, capture_output=True, timeout=5)
80
+ if result.returncode == 0:
81
+ available = True
82
+ except:
83
+ pass
84
+
85
+ if available:
86
+ print(f' ✅ {name}: available — {desc}')
87
+ elif severity == 'required':
88
+ print(f' ❌ {name}: NOT DETECTED — {desc}')
89
+ failures.append(name)
90
+ else:
91
+ print(f' ⚠️ {name}: not detected — {desc} (optional)')
92
+
93
+ if failures:
94
+ print('')
95
+ for name in failures:
96
+ print(f' → Ensure {name} is configured in opencode.json MCP servers')
97
+ sys.exit(1)
98
+ else:
99
+ sys.exit(0)
100
+ " 2>&1 || MCP_FAIL=1
85
101
  fi
86
102
 
87
103
  echo ""
@@ -94,7 +94,7 @@ Delegate to @code-reviewer. After return → Scoring Pipeline → update contrac
94
94
  3. **Tier 3 (Verdict)**: ≥70 PASS, 50-69 RETRY, <50 BLOCKED
95
95
 
96
96
  ### 5. Verify (loop)
97
- Run quality gates (verification-before-completion skill)
97
+ Run quality gates (format, compile, test, verify)
98
98
  If CRITICAL findings → BLOCK, fix, re-review. Max 3 iterations.
99
99
 
100
100
  ### 6. Ship
@@ -35,6 +35,7 @@
35
35
  { "source": ".opencode/rules/rules.json", "sections": ["all"] }
36
36
  ],
37
37
  "current_guidance": "",
38
+ "extension_skills": [],
38
39
  "permissions": {
39
40
  "do": [],
40
41
  "dont": [
@@ -23,7 +23,7 @@
23
23
  "properties": {
24
24
  "skills": {
25
25
  "type": "array",
26
- "description": "Recommended skills: orchestration-template, scoring-pipeline, adr-generator, verification-before-completion",
26
+ "description": "Skills to load for this agent (e.g., orchestration, scoring, quality gates)",
27
27
  "items": { "type": "string" },
28
28
  "default": ["orchestration-template", "scoring-pipeline", "verification-before-completion"]
29
29
  },
@@ -37,7 +37,7 @@
37
37
  "properties": {
38
38
  "skills": {
39
39
  "type": "array",
40
- "description": "Recommended skills: brainstorming, writing-plans, system-analyst",
40
+ "description": "Skills for analysis, requirements gathering, plan writing",
41
41
  "items": { "type": "string" },
42
42
  "default": ["brainstorming", "writing-plans", "system-analyst"]
43
43
  },
@@ -51,6 +51,7 @@
51
51
  "properties": {
52
52
  "skills": {
53
53
  "type": "array",
54
+ "description": "Skills for implementation, execution, testing",
54
55
  "items": { "type": "string" },
55
56
  "default": ["subagent-driven-development", "executing-plans", "test-driven-development"]
56
57
  },
@@ -64,6 +65,7 @@
64
65
  "properties": {
65
66
  "skills": {
66
67
  "type": "array",
68
+ "description": "Skills for code quality, security, performance review",
67
69
  "items": { "type": "string" },
68
70
  "default": ["qa-expert", "security-expert", "devops-expert"]
69
71
  },
@@ -77,6 +79,7 @@
77
79
  "properties": {
78
80
  "skills": {
79
81
  "type": "array",
82
+ "description": "Skills for verification, quality checks, post-analysis",
80
83
  "items": { "type": "string" },
81
84
  "default": ["verification-before-completion", "qa-expert"]
82
85
  },
@@ -117,6 +120,7 @@
117
120
  "properties": {
118
121
  "skills": {
119
122
  "type": "array",
123
+ "description": "Skills for architecture analysis, simplification, debugging",
120
124
  "items": { "type": "string" },
121
125
  "default": ["simplify", "systematic-debugging", "system-analyst"]
122
126
  },
@@ -1,66 +0,0 @@
1
- ---
2
- description: Java/Spring Boot conventions for opencode-kit projects. Hexagonal architecture, ArchUnit, Maven build.
3
- ---
4
-
5
- # Java Developer
6
-
7
- Load this skill if your project uses **Java + Spring Boot + Maven**.
8
-
9
- ## Build & Test
10
-
11
- Replace generic `npm` commands with Maven equivalents:
12
-
13
- | Generic | Java Equivalent |
14
- |---------|-----------------|
15
- | `npm test` | `mvn test` |
16
- | `npm run build` | `mvn compile` |
17
- | `npm run format` | `mvn spotless:apply` |
18
- | `npm test -- --all` | `mvn verify` |
19
-
20
- ## Quality Gates (run in order)
21
-
22
- ```sh
23
- mvn spotless:apply # Formatting (Google Java Style)
24
- mvn test # ArchUnit (7 rules) + unit tests
25
- mvn verify # SpotBugs + PMD CPD + full tests
26
- ```
27
-
28
- ## Agent Permission Overrides
29
-
30
- In `opencode.json`, add Maven permissions to agents:
31
-
32
- ```json
33
- "bash": {
34
- "mvn test*": "allow",
35
- "mvn compile*": "allow",
36
- "mvn verify": "allow",
37
- "mvn spotless:apply": "allow",
38
- "git diff*": "allow",
39
- "git log*": "allow"
40
- }
41
- ```
42
-
43
- ## Conventions
44
-
45
- ### Hexagonal Architecture
46
- ```
47
- application/ → domain model, ports, domain services
48
- infrastructure/ → web adapters, persistence, event handlers
49
- ```
50
-
51
- ### Writing Order
52
- Port → Service → Mapper → Adapter → Constants → Events → Tests
53
-
54
- ### Domain Models
55
- - `@Builder @Getter @Setter` — zero JPA annotations
56
- - Ports return **nullable**, never `Optional<T>`
57
- - No JPA relationship annotations (`@ManyToOne`, `@OneToMany`, etc.)
58
-
59
- ### ArchUnit Rules (7)
60
- 1. domainMustNotDependOnInfrastructure
61
- 2. domainModelsMustNotHaveJpaAnnotations
62
- 3. portsMustNotReturnOptional
63
- 4. entitiesMustNotUseJpaRelationshipAnnotations
64
- 5. layeredArchitectureShouldRespectHexagonalBoundaries
65
- 6. domainServicesMustBeAnnotatedWithService
66
- 7. repositoryAdaptersMustBeAnnotatedWithComponent