@ikieaneh/opencode-kit 0.5.5 → 0.5.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikieaneh/opencode-kit",
3
- "version": "0.5.5",
3
+ "version": "0.5.6",
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",
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env bash
2
+ # opencode-kit analytics — aggregate telemetry across phases
3
+ # Usage: bash src/analytics.sh [--json]
4
+ set -euo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
+ . "$SCRIPT_DIR/platform.sh"
8
+
9
+ TELEMETRY_DIR=".opencode/telemetry"
10
+ CONTRACT_FILE=".opencode/orchestration/contract.json"
11
+
12
+ RED='\033[0;31m'
13
+ GREEN='\033[0;32m'
14
+ YELLOW='\033[1;33m'
15
+ CYAN='\033[0;36m'
16
+ NC='\033[0m'
17
+
18
+ MODE="${1:-table}"
19
+
20
+ echo -e "${CYAN}📊 opencode-kit Analytics${NC}"
21
+ echo ""
22
+
23
+ if [ ! -f "$TELEMETRY_DIR/phases.jsonl" ] || [ ! -f "$TELEMETRY_DIR/summary.json" ]; then
24
+ echo -e "${YELLOW}No telemetry data yet. Run a few phases first.${NC}"
25
+ exit 0
26
+ fi
27
+
28
+ if [ -z "$PYTHON_CMD" ]; then
29
+ echo -e "${RED}Python required for analytics.${NC}"
30
+ exit 1
31
+ fi
32
+
33
+ $PYTHON_CMD -c "
34
+ import json
35
+
36
+ # Load phases
37
+ phases = []
38
+ try:
39
+ with open('$TELEMETRY_DIR/phases.jsonl') as f:
40
+ for line in f:
41
+ line = line.strip()
42
+ if line:
43
+ phases.append(json.loads(line))
44
+ except:
45
+ pass
46
+
47
+ # Load summary
48
+ summary = {}
49
+ try:
50
+ with open('$TELEMETRY_DIR/summary.json') as f:
51
+ summary = json.load(f)
52
+ except:
53
+ pass
54
+
55
+ if not phases:
56
+ print(' No phases recorded')
57
+ exit(0)
58
+
59
+ total_ms = sum(p.get('elapsed_ms', 0) for p in phases)
60
+ avg_ms = total_ms / len(phases) if phases else 0
61
+
62
+ print(f' Total sessions: {len(phases)}')
63
+ print(f' Total time: {total_ms/1000:.1f}s ({total_ms/60000:.1f}m)')
64
+ print(f' Avg per phase: {avg_ms/1000:.1f}s')
65
+ print('')
66
+ print(f' Phase Breakdown:')
67
+ for p in phases:
68
+ frm = p.get('from', '?')
69
+ to = p.get('to', '?')
70
+ ms = p.get('elapsed_ms', 0)
71
+ bar = '█' * max(1, int(ms / max(1, total_ms) * 30))
72
+ print(f' {frm:16s} → {to:16s} {ms/1000:6.1f}s {bar}')
73
+
74
+ # Cost estimate (rough: ~$0.15/1M tokens, ~1000 tok/s)
75
+ est_tokens = int(total_ms / 1000 * 1000) # rough: 1000 tok/sec
76
+ est_cost = est_tokens / 1_000_000 * 0.15
77
+ print(f'')
78
+ print(f' Estimated tokens: {est_tokens:,} (~{est_cost:.4f} USD at $0.15/1M tok)')
79
+ " 2>/dev/null || echo " ⚠️ Analytics failed"
package/src/init.sh CHANGED
@@ -142,6 +142,18 @@ if [ "$PLUGIN_MODE" = false ]; then
142
142
  chmod +x .opencode/src/doctor.sh
143
143
  echo " ✅ doctor.sh (executable)"
144
144
 
145
+ cp "$KIT_DIR/src/status.sh" .opencode/src/status.sh
146
+ chmod +x .opencode/src/status.sh
147
+ echo " ✅ status.sh (executable)"
148
+
149
+ cp "$KIT_DIR/src/new-skill.sh" .opencode/src/new-skill.sh
150
+ chmod +x .opencode/src/new-skill.sh
151
+ echo " ✅ new-skill.sh (executable)"
152
+
153
+ cp "$KIT_DIR/src/analytics.sh" .opencode/src/analytics.sh
154
+ chmod +x .opencode/src/analytics.sh
155
+ echo " ✅ analytics.sh (executable)"
156
+
145
157
  # --- Copy agent templates (pre-flight gates) ---
