arkaos 4.3.1 → 4.3.2
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 +1 -1
- package/VERSION +1 -1
- package/arka/SKILL.md +4 -4
- package/arka/skills/costs/SKILL.md +1 -1
- package/arka/skills/fusion/SKILL.md +3 -3
- package/config/claude-agents/marta-cqo.md +1 -1
- package/config/claude-agents/paulo-tech-lead.md +1 -1
- package/config/constitution.yaml +5 -5
- package/config/hooks/_lib/arka_python.ps1 +43 -0
- package/config/hooks/_lib/arka_python.sh +63 -0
- package/config/hooks/agent-provision.sh +8 -1
- package/config/hooks/cwd-changed.sh +6 -2
- package/config/hooks/post-tool-use-v2.sh +6 -2
- package/config/hooks/post-tool-use.sh +8 -17
- package/config/hooks/pre-tool-use.ps1 +8 -6
- package/config/hooks/pre-tool-use.sh +8 -17
- package/config/hooks/session-start.sh +23 -21
- package/config/hooks/stop.ps1 +7 -5
- package/config/hooks/stop.sh +8 -17
- package/config/hooks/token-hygiene.sh +5 -1
- package/config/hooks/user-prompt-submit-v2.sh +13 -9
- package/config/hooks/user-prompt-submit.sh +8 -17
- package/core/runtime/__pycache__/llm_provider.cpython-312.pyc +0 -0
- package/core/runtime/__pycache__/openrouter_provider.cpython-312.pyc +0 -0
- package/core/workflow/state_reader.sh +12 -5
- package/departments/ops/skills/update/SKILL.md +2 -2
- package/departments/ops/skills/update/references/sync-engine.md +1 -1
- package/departments/quality/SKILL.md +1 -1
- package/installer/index.js +14 -0
- package/installer/update.js +13 -0
- package/package.json +5 -2
- package/pyproject.toml +1 -1
- package/scripts/seed_initial_patterns.py +1 -1
package/README.md
CHANGED
|
@@ -491,7 +491,7 @@ npx arkaos uninstall # Remove ArkaOS
|
|
|
491
491
|
**Release pipeline (operator-side, headless):**
|
|
492
492
|
|
|
493
493
|
```
|
|
494
|
-
|
|
494
|
+
~/.arkaos/bin/arka-py -m core.release.preflight_cli --expected-npm-user <user>
|
|
495
495
|
# Step 0 NON-NEGOTIABLE before any tag/push/publish (v2.43.0+).
|
|
496
496
|
# Six checks: version-alignment / npm-auth / npm-publish-capability /
|
|
497
497
|
# gh-auth / git-remote / git-clean. Plus no-client-name-leaks
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.3.
|
|
1
|
+
4.3.2
|
package/arka/SKILL.md
CHANGED
|
@@ -180,10 +180,10 @@ violation (squad-routing, arka-supremacy, spec-driven, mandatory-qa).
|
|
|
180
180
|
| Command | Description |
|
|
181
181
|
|---------|-------------|
|
|
182
182
|
| `/arka status` | System status (version, departments, agents, active projects). Includes **LLM costs (24h)** section: top-line cost + cache hit rate + call count from `core.runtime.llm_cost_telemetry.summarise(period="today")`. Also includes **Enforcement (24h)** section: total calls, block rate, top blocked tools/reasons from `core.governance.enforcement_telemetry.summarise(period="today")` (PR19 v2.41.0). Plus **Reorganization (today)** section: today's proposal path + artifact count from `core.cognition.reorganizer_scheduler.status_summary()` (PR24 v2.46.0). |
|
|
183
|
-
| `/arka costs [period]` | LLM cost visibility — aggregates telemetry by day/week/month/all, with top expensive sessions. See `arka/skills/costs/SKILL.md`. Shells out to
|
|
184
|
-
| `/arka enforcement [period]` | Enforcement compliance — aggregates flow-marker enforcement telemetry by day/week/month/all. Shows block rate, top blocked tools, top reasons. Shells out to
|
|
185
|
-
| `/arka compliance [period]` | Behavior compliance summary (PR29 v2.48.0) — aggregates stop-hook telemetry by day/week/month/all. Shows rates for the four contracts: closing marker, `[arka:meta]` tag, KB citation pass, sycophancy clean. Shells out to
|
|
186
|
-
| `/arka reorganize [--since-days N]` | Dreaming → Agent reorganizer. Aggregates recent KB pattern/anti-pattern/lesson artifacts (default last 7 days) into a markdown proposal at `~/.arkaos/reorganize-proposals/<date>.md`. **Propose-only** — never modifies agent YAMLs. Sanitizes client identifiers from titles and body excerpts; drops `tags:` field entirely to prevent project-name leaks. **Auto-fires on session start when today's proposal is missing** (PR24 v2.46.0 stale-aware trigger, 30s timeout, background). Shells out to
|
|
183
|
+
| `/arka costs [period]` | LLM cost visibility — aggregates telemetry by day/week/month/all, with top expensive sessions. See `arka/skills/costs/SKILL.md`. Shells out to `~/.arkaos/bin/arka-py -m core.runtime.llm_cost_telemetry_cli <period>`. |
|
|
184
|
+
| `/arka enforcement [period]` | Enforcement compliance — aggregates flow-marker enforcement telemetry by day/week/month/all. Shows block rate, top blocked tools, top reasons. Shells out to `~/.arkaos/bin/arka-py -m core.governance.enforcement_telemetry_cli <period>`. |
|
|
185
|
+
| `/arka compliance [period]` | Behavior compliance summary (PR29 v2.48.0) — aggregates stop-hook telemetry by day/week/month/all. Shows rates for the four contracts: closing marker, `[arka:meta]` tag, KB citation pass, sycophancy clean. Shells out to `~/.arkaos/bin/arka-py -m core.governance.compliance_telemetry_cli <period>`. |
|
|
186
|
+
| `/arka reorganize [--since-days N]` | Dreaming → Agent reorganizer. Aggregates recent KB pattern/anti-pattern/lesson artifacts (default last 7 days) into a markdown proposal at `~/.arkaos/reorganize-proposals/<date>.md`. **Propose-only** — never modifies agent YAMLs. Sanitizes client identifiers from titles and body excerpts; drops `tags:` field entirely to prevent project-name leaks. **Auto-fires on session start when today's proposal is missing** (PR24 v2.46.0 stale-aware trigger, 30s timeout, background). Shells out to `~/.arkaos/bin/arka-py -m core.cognition.reorganizer_cli [--since-days N] [--dry-run]`. |
|
|
187
187
|
| `/arka standup` | Daily standup (projects, priorities, blockers, updates) |
|
|
188
188
|
| `/arka monitor` | System health monitoring |
|
|
189
189
|
| `/arka onboard <path>` | Onboard an existing project into ArkaOS |
|
|
@@ -42,7 +42,7 @@ surfaces usage and emits soft advisories. It never blocks a call.
|
|
|
42
42
|
This skill shells out to the Python CLI:
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
|
|
45
|
+
~/.arkaos/bin/arka-py -m core.runtime.llm_cost_telemetry_cli <period>
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
Source:
|
|
@@ -24,9 +24,9 @@ mechanical work economises.
|
|
|
24
24
|
Run and read all three:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
~/.arkaos/bin/arka-py -m core.runtime.model_router_cli discover # Ollama + local models
|
|
28
|
+
~/.arkaos/bin/arka-py -m core.runtime.model_router_cli --json # current routing
|
|
29
|
+
~/.arkaos/bin/arka-py -m core.runtime.model_router_cli usage --period week --json
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
Also check key presence (never print values): `OPENROUTER_API_KEY` /
|
|
@@ -23,7 +23,7 @@ evidence, not from model size.
|
|
|
23
23
|
## Review Rubric (evidence interpretation, not role-play)
|
|
24
24
|
|
|
25
25
|
1. Run the engine first — no verdict without a report:
|
|
26
|
-
|
|
26
|
+
`~/.arkaos/bin/arka-py -m core.governance.evidence_checks <project_dir> [--changed-files ...] [--test-command '...'] --json`
|
|
27
27
|
2. Dispatch Eduardo (spellcheck + changed copy) and Francisca
|
|
28
28
|
(lint/typecheck/tests/coverage/security-grep) with the report and the
|
|
29
29
|
structured output schema `QG_VERDICT_JSON_SCHEMA` from
|
|
@@ -24,7 +24,7 @@ not cut corners to look fast.
|
|
|
24
24
|
dispatch with `[arka:dispatch] paulo -> <specialist>`.
|
|
25
25
|
3. Evidence over narration: a task is done when its tests RAN and exited 0
|
|
26
26
|
on record — never when a subagent says it is done. Run
|
|
27
|
-
|
|
27
|
+
`~/.arkaos/bin/arka-py -m core.governance.evidence_checks <project_dir> --json` before
|
|
28
28
|
claiming completion.
|
|
29
29
|
4. Submit to the Quality Gate (marta-cqo) with the evidence report; expect
|
|
30
30
|
a structured `QGVerdict` back. REJECTED means loop, not negotiate.
|
package/config/constitution.yaml
CHANGED
|
@@ -142,7 +142,7 @@ enforcement_levels:
|
|
|
142
142
|
scope: "All technical: code quality, tests, UX/UI, data integrity, security, performance"
|
|
143
143
|
veto_power: true
|
|
144
144
|
process:
|
|
145
|
-
- "Evidence engine runs first:
|
|
145
|
+
- "Evidence engine runs first: ~/.arkaos/bin/arka-py -m core.governance.evidence_checks — the verdict derives from its report"
|
|
146
146
|
- "Marta receives all output from execution phase plus the evidence report"
|
|
147
147
|
- "Marta dispatches Eduardo (text) and Francisca (technical) in parallel, each in an INDEPENDENT subagent context (clean context, no stake in the work being approved)"
|
|
148
148
|
- "Each reviewer returns a structured QGVerdict (APPROVED or REJECTED) with specific issues; the verdict MUST name the benchmark used (reference_companies.application) and enumerate the concrete rejections a top-tier lead would raise; evidence overall=fail forces REJECTED"
|
|
@@ -197,7 +197,7 @@ enforcement_levels:
|
|
|
197
197
|
# ─── Rule added in PR3 Squad Intelligence Upgrade (2026-05-28) ───────
|
|
198
198
|
- id: agent-experience-persistence
|
|
199
199
|
rule: "Quality Gate REJECTED verdicts MUST result in an Experience record for the failing agent, written to ~/.arkaos/agents/<agent_id>/experiences.jsonl via core.governance.cqo_experience_recorder. Next dispatch of that agent loads the experiences via the Synapse L2.6 layer (core.synapse.agent_experiences_layer) so the lesson carries across sessions. Without this, REJECTED reports evaporate as conversation turns and the same structural mistakes recur."
|
|
200
|
-
enforcement: "PR3 v3.74.0 ships the storage, parser, and Synapse layer. v3.74.1 will wire a PostToolUse hook on the Agent tool that auto-records on REJECTED verdicts. Until then orchestrators MUST call cqo_experience_recorder.record_from_verdict() after every CQO dispatch. Audit via
|
|
200
|
+
enforcement: "PR3 v3.74.0 ships the storage, parser, and Synapse layer. v3.74.1 will wire a PostToolUse hook on the Agent tool that auto-records on REJECTED verdicts. Until then orchestrators MUST call cqo_experience_recorder.record_from_verdict() after every CQO dispatch. Audit via ~/.arkaos/bin/arka-py -m core.governance.agent_experiences_cli list <agent_id>."
|
|
201
201
|
|
|
202
202
|
should:
|
|
203
203
|
description: "Best practices. Encouraged but not enforced."
|
|
@@ -221,17 +221,17 @@ enforcement_levels:
|
|
|
221
221
|
# ─── Rule added in PR6 Squad Intelligence Upgrade (2026-05-28) ───────
|
|
222
222
|
- id: design-system-locked
|
|
223
223
|
rule: "Each project SHOULD declare a `design-system.yaml` at its root listing tokens (colors, spacing, fonts), allowed_components, file_globs to scan, and forbidden_patterns with suggestions. The per-project linter (core.governance.design_system_lint) detects UI/UX drift — hex literals outside the palette, inline style attributes, raw HTML where a Nuxt UI component exists, etc. Adoption is opt-in per project (no YAML at project root → no violations). v3.77.0 is advisory-only; pre-commit hook integration lands in v3.77.x once the rule sets stabilise across the operator's projects."
|
|
224
|
-
enforcement: "Run via
|
|
224
|
+
enforcement: "Run via `~/.arkaos/bin/arka-py -m core.governance.design_system_lint_cli <project_path>` (text or JSON output, optional --exit-on-violations). Example template at `docs/examples/design-system-example.yaml`."
|
|
225
225
|
|
|
226
226
|
# ─── Rule added in PR5 Squad Intelligence Upgrade (2026-05-28) ───────
|
|
227
227
|
- id: dna-fidelity-warn
|
|
228
228
|
rule: "Agent outputs are compared against the `signature_markers` block in each agent's YAML at the end of every turn. Forbidden patterns (avoid_patterns) and missing opening phrases (opening_phrases) generate FidelityViolation records in ~/.arkaos/telemetry/dna-fidelity.jsonl. v3.76.0 is soft-warn — violations are recorded for telemetry and operator review, not blocked. Hard-block mode lands later once the marker set is calibrated against real production usage."
|
|
229
|
-
enforcement: "Stop hook (config/hooks/stop.sh) calls core.governance.dna_fidelity.check_fidelity at turn end. Telemetry inspection:
|
|
229
|
+
enforcement: "Stop hook (config/hooks/stop.sh) calls core.governance.dna_fidelity.check_fidelity at turn end. Telemetry inspection: ~/.arkaos/bin/arka-py -m core.governance.dna_fidelity_cli list|summary. Agents in scope for v3.76.0: tech-lead-paulo, cqo-marta, copy-director-eduardo, tech-director-francisca. Remaining 61 agent YAMLs get signature_markers in v3.76.x curation work."
|
|
230
230
|
|
|
231
231
|
# ─── Rule added in PR4 Squad Intelligence Upgrade (2026-05-28) ───────
|
|
232
232
|
- id: pattern-library-first
|
|
233
233
|
rule: "Before designing any new feature, consult the Pattern Library (core.knowledge.pattern_cards). If a similar pattern exists, reuse it or explicitly document why divergence is justified in the spec. New patterns SHOULD be registered with record_pattern() after Quality Gate APPROVED so future feature work inherits the prior art."
|
|
234
|
-
enforcement: "Synapse layer L7.5 (core.synapse.pattern_library_layer) auto-injects top matching cards as context. Audit via
|
|
234
|
+
enforcement: "Synapse layer L7.5 (core.synapse.pattern_library_layer) auto-injects top matching cards as context. Audit via ~/.arkaos/bin/arka-py -m core.knowledge.pattern_cards_cli list. SHOULD level — promoted from advisory once telemetry shows consistent consultation."
|
|
235
235
|
|
|
236
236
|
tier_hierarchy:
|
|
237
237
|
description: "Agent authority levels inspired by SpaceX/Google/Anthropic org structures"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# ArkaOS shared Python resolver (PowerShell side) — single source of truth.
|
|
2
|
+
#
|
|
3
|
+
# Windows mirror of config/hooks/_lib/arka_python.sh and
|
|
4
|
+
# installer/python-resolver.js. Prefers the ~/.arkaos venv (has pyyaml/
|
|
5
|
+
# pydantic); never silently falls back to a system python that lacks ArkaOS
|
|
6
|
+
# deps. Dot-source this file: it sets $env:ARKA_PY.
|
|
7
|
+
#
|
|
8
|
+
# Resolution order:
|
|
9
|
+
# 1. $env:ARKAOS_PYTHON (explicit override), if it exists.
|
|
10
|
+
# 2. The ArkaOS venv — Scripts\python.exe (Windows) then bin/python.
|
|
11
|
+
# 3. Any python3/python/py on PATH that can `import yaml`.
|
|
12
|
+
# 4. Bare `python` as a last resort.
|
|
13
|
+
|
|
14
|
+
function Resolve-ArkaPython {
|
|
15
|
+
if ($env:ARKAOS_PYTHON -and (Test-Path -LiteralPath $env:ARKAOS_PYTHON)) {
|
|
16
|
+
return $env:ARKAOS_PYTHON
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
$base = if ($env:USERPROFILE) { $env:USERPROFILE } elseif ($HOME) { $HOME } else { "" }
|
|
20
|
+
if ($base) {
|
|
21
|
+
$candidates = @(
|
|
22
|
+
(Join-Path $base ".arkaos\venv\Scripts\python.exe"),
|
|
23
|
+
(Join-Path $base ".arkaos/venv/bin/python"),
|
|
24
|
+
(Join-Path $base ".arkaos\.venv\Scripts\python.exe"),
|
|
25
|
+
(Join-Path $base ".arkaos/.venv/bin/python")
|
|
26
|
+
)
|
|
27
|
+
foreach ($c in $candidates) {
|
|
28
|
+
if (Test-Path -LiteralPath $c) { return $c }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
foreach ($name in @("python3", "python", "py")) {
|
|
33
|
+
$cmd = Get-Command $name -ErrorAction SilentlyContinue
|
|
34
|
+
if ($cmd) {
|
|
35
|
+
& $cmd.Source -c "import yaml" 2>$null
|
|
36
|
+
if ($LASTEXITCODE -eq 0) { return $cmd.Source }
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return "python"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
$env:ARKA_PY = Resolve-ArkaPython
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# shellcheck shell=bash
|
|
2
|
+
# ArkaOS shared Python resolver (shell side) — single source of truth.
|
|
3
|
+
#
|
|
4
|
+
# Mirrors installer/python-resolver.js (getArkaosPython). Every hook, the
|
|
5
|
+
# state reader, the agent-provision helper, and the `arka-py` shim source
|
|
6
|
+
# THIS file instead of probing for `python3` on their own. Rationale: an
|
|
7
|
+
# unrelated project venv first on PATH, or a system python without pyyaml/
|
|
8
|
+
# pydantic, silently degrades every gate. The ArkaOS venv is authoritative.
|
|
9
|
+
#
|
|
10
|
+
# Contract of arka_resolve_python():
|
|
11
|
+
# Echoes the interpreter path and returns 0 when a provisioned ArkaOS
|
|
12
|
+
# interpreter is found; echoes a best-effort fallback and returns 1 when
|
|
13
|
+
# only a bare `python3` remains (caller degrades gracefully).
|
|
14
|
+
#
|
|
15
|
+
# Resolution order:
|
|
16
|
+
# 1. $ARKAOS_PYTHON (explicit operator override), if executable.
|
|
17
|
+
# 2. The ArkaOS venv — ~/.arkaos/venv then ~/.arkaos/.venv, python then
|
|
18
|
+
# python3. `[ -x ]` follows symlinks, so a Homebrew-rotated broken
|
|
19
|
+
# symlink is skipped automatically.
|
|
20
|
+
# 3. Any python3 on PATH / known locations that can `import yaml`.
|
|
21
|
+
# 4. Bare `python3` as a last resort (return 1).
|
|
22
|
+
|
|
23
|
+
arka_resolve_python() {
|
|
24
|
+
local cand
|
|
25
|
+
|
|
26
|
+
if [ -n "${ARKAOS_PYTHON:-}" ] && [ -x "${ARKAOS_PYTHON}" ]; then
|
|
27
|
+
printf '%s\n' "${ARKAOS_PYTHON}"
|
|
28
|
+
return 0
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
for cand in \
|
|
32
|
+
"$HOME/.arkaos/venv/bin/python" \
|
|
33
|
+
"$HOME/.arkaos/venv/bin/python3" \
|
|
34
|
+
"$HOME/.arkaos/.venv/bin/python" \
|
|
35
|
+
"$HOME/.arkaos/.venv/bin/python3"; do
|
|
36
|
+
if [ -x "$cand" ]; then
|
|
37
|
+
printf '%s\n' "$cand"
|
|
38
|
+
return 0
|
|
39
|
+
fi
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
for cand in python3 /opt/homebrew/bin/python3 /usr/local/bin/python3 /usr/bin/python3; do
|
|
43
|
+
if command -v "$cand" >/dev/null 2>&1 && "$cand" -c "import yaml" >/dev/null 2>&1; then
|
|
44
|
+
printf '%s\n' "$cand"
|
|
45
|
+
return 0
|
|
46
|
+
fi
|
|
47
|
+
done
|
|
48
|
+
|
|
49
|
+
printf '%s\n' "python3"
|
|
50
|
+
return 1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# Sourcing this file exports ARKA_PY once, so hooks can `exec "$ARKA_PY" ...`
|
|
54
|
+
# without each re-running the probe. Callers that need the return code call
|
|
55
|
+
# arka_resolve_python directly.
|
|
56
|
+
#
|
|
57
|
+
# `|| true` is REQUIRED: arka_resolve_python returns 1 on the last-resort
|
|
58
|
+
# fallback, and under `set -e` a failing command substitution in an
|
|
59
|
+
# assignment aborts the sourcing file mid-way (reproduced on bash 3.2.57).
|
|
60
|
+
# We still want ARKA_PY set to the fallback value, so swallow the status and
|
|
61
|
+
# keep the export unconditional.
|
|
62
|
+
ARKA_PY="$(arka_resolve_python)" || true
|
|
63
|
+
export ARKA_PY
|
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
set -euo pipefail
|
|
9
9
|
|
|
10
|
+
# ─── Shared Python resolver (exports ARKA_PY) ──────────────────────────
|
|
11
|
+
# The resolver guards its own ARKA_PY assignment with `|| true`, so sourcing
|
|
12
|
+
# is set -e-safe even on the last-resort fallback. The trailing `|| true`
|
|
13
|
+
# here is belt-and-suspenders for a partially-updated lib.
|
|
14
|
+
_ARKA_LIB="$(dirname "${BASH_SOURCE[0]:-$0}")/_lib/arka_python.sh"
|
|
15
|
+
if [ -f "$_ARKA_LIB" ]; then . "$_ARKA_LIB" || true; else ARKA_PY="python3"; fi
|
|
16
|
+
|
|
10
17
|
# Hook contract: stdin is a JSON payload with fields tool_name + tool_input.
|
|
11
18
|
payload="$(cat)"
|
|
12
19
|
|
|
@@ -44,7 +51,7 @@ fi
|
|
|
44
51
|
if [ -d "$core_root/departments" ]; then
|
|
45
52
|
mkdir -p "$project_agents_dir"
|
|
46
53
|
set +e
|
|
47
|
-
|
|
54
|
+
"$ARKA_PY" - "$core_root" "$subagent_type" "$target" <<'PY'
|
|
48
55
|
import os, re, sys
|
|
49
56
|
from pathlib import Path
|
|
50
57
|
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
input=$(cat)
|
|
9
9
|
NEW_CWD=$(echo "$input" | jq -r '.cwd // ""' 2>/dev/null)
|
|
10
10
|
|
|
11
|
+
# ─── Shared Python resolver (exports ARKA_PY) ──────────────────────────
|
|
12
|
+
_ARKA_LIB="$(dirname "${BASH_SOURCE[0]:-$0}")/_lib/arka_python.sh"
|
|
13
|
+
if [ -f "$_ARKA_LIB" ]; then . "$_ARKA_LIB"; else ARKA_PY="python3"; fi
|
|
14
|
+
|
|
11
15
|
if [ -z "$NEW_CWD" ] || [ ! -d "$NEW_CWD" ]; then
|
|
12
16
|
exit 0
|
|
13
17
|
fi
|
|
@@ -23,8 +27,8 @@ fi
|
|
|
23
27
|
ECOSYSTEM=""
|
|
24
28
|
ECOSYSTEM_NAME=""
|
|
25
29
|
|
|
26
|
-
if [ -f "$ECOSYSTEMS_FILE" ] && command -v
|
|
27
|
-
eval "$(
|
|
30
|
+
if [ -f "$ECOSYSTEMS_FILE" ] && command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
31
|
+
eval "$("$ARKA_PY" -c "
|
|
28
32
|
import json, os, sys
|
|
29
33
|
|
|
30
34
|
cwd = '$NEW_CWD'
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
input=$(cat)
|
|
9
9
|
|
|
10
|
+
# ─── Shared Python resolver (exports ARKA_PY) ──────────────────────────
|
|
11
|
+
_ARKA_LIB="$(dirname "${BASH_SOURCE[0]:-$0}")/_lib/arka_python.sh"
|
|
12
|
+
if [ -f "$_ARKA_LIB" ]; then . "$_ARKA_LIB"; else ARKA_PY="python3"; fi
|
|
13
|
+
|
|
10
14
|
ARKAOS_HOME="${HOME}/.arkaos"
|
|
11
15
|
GOTCHAS_FILE="$ARKAOS_HOME/gotchas.json"
|
|
12
16
|
|
|
@@ -74,8 +78,8 @@ project=$(basename "$cwd")
|
|
|
74
78
|
echo "[]" > "$GOTCHAS_FILE"
|
|
75
79
|
fi
|
|
76
80
|
|
|
77
|
-
if command -v
|
|
78
|
-
|
|
81
|
+
if command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
82
|
+
"$ARKA_PY" -c "
|
|
79
83
|
import json, sys
|
|
80
84
|
try:
|
|
81
85
|
with open('$GOTCHAS_FILE') as f:
|
|
@@ -31,7 +31,11 @@ if [ -z "${ARKAOS_ROOT:-}" ]; then
|
|
|
31
31
|
fi
|
|
32
32
|
export ARKAOS_ROOT
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
# ─── Shared Python resolver (exports ARKA_PY) ──────────────────────────
|
|
35
|
+
_ARKA_LIB="$(dirname "${BASH_SOURCE[0]:-$0}")/_lib/arka_python.sh"
|
|
36
|
+
if [ -f "$_ARKA_LIB" ]; then . "$_ARKA_LIB"; else ARKA_PY="python3"; fi
|
|
37
|
+
|
|
38
|
+
if ! command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
35
39
|
echo '{}'
|
|
36
40
|
exit 0
|
|
37
41
|
fi
|
|
@@ -49,20 +53,7 @@ if [ ! -f "$ARKAOS_ROOT/core/hooks/post_tool_use.py" ]; then
|
|
|
49
53
|
fi
|
|
50
54
|
fi
|
|
51
55
|
|
|
52
|
-
# Interpreter resolution
|
|
53
|
-
#
|
|
54
|
-
# python3 without yaml and silently degrade every gate.
|
|
55
|
-
_PY=""
|
|
56
|
-
for _cand in "$HOME/.arkaos/venv/bin/python3" "$HOME/.arkaos/.venv/bin/python3"; do
|
|
57
|
-
if [ -x "$_cand" ]; then _PY="$_cand"; break; fi
|
|
58
|
-
done
|
|
59
|
-
if [ -z "$_PY" ]; then
|
|
60
|
-
_PY="python3"
|
|
61
|
-
if ! "$_PY" -c "import yaml" 2>/dev/null; then
|
|
62
|
-
for _cand in /opt/homebrew/bin/python3 /usr/local/bin/python3 /usr/bin/python3; do
|
|
63
|
-
if [ -x "$_cand" ] && "$_cand" -c "import yaml" 2>/dev/null; then _PY="$_cand"; break; fi
|
|
64
|
-
done
|
|
65
|
-
fi
|
|
66
|
-
fi
|
|
56
|
+
# Interpreter resolution handled by the shared resolver (ARKA_PY): prefers
|
|
57
|
+
# the ArkaOS venv (has pyyaml/pydantic), falls back to a yaml-capable python3.
|
|
67
58
|
PYTHONPATH="$ARKAOS_ROOT${PYTHONPATH:+:$PYTHONPATH}" \
|
|
68
|
-
exec "$
|
|
59
|
+
exec "$ARKA_PY" -m core.hooks.post_tool_use
|
|
@@ -39,9 +39,11 @@ if ([string]::IsNullOrWhiteSpace($env:ARKAOS_ROOT)) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (-
|
|
42
|
+
# Shared resolver (venv-first, yaml-verified). Mirrors _lib/arka_python.sh.
|
|
43
|
+
$arkaLib = Join-Path $PSScriptRoot "_lib\arka_python.ps1"
|
|
44
|
+
if (Test-Path -LiteralPath $arkaLib) { . $arkaLib }
|
|
45
|
+
$pythonExe = $env:ARKA_PY
|
|
46
|
+
if (-not $pythonExe) { exit 0 }
|
|
45
47
|
|
|
46
48
|
# --- KB-first gate (Task #6, runs before flow-marker gate) ---
|
|
47
49
|
$queryHint = ""
|
|
@@ -91,7 +93,7 @@ print(json.dumps({
|
|
|
91
93
|
}))
|
|
92
94
|
'@
|
|
93
95
|
|
|
94
|
-
$kbDecisionJson = $kbScript | & $
|
|
96
|
+
$kbDecisionJson = $kbScript | & $pythonExe -
|
|
95
97
|
if (-not [string]::IsNullOrWhiteSpace($kbDecisionJson)) {
|
|
96
98
|
try {
|
|
97
99
|
$kbDecision = $kbDecisionJson | ConvertFrom-Json
|
|
@@ -172,7 +174,7 @@ print(json.dumps({
|
|
|
172
174
|
}))
|
|
173
175
|
'@
|
|
174
176
|
|
|
175
|
-
$spDecisionJson = $spScript | & $
|
|
177
|
+
$spDecisionJson = $spScript | & $pythonExe -
|
|
176
178
|
if (-not [string]::IsNullOrWhiteSpace($spDecisionJson)) {
|
|
177
179
|
try {
|
|
178
180
|
$spDecision = $spDecisionJson | ConvertFrom-Json
|
|
@@ -241,7 +243,7 @@ print(json.dumps({
|
|
|
241
243
|
}))
|
|
242
244
|
'@
|
|
243
245
|
|
|
244
|
-
$decisionJson = $pyScript | & $
|
|
246
|
+
$decisionJson = $pyScript | & $pythonExe -
|
|
245
247
|
if ([string]::IsNullOrWhiteSpace($decisionJson)) { exit 0 }
|
|
246
248
|
|
|
247
249
|
try {
|
|
@@ -34,8 +34,12 @@ if [ -z "${ARKAOS_ROOT:-}" ]; then
|
|
|
34
34
|
fi
|
|
35
35
|
export ARKAOS_ROOT
|
|
36
36
|
|
|
37
|
+
# ─── Shared Python resolver (exports ARKA_PY) ──────────────────────────
|
|
38
|
+
_ARKA_LIB="$(dirname "${BASH_SOURCE[0]:-$0}")/_lib/arka_python.sh"
|
|
39
|
+
if [ -f "$_ARKA_LIB" ]; then . "$_ARKA_LIB"; else ARKA_PY="python3"; fi
|
|
40
|
+
|
|
37
41
|
# ─── Degrade gracefully (fail open, same as before) ─────────────────────
|
|
38
|
-
if ! command -v
|
|
42
|
+
if ! command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
39
43
|
exit 0
|
|
40
44
|
fi
|
|
41
45
|
# Self-root fallback: the wrapper ships next to its python entrypoint, so
|
|
@@ -52,20 +56,7 @@ if [ ! -f "$ARKAOS_ROOT/core/hooks/pre_tool_use.py" ]; then
|
|
|
52
56
|
fi
|
|
53
57
|
|
|
54
58
|
# ─── Single python process; stdin/stdout/stderr/exit-code pass through ──
|
|
55
|
-
# Interpreter resolution
|
|
56
|
-
#
|
|
57
|
-
# python3 without yaml and silently degrade every gate.
|
|
58
|
-
_PY=""
|
|
59
|
-
for _cand in "$HOME/.arkaos/venv/bin/python3" "$HOME/.arkaos/.venv/bin/python3"; do
|
|
60
|
-
if [ -x "$_cand" ]; then _PY="$_cand"; break; fi
|
|
61
|
-
done
|
|
62
|
-
if [ -z "$_PY" ]; then
|
|
63
|
-
_PY="python3"
|
|
64
|
-
if ! "$_PY" -c "import yaml" 2>/dev/null; then
|
|
65
|
-
for _cand in /opt/homebrew/bin/python3 /usr/local/bin/python3 /usr/bin/python3; do
|
|
66
|
-
if [ -x "$_cand" ] && "$_cand" -c "import yaml" 2>/dev/null; then _PY="$_cand"; break; fi
|
|
67
|
-
done
|
|
68
|
-
fi
|
|
69
|
-
fi
|
|
59
|
+
# Interpreter resolution handled by the shared resolver (ARKA_PY): prefers
|
|
60
|
+
# the ArkaOS venv (has pyyaml/pydantic), falls back to a yaml-capable python3.
|
|
70
61
|
PYTHONPATH="$ARKAOS_ROOT${PYTHONPATH:+:$PYTHONPATH}" \
|
|
71
|
-
exec "$
|
|
62
|
+
exec "$ARKA_PY" -m core.hooks.pre_tool_use
|
|
@@ -9,9 +9,13 @@ NAME="founder"
|
|
|
9
9
|
COMPANY="WizardingCode"
|
|
10
10
|
VERSION="2.x"
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
# ─── Shared Python resolver (exports ARKA_PY) ──────────────────────────
|
|
13
|
+
_ARKA_LIB="$(dirname "${BASH_SOURCE[0]:-$0}")/_lib/arka_python.sh"
|
|
14
|
+
if [ -f "$_ARKA_LIB" ]; then . "$_ARKA_LIB"; else ARKA_PY="python3"; fi
|
|
15
|
+
|
|
16
|
+
if [ -f "$HOME/.arkaos/profile.json" ] && command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
17
|
+
NAME=$("$ARKA_PY" -c "import json; p=json.load(open('$HOME/.arkaos/profile.json')); print(p.get('name', p.get('role', 'founder')))" 2>/dev/null || echo "founder")
|
|
18
|
+
COMPANY=$("$ARKA_PY" -c "import json; print(json.load(open('$HOME/.arkaos/profile.json')).get('company', 'WizardingCode'))" 2>/dev/null || echo "WizardingCode")
|
|
15
19
|
fi
|
|
16
20
|
|
|
17
21
|
if [ -f "$HOME/.arkaos/.repo-path" ]; then
|
|
@@ -29,7 +33,7 @@ SYNC_STATE="$HOME/.arkaos/sync-state.json"
|
|
|
29
33
|
DRIFT=""
|
|
30
34
|
|
|
31
35
|
if [ -f "$SYNC_STATE" ]; then
|
|
32
|
-
SYNCED=$(
|
|
36
|
+
SYNCED=$("$ARKA_PY" -c "import json; print(json.load(open('$SYNC_STATE'))['version'])" 2>/dev/null || echo "none")
|
|
33
37
|
if [ "$SYNCED" != "$VERSION" ]; then
|
|
34
38
|
DRIFT="\\n[arka:update-available] Core v${VERSION} != synced v${SYNCED}. Run /arka update."
|
|
35
39
|
fi
|
|
@@ -71,11 +75,11 @@ _FORGE_LINE=""
|
|
|
71
75
|
if [ -f "$_FORGE_ACTIVE" ]; then
|
|
72
76
|
_FORGE_ID=$(cat "$_FORGE_ACTIVE" 2>/dev/null)
|
|
73
77
|
_FORGE_FILE="$_FORGE_PLANS/${_FORGE_ID}.yaml"
|
|
74
|
-
if [ -f "$_FORGE_FILE" ] && command -v
|
|
75
|
-
_FORGE_NAME=$(FORGE_FILE="$_FORGE_FILE"
|
|
76
|
-
_FORGE_STATUS=$(FORGE_FILE="$_FORGE_FILE"
|
|
77
|
-
_FORGE_PHASES=$(FORGE_FILE="$_FORGE_FILE"
|
|
78
|
-
_FORGE_BRANCH=$(FORGE_FILE="$_FORGE_FILE"
|
|
78
|
+
if [ -f "$_FORGE_FILE" ] && command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
79
|
+
_FORGE_NAME=$(FORGE_FILE="$_FORGE_FILE" "$ARKA_PY" -c "import yaml,os; d=yaml.safe_load(open(os.environ['FORGE_FILE'])); print(d.get('name',''))" 2>/dev/null)
|
|
80
|
+
_FORGE_STATUS=$(FORGE_FILE="$_FORGE_FILE" "$ARKA_PY" -c "import yaml,os; d=yaml.safe_load(open(os.environ['FORGE_FILE'])); print(d.get('status',''))" 2>/dev/null)
|
|
81
|
+
_FORGE_PHASES=$(FORGE_FILE="$_FORGE_FILE" "$ARKA_PY" -c "import yaml,os; d=yaml.safe_load(open(os.environ['FORGE_FILE'])); print(len(d.get('plan_phases',[])))" 2>/dev/null)
|
|
82
|
+
_FORGE_BRANCH=$(FORGE_FILE="$_FORGE_FILE" "$ARKA_PY" -c "import yaml,os; d=yaml.safe_load(open(os.environ['FORGE_FILE'])); print(d.get('governance',{}).get('branch_strategy',''))" 2>/dev/null)
|
|
79
83
|
|
|
80
84
|
if [ "$_FORGE_STATUS" = "approved" ]; then
|
|
81
85
|
_FORGE_LINE=" ⚒ Forge plan pending: ${_FORGE_NAME} | Phases: ${_FORGE_PHASES} | /forge resume"
|
|
@@ -110,12 +114,10 @@ MSG+="\\nAbsence is measured by the Stop hook (warn-only in v2.34.0) before prom
|
|
|
110
114
|
# dashboard/CLI model choices actually govern agent dispatch. Cheap
|
|
111
115
|
# (single python read); skipped silently if the config can't be resolved.
|
|
112
116
|
if [ -n "$REPO" ]; then
|
|
113
|
-
#
|
|
114
|
-
# python3 usually lacks them and routing_directive() would return "".
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if command -v "$_MF_PY" &>/dev/null || [ -x "$_MF_PY" ]; then
|
|
118
|
-
_MF_DIRECTIVE=$(cd "$REPO" && PYTHONPATH="$REPO" "$_MF_PY" -c "
|
|
117
|
+
# ARKA_PY already resolves to the venv python (has pydantic + yaml); the
|
|
118
|
+
# ambient python3 usually lacks them and routing_directive() would return "".
|
|
119
|
+
if command -v "$ARKA_PY" >/dev/null 2>&1 || [ -x "$ARKA_PY" ]; then
|
|
120
|
+
_MF_DIRECTIVE=$(cd "$REPO" && PYTHONPATH="$REPO" "$ARKA_PY" -c "
|
|
119
121
|
try:
|
|
120
122
|
from core.runtime.model_routing_context import routing_directive
|
|
121
123
|
print(routing_directive())
|
|
@@ -132,12 +134,12 @@ fi
|
|
|
132
134
|
# If today's proposal file is missing, fire the reorganizer in the
|
|
133
135
|
# background with a 30s timeout. Best-effort, never blocks session
|
|
134
136
|
# start. Multiple sessions per day no-op because the file now exists.
|
|
135
|
-
if [ -n "$REPO" ] && command -v
|
|
137
|
+
if [ -n "$REPO" ] && command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
136
138
|
_PROPOSAL_DIR="$HOME/.arkaos/reorganize-proposals"
|
|
137
139
|
_TODAY="$(date -u +%Y-%m-%d).md"
|
|
138
140
|
if [ ! -f "$_PROPOSAL_DIR/$_TODAY" ]; then
|
|
139
141
|
(
|
|
140
|
-
cd "$REPO" && timeout 30s
|
|
142
|
+
cd "$REPO" && timeout 30s "$ARKA_PY" -m core.cognition.reorganizer_cli >/dev/null 2>&1
|
|
141
143
|
) &
|
|
142
144
|
disown 2>/dev/null || true
|
|
143
145
|
fi
|
|
@@ -149,7 +151,7 @@ fi
|
|
|
149
151
|
# starts API+UI. Background + disown so it never touches the 5s budget.
|
|
150
152
|
# Toggle off: ~/.arkaos/config.json -> {"dashboard": {"ensure_on_session": false}}
|
|
151
153
|
if [ -n "$REPO" ] && [ -f "$REPO/scripts/start-dashboard.sh" ]; then
|
|
152
|
-
_DASH_ENSURE=$(
|
|
154
|
+
_DASH_ENSURE=$("$ARKA_PY" -c "import json; print(json.load(open('$HOME/.arkaos/config.json')).get('dashboard',{}).get('ensure_on_session', True))" 2>/dev/null || echo "True")
|
|
153
155
|
if [ "$_DASH_ENSURE" = "True" ] || [ "$_DASH_ENSURE" = "true" ]; then
|
|
154
156
|
mkdir -p "$HOME/.arkaos/logs"
|
|
155
157
|
(
|
|
@@ -166,8 +168,8 @@ if [ -n "$REPO" ] && [ -f "$REPO/scripts/start-dashboard.sh" ]; then
|
|
|
166
168
|
fi
|
|
167
169
|
|
|
168
170
|
# --- Session Memory Resume Context ---
|
|
169
|
-
if command -v
|
|
170
|
-
_SESSION_CTX=$(cd "$REPO" &&
|
|
171
|
+
if command -v "$ARKA_PY" >/dev/null 2>&1 && [ -n "$REPO" ]; then
|
|
172
|
+
_SESSION_CTX=$(cd "$REPO" && "$ARKA_PY" -c "
|
|
171
173
|
import sys
|
|
172
174
|
sys.path.insert(0, '$REPO')
|
|
173
175
|
try:
|
|
@@ -182,7 +184,7 @@ except Exception:
|
|
|
182
184
|
fi
|
|
183
185
|
|
|
184
186
|
# ─── Output as systemMessage (same protocol as claude-mem) ─────────────
|
|
185
|
-
|
|
187
|
+
"$ARKA_PY" -c "
|
|
186
188
|
import json
|
|
187
189
|
msg = '''$(echo -e "$MSG")'''
|
|
188
190
|
print(json.dumps({'systemMessage': msg}))
|
package/config/hooks/stop.ps1
CHANGED
|
@@ -43,9 +43,11 @@ if ([string]::IsNullOrWhiteSpace($env:ARKAOS_ROOT)) {
|
|
|
43
43
|
$enforcerPy = Join-Path $env:ARKAOS_ROOT "core/workflow/flow_enforcer.py"
|
|
44
44
|
if (-not (Test-Path $enforcerPy)) { exit 0 }
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (-
|
|
46
|
+
# Shared resolver (venv-first, yaml-verified). Mirrors _lib/arka_python.sh.
|
|
47
|
+
$arkaLib = Join-Path $PSScriptRoot "_lib\arka_python.ps1"
|
|
48
|
+
if (Test-Path -LiteralPath $arkaLib) { . $arkaLib }
|
|
49
|
+
$pythonExe = $env:ARKA_PY
|
|
50
|
+
if (-not $pythonExe) { exit 0 }
|
|
49
51
|
|
|
50
52
|
$env:SESSION_ID_VAL = $sessionId
|
|
51
53
|
$env:TRANSCRIPT_PATH_VAL = $transcriptPath
|
|
@@ -102,7 +104,7 @@ except Exception:
|
|
|
102
104
|
pass
|
|
103
105
|
'@
|
|
104
106
|
|
|
105
|
-
$pyScript | & $
|
|
107
|
+
$pyScript | & $pythonExe - | Out-Null
|
|
106
108
|
|
|
107
109
|
# ─── Auto-documentor enqueue (fire-and-forget) ─────────────────────────
|
|
108
110
|
# Queues a background job when classifier flagged flow, QG approved, and
|
|
@@ -178,7 +180,7 @@ except Exception:
|
|
|
178
180
|
'@
|
|
179
181
|
|
|
180
182
|
try {
|
|
181
|
-
$autoDocScript | & $
|
|
183
|
+
$autoDocScript | & $pythonExe - | Out-Null
|
|
182
184
|
} catch {
|
|
183
185
|
# Swallow — enqueue is fire-and-forget.
|
|
184
186
|
}
|
package/config/hooks/stop.sh
CHANGED
|
@@ -33,7 +33,11 @@ if [ -z "${ARKAOS_ROOT:-}" ]; then
|
|
|
33
33
|
fi
|
|
34
34
|
export ARKAOS_ROOT
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
# ─── Shared Python resolver (exports ARKA_PY) ──────────────────────────
|
|
37
|
+
_ARKA_LIB="$(dirname "${BASH_SOURCE[0]:-$0}")/_lib/arka_python.sh"
|
|
38
|
+
if [ -f "$_ARKA_LIB" ]; then . "$_ARKA_LIB"; else ARKA_PY="python3"; fi
|
|
39
|
+
|
|
40
|
+
if ! command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
37
41
|
exit 0
|
|
38
42
|
fi
|
|
39
43
|
# Self-root fallback: the wrapper ships next to its python entrypoint, so
|
|
@@ -49,21 +53,8 @@ if [ ! -f "$ARKAOS_ROOT/core/hooks/stop.py" ]; then
|
|
|
49
53
|
fi
|
|
50
54
|
fi
|
|
51
55
|
|
|
52
|
-
# Interpreter resolution
|
|
53
|
-
#
|
|
54
|
-
# python3 without yaml and silently degrade every gate.
|
|
55
|
-
_PY=""
|
|
56
|
-
for _cand in "$HOME/.arkaos/venv/bin/python3" "$HOME/.arkaos/.venv/bin/python3"; do
|
|
57
|
-
if [ -x "$_cand" ]; then _PY="$_cand"; break; fi
|
|
58
|
-
done
|
|
59
|
-
if [ -z "$_PY" ]; then
|
|
60
|
-
_PY="python3"
|
|
61
|
-
if ! "$_PY" -c "import yaml" 2>/dev/null; then
|
|
62
|
-
for _cand in /opt/homebrew/bin/python3 /usr/local/bin/python3 /usr/bin/python3; do
|
|
63
|
-
if [ -x "$_cand" ] && "$_cand" -c "import yaml" 2>/dev/null; then _PY="$_cand"; break; fi
|
|
64
|
-
done
|
|
65
|
-
fi
|
|
66
|
-
fi
|
|
56
|
+
# Interpreter resolution handled by the shared resolver (ARKA_PY): prefers
|
|
57
|
+
# the ArkaOS venv (has pyyaml/pydantic), falls back to a yaml-capable python3.
|
|
67
58
|
PYTHONPATH="$ARKAOS_ROOT${PYTHONPATH:+:$PYTHONPATH}" \
|
|
68
|
-
"$
|
|
59
|
+
"$ARKA_PY" -m core.hooks.stop
|
|
69
60
|
exit 0
|
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
|
|
14
14
|
set +e # never fail
|
|
15
15
|
|
|
16
|
+
# ─── Shared Python resolver (exports ARKA_PY) ──────────────────────────
|
|
17
|
+
_ARKA_LIB="$(dirname "${BASH_SOURCE[0]:-$0}")/_lib/arka_python.sh"
|
|
18
|
+
if [ -f "$_ARKA_LIB" ]; then . "$_ARKA_LIB"; else ARKA_PY="python3"; fi
|
|
19
|
+
|
|
16
20
|
_prompt="${ARKA_PROMPT:-}"
|
|
17
21
|
_transcript="${ARKA_TRANSCRIPT_PATH:-}"
|
|
18
22
|
_suggestions=""
|
|
@@ -64,7 +68,7 @@ if [ -n "$_transcript" ] && [ -f "$_transcript" ] && [ -n "$_prompt" ]; then
|
|
|
64
68
|
_cur_kw=$(_kw "$_prompt" | head -20)
|
|
65
69
|
# pull last 3 user messages from transcript jsonl
|
|
66
70
|
_prior=$(tail -n 200 "$_transcript" 2>/dev/null \
|
|
67
|
-
|
|
|
71
|
+
| "$ARKA_PY" -c "
|
|
68
72
|
import sys, json
|
|
69
73
|
msgs=[]
|
|
70
74
|
for line in sys.stdin:
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
input=$(cat)
|
|
9
9
|
|
|
10
|
+
# ─── Shared Python resolver (exports ARKA_PY) ──────────────────────────
|
|
11
|
+
_ARKA_LIB="$(dirname "${BASH_SOURCE[0]:-$0}")/_lib/arka_python.sh"
|
|
12
|
+
if [ -f "$_ARKA_LIB" ]; then . "$_ARKA_LIB"; else ARKA_PY="python3"; fi
|
|
13
|
+
|
|
10
14
|
# ─── V1 Migration Detection ─────────────────────────────────────────────
|
|
11
15
|
V1_PATHS=("$HOME/.claude/skills/arka-os" "$HOME/.claude/skills/arkaos")
|
|
12
16
|
MIGRATION_MARKER="$HOME/.arkaos/migrated-from-v1"
|
|
@@ -27,12 +31,12 @@ if [ -f "$ARKAOS_VERSION_FILE" ]; then
|
|
|
27
31
|
if [ -f "$_REPO_PATH/VERSION" ]; then
|
|
28
32
|
_CURRENT_VERSION=$(cat "$_REPO_PATH/VERSION")
|
|
29
33
|
elif [ -f "$_REPO_PATH/package.json" ]; then
|
|
30
|
-
_CURRENT_VERSION=$(
|
|
34
|
+
_CURRENT_VERSION=$("$ARKA_PY" -c "import json; print(json.load(open('$_REPO_PATH/package.json'))['version'])" 2>/dev/null || echo "")
|
|
31
35
|
fi
|
|
32
36
|
|
|
33
37
|
if [ -n "${_CURRENT_VERSION:-}" ]; then
|
|
34
38
|
if [ -f "$SYNC_STATE" ]; then
|
|
35
|
-
_SYNCED_VERSION=$(
|
|
39
|
+
_SYNCED_VERSION=$("$ARKA_PY" -c "import json; print(json.load(open('$SYNC_STATE'))['version'])" 2>/dev/null || echo "none")
|
|
36
40
|
else
|
|
37
41
|
_SYNCED_VERSION="none"
|
|
38
42
|
fi
|
|
@@ -53,9 +57,9 @@ if [ ! -f "$_SESSION_MARKER" ] && [ ! -f "/tmp/arkaos-greeted-today" ]; then
|
|
|
53
57
|
_GREETING_COMPANY=""
|
|
54
58
|
_GREETING_VERSION=""
|
|
55
59
|
|
|
56
|
-
if [ -f "$HOME/.arkaos/profile.json" ] && command -v
|
|
57
|
-
_GREETING_NAME=$(
|
|
58
|
-
_GREETING_COMPANY=$(
|
|
60
|
+
if [ -f "$HOME/.arkaos/profile.json" ] && command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
61
|
+
_GREETING_NAME=$("$ARKA_PY" -c "import json; p=json.load(open('$HOME/.arkaos/profile.json')); print(p.get('name', p.get('role', 'founder')))" 2>/dev/null)
|
|
62
|
+
_GREETING_COMPANY=$("$ARKA_PY" -c "import json; print(json.load(open('$HOME/.arkaos/profile.json')).get('company', ''))" 2>/dev/null)
|
|
59
63
|
fi
|
|
60
64
|
|
|
61
65
|
if [ -f "$HOME/.arkaos/.repo-path" ]; then
|
|
@@ -111,12 +115,12 @@ fi
|
|
|
111
115
|
python_result=""
|
|
112
116
|
BRIDGE_SCRIPT="${ARKAOS_ROOT}/scripts/synapse-bridge.py"
|
|
113
117
|
|
|
114
|
-
if command -v
|
|
115
|
-
bridge_output=$(echo "{\"user_input\":$(echo "$user_input" |
|
|
116
|
-
| ARKAOS_ROOT="$ARKAOS_ROOT"
|
|
118
|
+
if command -v "$ARKA_PY" >/dev/null 2>&1 && [ -f "$BRIDGE_SCRIPT" ]; then
|
|
119
|
+
bridge_output=$(echo "{\"user_input\":$(echo "$user_input" | "$ARKA_PY" -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo '""')}" \
|
|
120
|
+
| ARKAOS_ROOT="$ARKAOS_ROOT" "$ARKA_PY" "$BRIDGE_SCRIPT" --root "$ARKAOS_ROOT" 2>/dev/null)
|
|
117
121
|
|
|
118
122
|
if [ -n "$bridge_output" ]; then
|
|
119
|
-
python_result=$(echo "$bridge_output" |
|
|
123
|
+
python_result=$(echo "$bridge_output" | "$ARKA_PY" -c "import sys,json; print(json.loads(sys.stdin.read()).get('context_string',''))" 2>/dev/null)
|
|
120
124
|
fi
|
|
121
125
|
fi
|
|
122
126
|
|
|
@@ -34,9 +34,13 @@ if [ -z "${ARKAOS_ROOT:-}" ]; then
|
|
|
34
34
|
fi
|
|
35
35
|
export ARKAOS_ROOT
|
|
36
36
|
|
|
37
|
+
# ─── Shared Python resolver (exports ARKA_PY) ──────────────────────────
|
|
38
|
+
_ARKA_LIB="$(dirname "${BASH_SOURCE[0]:-$0}")/_lib/arka_python.sh"
|
|
39
|
+
if [ -f "$_ARKA_LIB" ]; then . "$_ARKA_LIB"; else ARKA_PY="python3"; fi
|
|
40
|
+
|
|
37
41
|
_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"}'
|
|
38
42
|
|
|
39
|
-
if ! command -v
|
|
43
|
+
if ! command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
40
44
|
echo "$_ARKA_L0_FALLBACK"
|
|
41
45
|
exit 0
|
|
42
46
|
fi
|
|
@@ -54,20 +58,7 @@ if [ ! -f "$ARKAOS_ROOT/core/hooks/user_prompt_submit.py" ]; then
|
|
|
54
58
|
fi
|
|
55
59
|
fi
|
|
56
60
|
|
|
57
|
-
# Interpreter resolution
|
|
58
|
-
#
|
|
59
|
-
# python3 without yaml and silently degrade every gate.
|
|
60
|
-
_PY=""
|
|
61
|
-
for _cand in "$HOME/.arkaos/venv/bin/python3" "$HOME/.arkaos/.venv/bin/python3"; do
|
|
62
|
-
if [ -x "$_cand" ]; then _PY="$_cand"; break; fi
|
|
63
|
-
done
|
|
64
|
-
if [ -z "$_PY" ]; then
|
|
65
|
-
_PY="python3"
|
|
66
|
-
if ! "$_PY" -c "import yaml" 2>/dev/null; then
|
|
67
|
-
for _cand in /opt/homebrew/bin/python3 /usr/local/bin/python3 /usr/bin/python3; do
|
|
68
|
-
if [ -x "$_cand" ] && "$_cand" -c "import yaml" 2>/dev/null; then _PY="$_cand"; break; fi
|
|
69
|
-
done
|
|
70
|
-
fi
|
|
71
|
-
fi
|
|
61
|
+
# Interpreter resolution handled by the shared resolver (ARKA_PY): prefers
|
|
62
|
+
# the ArkaOS venv (has pyyaml/pydantic), falls back to a yaml-capable python3.
|
|
72
63
|
PYTHONPATH="$ARKAOS_ROOT${PYTHONPATH:+:$PYTHONPATH}" \
|
|
73
|
-
exec "$
|
|
64
|
+
exec "$ARKA_PY" -m core.hooks.user_prompt_submit
|
|
Binary file
|
|
Binary file
|
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
# Dependencies: jq (required)
|
|
6
6
|
# ============================================================================
|
|
7
7
|
|
|
8
|
+
# ─── Shared Python resolver (exports ARKA_PY) ──────────────────────────
|
|
9
|
+
# The lib is not a sibling here; try the in-repo path then the installed tree.
|
|
10
|
+
for _l in "$(dirname "${BASH_SOURCE[0]:-$0}")/../../config/hooks/_lib/arka_python.sh" "$HOME/.arkaos/config/hooks/_lib/arka_python.sh"; do
|
|
11
|
+
if [ -f "$_l" ]; then . "$_l"; break; fi
|
|
12
|
+
done
|
|
13
|
+
: "${ARKA_PY:=python3}"
|
|
14
|
+
|
|
8
15
|
STATE_FILE="$HOME/.arkaos/workflow-state.json"
|
|
9
16
|
|
|
10
17
|
if [ ! -f "$STATE_FILE" ]; then
|
|
@@ -73,11 +80,11 @@ case "$CMD" in
|
|
|
73
80
|
echo "none"
|
|
74
81
|
exit 0
|
|
75
82
|
fi
|
|
76
|
-
if command -v
|
|
77
|
-
_F_NAME=$(FORGE_FILE="$_FORGE_FILE"
|
|
78
|
-
_F_STATUS=$(FORGE_FILE="$_FORGE_FILE"
|
|
79
|
-
_F_PHASES=$(FORGE_FILE="$_FORGE_FILE"
|
|
80
|
-
_F_BRANCH=$(FORGE_FILE="$_FORGE_FILE"
|
|
83
|
+
if command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
84
|
+
_F_NAME=$(FORGE_FILE="$_FORGE_FILE" "$ARKA_PY" -c "import yaml,os; d=yaml.safe_load(open(os.environ['FORGE_FILE'])); print(d.get('name',''))" 2>/dev/null)
|
|
85
|
+
_F_STATUS=$(FORGE_FILE="$_FORGE_FILE" "$ARKA_PY" -c "import yaml,os; d=yaml.safe_load(open(os.environ['FORGE_FILE'])); print(d.get('status',''))" 2>/dev/null)
|
|
86
|
+
_F_PHASES=$(FORGE_FILE="$_FORGE_FILE" "$ARKA_PY" -c "import yaml,os; d=yaml.safe_load(open(os.environ['FORGE_FILE'])); print(len(d.get('plan_phases',[])))" 2>/dev/null)
|
|
87
|
+
_F_BRANCH=$(FORGE_FILE="$_FORGE_FILE" "$ARKA_PY" -c "import yaml,os; d=yaml.safe_load(open(os.environ['FORGE_FILE'])); print(d.get('governance',{}).get('branch_strategy',''))" 2>/dev/null)
|
|
81
88
|
echo "${_FORGE_ID}|${_F_NAME}|${_F_STATUS}|${_F_PHASES}|${_F_BRANCH}"
|
|
82
89
|
else
|
|
83
90
|
echo "${_FORGE_ID}|||0|"
|
|
@@ -23,7 +23,7 @@ Hybrid sync engine: Python handles deterministic operations (MCPs, settings, des
|
|
|
23
23
|
|
|
24
24
|
1. **One-stop: npm refresh + engine (PR61 v2.78.0 orchestrator).**
|
|
25
25
|
```bash
|
|
26
|
-
cd $ARKAOS_ROOT &&
|
|
26
|
+
cd $ARKAOS_ROOT && ~/.arkaos/bin/arka-py -m core.sync.update_orchestrator --home ~/.arkaos --skills ~/.claude/skills --output json
|
|
27
27
|
```
|
|
28
28
|
The orchestrator detects whether the running ArkaOS is behind npm
|
|
29
29
|
latest. When stale, it shells out to `npx arkaos@latest update`
|
|
@@ -38,7 +38,7 @@ Hybrid sync engine: Python handles deterministic operations (MCPs, settings, des
|
|
|
38
38
|
silently skips the npm step and falls through to the engine.
|
|
39
39
|
|
|
40
40
|
Fallback (no orchestrator): the underlying engine still runs the
|
|
41
|
-
same way via
|
|
41
|
+
same way via `~/.arkaos/bin/arka-py -m core.sync.engine ...` for callers that
|
|
42
42
|
don't need the version-drift gate.
|
|
43
43
|
|
|
44
44
|
2. **Phase 4 (intelligent, AI subagent):** After the engine completes, dispatch ONE subagent with the engine's JSON report + the feature registry (`core/sync/features/*.yaml`). The subagent injects/removes feature sections in each `~/.claude/skills/arka-{ecosystem}/SKILL.md` while preserving all custom content.
|
|
@@ -7,7 +7,7 @@ Referenced from SKILL.md. Read only when needed.
|
|
|
7
7
|
Run the sync engine from the ArkaOS repo root:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
cd $ARKAOS_ROOT &&
|
|
10
|
+
cd $ARKAOS_ROOT && ~/.arkaos/bin/arka-py -m core.sync.engine --home ~/.arkaos --skills ~/.claude/skills --output json
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
The engine handles deterministic operations and returns a JSON report.
|
|
@@ -24,7 +24,7 @@ Any Department Workflow:
|
|
|
24
24
|
...
|
|
25
25
|
Phase N-1: QUALITY GATE
|
|
26
26
|
1. Run the evidence engine over the project/diff:
|
|
27
|
-
|
|
27
|
+
~/.arkaos/bin/arka-py -m core.governance.evidence_checks <project_dir> \
|
|
28
28
|
[--changed-files f1,f2] [--test-command '...'] --json
|
|
29
29
|
2. Marta dispatches Eduardo + Francisca to INTERPRET the report:
|
|
30
30
|
- Eduardo: spellcheck section + prose review of changed copy
|
package/installer/index.js
CHANGED
|
@@ -165,6 +165,12 @@ export async function install({ runtime, path, force, skipSystem, withOllama })
|
|
|
165
165
|
copyFileSync(cmdSrc, join(binDir, "arka-claude.cmd"));
|
|
166
166
|
installed = true;
|
|
167
167
|
}
|
|
168
|
+
// arka-py — the ArkaOS Python entrypoint SKILL.md commands invoke.
|
|
169
|
+
const pyPsSrc = join(ARKAOS_ROOT, "bin", "arka-py.ps1");
|
|
170
|
+
const pyCmdSrc = join(ARKAOS_ROOT, "bin", "arka-py.cmd");
|
|
171
|
+
if (existsSync(pyPsSrc)) copyFileSync(pyPsSrc, join(binDir, "arka-py.ps1"));
|
|
172
|
+
if (existsSync(pyCmdSrc)) copyFileSync(pyCmdSrc, join(binDir, "arka-py.cmd"));
|
|
173
|
+
if (existsSync(pyPsSrc) || existsSync(pyCmdSrc)) ok("arka-py interpreter shim installed (.cmd + .ps1)");
|
|
168
174
|
if (installed) {
|
|
169
175
|
ok("arka-claude wrapper installed (.cmd + .ps1)");
|
|
170
176
|
console.log(` Add to PATH: setx PATH "%PATH%;%USERPROFILE%\\.arkaos\\bin"`);
|
|
@@ -179,6 +185,14 @@ export async function install({ runtime, path, force, skipSystem, withOllama })
|
|
|
179
185
|
console.log(` Add to PATH: export PATH="$HOME/.arkaos/bin:$PATH"`);
|
|
180
186
|
console.log(` Optional alias: alias claude="arka-claude"`);
|
|
181
187
|
}
|
|
188
|
+
// arka-py — the ArkaOS Python entrypoint SKILL.md commands invoke so the
|
|
189
|
+
// agent never runs a bare `python` that lacks ArkaOS deps (pyyaml, ...).
|
|
190
|
+
const arkaPySrc = join(ARKAOS_ROOT, "bin", "arka-py");
|
|
191
|
+
if (existsSync(arkaPySrc)) {
|
|
192
|
+
copyFileSync(arkaPySrc, join(binDir, "arka-py"));
|
|
193
|
+
try { chmodSync(join(binDir, "arka-py"), 0o755); } catch {}
|
|
194
|
+
ok("arka-py interpreter shim installed");
|
|
195
|
+
}
|
|
182
196
|
}
|
|
183
197
|
const claudeMdSrc = join(ARKAOS_ROOT, "config", "user-claude.md");
|
|
184
198
|
const userClaudeMd = join(homedir(), ".claude", "CLAUDE.md");
|
package/installer/update.js
CHANGED
|
@@ -248,6 +248,13 @@ export async function update() {
|
|
|
248
248
|
if (existsSync(psSrc) || existsSync(cmdSrc)) {
|
|
249
249
|
console.log(" ✓ arka-claude wrapper updated (.cmd + .ps1)");
|
|
250
250
|
}
|
|
251
|
+
const pyPsSrc = join(ARKAOS_ROOT, "bin", "arka-py.ps1");
|
|
252
|
+
const pyCmdSrc = join(ARKAOS_ROOT, "bin", "arka-py.cmd");
|
|
253
|
+
if (existsSync(pyPsSrc)) copyFileSync(pyPsSrc, join(binDir, "arka-py.ps1"));
|
|
254
|
+
if (existsSync(pyCmdSrc)) copyFileSync(pyCmdSrc, join(binDir, "arka-py.cmd"));
|
|
255
|
+
if (existsSync(pyPsSrc) || existsSync(pyCmdSrc)) {
|
|
256
|
+
console.log(" ✓ arka-py interpreter shim updated (.cmd + .ps1)");
|
|
257
|
+
}
|
|
251
258
|
} else {
|
|
252
259
|
const wrapperSrc = join(ARKAOS_ROOT, "bin", "arka-claude");
|
|
253
260
|
if (existsSync(wrapperSrc)) {
|
|
@@ -255,6 +262,12 @@ export async function update() {
|
|
|
255
262
|
try { chmodSync(join(binDir, "arka-claude"), 0o755); } catch {}
|
|
256
263
|
console.log(" ✓ arka-claude wrapper updated");
|
|
257
264
|
}
|
|
265
|
+
const arkaPySrc = join(ARKAOS_ROOT, "bin", "arka-py");
|
|
266
|
+
if (existsSync(arkaPySrc)) {
|
|
267
|
+
copyFileSync(arkaPySrc, join(binDir, "arka-py"));
|
|
268
|
+
try { chmodSync(join(binDir, "arka-py"), 0o755); } catch {}
|
|
269
|
+
console.log(" ✓ arka-py interpreter shim updated");
|
|
270
|
+
}
|
|
258
271
|
}
|
|
259
272
|
const userClaudeMd = join(homedir(), ".claude", "CLAUDE.md");
|
|
260
273
|
const claudeMdSrc = join(ARKAOS_ROOT, "config", "user-claude.md");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arkaos",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.2",
|
|
4
4
|
"description": "The Operating System for AI Agent Teams",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -58,5 +58,8 @@
|
|
|
58
58
|
"CONSTITUTION.md",
|
|
59
59
|
"README.md",
|
|
60
60
|
"LICENSE"
|
|
61
|
-
]
|
|
61
|
+
],
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"eslint": "^8.57.1"
|
|
64
|
+
}
|
|
62
65
|
}
|
package/pyproject.toml
CHANGED
|
@@ -175,7 +175,7 @@ def main() -> int:
|
|
|
175
175
|
for card in _INITIAL_PATTERNS:
|
|
176
176
|
record_pattern(card)
|
|
177
177
|
print(f"Seeded {len(_INITIAL_PATTERNS)} pattern cards.")
|
|
178
|
-
print("Inspect:
|
|
178
|
+
print("Inspect: ~/.arkaos/bin/arka-py -m core.knowledge.pattern_cards_cli list")
|
|
179
179
|
return 0
|
|
180
180
|
|
|
181
181
|
|