@ikieaneh/opencode-kit 0.5.7 → 0.5.8
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/README.md +19 -0
- package/package.json +1 -1
- package/src/adr.sh +2 -0
- package/src/analytics.sh +1 -0
- package/src/diff.sh +95 -0
- package/src/doctor.sh +1 -0
- package/src/global-config.sh +1 -0
- package/src/init.sh +6 -1
- package/src/postflight.sh +42 -0
- package/src/preflight.sh +1 -0
- package/src/status.sh +1 -0
- package/src/telemetry.sh +1 -0
- package/src/update.sh +1 -0
package/README.md
CHANGED
|
@@ -224,6 +224,25 @@ INIT → PLAN → PLAN_SCORED → EXECUTE → EXECUTE_SCORED → REVIEW → REVI
|
|
|
224
224
|
|
|
225
225
|
Each phase transition requires a score ≥70 to proceed.
|
|
226
226
|
|
|
227
|
+
### CLI Commands
|
|
228
|
+
|
|
229
|
+
Once installed, run these from the project root:
|
|
230
|
+
|
|
231
|
+
| Command | Purpose |
|
|
232
|
+
|---------|---------|
|
|
233
|
+
| `bash .opencode/src/status.sh` | Dashboard — contract state, telemetry, rules |
|
|
234
|
+
| `bash .opencode/src/doctor.sh` | Diagnostics — MCPs, contract, git, persistence |
|
|
235
|
+
| `bash .opencode/src/analytics.sh` | Telemetry aggregation — phase times, cost estimates |
|
|
236
|
+
| `bash .opencode/src/diff.sh` [branch1] [branch2] | Compare contract state between branches |
|
|
237
|
+
| `bash .opencode/src/adr.sh` | Record a new Architecture Decision Record |
|
|
238
|
+
| `bash .opencode/src/telemetry.sh` | View telemetry details |
|
|
239
|
+
| `bash .opencode/src/new-skill.sh` <name> | Scaffold a new skill SKILL.md |
|
|
240
|
+
| `bash .opencode/rules/validation.sh` | Validate rules compliance |
|
|
241
|
+
| `npx opencode-kit --version` | Print version |
|
|
242
|
+
| `npx opencode-kit --help` | Print help |
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
227
246
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
|
228
247
|
|
|
229
248
|
<!-- STRUCTURE -->
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ikieaneh/opencode-kit",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.8",
|
|
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/src/adr.sh
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
set -euo pipefail
|
|
6
6
|
|
|
7
7
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
+
# shellcheck source=./platform.sh
|
|
8
9
|
. "$SCRIPT_DIR/platform.sh"
|
|
9
10
|
|
|
10
11
|
CONTRACT_FILE=".opencode/orchestration/contract.json"
|
|
@@ -87,6 +88,7 @@ fi
|
|
|
87
88
|
|
|
88
89
|
# --- Build ADR entry ---
|
|
89
90
|
# --- Build ADR entry via heredoc to avoid nested quote issues ---
|
|
91
|
+
# shellcheck disable=SC2001
|
|
90
92
|
$PYTHON_CMD -c "
|
|
91
93
|
import json, sys, os
|
|
92
94
|
|
package/src/analytics.sh
CHANGED
package/src/diff.sh
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# opencode-kit diff — compare contract state between branches
|
|
3
|
+
# Usage: bash src/diff.sh [branch1] [branch2]
|
|
4
|
+
# Default: compares current branch vs main
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
+
# shellcheck source=./platform.sh
|
|
9
|
+
. "$SCRIPT_DIR/platform.sh"
|
|
10
|
+
|
|
11
|
+
CONTRACT_FILE=".opencode/orchestration/contract.json"
|
|
12
|
+
BRANCH_A="${1:-main}"
|
|
13
|
+
BRANCH_B="${2:-HEAD}"
|
|
14
|
+
|
|
15
|
+
RED='\033[0;31m'
|
|
16
|
+
GREEN='\033[0;32m'
|
|
17
|
+
YELLOW='\033[1;33m'
|
|
18
|
+
CYAN='\033[0;36m'
|
|
19
|
+
NC='\033[0m'
|
|
20
|
+
|
|
21
|
+
echo -e "${CYAN}📋 opencode-kit diff: $BRANCH_A ↔ $BRANCH_B${NC}"
|
|
22
|
+
echo ""
|
|
23
|
+
|
|
24
|
+
# Extract contract from a git ref
|
|
25
|
+
get_contract_state() {
|
|
26
|
+
local branch="$1"
|
|
27
|
+
local content
|
|
28
|
+
content=$(git show "$branch:$CONTRACT_FILE" 2>/dev/null || echo "")
|
|
29
|
+
if [ -z "$content" ]; then
|
|
30
|
+
echo ""
|
|
31
|
+
return 1
|
|
32
|
+
fi
|
|
33
|
+
echo "$content"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
CONTRACT_A=$(get_contract_state "$BRANCH_A")
|
|
37
|
+
CONTRACT_B=$(get_contract_state "$BRANCH_B")
|
|
38
|
+
|
|
39
|
+
if [ -z "$CONTRACT_A" ] && [ -z "$CONTRACT_B" ]; then
|
|
40
|
+
echo -e "${YELLOW}No contract found in either branch.${NC}"
|
|
41
|
+
exit 0
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Show state diff
|
|
45
|
+
if [ -n "$PYTHON_CMD" ]; then
|
|
46
|
+
$PYTHON_CMD -c "
|
|
47
|
+
import json, sys
|
|
48
|
+
|
|
49
|
+
def get_state(c):
|
|
50
|
+
try:
|
|
51
|
+
d = json.loads(c)
|
|
52
|
+
return {
|
|
53
|
+
'state': d.get('state', '?'),
|
|
54
|
+
'goal': (d.get('requirements', {}) or {}).get('goal', '?'),
|
|
55
|
+
'score': (d.get('score', {}) or {}).get('combined', '?'),
|
|
56
|
+
'phases': (d.get('metrics', {}) or {}).get('phases_completed', []),
|
|
57
|
+
'adrs': len((d.get('decisions', {}) or {}).get('adr_log', [])),
|
|
58
|
+
'version': d.get('contract_version', '?')
|
|
59
|
+
}
|
|
60
|
+
except:
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
a = get_state('''$CONTRACT_A''') if '''$CONTRACT_A''' else None
|
|
64
|
+
b = get_state('''$CONTRACT_B''') if '''$CONTRACT_B''' else None
|
|
65
|
+
|
|
66
|
+
if a and b:
|
|
67
|
+
print(f' Field $BRANCH_A $BRANCH_B')
|
|
68
|
+
print(f' {"─"*50}')
|
|
69
|
+
for field in ['state', 'goal', 'score', 'version']:
|
|
70
|
+
va = str(a.get(field, '?'))[:20]
|
|
71
|
+
vb = str(b.get(field, '?'))[:20]
|
|
72
|
+
marker = ' ←→' if va != vb else ' '
|
|
73
|
+
print(f' {field:20s} {va:20s} {marker} {vb:20s}')
|
|
74
|
+
print(f' phases {len(a.get(\"phases\",[])):3d} completed {len(b.get(\"phases\",[])):3d} completed')
|
|
75
|
+
print(f' ADRs {a.get(\"adrs\",0):3d} recorded {b.get(\"adrs\",0):3d} recorded')
|
|
76
|
+
elif a and not b:
|
|
77
|
+
print(f' Contract exists in $BRANCH_A but NOT in $BRANCH_B')
|
|
78
|
+
print(f' State: {a.get(\"state\",\"?\")}')
|
|
79
|
+
elif b and not a:
|
|
80
|
+
print(f' Contract exists in $BRANCH_B but NOT in $BRANCH_A')
|
|
81
|
+
print(f' State: {b.get(\"state\",\"?\")}')
|
|
82
|
+
" 2>/dev/null || echo -e "${YELLOW}Could not parse contract JSON${NC}"
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# Raw git diff
|
|
86
|
+
echo ""
|
|
87
|
+
echo -e "${CYAN}Raw diff:${NC}"
|
|
88
|
+
if git diff "$BRANCH_A" "$BRANCH_B" -- "$CONTRACT_FILE" 2>/dev/null | head -40; then
|
|
89
|
+
if ! git diff --exit-code "$BRANCH_A" "$BRANCH_B" -- "$CONTRACT_FILE" &>/dev/null; then
|
|
90
|
+
:
|
|
91
|
+
fi
|
|
92
|
+
fi
|
|
93
|
+
echo ""
|
|
94
|
+
echo -e "Run: ${GREEN}bash .opencode/src/diff.sh${NC} (default: main vs HEAD)"
|
|
95
|
+
echo -e " ${GREEN}bash .opencode/src/diff.sh staging feature-x${NC} (custom branches)"
|
package/src/doctor.sh
CHANGED
package/src/global-config.sh
CHANGED
package/src/init.sh
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
|
|
8
8
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
9
|
+
# shellcheck source=./platform.sh
|
|
9
10
|
. "$SCRIPT_DIR/platform.sh"
|
|
10
11
|
. "$SCRIPT_DIR/global-config.sh"
|
|
11
12
|
KIT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
@@ -88,7 +89,7 @@ if [ -d ".opencode" ]; then
|
|
|
88
89
|
fi
|
|
89
90
|
|
|
90
91
|
# --- Scaffold directories ---
|
|
91
|
-
mkdir -p .opencode/orchestration .opencode/rules .opencode/agents .opencode/src
|
|
92
|
+
mkdir -p .opencode/orchestration .opencode/rules .opencode/agents .opencode/src .opencode/templates
|
|
92
93
|
|
|
93
94
|
# --- Copy templates ---
|
|
94
95
|
echo ""
|
|
@@ -154,6 +155,10 @@ if [ "$PLUGIN_MODE" = false ]; then
|
|
|
154
155
|
chmod +x .opencode/src/analytics.sh
|
|
155
156
|
echo " ✅ analytics.sh (executable)"
|
|
156
157
|
|
|
158
|
+
cp "$KIT_DIR/src/diff.sh" .opencode/src/diff.sh
|
|
159
|
+
chmod +x .opencode/src/diff.sh
|
|
160
|
+
echo " ✅ diff.sh (executable)"
|
|
161
|
+
|
|
157
162
|
# --- Copy agent templates (pre-flight gates) ---
|
|
158
163
|
for agent in orchestrator planner task-manager code-reviewer learner fixer; do
|
|
159
164
|
if [ -f "$KIT_DIR/templates/agents/$agent.md" ]; then
|
package/src/postflight.sh
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
set -euo pipefail
|
|
5
5
|
|
|
6
6
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
7
|
+
# shellcheck source=./platform.sh
|
|
7
8
|
. "$SCRIPT_DIR/platform.sh"
|
|
8
9
|
|
|
9
10
|
CONTRACT_KEY="orchestration-contract"
|
|
@@ -12,6 +13,7 @@ STATE_FILE="STATE.md"
|
|
|
12
13
|
TELEMETRY_DIR=".opencode/telemetry"
|
|
13
14
|
START_TIME_FILE=".opencode/telemetry/.phase_start"
|
|
14
15
|
STATE_BACKUP_DIR=".opencode/state"
|
|
16
|
+
TEMPLATE_FILE=".opencode/templates/contract.json"
|
|
15
17
|
|
|
16
18
|
mkdir -p "$TELEMETRY_DIR" "$STATE_BACKUP_DIR"
|
|
17
19
|
|
|
@@ -46,6 +48,46 @@ if [ -z "$CURRENT_CONTRACT" ]; then
|
|
|
46
48
|
fi
|
|
47
49
|
fi
|
|
48
50
|
|
|
51
|
+
# --- Step 1b: Contract migration (auto-upgrade old schema) ---
|
|
52
|
+
if [ -n "$CURRENT_CONTRACT" ] && [ -f "$TEMPLATE_FILE" ] && [ -n "$PYTHON_CMD" ]; then
|
|
53
|
+
MIGRATED=$($PYTHON_CMD -c "
|
|
54
|
+
import json
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
contract = json.loads('''$CURRENT_CONTRACT''')
|
|
58
|
+
with open('$TEMPLATE_FILE') as f:
|
|
59
|
+
template = json.load(f)
|
|
60
|
+
|
|
61
|
+
# Check version
|
|
62
|
+
old_ver = contract.get('contract_version', '0.0.0')
|
|
63
|
+
new_ver = template.get('contract_version', '0.5.2')
|
|
64
|
+
|
|
65
|
+
if old_ver == new_ver and all(k in contract for k in ['state','requirements','governance','score']):
|
|
66
|
+
print('NO_MIGRATION')
|
|
67
|
+
else:
|
|
68
|
+
# Merge missing top-level fields from template
|
|
69
|
+
for key in template:
|
|
70
|
+
if key not in contract:
|
|
71
|
+
contract[key] = template[key]
|
|
72
|
+
# Merge governance.extension_skills if missing
|
|
73
|
+
if 'extension_skills' not in contract.get('governance', {}):
|
|
74
|
+
if 'governance' not in contract:
|
|
75
|
+
contract['governance'] = {}
|
|
76
|
+
contract['governance']['extension_skills'] = []
|
|
77
|
+
# Update version
|
|
78
|
+
contract['contract_version'] = new_ver
|
|
79
|
+
print(json.dumps(contract))
|
|
80
|
+
except Exception as e:
|
|
81
|
+
print('MIGRATE_ERROR:'+str(e))
|
|
82
|
+
" 2>/dev/null || echo "MIGRATE_ERROR")
|
|
83
|
+
|
|
84
|
+
if [ -n "$MIGRATED" ] && [ "$MIGRATED" != "NO_MIGRATION" ] && [ "$MIGRATED" != "MIGRATE_ERROR" ]; then
|
|
85
|
+
CURRENT_CONTRACT="$MIGRATED"
|
|
86
|
+
echo "$MIGRATED" > "$CONTRACT_FILE"
|
|
87
|
+
echo " 🔄 Contract migrated to v$(echo "$MIGRATED" | $PYTHON_CMD -c "import sys,json; print(json.load(sys.stdin).get('contract_version','?'))" 2>/dev/null)"
|
|
88
|
+
fi
|
|
89
|
+
fi
|
|
90
|
+
|
|
49
91
|
# --- Step 2: Persist (try lean-ctx first, fall back to file) ---
|
|
50
92
|
PERSISTED=false
|
|
51
93
|
if lean-ctx ctx_knowledge remember \
|
package/src/preflight.sh
CHANGED
package/src/status.sh
CHANGED
package/src/telemetry.sh
CHANGED