146
158
  for agent in orchestrator planner task-manager code-reviewer learner fixer; do
147
159
  if [ -f "$KIT_DIR/templates/agents/$agent.md" ]; then
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env bash
2
+ # opencode-kit new skill — scaffold a new skill SKILL.md
3
+ # Usage: bash src/new-skill.sh <skill-name> [description]
4
+ set -euo pipefail
5
+
6
+ RED='\033[0;31m'
7
+ GREEN='\033[0;32m'
8
+ CYAN='\033[0;36m'
9
+ NC='\033[0m'
10
+
11
+ NAME="${1:-}"
12
+ DESC="${2:-A custom skill for this project}"
13
+ SKILLS_DIR=".opencode/skills"
14
+
15
+ if [ -z "$NAME" ]; then
16
+ echo -e "${RED}Usage: bash src/new-skill.sh <skill-name> [description]${NC}"
17
+ echo " Example: bash src/new-skill.sh python-conventions \"Python/Django conventions\""
18
+ exit 1
19
+ fi
20
+
21
+ SKILL_PATH="$SKILLS_DIR/$NAME"
22
+ SKILL_FILE="$SKILL_PATH/SKILL.md"
23
+
24
+ if [ -d "$SKILL_PATH" ]; then
25
+ echo -e "${RED}❌ Skill already exists: $SKILL_PATH${NC}"
26
+ exit 1
27
+ fi
28
+
29
+ mkdir -p "$SKILL_PATH"
30
+
31
+ cat > "$SKILL_FILE" << SKILLEOF
32
+ ---
33
+ description: $DESC
34
+ ---
35
+
36
+ # $NAME
37
+
38
+ ## Conventions
39
+
40
+ ...
41
+
42
+ ## Commands
43
+
44
+ | Action | Command |
45
+ |--------|---------|
46
+ | Test | ... |
47
+ | Build | ... |
48
+ | Format | ... |
49
+
50
+ ## Rules
51
+
52
+ ...
53
+ SKILLEOF
54
+
55
+ echo -e "${GREEN}✅ Skill created: $SKILL_FILE${NC}"
56
+ echo ""
57
+ echo " To use it, add to opencode.json:"
58
+ echo ' "skills": ["'$NAME'", "orchestration-template"]'
59
+ echo ""
60
+ echo " Or load it ad-hoc with: /skill $NAME"
package/src/status.sh ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env bash
2
+ # opencode-kit status — pretty terminal dashboard
3
+ # Usage: bash src/status.sh
4
+ set -euo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
+ . "$SCRIPT_DIR/platform.sh"
8
+
9
+ CONTRACT_FILE=".opencode/orchestration/contract.json"
10
+ RULES_FILE=".opencode/rules/rules.json"
11
+ TELEMETRY_DIR=".opencode/telemetry"
12
+
13
+ RED='\033[0;31m'
14
+ GREEN='\033[0;32m'
15
+ YELLOW='\033[1;33m'
16
+ CYAN='\033[0;36m'
17
+ BOLD='\033[1m'
18
+ NC='\033[0m'
19
+
20
+ echo ""
21
+ echo -e "${CYAN}${BOLD}╔══════════════════════════════════════════╗${NC}"
22
+ echo -e "${CYAN}${BOLD}║ opencode-kit Dashboard ║${NC}"
23
+ echo -e "${CYAN}${BOLD}╚══════════════════════════════════════════╝${NC}"
24
+ echo ""
25
+
26
+ # === Contract State ===
27
+ if [ -f "$CONTRACT_FILE" ] && [ -n "$PYTHON_CMD" ]; then
28
+ $PYTHON_CMD -c "
29
+ import json
30
+ with open('$CONTRACT_FILE') as f:
31
+ c = json.load(f)
32
+
33
+ state = c.get('state', 'UNKNOWN')
34
+ ver = c.get('contract_version', '?')
35
+ goal = c.get('requirements', {}).get('goal', 'Not set')
36
+ phases = c.get('metrics', {}).get('phases_completed', [])
37
+ score = c.get('score', {}).get('combined', 0)
38
+ verdict = c.get('score', {}).get('verdict', 'PENDING')
39
+ adrs = len(c.get('decisions', {}).get('adr_log', []))
40
+ ext_skills = c.get('governance', {}).get('extension_skills', [])
41
+
42
+ # State color
43
+ state_colors = {
44
+ 'INIT': '\033[0;36m',
45
+ 'PLAN': '\033[1;33m',
46
+ 'PLAN_SCORED': '\033[1;33m',
47
+ 'EXECUTE': '\033[0;32m',
48
+ 'EXECUTE_SCORED': '\033[0;32m',
49
+ 'REVIEW': '\033[0;34m',
50
+ 'REVIEW_SCORED': '\033[0;34m',
51
+ 'COMPLETE': '\033[0;32m',
52
+ 'BLOCKED': '\033[0;31m',
53
+ }
54
+ color = state_colors.get(state, '\033[0m')
55
+ nc = '\033[0m'
56
+
57
+ print(f' ${BOLD}Contract State:${NC} {color}{state}{nc} (v{ver})')
58
+ print(f' ${BOLD}Goal:${NC} {goal[:70]}...' if len(goal) > 70 else f' ${BOLD}Goal:${NC} {goal}')
59
+ print(f' ${BOLD}Score:${NC} {score}/100 ({verdict})')
60
+ print(f' ${BOLD}Phases:${NC} {len(phases)} completed: {\" → \".join(phases[-4:])}')
61
+ print(f' ${BOLD}ADRs:${NC} {adrs} recorded')
62
+ if ext_skills:
63
+ print(f' ${BOLD}Extension Skills:${NC} {\", \".join(ext_skills)}')
64
+ " 2>/dev/null || echo " ⚠️ Could not parse contract"
65
+ else
66
+ echo -e " ${YELLOW}⚠️ No contract found${NC}"
67
+ fi
68
+
69
+ # === Telemetry ===
70
+ echo ""
71
+ echo -e "${BOLD}⏱ Telemetry${NC}"
72
+ if [ -f "$TELEMETRY_DIR/summary.json" ] && [ -n "$PYTHON_CMD" ]; then
73
+ $PYTHON_CMD -c "
74
+ import json
75
+ with open('$TELEMETRY_DIR/summary.json') as f:
76
+ t = json.load(f)
77
+ total_s = t.get('total_elapsed_s', 0)
78
+ phases = t.get('phases_completed', [])
79
+ print(f' Total time: {total_s}s across {len(phases)} phases')
80
+ " 2>/dev/null
81
+ else
82
+ echo -e " ${YELLOW}No telemetry data yet${NC}"
83
+ fi
84
+
85
+ # === Rules ===
86
+ echo ""
87
+ echo -e "${BOLD}📋 Rules${NC}"
88
+ if [ -f "$RULES_FILE" ] && [ -n "$PYTHON_CMD" ]; then
89
+ $PYTHON_CMD -c "
90
+ import json
91
+ with open('$RULES_FILE') as f:
92
+ r = json.load(f)
93
+ rules = r.get('rules', [])
94
+ critical = [x for x in rules if x.get('severity') == 'CRITICAL']
95
+ high = [x for x in rules if x.get('severity') == 'HIGH']
96
+ required_mcps = list(r.get('required_mcps', {}).keys())
97
+ required_mcps = [m for m in required_mcps if m != 'description']
98
+ mcps = list(r.get('required_mcps', {}).keys())
99
+ mcps = [m for m in mcps if m != 'description']
100
+ print(f' {len(critical)} CRITICAL rules, {len(high)} HIGH rules')
101
+ if mcps:
102
+ print(f' Required MCPs: {\", \".join(mcps)}')
103
+ " 2>/dev/null
104
+ else
105
+ echo -e " ${YELLOW}No rules.json${NC}"
106
+ fi
107
+
108
+ # === Quick actions ===
109
+ echo ""
110
+ echo -e "${BOLD}⚡ Quick Actions${NC}"
111
+ echo " bash .opencode/src/doctor.sh — Run diagnostics"
112
+ echo " bash .opencode/src/telemetry.sh — View telemetry details"
113
+ echo " bash .opencode/src/adr.sh — Record new ADR"
114
+ echo ""
package/src/verify.sh CHANGED
@@ -41,7 +41,7 @@ mkdir -p .opencode/telemetry 2>/dev/null
41
41
  echo " ✅ telemetry directory ready"
42
42
 
43
43
  # --- Check 4: scripts executable ---
44
- for script in ".opencode/src/preflight.sh" ".opencode/src/postflight.sh" ".opencode/src/telemetry.sh"; do
44
+ for script in ".opencode/src/preflight.sh" ".opencode/src/postflight.sh" ".opencode/src/telemetry.sh" ".opencode/src/doctor.sh" ".opencode/src/status.sh"; do
45
45
  if [ -x "$script" ]; then
46
46
  echo " ✅ $script (executable)"
47
47
  elif [ -f "$script" ]; then