arkaos 5.13.0 → 5.15.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/THE-ARKAOS-GUIDE.md +1 -1
- package/VERSION +1 -1
- package/config/evals/marketing.yaml +4 -4
- package/config/hooks/_lib/arka_python.sh +104 -0
- package/config/hooks/pre-tool-use.cjs +79 -1
- package/config/hooks/pre-tool-use.sh +19 -2
- package/core/cognition/dreaming.py +323 -26
- package/core/cognition/reorganizer.py +18 -6
- package/core/cognition/reorganizer_cli.py +61 -14
- package/core/governance/evidence_checks.py +1001 -37
- package/core/hooks/_shared.py +132 -0
- package/core/hooks/post_tool_use.py +38 -3
- package/core/hooks/pre_tool_use.py +13 -0
- package/core/hooks/stop.py +38 -1
- package/core/hooks/stop_governance.py +6 -2
- package/core/runtime/user_paths.py +40 -8
- package/core/sync/engine.py +2 -0
- package/core/sync/feature_injector.py +182 -0
- package/core/sync/features/workflow-tiers.yaml +1 -1
- package/core/sync/marker_audit.py +253 -0
- package/core/sync/reporter.py +74 -2
- package/core/sync/schema.py +103 -1
- package/core/terminal/session.py +64 -32
- package/departments/dev/skills/security-compliance/SKILL.md +0 -5
- package/departments/dev/skills/threejs/SKILL.md +2 -2
- package/departments/landing/skills/offer-create/references/offer-formats.md +2 -2
- package/departments/marketing/skills/ad-creative/SKILL.md +1 -1
- package/departments/marketing/skills/ad-creative/references/creative-review-page.md +5 -5
- package/departments/ops/skills/gdpr-compliance/SKILL.md +0 -5
- package/departments/ops/skills/iso27001/SKILL.md +0 -5
- package/departments/ops/skills/quality-management/SKILL.md +0 -5
- package/departments/ops/skills/risk-management/SKILL.md +0 -5
- package/departments/ops/skills/soc2-compliance/SKILL.md +0 -5
- package/departments/ops/skills/update/references/sync-engine.md +1 -1
- package/departments/ops/skills/update/references/workflows.md +2 -1
- package/departments/sales/skills/prospecting/references/demand-signals.md +1 -1
- package/harness/codex/AGENTS.md +1 -1
- package/harness/copilot/copilot-instructions.md +1 -1
- package/harness/cursor/rules/arkaos.mdc +2 -2
- package/harness/gemini/GEMINI.md +1 -1
- package/harness/opencode/AGENTS.md +1 -1
- package/harness/opencode/agents/arka-architect-gabriel.md +1 -1
- package/harness/opencode/agents/arka-brand-director-valentina.md +1 -1
- package/harness/opencode/agents/arka-cfo-helena.md +1 -1
- package/harness/opencode/agents/arka-chief-of-staff-afonso.md +1 -1
- package/harness/opencode/agents/arka-community-strategist-beatriz.md +1 -1
- package/harness/opencode/agents/arka-content-strategist-rafael.md +1 -1
- package/harness/opencode/agents/arka-conversion-strategist-ines.md +1 -1
- package/harness/opencode/agents/arka-coo-sofia.md +1 -1
- package/harness/opencode/agents/arka-copy-director-eduardo.md +1 -1
- package/harness/opencode/agents/arka-cqo-marta.md +1 -1
- package/harness/opencode/agents/arka-cto-marco.md +1 -1
- package/harness/opencode/agents/arka-design-ops-lead-iris.md +1 -1
- package/harness/opencode/agents/arka-ecom-director-ricardo.md +1 -1
- package/harness/opencode/agents/arka-knowledge-director-clara.md +1 -1
- package/harness/opencode/agents/arka-leadership-director-rodrigo.md +1 -1
- package/harness/opencode/agents/arka-marketing-director-luna.md +1 -1
- package/harness/opencode/agents/arka-ops-lead-daniel.md +1 -1
- package/harness/opencode/agents/arka-pm-director-carolina.md +1 -1
- package/harness/opencode/agents/arka-revops-lead-vicente.md +1 -1
- package/harness/opencode/agents/arka-saas-strategist-tiago.md +1 -1
- package/harness/opencode/agents/arka-sales-director-miguel.md +1 -1
- package/harness/opencode/agents/arka-strategy-director-tomas.md +1 -1
- package/harness/opencode/agents/arka-tech-director-francisca.md +1 -1
- package/harness/opencode/agents/arka-tech-lead-paulo.md +1 -1
- package/harness/opencode/agents/arka-video-producer-simao.md +1 -1
- package/harness/zed/.rules +1 -1
- package/installer/claude-md.js +42 -4
- package/knowledge/skills-manifest.json +1 -1
- package/package.json +3 -1
- package/pyproject.toml +41 -2
- package/scripts/dashboard-api.py +16 -1
- package/scripts/fenced-code-allowlist.json +308 -0
- package/scripts/lint_fenced_code.mjs +591 -0
- package/scripts/skills_catalog_gen.py +21 -8
- package/scripts/start-dashboard.ps1 +14 -0
- package/scripts/tools/docs_stats.py +42 -2
package/THE-ARKAOS-GUIDE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The ArkaOS Guide
|
|
2
2
|
|
|
3
|
-
> v5.
|
|
3
|
+
> v5.14.0 — 89 agents, 17 departments, 340 skills, 306 commands, 20 ADRs.
|
|
4
4
|
> One file, everything you need to start. Generated by `scripts/guide_gen.py` — never hand-edited.
|
|
5
5
|
|
|
6
6
|
## What it is
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.
|
|
1
|
+
5.15.0
|
|
@@ -389,7 +389,7 @@
|
|
|
389
389
|
the carousel frames, and the different headline options they can compare. Can you put
|
|
390
390
|
that together?
|
|
391
391
|
expected_properties:
|
|
392
|
-
- Produces a creative review page
|
|
392
|
+
- Produces a self-contained HTML creative review page, not plain markdown
|
|
393
393
|
- Populates the DATA object (concept tabs, in-feed preview, frame storyboard, headline variations,
|
|
394
394
|
copy, destination)
|
|
395
395
|
- Labels storyboard frames by narrative job rather than by pictured content
|
|
@@ -398,9 +398,9 @@
|
|
|
398
398
|
- Does not present invented stats or stock imagery as the brand's real assets
|
|
399
399
|
- Uses placeholders for unrendered frames and keeps image paths relative
|
|
400
400
|
- Explains how to deliver the page (open locally / host / hand off the file)
|
|
401
|
-
rubric: Should recognize this as a creative review page request and apply
|
|
402
|
-
|
|
403
|
-
|
|
401
|
+
rubric: Should recognize this as a creative review page request and apply the build spec in
|
|
402
|
+
references/creative-review-page.md rather than producing plain markdown. Should build a
|
|
403
|
+
single self-contained review.html in the output folder and populate its DATA block with the
|
|
404
404
|
four concepts as tabs, each with an in-feed Instagram preview, a labeled frame-by-frame
|
|
405
405
|
storyboard (frames labeled by narrative job — Hook / Problem / Proof / Ask — not by pictured
|
|
406
406
|
content), selectable headline variations, primary text, and destination/CTA. Should curate
|
|
@@ -154,3 +154,107 @@ arka_resolve_root() {
|
|
|
154
154
|
fi
|
|
155
155
|
printf '%s\n' "${ARKA_OS:-$HOME/.claude/skills/arkaos}"
|
|
156
156
|
}
|
|
157
|
+
|
|
158
|
+
# ─── Degraded-run telemetry ────────────────────────────────────────────
|
|
159
|
+
# A hook that fails open and says nothing is indistinguishable from a hook
|
|
160
|
+
# that ran and allowed. That ambiguity is not hypothetical: an ArkaOS venv
|
|
161
|
+
# that could not `import pydantic` made every gate on one machine allow
|
|
162
|
+
# silently for months, and the same silence previously kept two real bugs
|
|
163
|
+
# invisible while manufacturing a third that never existed (Cross-Machine
|
|
164
|
+
# Lab, X3).
|
|
165
|
+
#
|
|
166
|
+
# Two hard rules, both deliberate:
|
|
167
|
+
#
|
|
168
|
+
# 1. NEVER write to stderr. Claude Code surfaces hook stderr to the user
|
|
169
|
+
# as an error, so a diagnostic there converts a silent degradation
|
|
170
|
+
# into visible noise on every event — trading one bad failure mode
|
|
171
|
+
# for a worse one. The record goes to a file; only a reader who wants
|
|
172
|
+
# it pays for it.
|
|
173
|
+
# 2. NEVER change the exit code. Fail-open is the correct posture for a
|
|
174
|
+
# governance hook: a broken interpreter must not block the user's
|
|
175
|
+
# work. This makes the degradation legible, not fatal.
|
|
176
|
+
#
|
|
177
|
+
# One JSON line per event, appended. Failure to write is swallowed —
|
|
178
|
+
# telemetry must never be the thing that breaks a hook.
|
|
179
|
+
#
|
|
180
|
+
# Growth cap: mirrors DEGRADED_LOG_MAX_BYTES in core/hooks/_shared.py. This
|
|
181
|
+
# writer needs it MORE than the Python one, not less — the cases it records
|
|
182
|
+
# (no interpreter, missing entrypoint) fire on every single tool call, so an
|
|
183
|
+
# uncapped log on a broken machine is the runaway, not a corner case.
|
|
184
|
+
ARKA_DEGRADED_MAX_BYTES=5242880
|
|
185
|
+
|
|
186
|
+
arka_hook_degraded() {
|
|
187
|
+
local hook="${1:-unknown}" reason="${2:-unknown}" detail="${3:-}"
|
|
188
|
+
local dir="$HOME/.arkaos/telemetry"
|
|
189
|
+
local file="$dir/hook-degraded.jsonl"
|
|
190
|
+
local stamp bytes
|
|
191
|
+
stamp="$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null)" || stamp=""
|
|
192
|
+
# Keep detail on one line and out of the JSON grammar's way. Every C0
|
|
193
|
+
# control character (and DEL) becomes a space: a raw tab, \r or \001
|
|
194
|
+
# reaching the printf below emits a byte JSON forbids inside a string, so
|
|
195
|
+
# one degraded event carrying a Python traceback used to poison the whole
|
|
196
|
+
# line for every reader. Translated rather than deleted so words do not
|
|
197
|
+
# fuse — "expected\tgot" must stay two tokens. LC_ALL=C keeps the range
|
|
198
|
+
# byte-wise; tr pads set2 by repeating its last character (POSIX).
|
|
199
|
+
detail="$(printf '%s' "$detail" | LC_ALL=C tr '\000-\037\177' ' ' \
|
|
200
|
+
| cut -c1-400)"
|
|
201
|
+
detail="${detail//\\/\\\\}"
|
|
202
|
+
detail="${detail//\"/\\\"}"
|
|
203
|
+
if [ -f "$file" ]; then
|
|
204
|
+
bytes="$(wc -c < "$file" 2>/dev/null | tr -d ' ')"
|
|
205
|
+
case "$bytes" in
|
|
206
|
+
'' | *[!0-9]*) ;;
|
|
207
|
+
*)
|
|
208
|
+
if [ "$bytes" -ge "$ARKA_DEGRADED_MAX_BYTES" ]; then
|
|
209
|
+
mv -f "$file" "$file.1" 2>/dev/null || true
|
|
210
|
+
fi
|
|
211
|
+
;;
|
|
212
|
+
esac
|
|
213
|
+
fi
|
|
214
|
+
{
|
|
215
|
+
mkdir -p "$dir" 2>/dev/null &&
|
|
216
|
+
printf '{"ts":"%s","hook":"%s","reason":"%s","detail":"%s"}\n' \
|
|
217
|
+
"$stamp" "$hook" "$reason" "$detail" >> "$file"
|
|
218
|
+
} 2>/dev/null || true
|
|
219
|
+
return 0
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
# Run a hook entrypoint under the resolved interpreter, recording the
|
|
223
|
+
# degraded cases instead of exec'ing into silence.
|
|
224
|
+
#
|
|
225
|
+
# ─── Deliberate divergence: this path does NOT `exec` ───────────────────
|
|
226
|
+
# Every other .sh wrapper (post-tool-use, session-start, session-end,
|
|
227
|
+
# subagent-stop, user-prompt-submit) still ends in `exec "$ARKA_PY" -m …`.
|
|
228
|
+
# This one cannot, and the reason is structural rather than stylistic:
|
|
229
|
+
# `exec` REPLACES the shell with Python, so there is no surviving process
|
|
230
|
+
# to read the exit status afterwards. Recording "the entrypoint failed"
|
|
231
|
+
# requires observing the status the entrypoint exited with, which requires
|
|
232
|
+
# outliving it. Restoring `exec` here would silently delete the
|
|
233
|
+
# entrypoint-failed record — the single most valuable one, since it is the
|
|
234
|
+
# only witness to a broken interpreter that resolves but cannot run.
|
|
235
|
+
#
|
|
236
|
+
# Two measured costs, accepted knowingly:
|
|
237
|
+
# 1. One extra live process (this shell) for the hook's lifetime.
|
|
238
|
+
# 2. On a hard kill of the wrapper (Claude Code's 10s timeout), the
|
|
239
|
+
# Python child is reparented to PID 1 instead of dying with the
|
|
240
|
+
# shell — an orphan for the remainder of its own run. Not fixable by
|
|
241
|
+
# trapping: bash defers trap handling until the foreground command
|
|
242
|
+
# returns, and backgrounding the child would redirect its stdin from
|
|
243
|
+
# /dev/null in a non-interactive shell, which breaks the hook's stdin
|
|
244
|
+
# contract outright. The orphan is short-lived and harmless; a hook
|
|
245
|
+
# that cannot report its own failure is neither.
|
|
246
|
+
#
|
|
247
|
+
# Exit codes pass through UNCHANGED. Note which ones are NOT failures:
|
|
248
|
+
# 0 allow
|
|
249
|
+
# 2 the documented deny/block code — a gate doing its job, never logged
|
|
250
|
+
# Anything else means the entrypoint did not get to decide, which is
|
|
251
|
+
# exactly the case worth a record.
|
|
252
|
+
arka_run_hook() {
|
|
253
|
+
local hook="$1" module="$2" status
|
|
254
|
+
"$ARKA_PY" -m "$module"
|
|
255
|
+
status=$?
|
|
256
|
+
if [ "$status" -ne 0 ] && [ "$status" -ne 2 ]; then
|
|
257
|
+
arka_hook_degraded "$hook" "entrypoint-failed" "exit=$status module=$module py=$ARKA_PY"
|
|
258
|
+
fi
|
|
259
|
+
return "$status"
|
|
260
|
+
}
|
|
@@ -22,6 +22,62 @@ const path = require("node:path");
|
|
|
22
22
|
|
|
23
23
|
const FAIL_OPEN_EXIT = 0;
|
|
24
24
|
|
|
25
|
+
// Growth cap, mirroring DEGRADED_LOG_MAX_BYTES in core/hooks/_shared.py
|
|
26
|
+
// and ARKA_DEGRADED_MAX_BYTES in _lib/arka_python.sh.
|
|
27
|
+
const DEGRADED_MAX_BYTES = 5 * 1024 * 1024;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Record that this shim allowed because it could not run, not because it
|
|
31
|
+
* decided — the same JSONL line, in the same file, as record_degraded() in
|
|
32
|
+
* core/hooks/_shared.py and arka_hook_degraded() in _lib/arka_python.sh:
|
|
33
|
+
* {ts,hook,reason,detail}, appended, never on stderr, never fatal, never a
|
|
34
|
+
* change to the exit code.
|
|
35
|
+
*
|
|
36
|
+
* This surface needs it most, not least. On POSIX the installer registers
|
|
37
|
+
* THIS file as the PreToolUse command whenever it and the fastpath engine
|
|
38
|
+
* are deployed (installer/adapters/claude-code.js::hookEntry), so the .sh
|
|
39
|
+
* chain — the one that carries the shell telemetry — is reached only by
|
|
40
|
+
* delegation. Every fail-open below therefore happens BEFORE any other
|
|
41
|
+
* writer exists to observe it: instrumenting only the .sh would have left
|
|
42
|
+
* the default install's three silent exits exactly as silent as before.
|
|
43
|
+
*
|
|
44
|
+
* `via=cjs` leads every detail because `unhandled-fail-open` is a reason
|
|
45
|
+
* the Python entrypoint also emits; the surface has to be readable from
|
|
46
|
+
* the line itself.
|
|
47
|
+
*/
|
|
48
|
+
function recordDegraded(reason, detail) {
|
|
49
|
+
try {
|
|
50
|
+
const home = process.env.HOME || require("node:os").homedir();
|
|
51
|
+
const dir = path.join(home, ".arkaos", "telemetry");
|
|
52
|
+
const file = path.join(dir, "hook-degraded.jsonl");
|
|
53
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
54
|
+
try {
|
|
55
|
+
if (fs.statSync(file).size >= DEGRADED_MAX_BYTES) {
|
|
56
|
+
fs.renameSync(file, file + ".1");
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
// No log yet, or one that cannot be rotated: append regardless. A
|
|
60
|
+
// cap that suppresses the record defeats the point of recording.
|
|
61
|
+
}
|
|
62
|
+
const line = JSON.stringify({
|
|
63
|
+
// Second precision, no fractional part — byte-identical to the
|
|
64
|
+
// strftime/date formats the other two writers use.
|
|
65
|
+
ts: new Date().toISOString().replace(/\.\d+Z$/, "Z"),
|
|
66
|
+
hook: "pre-tool-use",
|
|
67
|
+
reason,
|
|
68
|
+
detail: String(detail == null ? "" : detail)
|
|
69
|
+
// JSON.stringify would escape control characters rather than emit
|
|
70
|
+
// them raw, but a tab-laden stack trace still makes the line
|
|
71
|
+
// unreadable; normalise for the same reason the shell writer does.
|
|
72
|
+
.replace(/[\u0000-\u001f\u007f]/g, " ")
|
|
73
|
+
.slice(0, 400),
|
|
74
|
+
});
|
|
75
|
+
fs.appendFileSync(file, line + "\n");
|
|
76
|
+
} catch {
|
|
77
|
+
// Telemetry must never be the thing that breaks a hook.
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
25
81
|
function readStdin() {
|
|
26
82
|
try {
|
|
27
83
|
return fs.readFileSync(0, "utf8");
|
|
@@ -34,6 +90,10 @@ function delegate(rawStdin) {
|
|
|
34
90
|
const sibling = path.join(__dirname, "pre-tool-use.sh");
|
|
35
91
|
if (!fs.existsSync(sibling)) {
|
|
36
92
|
// Missing sibling → bash would exit 127; the contract is fail-open.
|
|
93
|
+
// A split deploy that lands the .cjs without the .sh disables every
|
|
94
|
+
// gate for the whole install, so this is the highest-stakes silent
|
|
95
|
+
// allow in the file — it never reaches the shell writer.
|
|
96
|
+
recordDegraded("delegate-target-missing", `via=cjs sibling=${sibling}`);
|
|
37
97
|
process.exit(FAIL_OPEN_EXIT);
|
|
38
98
|
}
|
|
39
99
|
// Lazy require: the fast path never pays for child_process.
|
|
@@ -44,6 +104,16 @@ function delegate(rawStdin) {
|
|
|
44
104
|
env: { ...process.env, ARKA_HOOK_FASTPATH: "0" },
|
|
45
105
|
});
|
|
46
106
|
if (result.error || result.status === null) {
|
|
107
|
+
// Two distinct degradations, both invisible until now: bash could not
|
|
108
|
+
// be spawned at all (result.error — no bash on PATH, EACCES, EMFILE),
|
|
109
|
+
// or it was killed by a signal before deciding (status null). Neither
|
|
110
|
+
// is an allow the gate chain ever made.
|
|
111
|
+
const err = result.error;
|
|
112
|
+
recordDegraded(
|
|
113
|
+
"delegate-spawn-failed",
|
|
114
|
+
`via=cjs error=${err ? err.code || err.message : "none"} ` +
|
|
115
|
+
`status=${result.status} signal=${result.signal || "none"}`
|
|
116
|
+
);
|
|
47
117
|
process.exit(FAIL_OPEN_EXIT);
|
|
48
118
|
}
|
|
49
119
|
process.exit(result.status);
|
|
@@ -104,6 +174,14 @@ function main() {
|
|
|
104
174
|
|
|
105
175
|
try {
|
|
106
176
|
main();
|
|
107
|
-
} catch {
|
|
177
|
+
} catch (err) {
|
|
178
|
+
// The shim's own last resort. Structurally identical to the
|
|
179
|
+
// `unhandled-fail-open` handler at the bottom of core/hooks/
|
|
180
|
+
// pre_tool_use.py, and previously just as silent: exit 0, empty stdout,
|
|
181
|
+
// nothing anywhere to say the gate chain never ran.
|
|
182
|
+
recordDegraded(
|
|
183
|
+
"unhandled-fail-open",
|
|
184
|
+
`via=cjs ${err && err.stack ? err.stack : String(err)}`
|
|
185
|
+
);
|
|
108
186
|
process.exit(FAIL_OPEN_EXIT);
|
|
109
187
|
}
|
|
@@ -26,6 +26,14 @@
|
|
|
26
26
|
_ARKA_LIB="$(dirname "${BASH_SOURCE[0]:-$0}")/_lib/arka_python.sh"
|
|
27
27
|
if [ -f "$_ARKA_LIB" ]; then . "$_ARKA_LIB"; else ARKA_PY="python3"; fi
|
|
28
28
|
|
|
29
|
+
# A split deploy (wrapper present, _lib absent) must still run the hook —
|
|
30
|
+
# telemetry is an observer, never a dependency. These no-op stubs are
|
|
31
|
+
# defined only when the real ones did not arrive.
|
|
32
|
+
command -v arka_hook_degraded >/dev/null 2>&1 || arka_hook_degraded() { :; }
|
|
33
|
+
command -v arka_run_hook >/dev/null 2>&1 || arka_run_hook() {
|
|
34
|
+
shift; "$ARKA_PY" -m "$1"
|
|
35
|
+
}
|
|
36
|
+
|
|
29
37
|
# ─── Resolve ARKAOS_ROOT (validated — see arka_resolve_root in _lib) ────
|
|
30
38
|
# .repo-path can point at a purged npx cache; the shared resolver falls
|
|
31
39
|
# through to the ~/.arkaos/lib snapshot instead of exporting a dead root.
|
|
@@ -44,7 +52,10 @@ fi
|
|
|
44
52
|
export ARKAOS_ROOT
|
|
45
53
|
|
|
46
54
|
# ─── Degrade gracefully (fail open, same as before) ─────────────────────
|
|
55
|
+
# Still fail-open, but no longer silent: with no interpreter every gate in
|
|
56
|
+
# this hook allows, and that must be distinguishable from a gate that ran.
|
|
47
57
|
if ! command -v "$ARKA_PY" >/dev/null 2>&1; then
|
|
58
|
+
arka_hook_degraded "pre-tool-use" "no-interpreter" "ARKA_PY=$ARKA_PY"
|
|
48
59
|
exit 0
|
|
49
60
|
fi
|
|
50
61
|
# Self-root fallback: the wrapper ships next to its python entrypoint, so
|
|
@@ -56,6 +67,7 @@ if [ ! -f "$ARKAOS_ROOT/core/hooks/pre_tool_use.py" ]; then
|
|
|
56
67
|
ARKAOS_ROOT="$_SELF_ROOT"
|
|
57
68
|
export ARKAOS_ROOT
|
|
58
69
|
else
|
|
70
|
+
arka_hook_degraded "pre-tool-use" "entrypoint-missing" "root=$ARKAOS_ROOT"
|
|
59
71
|
exit 0
|
|
60
72
|
fi
|
|
61
73
|
fi
|
|
@@ -63,5 +75,10 @@ fi
|
|
|
63
75
|
# ─── Single python process; stdin/stdout/stderr/exit-code pass through ──
|
|
64
76
|
# Interpreter resolution handled by the shared resolver (ARKA_PY): prefers
|
|
65
77
|
# the ArkaOS venv (has pyyaml/pydantic), falls back to a yaml-capable python3.
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
#
|
|
79
|
+
# NOT `exec`, unlike every other .sh wrapper here — deliberate, and the
|
|
80
|
+
# trade-off is written out in full at arka_run_hook in _lib/arka_python.sh.
|
|
81
|
+
# Short version: exec replaces this shell with Python, leaving nobody to
|
|
82
|
+
# read the exit status, and the status IS the entrypoint-failed signal.
|
|
83
|
+
export PYTHONPATH="$ARKAOS_ROOT${PYTHONPATH:+:$PYTHONPATH}"
|
|
84
|
+
arka_run_hook "pre-tool-use" core.hooks.pre_tool_use
|