arkaos 2.6.0 → 2.8.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/VERSION +1 -1
- package/config/constitution.yaml +8 -0
- package/config/hooks/cwd-changed.sh +104 -0
- package/config/hooks/session-start.sh +60 -0
- package/config/hooks/user-prompt-submit-v2.sh +26 -1
- package/config/hooks/user-prompt-submit.sh +105 -277
- package/config/settings-template.json +22 -0
- package/config/standards/ecosystem-workflow.md +60 -0
- package/config/user-claude.md +15 -0
- package/installer/adapters/claude-code.js +26 -0
- package/installer/index.js +39 -16
- package/installer/update.js +32 -11
- package/knowledge/agents-registry.json +6 -6
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/departments/ecommerce/SKILL.md +0 -363
- package/departments/ecommerce/agents/ecommerce-manager.md +0 -91
- package/departments/knowledge/SKILL.md +0 -474
- package/departments/knowledge/agents/knowledge-curator.md +0 -89
- package/departments/operations/SKILL.md +0 -422
- package/departments/operations/agents/coo.md +0 -88
- /package/departments/{knowledge → kb}/scripts/kb-check-capabilities.sh +0 -0
- /package/departments/{knowledge → kb}/scripts/kb-cleanup.sh +0 -0
- /package/departments/{knowledge → kb}/scripts/kb-queue.sh +0 -0
- /package/departments/{knowledge → kb}/scripts/kb-status.sh +0 -0
- /package/departments/{knowledge → kb}/scripts/kb-worker.sh +0 -0
|
@@ -1,312 +1,140 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# ============================================================================
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# Timeout: 10s | Output: JSON to stdout | Target: <
|
|
3
|
+
# ArkaOS v2 — UserPromptSubmit Hook (Synapse v2 Bridge)
|
|
4
|
+
# Calls Python Synapse engine for 8-layer context injection
|
|
5
|
+
# Timeout: 10s | Output: JSON to stdout | Target: <100ms
|
|
6
6
|
# ============================================================================
|
|
7
7
|
|
|
8
8
|
input=$(cat)
|
|
9
9
|
|
|
10
|
-
# ───
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
_hook_ms() {
|
|
14
|
-
local end_ns=$(date +%s%N 2>/dev/null || echo "0")
|
|
15
|
-
if [ "$_HOOK_START_NS" != "0" ] && [ "$end_ns" != "0" ] && [ ${#end_ns} -gt 10 ]; then
|
|
16
|
-
echo $(( (end_ns - _HOOK_START_NS) / 1000000 ))
|
|
17
|
-
else
|
|
18
|
-
echo $(( ($(date +%s) - _HOOK_START) * 1000 ))
|
|
19
|
-
fi
|
|
20
|
-
}
|
|
10
|
+
# ─── V1 Migration Detection ─────────────────────────────────────────────
|
|
11
|
+
V1_PATHS=("$HOME/.claude/skills/arka-os" "$HOME/.claude/skills/arkaos")
|
|
12
|
+
MIGRATION_MARKER="$HOME/.arkaos/migrated-from-v1"
|
|
21
13
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
for v1_path in "${V1_PATHS[@]}"; do
|
|
15
|
+
if [ -d "$v1_path" ] && [ ! -f "$MIGRATION_MARKER" ]; then
|
|
16
|
+
echo "{\"additionalContext\": \"[MIGRATION] ArkaOS v1 detected at $v1_path. Run: npx arkaos migrate — This will backup v1, preserve your data, and install v2. See: https://github.com/andreagroferreira/arka-os#install\"}"
|
|
17
|
+
exit 0
|
|
18
|
+
fi
|
|
19
|
+
done
|
|
20
|
+
|
|
21
|
+
# ─── Sync Version Detection ────────────────────────────────────────────
|
|
22
|
+
SYNC_STATE="$HOME/.arkaos/sync-state.json"
|
|
23
|
+
ARKAOS_VERSION_FILE="$HOME/.arkaos/.repo-path"
|
|
24
|
+
|
|
25
|
+
if [ -f "$ARKAOS_VERSION_FILE" ]; then
|
|
26
|
+
_REPO_PATH=$(cat "$ARKAOS_VERSION_FILE")
|
|
27
|
+
if [ -f "$_REPO_PATH/VERSION" ]; then
|
|
28
|
+
_CURRENT_VERSION=$(cat "$_REPO_PATH/VERSION")
|
|
29
|
+
elif [ -f "$_REPO_PATH/package.json" ]; then
|
|
30
|
+
_CURRENT_VERSION=$(python3 -c "import json; print(json.load(open('$_REPO_PATH/package.json'))['version'])" 2>/dev/null || echo "")
|
|
31
|
+
fi
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
if [ -n "${_CURRENT_VERSION:-}" ]; then
|
|
34
|
+
if [ -f "$SYNC_STATE" ]; then
|
|
35
|
+
_SYNCED_VERSION=$(python3 -c "import json; print(json.load(open('$SYNC_STATE'))['version'])" 2>/dev/null || echo "none")
|
|
36
|
+
else
|
|
37
|
+
_SYNCED_VERSION="none"
|
|
38
|
+
fi
|
|
31
39
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
cache_get() {
|
|
35
|
-
local file="$CACHE_DIR/$1"
|
|
36
|
-
local ttl="$2"
|
|
37
|
-
if [ -f "$file" ]; then
|
|
38
|
-
local age=$(( $(date +%s) - $(stat -f%m "$file" 2>/dev/null || stat -c%Y "$file" 2>/dev/null || echo 0) ))
|
|
39
|
-
if [ "$age" -lt "$ttl" ]; then
|
|
40
|
-
cat "$file"
|
|
41
|
-
return 0
|
|
40
|
+
if [ "$_CURRENT_VERSION" != "$_SYNCED_VERSION" ]; then
|
|
41
|
+
_SYNC_NOTICE="[arka:update-available] ArkaOS v${_CURRENT_VERSION} installed (synced: ${_SYNCED_VERSION}). Run /arka update to sync all projects. "
|
|
42
42
|
fi
|
|
43
43
|
fi
|
|
44
|
-
|
|
45
|
-
}
|
|
44
|
+
fi
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
46
|
+
# ─── Session Greeting (now handled by SessionStart hook via systemMessage) ──
|
|
47
|
+
_ARKA_GREETING=""
|
|
50
48
|
|
|
51
|
-
# ───
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
[
|
|
56
|
-
|
|
57
|
-
L0="[Constitution] NON-NEGOTIABLE: branch-isolation, obsidian-output, authority-boundaries, security-gate, context-first, solid-clean-code, spec-driven, human-writing, squad-routing, full-visibility, sequential-validation, mandatory-qa, arka-supremacy | QUALITY-GATE: marta-cqo, eduardo-copy, francisca-tech-ux | MUST: conventional-commits, test-coverage, pattern-matching, actionable-output, memory-persistence"
|
|
58
|
-
cache_set "constitution" "$L0"
|
|
49
|
+
# ─── Performance Timing ──────────────────────────────────────────────────
|
|
50
|
+
_HOOK_START_NS=$(date +%s%N 2>/dev/null || echo "0")
|
|
51
|
+
_hook_ms() {
|
|
52
|
+
local end_ns=$(date +%s%N 2>/dev/null || echo "0")
|
|
53
|
+
if [ "$_HOOK_START_NS" != "0" ] && [ "$end_ns" != "0" ] && [ ${#end_ns} -gt 10 ]; then
|
|
54
|
+
echo $(( (end_ns - _HOOK_START_NS) / 1000000 ))
|
|
59
55
|
else
|
|
60
|
-
|
|
56
|
+
echo "0"
|
|
61
57
|
fi
|
|
62
58
|
}
|
|
63
|
-
[ -n "$L0" ] && CONTEXT_PARTS+=("$L0")
|
|
64
|
-
_L0_MS=$(_hook_ms)
|
|
65
|
-
|
|
66
|
-
# ─── L1: Department Routing (no cache — fast string match) ───────────────
|
|
67
|
-
PROMPT_LOWER=$(echo "$PROMPT" | tr '[:upper:]' '[:lower:]')
|
|
68
|
-
DETECTED_DEPT=""
|
|
69
59
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
elif
|
|
75
|
-
|
|
76
|
-
elif
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\b(task|email|calendar|automate|meeting|workflow|process|schedule|slack|discord|notify)\b'; then
|
|
81
|
-
DETECTED_DEPT="operations"
|
|
82
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\b(learn|persona|knowledge|youtube|transcribe|article|research)\b'; then
|
|
83
|
-
DETECTED_DEPT="knowledge"
|
|
84
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\b(brand|logo|colors|palette|mockup|photoshoot|brand.?identity|brand.?guide|mood.?board|naming|positioning|visual.?design|motion.?design|brand.?video|social.?kit)\b'; then
|
|
85
|
-
DETECTED_DEPT="brand"
|
|
86
|
-
fi
|
|
87
|
-
[ -n "$DETECTED_DEPT" ] && CONTEXT_PARTS+=("[dept:$DETECTED_DEPT]")
|
|
88
|
-
_L1_MS=$(( $(_hook_ms) - ${_L0_MS:-0} ))
|
|
89
|
-
|
|
90
|
-
# ─── L2: Agent Memory (30s cache) ────────────────────────────────────────
|
|
91
|
-
# Detect agent name from prompt
|
|
92
|
-
DETECTED_AGENT=""
|
|
93
|
-
if echo "$PROMPT_LOWER" | grep -qE '\bmarco\b|/.*cto\b'; then
|
|
94
|
-
DETECTED_AGENT="cto"
|
|
95
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bpaulo\b|tech.?lead'; then
|
|
96
|
-
DETECTED_AGENT="tech-lead"
|
|
97
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bgabriel\b|architect'; then
|
|
98
|
-
DETECTED_AGENT="architect"
|
|
99
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bandre\b|senior.?dev|backend'; then
|
|
100
|
-
DETECTED_AGENT="senior-dev"
|
|
101
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bdiana\b|frontend.?dev'; then
|
|
102
|
-
DETECTED_AGENT="frontend-dev"
|
|
103
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bbruno\b|security'; then
|
|
104
|
-
DETECTED_AGENT="security"
|
|
105
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bcarlos\b|devops'; then
|
|
106
|
-
DETECTED_AGENT="devops"
|
|
107
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\brita\b|\bqa\b'; then
|
|
108
|
-
DETECTED_AGENT="qa"
|
|
109
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\blucas\b|analyst'; then
|
|
110
|
-
DETECTED_AGENT="analyst"
|
|
111
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bhelena\b|cfo'; then
|
|
112
|
-
DETECTED_AGENT="cfo"
|
|
113
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bsofia\b|coo'; then
|
|
114
|
-
DETECTED_AGENT="coo"
|
|
115
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bluna\b|content.?creator'; then
|
|
116
|
-
DETECTED_AGENT="content-creator"
|
|
117
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bricardo\b|ecommerce.?manager'; then
|
|
118
|
-
DETECTED_AGENT="ecommerce-manager"
|
|
119
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\btomas\b|strategist'; then
|
|
120
|
-
DETECTED_AGENT="strategist"
|
|
121
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bclara\b|knowledge.?curator'; then
|
|
122
|
-
DETECTED_AGENT="knowledge-curator"
|
|
123
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bvalentina\b|creative.?director'; then
|
|
124
|
-
DETECTED_AGENT="creative-director"
|
|
125
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bmateus\b|brand.?strategist'; then
|
|
126
|
-
DETECTED_AGENT="brand-strategist"
|
|
127
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\bisabel\b|visual.?designer'; then
|
|
128
|
-
DETECTED_AGENT="visual-designer"
|
|
129
|
-
elif echo "$PROMPT_LOWER" | grep -qE '\brafael\b|motion.?designer'; then
|
|
130
|
-
DETECTED_AGENT="motion-designer"
|
|
60
|
+
# ─── Paths ───────────────────────────────────────────────────────────────
|
|
61
|
+
# Resolve ARKAOS_ROOT: env var → .repo-path → npm package → fallback
|
|
62
|
+
if [ -n "${ARKAOS_ROOT:-}" ]; then
|
|
63
|
+
: # already set
|
|
64
|
+
elif [ -f "$HOME/.arkaos/.repo-path" ]; then
|
|
65
|
+
ARKAOS_ROOT=$(cat "$HOME/.arkaos/.repo-path")
|
|
66
|
+
elif [ -d "$HOME/.arkaos" ]; then
|
|
67
|
+
ARKAOS_ROOT="$HOME/.arkaos"
|
|
68
|
+
else
|
|
69
|
+
ARKAOS_ROOT="/Users/andreagroferreira/.npm/_npx/67d92defd11b9985/node_modules/arkaos"
|
|
131
70
|
fi
|
|
71
|
+
export ARKAOS_ROOT
|
|
132
72
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
AGENT_CTX=$(cache_get "$AGENT_CACHE_KEY" 30) || {
|
|
136
|
-
AGENT_MEM="$HOME/.claude/agent-memory/arka-${DETECTED_AGENT}/MEMORY.md"
|
|
137
|
-
AGENT_CTX="[agent:$DETECTED_AGENT"
|
|
73
|
+
CACHE_DIR="/tmp/arkaos-context-cache"
|
|
74
|
+
CACHE_TTL=300 # Constitution cache: 5 minutes
|
|
138
75
|
|
|
139
|
-
|
|
140
|
-
REPO_PATH=$(cat "$ARKA_OS/.repo-path" 2>/dev/null || echo "")
|
|
141
|
-
REGISTRY_FILE="$REPO_PATH/knowledge/agents-registry.json"
|
|
142
|
-
if [ -f "$REGISTRY_FILE" ] && command -v jq &>/dev/null; then
|
|
143
|
-
DISC_COMBO=$(jq -r --arg id "$DETECTED_AGENT" '.agents[] | select(.id == $id) | .disc.combination // ""' "$REGISTRY_FILE" 2>/dev/null)
|
|
144
|
-
[ -n "$DISC_COMBO" ] && AGENT_CTX+=" disc:$DISC_COMBO"
|
|
145
|
-
fi
|
|
146
|
-
|
|
147
|
-
if [ -f "$AGENT_MEM" ]; then
|
|
148
|
-
# Extract last 3 gotchas from agent memory
|
|
149
|
-
GOTCHAS=$(sed -n '/^## Gotchas/,/^## /{ /^## Gotchas/d; /^## /d; /^$/d; p; }' "$AGENT_MEM" 2>/dev/null | head -3)
|
|
150
|
-
if [ -n "$GOTCHAS" ]; then
|
|
151
|
-
AGENT_CTX+=" gotchas: $(echo "$GOTCHAS" | tr '\n' '; ' | head -c 200)"
|
|
152
|
-
fi
|
|
153
|
-
fi
|
|
76
|
+
mkdir -p "$CACHE_DIR" 2>/dev/null
|
|
154
77
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
78
|
+
# ─── Extract user input from hook JSON ───────────────────────────────────
|
|
79
|
+
user_input=""
|
|
80
|
+
if command -v jq &>/dev/null; then
|
|
81
|
+
user_input=$(echo "$input" | jq -r '.userInput // .message // ""' 2>/dev/null)
|
|
82
|
+
fi
|
|
83
|
+
# Fallback: try to get the raw text
|
|
84
|
+
if [ -z "$user_input" ]; then
|
|
85
|
+
user_input=$(echo "$input" | head -c 2000)
|
|
159
86
|
fi
|
|
160
|
-
_L2_MS=$(( $(_hook_ms) - ${_L0_MS:-0} - ${_L1_MS:-0} ))
|
|
161
87
|
|
|
162
|
-
# ───
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
PROJECT_CTX=$(cache_get "$PROJECT_CACHE_KEY" 30) || {
|
|
166
|
-
PROJECT_CTX=""
|
|
167
|
-
# Check ARKA OS projects/ directory
|
|
168
|
-
REPO_PATH=$(cat "$ARKA_OS/.repo-path" 2>/dev/null || echo "")
|
|
169
|
-
if [ -n "$REPO_PATH" ] && [ -d "$REPO_PATH/projects" ]; then
|
|
170
|
-
for proj_md in "$REPO_PATH/projects"/*/PROJECT.md; do
|
|
171
|
-
[ -f "$proj_md" ] || continue
|
|
172
|
-
PROJ_DIR=$(dirname "$proj_md")
|
|
173
|
-
if [ -f "$PROJ_DIR/.project-path" ]; then
|
|
174
|
-
PROJ_PATH=$(cat "$PROJ_DIR/.project-path" 2>/dev/null)
|
|
175
|
-
if [ -n "$PROJ_PATH" ] && [[ "$CWD" == "$PROJ_PATH"* ]]; then
|
|
176
|
-
PROJ_NAME=$(basename "$PROJ_DIR")
|
|
177
|
-
# Try to extract stack from PROJECT.md
|
|
178
|
-
PROJ_STACK=$(grep -i 'stack\|framework' "$proj_md" 2>/dev/null | head -1 | sed 's/.*: *//' | head -c 50)
|
|
179
|
-
PROJECT_CTX="[project:$PROJ_NAME"
|
|
180
|
-
[ -n "$PROJ_STACK" ] && PROJECT_CTX+=" stack:$PROJ_STACK"
|
|
181
|
-
PROJECT_CTX+="]"
|
|
182
|
-
break
|
|
183
|
-
fi
|
|
184
|
-
fi
|
|
185
|
-
done
|
|
186
|
-
fi
|
|
88
|
+
# ─── Try Python Synapse bridge first ────────────────────────────────────
|
|
89
|
+
python_result=""
|
|
90
|
+
BRIDGE_SCRIPT="${ARKAOS_ROOT}/scripts/synapse-bridge.py"
|
|
187
91
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
[ -d "$proj_dir" ] || continue
|
|
192
|
-
if [ -f "$proj_dir/.project-path" ]; then
|
|
193
|
-
PROJ_PATH=$(cat "$proj_dir/.project-path" 2>/dev/null)
|
|
194
|
-
if [ -n "$PROJ_PATH" ] && [[ "$CWD" == "$PROJ_PATH"* ]]; then
|
|
195
|
-
PROJ_NAME=$(basename "$proj_dir" | sed 's/^arka-//')
|
|
196
|
-
PROJECT_CTX="[project:$PROJ_NAME]"
|
|
197
|
-
break
|
|
198
|
-
fi
|
|
199
|
-
fi
|
|
200
|
-
done
|
|
201
|
-
fi
|
|
92
|
+
if command -v python3 &>/dev/null && [ -f "$BRIDGE_SCRIPT" ]; then
|
|
93
|
+
bridge_output=$(echo "{\"user_input\":$(echo "$user_input" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo '""')}" \
|
|
94
|
+
| ARKAOS_ROOT="$ARKAOS_ROOT" python3 "$BRIDGE_SCRIPT" --root "$ARKAOS_ROOT" 2>/dev/null)
|
|
202
95
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
96
|
+
if [ -n "$bridge_output" ]; then
|
|
97
|
+
python_result=$(echo "$bridge_output" | python3 -c "import sys,json; print(json.loads(sys.stdin.read()).get('context_string',''))" 2>/dev/null)
|
|
98
|
+
fi
|
|
206
99
|
fi
|
|
207
|
-
_L3_MS=$(( $(_hook_ms) - ${_L0_MS:-0} - ${_L1_MS:-0} - ${_L2_MS:-0} ))
|
|
208
100
|
|
|
209
|
-
# ───
|
|
210
|
-
if [ -
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
101
|
+
# ─── Fallback: Bash-only context (if Python unavailable) ────────────────
|
|
102
|
+
if [ -z "$python_result" ]; then
|
|
103
|
+
# L0: Constitution (cached)
|
|
104
|
+
L0=""
|
|
105
|
+
L0_CACHE="$CACHE_DIR/l0-constitution"
|
|
106
|
+
if [ -f "$L0_CACHE" ] && [ $(($(date +%s) - $(stat -f%m "$L0_CACHE" 2>/dev/null || stat -c%Y "$L0_CACHE" 2>/dev/null || echo 0))) -lt $CACHE_TTL ]; then
|
|
107
|
+
L0=$(cat "$L0_CACHE")
|
|
108
|
+
else
|
|
109
|
+
L0="[Constitution] NON-NEGOTIABLE: branch-isolation, obsidian-output, authority-boundaries, security-gate, context-first, solid-clean-code, spec-driven, human-writing, squad-routing, full-visibility, sequential-validation, mandatory-qa, arka-supremacy | QUALITY-GATE: marta-cqo, eduardo-copy, francisca-tech-ux | MUST: conventional-commits, test-coverage, pattern-matching, actionable-output, memory-persistence"
|
|
110
|
+
echo "$L0" > "$L0_CACHE" 2>/dev/null
|
|
214
111
|
fi
|
|
215
|
-
fi
|
|
216
|
-
_L4_MS=$(( $(_hook_ms) - ${_L0_MS:-0} - ${_L1_MS:-0} - ${_L2_MS:-0} - ${_L3_MS:-0} ))
|
|
217
112
|
|
|
218
|
-
#
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if [ -f "$GOTCHAS_FILE" ] && command -v jq &>/dev/null; then
|
|
225
|
-
# Get top 2 recurring errors for this department with count >= 3 (include suggestions)
|
|
226
|
-
TOP_GOTCHAS=$(jq -r --arg cat "$DETECTED_DEPT" \
|
|
227
|
-
'[.[] | select(.category == $cat and .count >= 3)] | sort_by(-.count) | .[0:2] | .[] |
|
|
228
|
-
if .suggestion then "\(.pattern) (x\(.count)) \u2192 \(.suggestion)" else "\(.pattern) (x\(.count))" end' \
|
|
229
|
-
"$GOTCHAS_FILE" 2>/dev/null)
|
|
230
|
-
if [ -n "$TOP_GOTCHAS" ]; then
|
|
231
|
-
GOTCHA_CTX="[gotchas:$DETECTED_DEPT $(echo "$TOP_GOTCHAS" | tr '\n' '; ' | head -c 300)]"
|
|
232
|
-
fi
|
|
233
|
-
fi
|
|
234
|
-
cache_set "$GOTCHA_CACHE_KEY" "$GOTCHA_CTX"
|
|
235
|
-
}
|
|
236
|
-
[ -n "$GOTCHA_CTX" ] && CONTEXT_PARTS+=("$GOTCHA_CTX")
|
|
237
|
-
fi
|
|
113
|
+
# L4: Git branch
|
|
114
|
+
L4=""
|
|
115
|
+
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
116
|
+
if [ -n "$branch" ] && [ "$branch" != "main" ] && [ "$branch" != "master" ] && [ "$branch" != "dev" ]; then
|
|
117
|
+
L4="[branch:$branch]"
|
|
118
|
+
fi
|
|
238
119
|
|
|
239
|
-
#
|
|
240
|
-
|
|
241
|
-
if [
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
# Extract words from prompt and match against registry keywords
|
|
249
|
-
CMD_HINT=$(jq -r --arg prompt "$PROMPT_LOWER" '
|
|
250
|
-
($prompt | split(" ") | map(select(length > 2))) as $words |
|
|
251
|
-
[.commands[] |
|
|
252
|
-
{id, command, department,
|
|
253
|
-
score: ([.keywords[] | . as $kw |
|
|
254
|
-
if ($words | any(. == $kw)) then 2
|
|
255
|
-
elif ($words | join(" ") | test($kw)) then 3
|
|
256
|
-
else 0 end
|
|
257
|
-
] | add // 0)}
|
|
258
|
-
] | sort_by(-.score) | [.[:2][] | select(.score > 0)] |
|
|
259
|
-
if length > 0 then
|
|
260
|
-
map("[hint:\(.command)]") | join(" ")
|
|
261
|
-
else "" end
|
|
262
|
-
' "$REGISTRY" 2>/dev/null)
|
|
263
|
-
fi
|
|
264
|
-
cache_set "$CMD_CACHE_KEY" "$CMD_HINT"
|
|
265
|
-
}
|
|
266
|
-
[ -n "$CMD_HINT" ] && CONTEXT_PARTS+=("$CMD_HINT")
|
|
267
|
-
fi
|
|
268
|
-
_L5_MS=$(( $(_hook_ms) - ${_L0_MS:-0} - ${_L1_MS:-0} - ${_L2_MS:-0} - ${_L3_MS:-0} - ${_L4_MS:-0} ))
|
|
120
|
+
# L7: Time
|
|
121
|
+
hour=$(date +%H)
|
|
122
|
+
if [ "$hour" -ge 5 ] && [ "$hour" -lt 12 ]; then
|
|
123
|
+
L7="[time:morning]"
|
|
124
|
+
elif [ "$hour" -ge 12 ] && [ "$hour" -lt 18 ]; then
|
|
125
|
+
L7="[time:afternoon]"
|
|
126
|
+
else
|
|
127
|
+
L7="[time:evening]"
|
|
128
|
+
fi
|
|
269
129
|
|
|
270
|
-
|
|
271
|
-
HOUR=$(date +%H)
|
|
272
|
-
if [ "$HOUR" -lt 12 ]; then
|
|
273
|
-
CONTEXT_PARTS+=("[time:morning]")
|
|
274
|
-
elif [ "$HOUR" -lt 18 ]; then
|
|
275
|
-
CONTEXT_PARTS+=("[time:afternoon]")
|
|
276
|
-
else
|
|
277
|
-
CONTEXT_PARTS+=("[time:evening]")
|
|
130
|
+
python_result="$L0 $L4 $L7"
|
|
278
131
|
fi
|
|
279
132
|
|
|
280
|
-
# ───
|
|
281
|
-
|
|
282
|
-
METRICS_FILE="$HOME/.arka-os/hook-metrics.json"
|
|
283
|
-
METRICS_LOCK="$HOME/.arka-os/hook-metrics.lock"
|
|
284
|
-
mkdir -p "$HOME/.arka-os"
|
|
285
|
-
(
|
|
286
|
-
if command -v flock &>/dev/null; then flock -w 2 200; else true; fi
|
|
287
|
-
[ ! -f "$METRICS_FILE" ] && echo '[]' > "$METRICS_FILE"
|
|
288
|
-
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
289
|
-
jq --argjson dur "$_DURATION_MS" --arg ts "$NOW" --arg hook "user-prompt-submit" \
|
|
290
|
-
--argjson l0 "${_L0_MS:-0}" --argjson l1 "${_L1_MS:-0}" --argjson l2 "${_L2_MS:-0}" \
|
|
291
|
-
--argjson l3 "${_L3_MS:-0}" --argjson l4 "${_L4_MS:-0}" --argjson l5 "${_L5_MS:-0}" \
|
|
292
|
-
'. += [{"hook": $hook, "duration_ms": $dur, "timestamp": $ts, "layers": {"L0": $l0, "L1": $l1, "L2": $l2, "L3": $l3, "L4": $l4, "L5": $l5}}] | .[-500:]' \
|
|
293
|
-
"$METRICS_FILE" > "$METRICS_FILE.tmp" 2>/dev/null && mv "$METRICS_FILE.tmp" "$METRICS_FILE"
|
|
294
|
-
) 200>"$METRICS_LOCK" 2>/dev/null
|
|
133
|
+
# ─── Output ──────────────────────────────────────────────────────────────
|
|
134
|
+
echo "{\"additionalContext\": \"${_ARKA_GREETING:-}${_SYNC_NOTICE:-}$python_result\"}"
|
|
295
135
|
|
|
296
|
-
# ───
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
CONTEXT+="$part "
|
|
301
|
-
done
|
|
302
|
-
CONTEXT="${CONTEXT% }"
|
|
303
|
-
|
|
304
|
-
jq -n --arg ctx "$CONTEXT" '{
|
|
305
|
-
"hookSpecificOutput": {
|
|
306
|
-
"hookEventName": "UserPromptSubmit",
|
|
307
|
-
"additionalContext": $ctx
|
|
308
|
-
}
|
|
309
|
-
}'
|
|
310
|
-
else
|
|
311
|
-
echo '{}'
|
|
136
|
+
# ─── Metrics ─────────────────────────────────────────────────────────────
|
|
137
|
+
elapsed=$(_hook_ms)
|
|
138
|
+
if [ "$elapsed" -gt 0 ] 2>/dev/null; then
|
|
139
|
+
echo "{\"hook\":\"user-prompt-submit-v2\",\"ms\":$elapsed}" >> "$CACHE_DIR/hook-metrics.jsonl" 2>/dev/null
|
|
312
140
|
fi
|
|
@@ -5,6 +5,17 @@
|
|
|
5
5
|
"padding": 2
|
|
6
6
|
},
|
|
7
7
|
"hooks": {
|
|
8
|
+
"SessionStart": [
|
|
9
|
+
{
|
|
10
|
+
"hooks": [
|
|
11
|
+
{
|
|
12
|
+
"type": "command",
|
|
13
|
+
"command": "{{HOOKS_DIR}}/session-start.sh",
|
|
14
|
+
"timeout": 5
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
],
|
|
8
19
|
"UserPromptSubmit": [
|
|
9
20
|
{
|
|
10
21
|
"hooks": [
|
|
@@ -37,6 +48,17 @@
|
|
|
37
48
|
}
|
|
38
49
|
]
|
|
39
50
|
}
|
|
51
|
+
],
|
|
52
|
+
"CwdChanged": [
|
|
53
|
+
{
|
|
54
|
+
"hooks": [
|
|
55
|
+
{
|
|
56
|
+
"type": "command",
|
|
57
|
+
"command": "{{HOOKS_DIR}}/cwd-changed.sh",
|
|
58
|
+
"timeout": 5
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
40
62
|
]
|
|
41
63
|
}
|
|
42
64
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# ArkaOS -- Standard Ecosystem Workflow
|
|
2
|
+
|
|
3
|
+
> All ecosystem skills MUST follow this workflow. No exceptions.
|
|
4
|
+
> This is referenced by all ecosystem SKILL.md files.
|
|
5
|
+
|
|
6
|
+
## Phase 1: Context Loading
|
|
7
|
+
|
|
8
|
+
- Read ecosystem registry (`~/.claude/skills/arka/knowledge/ecosystems.json`)
|
|
9
|
+
- Read project descriptor(s) for affected project(s)
|
|
10
|
+
- Read project CLAUDE.md if it exists
|
|
11
|
+
- Check git status and current branch
|
|
12
|
+
- Load relevant memory from claude-mem
|
|
13
|
+
|
|
14
|
+
## Phase 2: Context Verification (NON-NEGOTIABLE)
|
|
15
|
+
|
|
16
|
+
- Restate the request to confirm understanding
|
|
17
|
+
- Ask at least 1 clarifying question about scope or intent
|
|
18
|
+
- Challenge at least 1 assumption (devil's advocate)
|
|
19
|
+
- Search memory/knowledge base for prior related work
|
|
20
|
+
- Only proceed after user confirms understanding
|
|
21
|
+
|
|
22
|
+
## Phase 3: Analysis & Planning
|
|
23
|
+
|
|
24
|
+
- Identify affected projects within the ecosystem
|
|
25
|
+
- Determine which squad roles are needed
|
|
26
|
+
- Assess complexity (simple/medium/complex)
|
|
27
|
+
- Create execution plan with specific steps
|
|
28
|
+
|
|
29
|
+
## Phase 4: Plan Presentation & Approval
|
|
30
|
+
|
|
31
|
+
- Present the plan to the user with:
|
|
32
|
+
- Affected files/projects
|
|
33
|
+
- Squad roles assigned
|
|
34
|
+
- Estimated scope (small/medium/large)
|
|
35
|
+
- Risks or concerns
|
|
36
|
+
- Wait for explicit user approval
|
|
37
|
+
- Options: Approve / Modify / Cancel
|
|
38
|
+
|
|
39
|
+
## Phase 5: Execution
|
|
40
|
+
|
|
41
|
+
- Create feature branch (NON-NEGOTIABLE for code changes)
|
|
42
|
+
- Use worktree isolation for multi-file changes
|
|
43
|
+
- Squad agents execute in their domain
|
|
44
|
+
- Follow TDD where applicable
|
|
45
|
+
- Commit frequently with conventional commit messages
|
|
46
|
+
|
|
47
|
+
## Phase 6: Quality Gate (NON-NEGOTIABLE)
|
|
48
|
+
|
|
49
|
+
- **Marta** (CQO) orchestrates the review
|
|
50
|
+
- **Eduardo** (Copy Director) reviews all text output
|
|
51
|
+
- **Francisca** (Tech/UX Director) reviews all code and technical output
|
|
52
|
+
- Verdict: APPROVED or REJECTED
|
|
53
|
+
- REJECTED -> return to Phase 5 with specific feedback
|
|
54
|
+
- APPROVED -> proceed to Phase 7
|
|
55
|
+
|
|
56
|
+
## Phase 7: Documentation & Report
|
|
57
|
+
|
|
58
|
+
- Update Obsidian vault with deliverables
|
|
59
|
+
- Present final report to user
|
|
60
|
+
- Include: what was done, files changed, tests run, next steps
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# ArkaOS — User Instructions
|
|
2
|
+
|
|
3
|
+
## Version Drift Warning
|
|
4
|
+
|
|
5
|
+
When your context contains `[arka:update-available]`, show this warning before your response:
|
|
6
|
+
|
|
7
|
+
> ArkaOS update available. Run `/arka update` to sync all projects.
|
|
8
|
+
|
|
9
|
+
## Squad Routing
|
|
10
|
+
|
|
11
|
+
You are operating within ArkaOS. Every request routes through the appropriate department squad. Never respond as a generic assistant.
|
|
12
|
+
|
|
13
|
+
## Language
|
|
14
|
+
|
|
15
|
+
Match the user's language. When writing in Portuguese, use European Portuguese (pt-PT).
|
|
@@ -28,6 +28,19 @@ export default {
|
|
|
28
28
|
settings.hooks = {};
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// SessionStart — Branded greeting + version drift detection
|
|
32
|
+
settings.hooks.SessionStart = [
|
|
33
|
+
{
|
|
34
|
+
hooks: [
|
|
35
|
+
{
|
|
36
|
+
type: "command",
|
|
37
|
+
command: join(hooksDir, "session-start.sh"),
|
|
38
|
+
timeout: 5,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
|
|
31
44
|
// UserPromptSubmit — Synapse v2 context injection
|
|
32
45
|
settings.hooks.UserPromptSubmit = [
|
|
33
46
|
{
|
|
@@ -67,6 +80,19 @@ export default {
|
|
|
67
80
|
},
|
|
68
81
|
];
|
|
69
82
|
|
|
83
|
+
// CwdChanged — Project/ecosystem auto-detection
|
|
84
|
+
settings.hooks.CwdChanged = [
|
|
85
|
+
{
|
|
86
|
+
hooks: [
|
|
87
|
+
{
|
|
88
|
+
type: "command",
|
|
89
|
+
command: join(hooksDir, "cwd-changed.sh"),
|
|
90
|
+
timeout: 5,
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
|
|
70
96
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
71
97
|
console.log(" Claude Code hooks configured.");
|
|
72
98
|
},
|