@ikieaneh/opencode-kit 0.6.1 → 0.6.3

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/src/preflight.sh DELETED
@@ -1,138 +0,0 @@
1
- #!/usr/bin/env bash
2
- # ⛔ opencode-kit preflight — MANDATORY enforcement gate
3
- # Must run before any tool call. Exits with error if rules violated.
4
- set -euo pipefail
5
-
6
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
- # shellcheck source=./platform.sh
8
- . "$SCRIPT_DIR/platform.sh"
9
-
10
- CONTRACT_KEY="orchestration-contract"
11
- RULES_FILE=".opencode/rules/rules.json"
12
- CONTRACT_FILE=".opencode/orchestration/contract.json"
13
-
14
- RED='\033[0;31m'
15
- GREEN='\033[0;32m'
16
- YELLOW='\033[1;33m'
17
- NC='\033[0m'
18
-
19
- echo "[opencode-kit] ⛔ Pre-flight check..."
20
-
21
- # --- Check 1: contract.json exists on disk ---
22
- if [ ! -f "$CONTRACT_FILE" ]; then
23
- echo -e "${RED}⛔ FAILED: $CONTRACT_FILE not found. Run 'opencode-kit init' first.${NC}"
24
- exit 1
25
- fi
26
- echo " ✅ contract.json exists"
27
-
28
- # --- Check 2: not on main ---
29
- BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
30
- if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
31
- echo -e "${RED}⛔ FAILED: On '$BRANCH' branch. Create a feature branch first.${NC}"
32
- echo " → git checkout -b feature/<YYYYMMDD>-<description>"
33
- exit 1
34
- fi
35
- echo " ✅ Branch: $BRANCH (safe)"
36
-
37
- # --- Check 3: MCP Availability (from rules.json) ---
38
- echo ""
39
- echo " Checking MCP availability from rules.json..."
40
-
41
- MCP_FAIL=0
42
-
43
- if [ -n "$PYTHON_CMD" ] && [ -f "$RULES_FILE" ]; then
44
- # Parse required_mcps from rules.json
45
- $PYTHON_CMD -c "
46
- import json, sys, subprocess, os
47
-
48
- with open('$RULES_FILE') as f:
49
- rules = json.load(f)
50
-
51
- mcps = rules.get('required_mcps', {})
52
- if not isinstance(mcps, dict) or 'description' in mcps:
53
- # Skip the meta-description field
54
- mcps = {k: v for k, v in mcps.items() if k != 'description' and isinstance(v, dict)}
55
-
56
- if not mcps:
57
- print(' ℹ️ No required_mcps defined in rules.json — skipping MCP checks')
58
- sys.exit(0)
59
-
60
- failures = []
61
- for name, cfg in mcps.items():
62
- cli_check = cfg.get('check_cli', '')
63
- tool_check = cfg.get('check_tool', '')
64
- severity = cfg.get('severity', 'optional')
65
- desc = cfg.get('description', name)
66
-
67
- available = False
68
- # Try CLI check first
69
- if cli_check:
70
- try:
71
- result = subprocess.run(cli_check, shell=True, capture_output=True, timeout=5)
72
- if result.returncode == 0:
73
- available = True
74
- except:
75
- pass
76
-
77
- # Try tool check as fallback
78
- if not available and tool_check:
79
- try:
80
- result = subprocess.run(tool_check, shell=True, capture_output=True, timeout=5)
81
- if result.returncode == 0:
82
- available = True
83
- except:
84
- pass
85
-
86
- if available:
87
- print(f' ✅ {name}: available — {desc}')
88
- elif severity == 'required':
89
- print(f' ❌ {name}: NOT DETECTED — {desc}')
90
- failures.append(name)
91
- else:
92
- print(f' ⚠️ {name}: not detected — {desc} (optional)')
93
-
94
- if failures:
95
- print('')
96
- for name in failures:
97
- print(f' → Ensure {name} is configured in opencode.json MCP servers')
98
- sys.exit(1)
99
- else:
100
- sys.exit(0)
101
- " 2>&1 || MCP_FAIL=1
102
- fi
103
-
104
- echo ""
105
-
106
- # --- Check 4: rules.json exists ---
107
- if [ ! -f "$RULES_FILE" ]; then
108
- echo -e "${YELLOW}⚠️ WARNING: $RULES_FILE not found. Rules enforcement disabled.${NC}"
109
- else
110
- echo " ✅ rules.json found"
111
- fi
112
-
113
- # --- Telemetry: record phase start ---
114
- mkdir -p .opencode/telemetry
115
- echo $(date +%s) > .opencode/telemetry/.phase_start
116
-
117
- # --- Check 5: contract state validation ---
118
- if [ -n "$PYTHON_CMD" ] && [ -f "$CONTRACT_FILE" ]; then
119
- STATE=$($PYTHON_CMD -c "
120
- import json,sys
121
- try:
122
- with open('$CONTRACT_FILE') as f: d=json.load(f)
123
- print(d.get('state','UNKNOWN'))
124
- except: print('PARSE_ERROR')
125
- " 2>/dev/null)
126
- if [ "$STATE" = "PARSE_ERROR" ] || [ "$STATE" = "UNKNOWN" ]; then
127
- echo -e "${YELLOW} ⚠️ Contract state: unknown — contract.json may be malformed${NC}"
128
- else
129
- echo " ✅ Contract state: $STATE"
130
- fi
131
- fi
132
-
133
- # --- Final verdict ---
134
- if [ "$MCP_FAIL" -eq 1 ]; then
135
- echo -e "${YELLOW}[opencode-kit] ⛔ Pre-flight completed with WARNINGS. Missing MCPs may cause failures.${NC}"
136
- else
137
- echo "[opencode-kit] ✅ Pre-flight passed. All MCPs available. Proceed."
138
- fi
package/src/status.sh DELETED
@@ -1,113 +0,0 @@
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
- # shellcheck source=./platform.sh
8
- . "$SCRIPT_DIR/platform.sh"
9
-
10
- CONTRACT_FILE=".opencode/orchestration/contract.json"
11
- RULES_FILE=".opencode/rules/rules.json"
12
- TELEMETRY_DIR=".opencode/telemetry"
13
-
14
- RED='\033[0;31m'
15
- GREEN='\033[0;32m'
16
- YELLOW='\033[1;33m'
17
- CYAN='\033[0;36m'
18
- BOLD='\033[1m'
19
- NC='\033[0m'
20
-
21
- echo ""
22
- echo -e "${CYAN}${BOLD}##══════════════════════════════════════════╗${NC}"
23
- echo -e "${CYAN}${BOLD}# opencode-kit Dashboard #${NC}"
24
- echo -e "${CYAN}${BOLD}##══════════════════════════════════════════╝${NC}"
25
- echo ""
26
-
27
- # === Contract State ===
28
- if [ -f "$CONTRACT_FILE" ] && [ -n "$PYTHON_CMD" ]; then
29
- $PYTHON_CMD -c "
30
- import json
31
- with open('$CONTRACT_FILE') as f:
32
- c = json.load(f)
33
-
34
- state = c.get('state', 'UNKNOWN')
35
- ver = c.get('contract_version', '?')
36
- goal = c.get('requirements', {}).get('goal', 'Not set')
37
- phases = c.get('metrics', {}).get('phases_completed', [])
38
- score = c.get('score', {}).get('combined', 0)
39
- verdict = c.get('score', {}).get('verdict', 'PENDING')
40
- adrs = len(c.get('decisions', {}).get('adr_log', []))
41
- ext_skills = c.get('governance', {}).get('extension_skills', [])
42
-
43
- # State color
44
- state_colors = {
45
- 'INIT': '\033[0;36m',
46
- 'PLAN': '\033[1;33m',
47
- 'PLAN_SCORED': '\033[1;33m',
48
- 'EXECUTE': '\033[0;32m',
49
- 'EXECUTE_SCORED': '\033[0;32m',
50
- 'REVIEW': '\033[0;34m',
51
- 'REVIEW_SCORED': '\033[0;34m',
52
- 'COMPLETE': '\033[0;32m',
53
- 'BLOCKED': '\033[0;31m',
54
- }
55
- color = state_colors.get(state, '\033[0m')
56
- nc = '\033[0m'
57
-
58
- print(f' ${BOLD}Contract State:${NC} {color}{state}{nc} (v{ver})')
59
- print(f' ${BOLD}Goal:${NC} {goal[:70]}...' if len(goal) > 70 else f' ${BOLD}Goal:${NC} {goal}')
60
- print(f' ${BOLD}Score:${NC} {score}/100 ({verdict})')
61
- print(f' ${BOLD}Phases:${NC} {len(phases)} completed: {\" → \".join(phases[-4:])}')
62
- print(f' ${BOLD}ADRs:${NC} {adrs} recorded')
63
- if ext_skills:
64
- print(f' ${BOLD}Extension Skills:${NC} {\", \".join(ext_skills)}')
65
- " 2>/dev/null || echo " ⚠️ Could not parse contract"
66
- else
67
- echo -e " ${YELLOW}⚠️ No contract found${NC}"
68
- fi
69
-
70
- # === Telemetry ===
71
- echo ""
72
- echo -e "${BOLD}⏱ Telemetry${NC}"
73
- if [ -f "$TELEMETRY_DIR/summary.json" ] && [ -n "$PYTHON_CMD" ]; then
74
- $PYTHON_CMD -c "
75
- import json
76
- with open('$TELEMETRY_DIR/summary.json') as f:
77
- t = json.load(f)
78
- total_s = t.get('total_elapsed_s', 0)
79
- phases = t.get('phases_completed', [])
80
- print(f' Total time: {total_s}s across {len(phases)} phases')
81
- " 2>/dev/null
82
- else
83
- echo -e " ${YELLOW}No telemetry data yet${NC}"
84
- fi
85
-
86
- # === Rules ===
87
- echo ""
88
- echo -e "${BOLD}📋 Rules${NC}"
89
- if [ -f "$RULES_FILE" ] && [ -n "$PYTHON_CMD" ]; then
90
- $PYTHON_CMD -c "
91
- import json
92
- with open('$RULES_FILE') as f:
93
- r = json.load(f)
94
- rules = r.get('rules', [])
95
- critical = [x for x in rules if x.get('severity') == 'CRITICAL']
96
- high = [x for x in rules if x.get('severity') == 'HIGH']
97
- mcps = list(r.get('required_mcps', {}).keys())
98
- mcps = [m for m in mcps if m != 'description']
99
- print(f' {len(critical)} CRITICAL rules, {len(high)} HIGH rules')
100
- if mcps:
101
- print(f' Required MCPs: {\", \".join(mcps)}')
102
- " 2>/dev/null
103
- else
104
- echo -e " ${YELLOW}No rules.json${NC}"
105
- fi
106
-
107
- # === Quick actions ===
108
- echo ""
109
- echo -e "${BOLD}⚡ Quick Actions${NC}"
110
- echo " bash .opencode/src/doctor.sh — Run diagnostics"
111
- echo " bash .opencode/src/telemetry.sh — View telemetry details"
112
- echo " bash .opencode/src/adr.sh — Record new ADR"
113
- echo ""
package/src/telemetry.sh DELETED
@@ -1,67 +0,0 @@
1
- #!/usr/bin/env bash
2
- # opencode-kit telemetry — view phase telemetry
3
- # Usage: bash src/telemetry.sh [--json|--summary|--phases]
4
- set -euo pipefail
5
-
6
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
- # shellcheck source=./platform.sh
8
- . "$SCRIPT_DIR/platform.sh"
9
-
10
- TELEMETRY_DIR=".opencode/telemetry"
11
- CONTRACT_FILE=".opencode/orchestration/contract.json"
12
-
13
- RED='\033[0;31m'
14
- GREEN='\033[0;32m'
15
- YELLOW='\033[1;33m'
16
- CYAN='\033[0;36m'
17
- NC='\033[0m'
18
-
19
- MODE="${1:-summary}"
20
-
21
- echo -e "${CYAN}[opencode-kit] 📊 Telemetry${NC}"
22
- echo ""
23
-
24
- case "$MODE" in
25
- --json)
26
- if [ -f "$TELEMETRY_DIR/summary.json" ]; then
27
- cat "$TELEMETRY_DIR/summary.json"
28
- else
29
- echo -e "${YELLOW}No telemetry data yet. Run a phase first.${NC}"
30
- fi
31
- ;;
32
- --phases)
33
- if [ -f "$TELEMETRY_DIR/phases.jsonl" ]; then
34
- echo "Phase transitions:"
35
- cat "$TELEMETRY_DIR/phases.jsonl" | while IFS= read -r line; do
36
- [ -z "$line" ] && continue
37
- FROM=$(echo "$line" | $PYTHON_CMD -c "import sys,json; d=json.load(sys.stdin); print(d.get('from','?'))" 2>/dev/null)
38
- TO=$(echo "$line" | $PYTHON_CMD -c "import sys,json; d=json.load(sys.stdin); print(d.get('to','?'))" 2>/dev/null)
39
- MS=$(echo "$line" | $PYTHON_CMD -c "import sys,json; d=json.load(sys.stdin); print(d.get('elapsed_ms',0))" 2>/dev/null)
40
- printf " %-20s → %-20s %5.1fs\n" "$FROM" "$TO" "$($PYTHON_CMD -c "print($MS/1000)" 2>/dev/null || echo "0.0")"
41
- done
42
- else
43
- echo -e "${YELLOW}No phase data yet.${NC}"
44
- fi
45
- ;;
46
- --summary|*)
47
- if [ -f "$TELEMETRY_DIR/summary.json" ]; then
48
- TOTAL_S=$($PYTHON_CMD -c "import json; d=json.load(open('$TELEMETRY_DIR/summary.json')); print(d.get('total_elapsed_s',0))" 2>/dev/null || echo "0")
49
- PHASES=$($PYTHON_CMD -c "import json; d=json.load(open('$TELEMETRY_DIR/summary.json')); print(len(d.get('phases_completed',[])))" 2>/dev/null || echo "0")
50
- echo " Total elapsed: ${TOTAL_S}s"
51
- echo " Phases completed: $PHASES"
52
- echo ""
53
- echo " Latest phases:"
54
- tail -5 "$TELEMETRY_DIR/phases.jsonl" 2>/dev/null | while IFS= read -r line; do
55
- [ -z "$line" ] && continue
56
- TS=$(echo "$line" | $PYTHON_CMD -c "import sys,json; d=json.load(sys.stdin); print(d.get('ts','?'))" 2>/dev/null | cut -dT -f2 | cut -d. -f1)
57
- FROM=$(echo "$line" | $PYTHON_CMD -c "import sys,json; d=json.load(sys.stdin); print(d.get('from','?'))" 2>/dev/null)
58
- TO=$(echo "$line" | $PYTHON_CMD -c "import sys,json; d=json.load(sys.stdin); print(d.get('to','?'))" 2>/dev/null)
59
- MS=$(echo "$line" | $PYTHON_CMD -c "import sys,json; d=json.load(sys.stdin); print(d.get('elapsed_ms',0))" 2>/dev/null)
60
- echo " $TS $FROM → $TO ($((MS/1000))s)"
61
- done
62
- else
63
- echo -e "${YELLOW}No telemetry data yet. Run a phase first.${NC}"
64
- echo " Phases are recorded automatically by postflight.sh"
65
- fi
66
- ;;
67
- esac
package/src/update.sh DELETED
@@ -1,181 +0,0 @@
1
- #!/usr/bin/env bash
2
- # opencode-kit update — pull latest templates and scripts from GitHub
3
- # Preserves existing contract.json state (goal, scope, decisions).
4
- # Usage: bash src/update.sh [--dry-run] [--version <tag>]
5
- set -euo pipefail
6
-
7
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
- # shellcheck source=./platform.sh
9
- . "$SCRIPT_DIR/platform.sh"
10
-
11
- RED='\033[0;31m'
12
- GREEN='\033[0;32m'
13
- YELLOW='\033[1;33m'
14
- CYAN='\033[0;36m'
15
- NC='\033[0m'
16
-
17
- DRY_RUN=false
18
- VERSION="main"
19
- REPO_URL="https://github.com/RizkiRachman/opencode-kit.git"
20
-
21
- # --- Parse args ---
22
- while [ $# -gt 0 ]; do
23
- case "$1" in
24
- --dry-run) DRY_RUN=true; shift ;;
25
- --version) VERSION="$2"; shift 2 ;;
26
- -v) VERSION="$2"; shift 2 ;;
27
- *) echo -e "${RED}Unknown: $1${NC}"; exit 1 ;;
28
- esac
29
- done
30
-
31
- echo -e "${CYAN}[opencode-kit] 🔄 Update check${NC}"
32
- echo " Current dir: $PWD"
33
- echo " Source: $REPO_URL (branch: $VERSION)"
34
- echo " Dry run: $DRY_RUN"
35
- echo ""
36
-
37
- # --- Check we're in an opencode-kit project ---
38
- if [ ! -d ".opencode" ]; then
39
- echo -e "${RED}❌ No .opencode/ directory found. Are you in an opencode-kit project?${NC}"
40
- exit 1
41
- fi
42
-
43
- # --- Clone latest to temp ---
44
- TEMP_DIR=$(mktemp -d /tmp/opencode-kit-XXXXX)
45
- echo " Cloning latest version to $TEMP_DIR..."
46
-
47
- if ! git clone --depth 1 --branch "$VERSION" "$REPO_URL" "$TEMP_DIR" 2>/dev/null; then
48
- echo -e "${RED}❌ Failed to clone $REPO_URL (branch: $VERSION)${NC}"
49
- rm -rf "$TEMP_DIR"
50
- exit 1
51
- fi
52
- echo " ✅ Cloned"
53
-
54
- # --- Read versions ---
55
- CURRENT_VERSION=""
56
- if [ -f ".opencode/orchestration/contract.json" ]; then
57
- CURRENT_VERSION=$($PYTHON_CMD -c "
58
- import json
59
- with open('.opencode/orchestration/contract.json') as f:
60
- d=json.load(f)
61
- print(d.get('contract_version', 'unknown'))
62
- " 2>/dev/null || echo "unknown")
63
- fi
64
-
65
- LATEST_VERSION=$($PYTHON_CMD -c "
66
- import json
67
- with open('$TEMP_DIR/templates/contract.json') as f:
68
- d=json.load(f)
69
- print(d.get('contract_version', 'unknown'))
70
- " 2>/dev/null || echo "unknown")
71
-
72
- echo " Current version: $CURRENT_VERSION"
73
- echo " Latest version: $LATEST_VERSION"
74
- echo ""
75
-
76
- if [ "$CURRENT_VERSION" = "$LATEST_VERSION" ] && [ "$VERSION" = "main" ]; then
77
- echo -e "${GREEN}✅ Already up to date (v$CURRENT_VERSION)${NC}"
78
- rm -rf "$TEMP_DIR"
79
- exit 0
80
- fi
81
-
82
- # --- Backup contract state ---
83
- echo " Backing up contract state..."
84
- STATE_BACKUP=$(mktemp /tmp/opencode-contract-state-XXXXX.json)
85
- $PYTHON_CMD -c "
86
- import json
87
- with open('.opencode/orchestration/contract.json') as f:
88
- d = json.load(f)
89
- # Extract only the state fields to preserve
90
- state = {
91
- 'requirements': d.get('requirements', {}),
92
- 'scope': d.get('scope', {}),
93
- 'decisions': d.get('decisions', {}),
94
- 'governance': d.get('governance', {}),
95
- 'metrics': d.get('metrics', {}),
96
- 'lessons_learned': d.get('lessons_learned', []),
97
- 'retry': d.get('retry', {}),
98
- 'score': d.get('score', {}),
99
- 'outputs': d.get('outputs', {})
100
- }
101
- with open('$STATE_BACKUP', 'w') as f:
102
- json.dump(state, f, indent=2)
103
- " 2>/dev/null || echo " ⚠️ Could not backup contract state"
104
- echo " ✅ State backed up"
105
-
106
- # --- Files to update ---
107
- echo ""
108
- echo " Files to update:"
109
- UPDATES=0
110
-
111
- update_file() {
112
- local src="$1"
113
- local dst="$2"
114
- local label="$3"
115
- if [ -f "$src" ]; then
116
- if [ "$DRY_RUN" = true ]; then
117
- echo " [DRY-RUN] Would update: $label"
118
- else
119
- cp "$src" "$dst"
120
- chmod +x "$dst" 2>/dev/null || true
121
- echo " ✅ Updated: $label"
122
- fi
123
- UPDATES=$((UPDATES + 1))
124
- else
125
- echo " ⚠️ Source not found: $src"
126
- fi
127
- }
128
-
129
- # Update scripts
130
- for script in preflight.sh postflight.sh verify.sh adr.sh platform.sh; do
131
- update_file "$TEMP_DIR/src/$script" ".opencode/src/$script" "src/$script"
132
- done
133
-
134
- # Update init.sh (for future --force re-inits)
135
- update_file "$TEMP_DIR/src/init.sh" ".opencode/src/init.sh" "src/init.sh"
136
-
137
- # Update update.sh itself
138
- update_file "$TEMP_DIR/src/update.sh" ".opencode/src/update.sh" "src/update.sh"
139
-
140
- # Update rules
141
- update_file "$TEMP_DIR/rules/rules.json" ".opencode/rules/rules.json" "rules/rules.json"
142
- update_file "$TEMP_DIR/rules/validation.sh" ".opencode/rules/validation.sh" "rules/validation.sh"
143
-
144
- # Update agent templates (but NOT contract.json — preserve state)
145
- for agent in orchestrator planner task-manager code-reviewer learner fixer; do
146
- update_file "$TEMP_DIR/templates/agents/$agent.md" ".opencode/agents/$agent.md" "agents/$agent.md"
147
- done
148
-
149
- # Update superpowers contract template
150
- update_file "$TEMP_DIR/templates/superpowers-contract.json" ".opencode/templates/superpowers-contract.json" "superpowers-contract.json"
151
-
152
- # --- Restore contract state ---
153
- if [ "$DRY_RUN" = false ] && [ -f "$STATE_BACKUP" ]; then
154
- $PYTHON_CMD -c "
155
- import json
156
- with open('.opencode/orchestration/contract.json') as f:
157
- contract = json.load(f)
158
- with open('$STATE_BACKUP') as f:
159
- state = json.load(f)
160
- # Merge preserved state back into new contract
161
- for key, val in state.items():
162
- if val: # only overwrite if backup has data
163
- contract[key] = val
164
- # Update contract_version to latest
165
- contract['contract_version'] = '$LATEST_VERSION'
166
- with open('.opencode/orchestration/contract.json', 'w') as f:
167
- json.dump(contract, f, indent=2)
168
- " 2>/dev/null && echo " ✅ Contract state restored" || echo " ⚠️ Contract state restore failed"
169
- fi
170
-
171
- # --- Cleanup ---
172
- rm -rf "$TEMP_DIR" "$STATE_BACKUP"
173
-
174
- # --- Summary ---
175
- echo ""
176
- if [ "$DRY_RUN" = true ]; then
177
- echo -e "${YELLOW}[opencode-kit] 🔄 Dry run complete. $UPDATES files would be updated.${NC}"
178
- else
179
- echo -e "${GREEN}[opencode-kit] ✅ Update complete. $UPDATES files updated.${NC}"
180
- echo " Run .opencode/src/verify.sh to verify installation."
181
- fi
package/src/verify.sh DELETED
@@ -1,67 +0,0 @@
1
- #!/usr/bin/env bash
2
- # opencode-kit verify — check installation health
3
- set -euo pipefail
4
-
5
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
-
7
- echo "[opencode-kit] 🔍 Verify: checking installation..."
8
- FAIL=0
9
-
10
- # --- Check 1: required files exist ---
11
- for f in \
12
- ".opencode/orchestration/contract.json" \
13
- ".opencode/rules/rules.json" \
14
- ".opencode/templates/superpowers-contract.json"; do
15
- if [ -f "$f" ]; then
16
- echo " ✅ $f"
17
- else
18
- echo " ❌ $f MISSING"
19
- FAIL=1
20
- fi
21
- done
22
-
23
- # --- Check 2: agent .md files exist ---
24
- for agent in orchestrator planner task-manager code-reviewer learner fixer; do
25
- FILE=".opencode/agents/$agent.md"
26
- if [ -f "$FILE" ]; then
27
- # Check pre-flight gate exists in file
28
- if grep -q "load contract" "$FILE" 2>/dev/null; then
29
- echo " ✅ agents/$agent.md (has pre-flight gate)"
30
- else
31
- echo " ⚠️ agents/$agent.md (MISSING pre-flight gate)"
32
- fi
33
- else
34
- echo " ❌ agents/$agent.md MISSING"
35
- FAIL=1
36
- fi
37
- done
38
-
39
- # --- Check 3: telemetry directory ---
40
- mkdir -p .opencode/telemetry 2>/dev/null
41
- echo " ✅ telemetry directory ready"
42
-
43
- # --- Check 4: scripts executable ---
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
- if [ -x "$script" ]; then
46
- echo " ✅ $script (executable)"
47
- elif [ -f "$script" ]; then
48
- echo " ⚠️ $script (not executable — run chmod +x)"
49
- else
50
- echo " ❌ $script MISSING"
51
- FAIL=1
52
- fi
53
- done
54
-
55
- # --- Check 5: not on main ---
56
- BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
57
- if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
58
- echo " ⚠️ On '$BRANCH' branch — create a feature branch"
59
- fi
60
- echo " ℹ️ Branch: $BRANCH"
61
-
62
- if [ "$FAIL" -eq 1 ]; then
63
- echo "[opencode-kit] ❌ Verify FAILED — run 'opencode-kit init' to repair"
64
- exit 1
65
- fi
66
-
67
- echo "[opencode-kit] ✅ All checks passed"