arkaos 4.0.2 → 4.1.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/README.md +2 -2
- package/VERSION +1 -1
- package/arka/SKILL.md +16 -22
- package/arka/skills/flow/SKILL.md +108 -234
- package/config/claude-agents/eduardo-copy.md +53 -0
- package/config/claude-agents/francisca-tech.md +52 -0
- package/config/claude-agents/marta-cqo.md +52 -0
- package/config/claude-agents/paulo-tech-lead.md +50 -0
- package/config/cognition/schedules.yaml +15 -0
- package/config/constitution.yaml +17 -21
- package/config/hooks/_lib/workflow-classifier.sh +1 -1
- package/config/hooks/post-tool-use.sh +40 -539
- package/config/hooks/pre-tool-use.sh +32 -281
- package/config/hooks/session-start.sh +8 -10
- package/config/hooks/stop.sh +30 -425
- package/config/hooks/user-prompt-submit.sh +42 -459
- package/core/cognition/__pycache__/dreaming.cpython-313.pyc +0 -0
- package/core/cognition/dreaming.py +5 -0
- package/core/cognition/scheduler/__pycache__/daemon.cpython-313.pyc +0 -0
- package/core/cognition/scheduler/daemon.py +10 -0
- package/core/forge/__init__.py +2 -0
- package/core/forge/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/forge/__pycache__/orchestrator.cpython-313.pyc +0 -0
- package/core/forge/__pycache__/persistence.cpython-313.pyc +0 -0
- package/core/forge/__pycache__/renderer.cpython-313.pyc +0 -0
- package/core/forge/__pycache__/runtime_dispatcher.cpython-313.pyc +0 -0
- package/core/forge/__pycache__/schema.cpython-313.pyc +0 -0
- package/core/forge/orchestrator.py +50 -27
- package/core/forge/persistence.py +16 -0
- package/core/forge/renderer.py +16 -0
- package/core/forge/runtime_dispatcher.py +34 -19
- package/core/forge/schema.py +12 -0
- package/core/governance/__pycache__/__init__.cpython-312.pyc +0 -0
- package/core/governance/__pycache__/closing_marker_check.cpython-313.pyc +0 -0
- package/core/governance/__pycache__/compliance_telemetry.cpython-313.pyc +0 -0
- package/core/governance/__pycache__/constitution.cpython-312.pyc +0 -0
- package/core/governance/__pycache__/evidence_checks.cpython-313.pyc +0 -0
- package/core/governance/__pycache__/meta_tag_check.cpython-313.pyc +0 -0
- package/core/governance/__pycache__/qg_verdict.cpython-313.pyc +0 -0
- package/core/governance/__pycache__/review_workflow.cpython-313.pyc +0 -0
- package/core/governance/__pycache__/skill_proposer.cpython-313.pyc +0 -0
- package/core/governance/closing_marker_check.py +9 -5
- package/core/governance/compliance_telemetry.py +1 -1
- package/core/governance/compliance_telemetry_cli.py +1 -1
- package/core/governance/evidence_checks.py +421 -0
- package/core/governance/meta_tag_check.py +36 -0
- package/core/governance/qg_verdict.py +78 -0
- package/core/governance/review_workflow.py +34 -1
- package/core/governance/skill_proposer.py +2 -1
- package/core/hooks/__init__.py +12 -0
- package/core/hooks/__pycache__/__init__.cpython-312.pyc +0 -0
- package/core/hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/hooks/__pycache__/_shared.cpython-312.pyc +0 -0
- package/core/hooks/__pycache__/_shared.cpython-313.pyc +0 -0
- package/core/hooks/__pycache__/post_tool_use.cpython-312.pyc +0 -0
- package/core/hooks/__pycache__/post_tool_use.cpython-313.pyc +0 -0
- package/core/hooks/__pycache__/pre_tool_use.cpython-312.pyc +0 -0
- package/core/hooks/__pycache__/pre_tool_use.cpython-313.pyc +0 -0
- package/core/hooks/__pycache__/stop.cpython-312.pyc +0 -0
- package/core/hooks/__pycache__/stop.cpython-313.pyc +0 -0
- package/core/hooks/__pycache__/user_prompt_submit.cpython-312.pyc +0 -0
- package/core/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
- package/core/hooks/_shared.py +110 -0
- package/core/hooks/post_tool_use.py +689 -0
- package/core/hooks/pre_tool_use.py +267 -0
- package/core/hooks/stop.py +395 -0
- package/core/hooks/user_prompt_submit.py +600 -0
- package/core/jobs/__pycache__/__init__.cpython-312.pyc +0 -0
- package/core/jobs/__pycache__/auto_doc_worker.cpython-312.pyc +0 -0
- package/core/jobs/__pycache__/manager.cpython-312.pyc +0 -0
- package/core/knowledge/__pycache__/embedder.cpython-312.pyc +0 -0
- package/core/knowledge/__pycache__/embedder.cpython-313.pyc +0 -0
- package/core/knowledge/__pycache__/vector_store.cpython-312.pyc +0 -0
- package/core/knowledge/__pycache__/vector_store.cpython-313.pyc +0 -0
- package/core/knowledge/embedder.py +118 -11
- package/core/knowledge/vector_store.py +111 -14
- package/core/runtime/__pycache__/__init__.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/base.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/base.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/capabilities_cli.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/capabilities_cli.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/claude_code.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/claude_code.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/codex_cli.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/codex_cli.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/cost_governor.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/cost_governor.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/cursor.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/cursor.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/gemini_cli.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/gemini_cli.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/llm_provider.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/llm_provider.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/llm_retry.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/llm_retry.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/native_usage.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/native_usage.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/path_resolver.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/pricing.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/pricing.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/registry.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/registry.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/squad_orchestrator.cpython-312.pyc +0 -0
- package/core/runtime/base.py +29 -0
- package/core/runtime/capabilities_cli.py +74 -0
- package/core/runtime/claude_code.py +8 -0
- package/core/runtime/codex_cli.py +205 -37
- package/core/runtime/cost_governor.py +184 -0
- package/core/runtime/cursor.py +8 -0
- package/core/runtime/gemini_cli.py +8 -0
- package/core/runtime/llm_provider.py +32 -13
- package/core/runtime/llm_retry.py +233 -0
- package/core/runtime/native_usage.py +186 -0
- package/core/runtime/pricing.py +9 -0
- package/core/runtime/registry.py +3 -0
- package/core/shared/__pycache__/test_evidence.cpython-313-pytest-9.1.1.pyc +0 -0
- package/core/shared/__pycache__/test_evidence.cpython-313.pyc +0 -0
- package/core/shared/test_evidence.py +34 -0
- package/core/synapse/__pycache__/agent_experiences_layer.cpython-312.pyc +0 -0
- package/core/synapse/__pycache__/engine.cpython-312.pyc +0 -0
- package/core/synapse/__pycache__/engine.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/graph_context_layer.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/kb_cache.cpython-312.pyc +0 -0
- package/core/synapse/__pycache__/kb_cache.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/layers.cpython-312.pyc +0 -0
- package/core/synapse/__pycache__/layers.cpython-313.pyc +0 -0
- package/core/synapse/engine.py +7 -0
- package/core/synapse/graph_context_layer.py +212 -0
- package/core/synapse/kb_cache.py +3 -0
- package/core/synapse/layers.py +104 -20
- package/core/workflow/__pycache__/enforcer.cpython-313.pyc +0 -0
- package/core/workflow/__pycache__/flow_enforcer.cpython-312.pyc +0 -0
- package/core/workflow/__pycache__/flow_enforcer.cpython-313.pyc +0 -0
- package/core/workflow/__pycache__/gate_checkpoint.cpython-312.pyc +0 -0
- package/core/workflow/__pycache__/gate_checkpoint.cpython-313.pyc +0 -0
- package/core/workflow/__pycache__/research_gate.cpython-313.pyc +0 -0
- package/core/workflow/__pycache__/rules_registry.cpython-313.pyc +0 -0
- package/core/workflow/__pycache__/specialist_enforcer.cpython-312.pyc +0 -0
- package/core/workflow/__pycache__/specialist_enforcer.cpython-313.pyc +0 -0
- package/core/workflow/enforcer.py +5 -16
- package/core/workflow/flow_enforcer.py +36 -11
- package/core/workflow/gate_checkpoint.py +149 -0
- package/core/workflow/research_gate.py +15 -3
- package/core/workflow/rules_registry.py +137 -389
- package/core/workflow/specialist_enforcer.py +21 -4
- package/dashboard/app/pages/knowledge/index.vue +4 -1
- package/departments/ops/skills/n8n-flow/SKILL.md +13 -0
- package/departments/ops/skills/workflow-automate/SKILL.md +16 -0
- package/departments/quality/SKILL.md +45 -5
- package/departments/quality/agents/copy-director.yaml +3 -1
- package/departments/quality/agents/tech-director.yaml +3 -1
- package/installer/adapters/claude-code.js +46 -2
- package/installer/config-seed.js +39 -14
- package/installer/doctor.js +8 -0
- package/installer/graphify.js +153 -0
- package/installer/index.js +20 -0
- package/installer/init.js +11 -0
- package/installer/update.js +19 -0
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/scripts/__pycache__/dashboard-api.cpython-313.pyc +0 -0
- package/scripts/__pycache__/knowledge-index.cpython-313.pyc +0 -0
- package/scripts/__pycache__/synapse-bridge.cpython-312.pyc +0 -0
- package/scripts/__pycache__/synapse-bridge.cpython-313.pyc +0 -0
- package/scripts/knowledge-index.py +8 -2
- package/scripts/synapse-bridge.py +102 -26
|
@@ -1,475 +1,58 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# ============================================================================
|
|
3
|
-
# ArkaOS v2 — UserPromptSubmit Hook (
|
|
4
|
-
#
|
|
3
|
+
# ArkaOS v2 — UserPromptSubmit Hook (thin wrapper, PR-6 v4.1.0 hook hygiene)
|
|
4
|
+
#
|
|
5
|
+
# Delegates the ENTIRE event to ONE python process:
|
|
6
|
+
# python3 -m core.hooks.user_prompt_submit
|
|
7
|
+
#
|
|
8
|
+
# The entrypoint preserves the behavior contract of the previous
|
|
9
|
+
# ~31-spawn-site version:
|
|
10
|
+
# - V1 migration + sync-version detection ([arka:update-available]).
|
|
11
|
+
# - Per-turn cache reset: marker_cache.invalidate_marker +
|
|
12
|
+
# kb_cache.invalidate_obsidian_query.
|
|
13
|
+
# - Synapse bridge (scripts/synapse-bridge.py::run_bridge) called
|
|
14
|
+
# in-process — 12-layer context injection, no second interpreter.
|
|
15
|
+
# - Workflow-state / forge tags, KB auto-inject, bash-parity fallback
|
|
16
|
+
# context (constitution L0, branch, workflow, forge).
|
|
17
|
+
# - Token hygiene (context %, topic drift, large paste, vague ref).
|
|
18
|
+
# - Persistent [ARKA:ROUTE] reminder + workflow classifier that marks
|
|
19
|
+
# the session flow-required ([ARKA:WORKFLOW-REQUIRED]).
|
|
20
|
+
# - One-shot nudges (KB-cite, meta-tag, closing-marker) gated by
|
|
21
|
+
# effort level; cognitive context injection.
|
|
22
|
+
#
|
|
5
23
|
# Timeout: 10s | Output: JSON to stdout | Target: <100ms
|
|
6
24
|
# ============================================================================
|
|
7
25
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
32
|
-
|
|
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
|
|
39
|
-
|
|
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
|
-
fi
|
|
43
|
-
if [ -n "${ARKAOS_DEBUG:-}" ]; then
|
|
44
|
-
echo "[DEBUG] Detected version: ${_CURRENT_VERSION:-unknown}, synced: ${_SYNCED_VERSION:-none}" >&2
|
|
45
|
-
fi
|
|
46
|
-
fi
|
|
47
|
-
fi
|
|
48
|
-
|
|
49
|
-
# ─── Session Greeting (now handled by SessionStart hook via systemMessage) ──
|
|
50
|
-
_ARKA_GREETING=""
|
|
51
|
-
|
|
52
|
-
# ─── Performance Timing ──────────────────────────────────────────────────
|
|
53
|
-
_HOOK_START_NS=$(date +%s%N 2>/dev/null || echo "0")
|
|
54
|
-
_hook_ms() {
|
|
55
|
-
local end_ns=$(date +%s%N 2>/dev/null || echo "0")
|
|
56
|
-
if [ "$_HOOK_START_NS" != "0" ] && [ "$end_ns" != "0" ] && [ ${#end_ns} -gt 10 ]; then
|
|
57
|
-
echo $(( (end_ns - _HOOK_START_NS) / 1000000 ))
|
|
26
|
+
if [ -z "${ARKAOS_ROOT:-}" ]; then
|
|
27
|
+
if [ -f "$HOME/.arkaos/.repo-path" ]; then
|
|
28
|
+
ARKAOS_ROOT=$(cat "$HOME/.arkaos/.repo-path")
|
|
29
|
+
elif [ -d "$HOME/.arkaos" ]; then
|
|
30
|
+
ARKAOS_ROOT="$HOME/.arkaos"
|
|
58
31
|
else
|
|
59
|
-
|
|
32
|
+
ARKAOS_ROOT="${ARKA_OS:-$HOME/.claude/skills/arkaos}"
|
|
60
33
|
fi
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
# ─── Paths ───────────────────────────────────────────────────────────────
|
|
64
|
-
# Resolve ARKAOS_ROOT: env var → .repo-path → $HOME/.arkaos → portable fallback
|
|
65
|
-
if [ -n "${ARKAOS_ROOT:-}" ]; then
|
|
66
|
-
: # already set
|
|
67
|
-
elif [ -f "$HOME/.arkaos/.repo-path" ]; then
|
|
68
|
-
ARKAOS_ROOT=$(cat "$HOME/.arkaos/.repo-path")
|
|
69
|
-
elif [ -d "$HOME/.arkaos" ]; then
|
|
70
|
-
ARKAOS_ROOT="$HOME/.arkaos"
|
|
71
|
-
else
|
|
72
|
-
# Portable fallback — matches user-prompt-submit-v2.sh. Power users can
|
|
73
|
-
# override with the ARKA_OS env var. Reached only on corrupt/uninitialised
|
|
74
|
-
# installs; synapse-bridge.py will fail gracefully if the path is wrong.
|
|
75
|
-
ARKAOS_ROOT="${ARKA_OS:-$HOME/.claude/skills/arkaos}"
|
|
76
34
|
fi
|
|
77
35
|
export ARKAOS_ROOT
|
|
78
36
|
|
|
79
|
-
|
|
80
|
-
CACHE_TTL=300 # Constitution cache: 5 minutes
|
|
81
|
-
|
|
82
|
-
mkdir -p "$CACHE_DIR" 2>/dev/null
|
|
83
|
-
|
|
84
|
-
# ─── Extract user input from hook JSON ───────────────────────────────────
|
|
85
|
-
user_input=""
|
|
86
|
-
SESSION_ID=""
|
|
87
|
-
EFFORT_LEVEL=""
|
|
88
|
-
if command -v jq &>/dev/null; then
|
|
89
|
-
user_input=$(echo "$input" | jq -r '.userInput // .message // ""' 2>/dev/null)
|
|
90
|
-
SESSION_ID=$(echo "$input" | jq -r '.session_id // ""' 2>/dev/null)
|
|
91
|
-
# PR46 v2.65.0 — Claude Code W19 ships effort.level in hook stdin.
|
|
92
|
-
# Soft-block nudges (KB-first + meta-tag) are gated by effort: only
|
|
93
|
-
# surfaced at high|xhigh; low/medium skip the nudge to avoid forcing
|
|
94
|
-
# the model to comply with full contracts during cheap exploratory
|
|
95
|
-
# turns. Hard enforcement (PreToolUse flow_enforcer) runs regardless.
|
|
96
|
-
EFFORT_LEVEL=$(echo "$input" | jq -r '.effort.level // ""' 2>/dev/null)
|
|
97
|
-
fi
|
|
98
|
-
[ -z "$EFFORT_LEVEL" ] && EFFORT_LEVEL="${CLAUDE_EFFORT:-}"
|
|
99
|
-
|
|
100
|
-
# Decide whether soft-block nudges surface to the next turn.
|
|
101
|
-
_ARKA_SURFACE_NUDGES="true"
|
|
102
|
-
case "${EFFORT_LEVEL:-high}" in
|
|
103
|
-
low|medium) _ARKA_SURFACE_NUDGES="false" ;;
|
|
104
|
-
*) _ARKA_SURFACE_NUDGES="true" ;;
|
|
105
|
-
esac
|
|
106
|
-
|
|
107
|
-
# ─── Flow marker cache invalidation (v2 — new turn, reset ALLOW cache) ──
|
|
108
|
-
# Cheap, non-blocking, runs before Synapse so a stuck Python later cannot
|
|
109
|
-
# leave a stale marker alive across turns.
|
|
110
|
-
if [ -n "$SESSION_ID" ] && command -v python3 &>/dev/null; then
|
|
111
|
-
_INVALIDATE_ROOT="${ARKAOS_ROOT:-}"
|
|
112
|
-
if [ -z "$_INVALIDATE_ROOT" ] && [ -f "$HOME/.arkaos/.repo-path" ]; then
|
|
113
|
-
_INVALIDATE_ROOT=$(cat "$HOME/.arkaos/.repo-path" 2>/dev/null)
|
|
114
|
-
fi
|
|
115
|
-
[ -z "$_INVALIDATE_ROOT" ] && _INVALIDATE_ROOT="$HOME/.arkaos"
|
|
116
|
-
SESSION_ID="$SESSION_ID" PYTHONPATH="$_INVALIDATE_ROOT" python3 -c "
|
|
117
|
-
import os
|
|
118
|
-
try:
|
|
119
|
-
from core.workflow.marker_cache import invalidate_marker
|
|
120
|
-
invalidate_marker(os.environ.get('SESSION_ID', ''))
|
|
121
|
-
except Exception:
|
|
122
|
-
pass
|
|
123
|
-
try:
|
|
124
|
-
from core.synapse.kb_cache import invalidate_obsidian_query
|
|
125
|
-
invalidate_obsidian_query(os.environ.get('SESSION_ID', ''))
|
|
126
|
-
except Exception:
|
|
127
|
-
pass
|
|
128
|
-
" 2>/dev/null || true
|
|
129
|
-
fi
|
|
130
|
-
# Fallback: try to get the raw text
|
|
131
|
-
if [ -z "$user_input" ]; then
|
|
132
|
-
user_input=$(echo "$input" | head -c 2000)
|
|
133
|
-
fi
|
|
134
|
-
|
|
135
|
-
# ─── Load shared workflow classifier ─────────────────────────────────────
|
|
136
|
-
_CLASSIFIER_LIB="$(dirname "$0")/_lib/workflow-classifier.sh"
|
|
137
|
-
if [ -f "$_CLASSIFIER_LIB" ]; then
|
|
138
|
-
# shellcheck disable=SC1090
|
|
139
|
-
. "$_CLASSIFIER_LIB"
|
|
140
|
-
fi
|
|
141
|
-
|
|
142
|
-
# ─── Try Python Synapse bridge first ────────────────────────────────────
|
|
143
|
-
python_result=""
|
|
144
|
-
BRIDGE_SCRIPT="${ARKAOS_ROOT}/scripts/synapse-bridge.py"
|
|
145
|
-
|
|
146
|
-
# Determine which path we're using for debug output
|
|
147
|
-
if [ -n "${ARKAOS_DEBUG:-}" ]; then
|
|
148
|
-
echo "[DEBUG] ARKAOS_ROOT=${ARKAOS_ROOT}" >&2
|
|
149
|
-
echo "[DEBUG] BRIDGE_SCRIPT=${BRIDGE_SCRIPT}" >&2
|
|
150
|
-
fi
|
|
151
|
-
|
|
152
|
-
if command -v python3 &>/dev/null && [ -f "$BRIDGE_SCRIPT" ]; then
|
|
153
|
-
# Validate ARKAOS_ROOT before calling bridge
|
|
154
|
-
if [ ! -d "$ARKAOS_ROOT" ]; then
|
|
155
|
-
if [ -n "${ARKAOS_DEBUG:-}" ]; then
|
|
156
|
-
echo "[DEBUG] ARKAOS_ROOT is not a valid directory, skipping Python bridge" >&2
|
|
157
|
-
fi
|
|
158
|
-
else
|
|
159
|
-
_bridge_start=$(date +%s%N 2>/dev/null || echo "0")
|
|
160
|
-
bridge_output=$(echo "{\"user_input\":$(echo "$user_input" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo '""')}" \
|
|
161
|
-
| ARKAOS_ROOT="$ARKAOS_ROOT" python3 "$BRIDGE_SCRIPT" --root "$ARKAOS_ROOT" 2>/dev/null)
|
|
162
|
-
_bridge_status=$?
|
|
163
|
-
|
|
164
|
-
if [ -n "${ARKAOS_DEBUG:-}" ]; then
|
|
165
|
-
if [ "$_bridge_start" != "0" ] && [ $(date +%s%N 2>/dev/null || echo "0") != "0" ]; then
|
|
166
|
-
_bridge_ms=$(( ($(date +%s%N) - _bridge_start) / 1000000 ))
|
|
167
|
-
echo "[DEBUG] bridge completed in ${_bridge_ms}ms, exit=$_bridge_status" >&2
|
|
168
|
-
fi
|
|
169
|
-
echo "[DEBUG] bridge_output length=${#bridge_output}" >&2
|
|
170
|
-
fi
|
|
171
|
-
|
|
172
|
-
if [ -n "$bridge_output" ] && [ $_bridge_status -eq 0 ]; then
|
|
173
|
-
python_result=$(echo "$bridge_output" | python3 -c "import sys,json; print(json.loads(sys.stdin.read()).get('context_string',''))" 2>/dev/null)
|
|
174
|
-
if [ -n "${ARKAOS_DEBUG:-}" ]; then
|
|
175
|
-
echo "[DEBUG] python_result length=${#python_result}" >&2
|
|
176
|
-
fi
|
|
177
|
-
elif [ -n "${ARKAOS_DEBUG:-}" ]; then
|
|
178
|
-
echo "[DEBUG] bridge failed or returned empty, exit=$_bridge_status" >&2
|
|
179
|
-
fi
|
|
180
|
-
fi
|
|
181
|
-
|
|
182
|
-
# Append workflow state to synapse context (always, if python result was set)
|
|
183
|
-
if [ -n "$python_result" ]; then
|
|
184
|
-
_WF_READER="$ARKAOS_ROOT/core/workflow/state_reader.sh"
|
|
185
|
-
if [ -f "$_WF_READER" ] && bash "$_WF_READER" active 2>/dev/null; then
|
|
186
|
-
_WF_SUM=$(bash "$_WF_READER" summary 2>/dev/null)
|
|
187
|
-
_WF_N=$(echo "$_WF_SUM" | cut -d'|' -f1)
|
|
188
|
-
_WF_P=$(echo "$_WF_SUM" | cut -d'|' -f2)
|
|
189
|
-
_WF_B=$(echo "$_WF_SUM" | cut -d'|' -f4)
|
|
190
|
-
_WF_V=$(echo "$_WF_SUM" | cut -d'|' -f5)
|
|
191
|
-
_WF_TAG="[workflow:${_WF_N}] [phase:${_WF_P}] [branch:${_WF_B}] [violations:${_WF_V}]"
|
|
192
|
-
[ "$_WF_V" != "0" ] && _WF_TAG="WARNING: ${_WF_V} workflow violation(s). $_WF_TAG"
|
|
193
|
-
python_result="${python_result} ${_WF_TAG}"
|
|
194
|
-
fi
|
|
195
|
-
|
|
196
|
-
# --- Forge Context Injection ---
|
|
197
|
-
_FORGE_ACTIVE="$HOME/.arkaos/plans/active.yaml"
|
|
198
|
-
if [ -f "$_FORGE_ACTIVE" ]; then
|
|
199
|
-
_FORGE_ID=$(cat "$_FORGE_ACTIVE" 2>/dev/null)
|
|
200
|
-
_FORGE_FILE="$HOME/.arkaos/plans/${_FORGE_ID}.yaml"
|
|
201
|
-
if [ -f "$_FORGE_FILE" ] && command -v python3 &>/dev/null; then
|
|
202
|
-
_FORGE_STATUS=$(FORGE_FILE="$_FORGE_FILE" python3 -c "import yaml,os; d=yaml.safe_load(open(os.environ['FORGE_FILE'])); print(d.get('status',''))" 2>/dev/null)
|
|
203
|
-
_FORGE_TAG="[forge:${_FORGE_ID}] [forge-status:${_FORGE_STATUS}]"
|
|
204
|
-
python_result="${python_result} ${_FORGE_TAG}"
|
|
205
|
-
fi
|
|
206
|
-
fi
|
|
207
|
-
|
|
208
|
-
# --- Knowledge Auto-Inject (On-Demand via Session Cache) ---
|
|
209
|
-
if [ -n "$python_result" ] && [[ "$python_result" == *"[knowledge:"* ]]; then
|
|
210
|
-
_KB_SESSION_ID="${ARKAOS_SESSION_ID:-${CLAUDE_SESSION_ID:-bridge-$$}}"
|
|
211
|
-
_KB_PROJECT_HASH=$(echo "$ARKAOS_ROOT" | md5sum 2>/dev/null | cut -c1-12 || echo "default")
|
|
212
|
-
_KB_CACHE_DIR="/tmp/arkaos-kb-${_KB_PROJECT_HASH}"
|
|
213
|
-
|
|
214
|
-
if [ -n "${ARKAOS_DEBUG:-}" ]; then
|
|
215
|
-
echo "[DEBUG] KB session_id=${_KB_SESSION_ID}, project_hash=${_KB_PROJECT_HASH}" >&2
|
|
216
|
-
fi
|
|
217
|
-
|
|
218
|
-
if [ -d "$_KB_CACHE_DIR" ] && command -v python3 &>/dev/null; then
|
|
219
|
-
_KB_CONTENT=$(python3 -c "
|
|
220
|
-
import sys
|
|
221
|
-
sys.path.insert(0, '$ARKAOS_ROOT')
|
|
222
|
-
from core.synapse.kb_cache import KBSessionCache
|
|
223
|
-
cache = KBSessionCache(session_id='$_KB_SESSION_ID', project_path='$ARKAOS_ROOT')
|
|
224
|
-
results = cache.get_overlap('''$user_input''', threshold=0.3)
|
|
225
|
-
if results:
|
|
226
|
-
snippets = []
|
|
227
|
-
for r in results[:3]:
|
|
228
|
-
src = r.get('source', '').split('/')[-1] if r.get('source') else ''
|
|
229
|
-
txt = r.get('text', '')[:200].replace('\n', ' ')
|
|
230
|
-
snippets.append(f'{src}: {txt}' if src else txt)
|
|
231
|
-
print(' | '.join(snippets))
|
|
232
|
-
" 2>/dev/null)
|
|
37
|
+
_ARKA_L0_FALLBACK='{"additionalContext": "[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"}'
|
|
233
38
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
fi
|
|
238
|
-
python_result="${_KB_CONTENT} ${python_result}"
|
|
239
|
-
fi
|
|
240
|
-
fi
|
|
241
|
-
fi
|
|
242
|
-
fi
|
|
39
|
+
if ! command -v python3 &>/dev/null; then
|
|
40
|
+
echo "$_ARKA_L0_FALLBACK"
|
|
41
|
+
exit 0
|
|
243
42
|
fi
|
|
244
|
-
|
|
245
|
-
#
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
L0_CACHE="$CACHE_DIR/l0-constitution"
|
|
253
|
-
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
|
|
254
|
-
L0=$(cat "$L0_CACHE")
|
|
43
|
+
# Self-root fallback: the wrapper ships next to its python entrypoint, so
|
|
44
|
+
# when ARKAOS_ROOT points at a pre-PR-6 install without core/hooks/, use
|
|
45
|
+
# the root this script lives in.
|
|
46
|
+
if [ ! -f "$ARKAOS_ROOT/core/hooks/user_prompt_submit.py" ]; then
|
|
47
|
+
_SELF_ROOT="$(cd "$(dirname "$0")/../.." 2>/dev/null && pwd)"
|
|
48
|
+
if [ -n "$_SELF_ROOT" ] && [ -f "$_SELF_ROOT/core/hooks/user_prompt_submit.py" ]; then
|
|
49
|
+
ARKAOS_ROOT="$_SELF_ROOT"
|
|
50
|
+
export ARKAOS_ROOT
|
|
255
51
|
else
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
fi
|
|
259
|
-
|
|
260
|
-
# L4: Git branch
|
|
261
|
-
L4=""
|
|
262
|
-
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
263
|
-
if [ -n "$branch" ] && [ "$branch" != "main" ] && [ "$branch" != "master" ] && [ "$branch" != "dev" ]; then
|
|
264
|
-
L4="[branch:$branch]"
|
|
265
|
-
fi
|
|
266
|
-
|
|
267
|
-
# L7: Time — intentionally skipped in bash fallback.
|
|
268
|
-
# Low-signal tag that changed every prompt and invalidated prompt cache.
|
|
269
|
-
# The Python TimeLayer (cache_ttl=3600) is authoritative when available.
|
|
270
|
-
L7=""
|
|
271
|
-
|
|
272
|
-
# L8: Workflow state
|
|
273
|
-
L8=""
|
|
274
|
-
_WF_READER="$ARKAOS_ROOT/core/workflow/state_reader.sh"
|
|
275
|
-
if [ -f "$_WF_READER" ] && bash "$_WF_READER" active 2>/dev/null; then
|
|
276
|
-
_WF_SUM=$(bash "$_WF_READER" summary 2>/dev/null)
|
|
277
|
-
_WF_N=$(echo "$_WF_SUM" | cut -d'|' -f1)
|
|
278
|
-
_WF_P=$(echo "$_WF_SUM" | cut -d'|' -f2)
|
|
279
|
-
_WF_B=$(echo "$_WF_SUM" | cut -d'|' -f4)
|
|
280
|
-
_WF_V=$(echo "$_WF_SUM" | cut -d'|' -f5)
|
|
281
|
-
L8="[workflow:${_WF_N}] [phase:${_WF_P}] [branch:${_WF_B}] [violations:${_WF_V}]"
|
|
282
|
-
[ "$_WF_V" != "0" ] && L8="WARNING: ${_WF_V} workflow violation(s). $L8"
|
|
283
|
-
fi
|
|
284
|
-
|
|
285
|
-
# L9: Forge state
|
|
286
|
-
L9=""
|
|
287
|
-
_FORGE_ACTIVE_FB="$HOME/.arkaos/plans/active.yaml"
|
|
288
|
-
if [ -f "$_FORGE_ACTIVE_FB" ]; then
|
|
289
|
-
_FORGE_ID_FB=$(cat "$_FORGE_ACTIVE_FB" 2>/dev/null)
|
|
290
|
-
_FORGE_FILE_FB="$HOME/.arkaos/plans/${_FORGE_ID_FB}.yaml"
|
|
291
|
-
if [ -f "$_FORGE_FILE_FB" ] && command -v python3 &>/dev/null; then
|
|
292
|
-
_FORGE_STATUS_FB=$(FORGE_FILE="$_FORGE_FILE_FB" python3 -c "import yaml,os; d=yaml.safe_load(open(os.environ['FORGE_FILE'])); print(d.get('status',''))" 2>/dev/null)
|
|
293
|
-
L9="[forge:${_FORGE_ID_FB}] [forge-status:${_FORGE_STATUS_FB}]"
|
|
294
|
-
fi
|
|
295
|
-
fi
|
|
296
|
-
|
|
297
|
-
python_result="$L0 $L4 $L7 $L8 $L9"
|
|
298
|
-
fi
|
|
299
|
-
|
|
300
|
-
# ─── Token Hygiene suggestions (non-blocking) ───────────────────────────
|
|
301
|
-
_HYGIENE=""
|
|
302
|
-
_HYGIENE_SCRIPT="$(dirname "$0")/token-hygiene.sh"
|
|
303
|
-
if [ -f "$_HYGIENE_SCRIPT" ]; then
|
|
304
|
-
# Extract transcript path from input JSON if present
|
|
305
|
-
_TRANSCRIPT=""
|
|
306
|
-
if command -v jq &>/dev/null; then
|
|
307
|
-
_TRANSCRIPT=$(echo "$input" | jq -r '.transcript_path // ""' 2>/dev/null)
|
|
308
|
-
fi
|
|
309
|
-
_HYGIENE=$(ARKA_PROMPT="$user_input" \
|
|
310
|
-
ARKA_TRANSCRIPT_PATH="$_TRANSCRIPT" \
|
|
311
|
-
CLAUDE_CONTEXT_USED="${CLAUDE_CONTEXT_USED:-}" \
|
|
312
|
-
bash "$_HYGIENE_SCRIPT" 2>/dev/null)
|
|
313
|
-
fi
|
|
314
|
-
|
|
315
|
-
# ─── Persistent Routing Reminder ────────────────────────────────────────
|
|
316
|
-
# High-salience tag — ensures squad routing persists across conversation turns,
|
|
317
|
-
# not just on turn 1 when /arka skill content is fresh. See spec:
|
|
318
|
-
# docs/superpowers/specs/2026-04-14-persistent-routing-reminder-design.md
|
|
319
|
-
_ROUTE_REMINDER="
|
|
320
|
-
[ARKA:ROUTE]
|
|
321
|
-
EVERY response MUST route through a department squad.
|
|
322
|
-
NO generic assistant replies. Announce the squad before responding.
|
|
323
|
-
When [knowledge:N chunks] is present, cite at least one source.
|
|
324
|
-
If [knowledge:N chunks] is absent on a non-trivial ArkaOS topic, query Obsidian first."
|
|
325
|
-
|
|
326
|
-
# ─── Workflow Classifier (hard enforcement for creation/implementation) ──
|
|
327
|
-
# Uses the shared _lib/workflow-classifier.sh. When a creation/implementation
|
|
328
|
-
# verb is detected, the session is marked as flow-required so PreToolUse
|
|
329
|
-
# can block Write/Edit/MultiEdit until the agent emits [arka:routing] or
|
|
330
|
-
# [arka:trivial]. Explicit slash commands and bang shells pass through.
|
|
331
|
-
_WORKFLOW_DIRECTIVE=""
|
|
332
|
-
if [ -n "$user_input" ] && command -v arka_wf_classify &>/dev/null; then
|
|
333
|
-
if [ "$(arka_wf_classify "$user_input")" = "true" ]; then
|
|
334
|
-
# Mark session as flow-required (consumed by pre-tool-use.sh and stop.sh)
|
|
335
|
-
if command -v arka_wf_mark_required &>/dev/null; then
|
|
336
|
-
arka_wf_mark_required "$SESSION_ID"
|
|
337
|
-
fi
|
|
338
|
-
_WORKFLOW_DIRECTIVE="
|
|
339
|
-
[ARKA:WORKFLOW-REQUIRED] Your user request matched a CREATION/IMPLEMENTATION pattern.
|
|
340
|
-
The ArkaOS mandatory 13-phase flow applies. It is NON-NEGOTIABLE (constitution rule
|
|
341
|
-
mandatory-flow). You MUST walk every phase, in order, emitting a [arka:phase:N] tag
|
|
342
|
-
before each:
|
|
343
|
-
1. Input — restate the request verbatim.
|
|
344
|
-
2. Get context — profile, repo, git, cwd tag, session digests.
|
|
345
|
-
3. Decide route — emit [arka:routing] <dept> -> <lead>.
|
|
346
|
-
4. Call hierarchy — escalate to Tier 0 if strategic/cross-dept/security/financial.
|
|
347
|
-
5. Research — query Obsidian + vector DB, cite sources or declare the gap.
|
|
348
|
-
6. Call team — dispatch specialists via Agent tool.
|
|
349
|
-
7. Plan — run six parallel reviewers: positive, devil's advocate, Q&A, KB research,
|
|
350
|
-
best-solution validator, pessimistic. Synthesise into a spec.
|
|
351
|
-
8. Present plan — save to Obsidian + vector DB + ~/.arkaos/plans/, print inline.
|
|
352
|
-
9. Wait approval — EXPLICIT user go. Silence is NOT approval.
|
|
353
|
-
10. TODO list — atomic, ordered, independently verifiable.
|
|
354
|
-
11. Per-todo loop — team call -> complete -> QA (all tests, E2E, Playwright) ->
|
|
355
|
-
Security review -> Quality Gate (Marta + Eduardo + Francisca, Opus) -> Document.
|
|
356
|
-
Each step loops back on fail. No compound gates.
|
|
357
|
-
12. Loop until TODO is exhausted.
|
|
358
|
-
13. Detailed summary — what was done, where, how to verify, what is still open.
|
|
359
|
-
|
|
360
|
-
No Write, Edit, Bash-with-side-effects, or Agent dispatch before Phase 7 completes
|
|
361
|
-
for the affected item. No advancing a todo until QA AND Security AND Quality Gate
|
|
362
|
-
all pass for it. Phase 5 and Phase 8 require Obsidian/KB writes, not just reads.
|
|
363
|
-
|
|
364
|
-
Trivial override: single-file edit under 10 lines with imperative verb
|
|
365
|
-
(rename X, fix typo in Y). Emit [arka:trivial] <reason> as first line and proceed.
|
|
366
|
-
Anything else runs the full 13 phases. Source: arka/skills/flow/SKILL.md.
|
|
367
|
-
|
|
368
|
-
This is enforced by the hook and the session-start systemMessage, not by convention.
|
|
369
|
-
Skipping violates: mandatory-flow, squad-routing, spec-driven, mandatory-qa,
|
|
370
|
-
sequential-validation, full-visibility, arka-supremacy."
|
|
371
|
-
fi
|
|
372
|
-
fi
|
|
373
|
-
|
|
374
|
-
# ─── Cognitive context injection (PR4 v2.26.0 hooks-as-retrieval) ───────
|
|
375
|
-
# Read the context cache populated by the previous PostToolUse turn and
|
|
376
|
-
# inject any KB hits as an `[arka:context]` advisory. The Python helper
|
|
377
|
-
# has internal TTL filtering (10 min) and returns empty when there is no
|
|
378
|
-
# fresh cache, so this stays a no-op until the cognitive layer has data
|
|
379
|
-
# to share.
|
|
380
|
-
_ARKA_CONTEXT_HITS=""
|
|
381
|
-
if [ -n "$SESSION_ID" ]; then
|
|
382
|
-
_ARKAOS_REPO=$(cat "$HOME/.arkaos/.repo-path" 2>/dev/null || echo "")
|
|
383
|
-
if [ -n "$_ARKAOS_REPO" ] && [ -d "$_ARKAOS_REPO" ]; then
|
|
384
|
-
_ARKA_CONTEXT_HITS=$(PYTHONPATH="$_ARKAOS_REPO" python3 -m core.cognition.retrieval inject "$SESSION_ID" 2>/dev/null)
|
|
385
|
-
fi
|
|
386
|
-
fi
|
|
387
|
-
|
|
388
|
-
# ─── KB citation nudge (PR18 v2.40.0) ────────────────────────────────────
|
|
389
|
-
# Read the cite-check result written by the previous Stop hook. If the
|
|
390
|
-
# last assistant turn was on an ArkaOS topic without any citation, surface
|
|
391
|
-
# the suggestion to the model in this turn's additionalContext. One-shot:
|
|
392
|
-
# the file is deleted after read so the nudge does not repeat across turns.
|
|
393
|
-
_KB_CITE_NUDGE=""
|
|
394
|
-
if [ -n "$SESSION_ID" ] && [ "$_ARKA_SURFACE_NUDGES" = "true" ]; then
|
|
395
|
-
_CITE_FILE="/tmp/arkaos-cite/${SESSION_ID}.json"
|
|
396
|
-
if [ -f "$_CITE_FILE" ]; then
|
|
397
|
-
if command -v jq &>/dev/null; then
|
|
398
|
-
# NOTE: do not use `// true` here — jq's `//` treats false as needing
|
|
399
|
-
# the default, which would suppress the nudge in the exact case we
|
|
400
|
-
# care about. Read .passed raw and compare to the literal "false".
|
|
401
|
-
_CITE_PASSED=$(jq -r '.passed' "$_CITE_FILE" 2>/dev/null)
|
|
402
|
-
_CITE_SUGGEST=$(jq -r '.suggestion // ""' "$_CITE_FILE" 2>/dev/null)
|
|
403
|
-
if [ "$_CITE_PASSED" = "false" ] && [ -n "$_CITE_SUGGEST" ] && [ "$_CITE_SUGGEST" != "null" ]; then
|
|
404
|
-
_KB_CITE_NUDGE="[arka:suggest] ${_CITE_SUGGEST}"
|
|
405
|
-
fi
|
|
406
|
-
fi
|
|
407
|
-
rm -f "$_CITE_FILE" 2>/dev/null
|
|
408
|
-
fi
|
|
409
|
-
fi
|
|
410
|
-
|
|
411
|
-
# ─── Meta-tag nudge (PR30 v2.49.0) ───────────────────────────────────────
|
|
412
|
-
# Mirror of the KB citation nudge but for the [arka:meta] one-liner
|
|
413
|
-
# contract. One-shot; deleted after read.
|
|
414
|
-
_META_TAG_NUDGE=""
|
|
415
|
-
if [ -n "$SESSION_ID" ] && [ "$_ARKA_SURFACE_NUDGES" = "true" ]; then
|
|
416
|
-
_META_FILE="/tmp/arkaos-meta/${SESSION_ID}.json"
|
|
417
|
-
if [ -f "$_META_FILE" ]; then
|
|
418
|
-
if command -v jq &>/dev/null; then
|
|
419
|
-
_META_PASSED=$(jq -r '.passed' "$_META_FILE" 2>/dev/null)
|
|
420
|
-
_META_SUGGEST=$(jq -r '.suggestion // ""' "$_META_FILE" 2>/dev/null)
|
|
421
|
-
if [ "$_META_PASSED" = "false" ] && [ -n "$_META_SUGGEST" ] && [ "$_META_SUGGEST" != "null" ]; then
|
|
422
|
-
_META_TAG_NUDGE="[arka:suggest] ${_META_SUGGEST}"
|
|
423
|
-
fi
|
|
424
|
-
fi
|
|
425
|
-
rm -f "$_META_FILE" 2>/dev/null
|
|
426
|
-
fi
|
|
427
|
-
fi
|
|
428
|
-
|
|
429
|
-
# ─── Closing-marker nudge (PR59 v2.76.0) ─────────────────────────────────
|
|
430
|
-
# Mirror of meta-tag nudge but for [arka:phase:13] / [arka:trivial]
|
|
431
|
-
# closing markers. One-shot; deleted after read.
|
|
432
|
-
_CLOSING_MARKER_NUDGE=""
|
|
433
|
-
if [ -n "$SESSION_ID" ] && [ "$_ARKA_SURFACE_NUDGES" = "true" ]; then
|
|
434
|
-
_CLOSING_FILE="/tmp/arkaos-closing/${SESSION_ID}.json"
|
|
435
|
-
if [ -f "$_CLOSING_FILE" ]; then
|
|
436
|
-
if command -v jq &>/dev/null; then
|
|
437
|
-
_CLOSING_PASSED=$(jq -r '.passed' "$_CLOSING_FILE" 2>/dev/null)
|
|
438
|
-
_CLOSING_SUGGEST=$(jq -r '.suggestion // ""' "$_CLOSING_FILE" 2>/dev/null)
|
|
439
|
-
if [ "$_CLOSING_PASSED" = "false" ] && [ -n "$_CLOSING_SUGGEST" ] && [ "$_CLOSING_SUGGEST" != "null" ]; then
|
|
440
|
-
_CLOSING_MARKER_NUDGE="[arka:suggest] ${_CLOSING_SUGGEST}"
|
|
441
|
-
fi
|
|
442
|
-
fi
|
|
443
|
-
rm -f "$_CLOSING_FILE" 2>/dev/null
|
|
52
|
+
echo "$_ARKA_L0_FALLBACK"
|
|
53
|
+
exit 0
|
|
444
54
|
fi
|
|
445
55
|
fi
|
|
446
56
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
[ -n "$_HYGIENE" ] && _OUT_CONTEXT="$_OUT_CONTEXT $_HYGIENE"
|
|
450
|
-
[ -n "$_KB_CITE_NUDGE" ] && _OUT_CONTEXT="$_OUT_CONTEXT
|
|
451
|
-
$_KB_CITE_NUDGE"
|
|
452
|
-
[ -n "$_META_TAG_NUDGE" ] && _OUT_CONTEXT="$_OUT_CONTEXT
|
|
453
|
-
$_META_TAG_NUDGE"
|
|
454
|
-
[ -n "$_CLOSING_MARKER_NUDGE" ] && _OUT_CONTEXT="$_OUT_CONTEXT
|
|
455
|
-
$_CLOSING_MARKER_NUDGE"
|
|
456
|
-
[ -n "$_ARKA_CONTEXT_HITS" ] && _OUT_CONTEXT="$_OUT_CONTEXT
|
|
457
|
-
$_ARKA_CONTEXT_HITS"
|
|
458
|
-
# Escape for JSON
|
|
459
|
-
_OUT_JSON=$(python3 -c "import json,sys; print(json.dumps(sys.stdin.read()))" <<< "$_OUT_CONTEXT" 2>/dev/null)
|
|
460
|
-
if [ -n "$_OUT_JSON" ]; then
|
|
461
|
-
echo "{\"additionalContext\": $_OUT_JSON}"
|
|
462
|
-
else
|
|
463
|
-
echo "{\"additionalContext\": \"${_ARKA_GREETING:-}${_SYNC_NOTICE:-}$python_result\"}"
|
|
464
|
-
fi
|
|
465
|
-
|
|
466
|
-
# ─── Metrics ─────────────────────────────────────────────────────────────
|
|
467
|
-
# Count @-mentions in the prompt for at_mention_frequency telemetry. Mirrors
|
|
468
|
-
# the claude_code.at_mention OpenTelemetry event introduced in Claude Code
|
|
469
|
-
# 2.1.122, but works on any version because we count from the same input
|
|
470
|
-
# the hook already receives.
|
|
471
|
-
at_mentions=$(printf '%s' "$user_input" | grep -oE '(^|[[:space:]])@[A-Za-z0-9_./-]+' | wc -l | tr -d ' ')
|
|
472
|
-
elapsed=$(_hook_ms)
|
|
473
|
-
if [ "$elapsed" -gt 0 ] 2>/dev/null; then
|
|
474
|
-
echo "{\"hook\":\"user-prompt-submit-v2\",\"ms\":$elapsed,\"at_mentions\":${at_mentions:-0}}" >> "$CACHE_DIR/hook-metrics.jsonl" 2>/dev/null
|
|
475
|
-
fi
|
|
57
|
+
PYTHONPATH="$ARKAOS_ROOT${PYTHONPATH:+:$PYTHONPATH}" \
|
|
58
|
+
exec python3 -m core.hooks.user_prompt_submit
|
|
Binary file
|
|
@@ -54,6 +54,11 @@ class Insight:
|
|
|
54
54
|
"date": date_str,
|
|
55
55
|
"status": "surfaced",
|
|
56
56
|
"confidence": self.confidence,
|
|
57
|
+
# Grounding quarantine (PR-3 v4.1): Dreaming output is
|
|
58
|
+
# LLM-inferred, not extracted from authoritative sources.
|
|
59
|
+
# Synapse L2.5 reads this marker and excludes (or explicitly
|
|
60
|
+
# labels) these notes so they never masquerade as grounded KB.
|
|
61
|
+
"grounding": "inferred",
|
|
57
62
|
"sources": [f"[[{s}]]" for s in self.sources],
|
|
58
63
|
"tags": ["arkaos-dream", *self.tags],
|
|
59
64
|
"plugin_compat_version": "1.0",
|
|
Binary file
|
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Reads a YAML schedule config, acquires a file lock to prevent duplicate runs,
|
|
4
4
|
and executes Claude CLI commands with logging per task.
|
|
5
|
+
|
|
6
|
+
Goal mode (opt-in, v4.1.0): a schedule may pair `goal_condition` with
|
|
7
|
+
`task_budget` to append `--goal <condition> --task-budget <N>` to the
|
|
8
|
+
Claude CLI argv, so Research/Dreaming cycles run until the condition is
|
|
9
|
+
met instead of stopping when the prompt's phases run out. The pairing is
|
|
10
|
+
mandatory (`_goal_argv` raises otherwise) and only applies to the
|
|
11
|
+
prompt_file path — `python_module` entries ignore it. Commented-out
|
|
12
|
+
examples live in the installer-seeded template `config/cognition/
|
|
13
|
+
schedules.yaml` (deployed to `~/.arkaos/schedules.yaml`); nothing
|
|
14
|
+
goal-based auto-runs without the operator uncommenting it.
|
|
5
15
|
"""
|
|
6
16
|
|
|
7
17
|
import os
|
package/core/forge/__init__.py
CHANGED
|
@@ -67,6 +67,7 @@ from core.forge.orchestrator import (
|
|
|
67
67
|
|
|
68
68
|
from core.forge.runtime_dispatcher import (
|
|
69
69
|
ForgeTaskDispatcher,
|
|
70
|
+
ForgeDispatchUnavailableError,
|
|
70
71
|
ClaudeCodeForgeDispatcher,
|
|
71
72
|
ExplorerDispatchRequest,
|
|
72
73
|
CriticDispatchRequest,
|
|
@@ -131,6 +132,7 @@ __all__ = [
|
|
|
131
132
|
"CONSTITUTION_PHASES",
|
|
132
133
|
# runtime dispatcher
|
|
133
134
|
"ForgeTaskDispatcher",
|
|
135
|
+
"ForgeDispatchUnavailableError",
|
|
134
136
|
"ClaudeCodeForgeDispatcher",
|
|
135
137
|
"ExplorerDispatchRequest",
|
|
136
138
|
"CriticDispatchRequest",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|