arkaos 4.20.0 → 4.22.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 +1 -1
- package/VERSION +1 -1
- package/arka/SKILL.md +2 -1
- package/config/claude-agents/marta-cqo.md +9 -0
- package/config/standards/{claude-md-overlays → stack-rules}/laravel.md +11 -0
- package/config/standards/{claude-md-overlays → stack-rules}/node.md +10 -1
- package/config/standards/{claude-md-overlays → stack-rules}/nuxt.md +12 -1
- package/config/standards/stack-rules/php.md +13 -0
- package/config/standards/{claude-md-overlays → stack-rules}/python.md +5 -0
- package/config/standards/stack-rules/react.md +14 -0
- package/config/standards/stack-rules/vue.md +13 -0
- package/core/cognition/evolve.py +299 -0
- package/core/cognition/evolve_cli.py +55 -0
- package/core/governance/stop_lint.py +266 -0
- package/core/governance/stop_lint_telemetry.py +132 -0
- package/core/governance/tool_loop_check.py +111 -0
- package/core/hooks/stop.py +73 -22
- package/core/runtime/pricing.py +53 -19
- package/core/synapse/layers.py +49 -476
- package/core/synapse/layers_base.py +99 -0
- package/core/synapse/layers_kb.py +395 -0
- package/core/sync/content_syncer.py +79 -10
- package/dashboard/app/components/AgentDependencyGraph.vue +5 -5
- package/dashboard/app/components/AgentEditDrawer.vue +120 -52
- package/dashboard/app/components/AgentSuggestionsCard.vue +4 -2
- package/dashboard/app/components/ConfirmDialog.vue +2 -2
- package/dashboard/app/components/DashboardState.vue +5 -3
- package/dashboard/app/components/GlobalSearch.vue +11 -7
- package/dashboard/app/components/KeyboardShortcutsHelp.vue +8 -6
- package/dashboard/app/components/KnowledgeSourcesList.vue +13 -9
- package/dashboard/app/components/MarkdownEditor.vue +1 -1
- package/dashboard/app/components/NotificationsBell.vue +8 -4
- package/dashboard/app/components/OnboardingTour.vue +24 -11
- package/dashboard/app/components/PersonaCloneDialog.vue +15 -8
- package/dashboard/app/components/PersonaWizard.vue +105 -72
- package/dashboard/app/components/SidebarFavoritesWidget.vue +5 -5
- package/dashboard/app/components/SidebarStatsWidget.vue +3 -1
- package/dashboard/app/components/Terminal.vue +9 -8
- package/dashboard/app/components/TextDiff.vue +27 -15
- package/dashboard/app/composables/useActivityFeed.ts +3 -3
- package/dashboard/app/composables/useApi.ts +4 -2
- package/dashboard/app/composables/useConfirmDialog.ts +1 -1
- package/dashboard/app/composables/useFavorites.ts +8 -8
- package/dashboard/app/composables/useTerminalThemes.ts +13 -13
- package/dashboard/app/composables/useThemeColor.ts +7 -4
- package/dashboard/app/pages/agents/[id].vue +319 -159
- package/dashboard/app/pages/agents/compare.vue +152 -52
- package/dashboard/app/pages/agents/index.vue +68 -55
- package/dashboard/app/pages/agents/new.vue +125 -58
- package/dashboard/app/pages/audit.vue +13 -6
- package/dashboard/app/pages/budget.vue +20 -18
- package/dashboard/app/pages/commands.vue +26 -22
- package/dashboard/app/pages/departments/[dept].vue +67 -31
- package/dashboard/app/pages/departments/compare.vue +85 -27
- package/dashboard/app/pages/departments/index.vue +31 -7
- package/dashboard/app/pages/health.vue +19 -12
- package/dashboard/app/pages/knowledge/index.vue +190 -78
- package/dashboard/app/pages/models.vue +74 -28
- package/dashboard/app/pages/personas/[id].vue +322 -219
- package/dashboard/app/pages/personas/archetypes.vue +20 -6
- package/dashboard/app/pages/personas/compare-with-agent.vue +109 -39
- package/dashboard/app/pages/personas/compare.vue +196 -124
- package/dashboard/app/pages/personas/index.vue +67 -60
- package/dashboard/app/pages/personas/new.vue +1 -1
- package/dashboard/app/pages/settings.vue +1 -0
- package/dashboard/app/pages/tasks.vue +80 -38
- package/dashboard/app/pages/trash.vue +11 -9
- package/dashboard/app/pages/workflows.vue +29 -19
- package/dashboard/nuxt.config.ts +2 -1
- package/dashboard/package.json +5 -0
- package/departments/kb/skills/doc-extraction/SKILL.md +99 -0
- package/departments/kb/skills/doc-redaction/SKILL.md +103 -0
- package/departments/kb/skills/knowledge-ops/SKILL.md +88 -0
- package/departments/ops/skills/github-ops/SKILL.md +89 -0
- package/departments/ops/skills/terminal-ops/SKILL.md +83 -0
- package/installer/index.js +1 -1
- package/knowledge/commands-registry.json +16 -3
- package/knowledge/skills-manifest.json +66 -1
- package/package.json +1 -1
- package/pyproject.toml +1 -1
package/core/hooks/stop.py
CHANGED
|
@@ -13,9 +13,11 @@ Section order preserved exactly:
|
|
|
13
13
|
[arka:meta], kb-cite, sycophancy, closing marker, skill proposer,
|
|
14
14
|
kb=N reconciliation) → telemetry entry (mode: warn)
|
|
15
15
|
6. Gate checkpoint persistence (core/workflow/gate_checkpoint.py)
|
|
16
|
-
7.
|
|
16
|
+
7. Stop-lint batch enqueue (detached scoped lint —
|
|
17
|
+
core/governance/stop_lint.py, warn-only telemetry)
|
|
18
|
+
8. Auto-documentor enqueue (flow-required + QG APPROVED + external
|
|
17
19
|
research heuristic)
|
|
18
|
-
|
|
20
|
+
9. Belt-and-braces WF_MARKER removal
|
|
19
21
|
|
|
20
22
|
The transcript is read from disk ONCE and shared across native-usage,
|
|
21
23
|
flow validation, gate checkpoint, and the auto-doc external-research
|
|
@@ -24,13 +26,13 @@ heuristic (the old hook parsed it four times).
|
|
|
24
26
|
|
|
25
27
|
from __future__ import annotations
|
|
26
28
|
|
|
29
|
+
import contextlib
|
|
27
30
|
import json
|
|
28
31
|
import os
|
|
29
32
|
import re
|
|
30
|
-
from datetime import
|
|
33
|
+
from datetime import UTC, datetime
|
|
31
34
|
from pathlib import Path
|
|
32
35
|
|
|
33
|
-
from core.shared.temp_paths import arkaos_temp_dir
|
|
34
36
|
from core.hooks._shared import (
|
|
35
37
|
ensure_root_on_path,
|
|
36
38
|
get_str,
|
|
@@ -39,6 +41,7 @@ from core.hooks._shared import (
|
|
|
39
41
|
resolve_arkaos_root,
|
|
40
42
|
safe_session_id,
|
|
41
43
|
)
|
|
44
|
+
from core.shared.temp_paths import arkaos_temp_dir
|
|
42
45
|
|
|
43
46
|
_DISPATCH_RE = re.compile(
|
|
44
47
|
r"\[arka:dispatch\][ \t]*[A-Za-z0-9_-]+[ \t]*->[ \t]*([A-Za-z0-9_-]+)",
|
|
@@ -164,8 +167,8 @@ def _flow_checks(
|
|
|
164
167
|
from core.governance.phantom_action_check import (
|
|
165
168
|
current_turn_assistant_texts,
|
|
166
169
|
)
|
|
167
|
-
from core.workflow.gate_checkpoint import extract_latest_gate
|
|
168
170
|
from core.workflow import plan_approval
|
|
171
|
+
from core.workflow.gate_checkpoint import extract_latest_gate
|
|
169
172
|
turn = current_turn_assistant_texts(raw)
|
|
170
173
|
scan = turn if turn is not None else [last]
|
|
171
174
|
if session_id and extract_latest_gate(scan) == 2:
|
|
@@ -300,8 +303,31 @@ def _flow_checks(
|
|
|
300
303
|
except Exception:
|
|
301
304
|
pass
|
|
302
305
|
|
|
306
|
+
# Context-monitor tool-loop signal (warn-only): turn-boundary scan
|
|
307
|
+
# over the transcript sees every call, fast-pathed ones included.
|
|
308
|
+
loop_detected = False
|
|
309
|
+
loop_tool = ""
|
|
310
|
+
loop_repeats = 0
|
|
311
|
+
loop_pattern = ""
|
|
312
|
+
try:
|
|
313
|
+
from core.governance.tool_loop_check import check_tool_loops
|
|
314
|
+
lv = check_tool_loops(raw)
|
|
315
|
+
loop_detected = lv.detected
|
|
316
|
+
loop_tool = lv.tool
|
|
317
|
+
loop_repeats = lv.repeats
|
|
318
|
+
loop_pattern = lv.pattern
|
|
319
|
+
if lv.detected and safe_sid:
|
|
320
|
+
_write_tmp_state("arkaos-tool-loop", safe_sid, {
|
|
321
|
+
"tool": lv.tool,
|
|
322
|
+
"repeats": lv.repeats,
|
|
323
|
+
"pattern": lv.pattern,
|
|
324
|
+
"total_tool_uses": lv.total_tool_uses,
|
|
325
|
+
})
|
|
326
|
+
except Exception:
|
|
327
|
+
pass
|
|
328
|
+
|
|
303
329
|
entry = {
|
|
304
|
-
"ts": datetime.now(
|
|
330
|
+
"ts": datetime.now(UTC).isoformat(),
|
|
305
331
|
"session_id": session_id,
|
|
306
332
|
"cwd": cwd,
|
|
307
333
|
"event": "stop-hook-flow-check",
|
|
@@ -326,6 +352,10 @@ def _flow_checks(
|
|
|
326
352
|
"phantom_check_passed": phantom_passed,
|
|
327
353
|
"phantom_check_reason": phantom_reason,
|
|
328
354
|
"phantom_claims": phantom_claims,
|
|
355
|
+
"tool_loop_detected": loop_detected,
|
|
356
|
+
"tool_loop_tool": loop_tool,
|
|
357
|
+
"tool_loop_repeats": loop_repeats,
|
|
358
|
+
"tool_loop_pattern": loop_pattern,
|
|
329
359
|
"effort_level": effort_level,
|
|
330
360
|
"mode": "warn",
|
|
331
361
|
}
|
|
@@ -336,16 +366,14 @@ def _flow_checks(
|
|
|
336
366
|
except Exception:
|
|
337
367
|
pass
|
|
338
368
|
|
|
339
|
-
|
|
369
|
+
with contextlib.suppress(Exception):
|
|
340
370
|
clear_flow_required(session_id)
|
|
341
|
-
except Exception:
|
|
342
|
-
pass
|
|
343
371
|
|
|
344
372
|
|
|
345
373
|
def _auto_doc_enqueue(
|
|
346
374
|
session_id: str, transcript_path: str, raw: str | None
|
|
347
375
|
) -> None:
|
|
348
|
-
"""Section
|
|
376
|
+
"""Section 8: fire-and-forget auto-documentor job enqueue."""
|
|
349
377
|
try:
|
|
350
378
|
from core.jobs.auto_doc_worker import enqueue_job
|
|
351
379
|
from core.workflow.flow_enforcer import _load_last_assistant_messages
|
|
@@ -387,10 +415,8 @@ def _auto_doc_enqueue(
|
|
|
387
415
|
data = raw if raw is not None else ""
|
|
388
416
|
if not any(marker in data for marker in _EXTERNAL_MARKERS):
|
|
389
417
|
return
|
|
390
|
-
|
|
418
|
+
with contextlib.suppress(Exception):
|
|
391
419
|
enqueue_job(session_id, transcript_path, "APPROVED")
|
|
392
|
-
except Exception:
|
|
393
|
-
pass
|
|
394
420
|
|
|
395
421
|
|
|
396
422
|
def _session_memory_enabled() -> bool:
|
|
@@ -426,7 +452,33 @@ def _enqueue_turn_capture(session_id: str, transcript_path: str, cwd: str) -> No
|
|
|
426
452
|
env={**os.environ, "PYTHONPATH": repo},
|
|
427
453
|
start_new_session=True, # same pattern as _enqueue_cognition_capture
|
|
428
454
|
)
|
|
429
|
-
except Exception:
|
|
455
|
+
except Exception:
|
|
456
|
+
pass
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
def _enqueue_stop_lint(session_id: str, cwd: str) -> None:
|
|
460
|
+
"""Section 7: detached scoped lint batch — deterministic evidence
|
|
461
|
+
lands in telemetry (stop-lint.jsonl), never on the 5s hook budget."""
|
|
462
|
+
if not cwd or not Path(cwd).is_dir():
|
|
463
|
+
return
|
|
464
|
+
try:
|
|
465
|
+
from core.governance.stop_lint import mode as stop_lint_mode
|
|
466
|
+
if stop_lint_mode() == "off":
|
|
467
|
+
return
|
|
468
|
+
repo = repo_path()
|
|
469
|
+
if not repo or not Path(repo).is_dir():
|
|
470
|
+
return
|
|
471
|
+
import subprocess
|
|
472
|
+
import sys as _sys
|
|
473
|
+
subprocess.Popen(
|
|
474
|
+
[_sys.executable, "-m", "core.governance.stop_lint",
|
|
475
|
+
cwd, session_id or ""],
|
|
476
|
+
stdout=subprocess.DEVNULL,
|
|
477
|
+
stderr=subprocess.DEVNULL,
|
|
478
|
+
env={**os.environ, "PYTHONPATH": repo},
|
|
479
|
+
start_new_session=True, # same pattern as _enqueue_turn_capture
|
|
480
|
+
)
|
|
481
|
+
except Exception: # best-effort, hook never breaks
|
|
430
482
|
pass
|
|
431
483
|
|
|
432
484
|
|
|
@@ -450,7 +502,7 @@ def _enqueue_routing_rebuild() -> None:
|
|
|
450
502
|
env={**os.environ, "PYTHONPATH": repo},
|
|
451
503
|
start_new_session=True,
|
|
452
504
|
)
|
|
453
|
-
except Exception:
|
|
505
|
+
except Exception:
|
|
454
506
|
pass
|
|
455
507
|
|
|
456
508
|
|
|
@@ -479,10 +531,8 @@ def main(stdin_json: dict | None = None) -> int:
|
|
|
479
531
|
|
|
480
532
|
_native_usage(transcript_path, session_id, raw)
|
|
481
533
|
|
|
482
|
-
|
|
534
|
+
with contextlib.suppress(Exception):
|
|
483
535
|
_enqueue_turn_capture(session_id, transcript_path, cwd)
|
|
484
|
-
except Exception: # noqa: BLE001 — never let capture break the hook
|
|
485
|
-
pass
|
|
486
536
|
|
|
487
537
|
_enqueue_routing_rebuild()
|
|
488
538
|
|
|
@@ -494,13 +544,13 @@ def main(stdin_json: dict | None = None) -> int:
|
|
|
494
544
|
if (Path(root) / "core" / "workflow" / "flow_enforcer.py").is_file():
|
|
495
545
|
_flow_checks(session_id, transcript_path, cwd, effort_level, raw)
|
|
496
546
|
|
|
547
|
+
_enqueue_stop_lint(session_id, cwd)
|
|
548
|
+
|
|
497
549
|
_auto_doc_enqueue(session_id, transcript_path, raw)
|
|
498
550
|
|
|
499
551
|
# Belt-and-braces marker removal (session id already allowlisted).
|
|
500
|
-
|
|
552
|
+
with contextlib.suppress(OSError):
|
|
501
553
|
wf_marker.unlink(missing_ok=True)
|
|
502
|
-
except OSError:
|
|
503
|
-
pass
|
|
504
554
|
return 0
|
|
505
555
|
|
|
506
556
|
|
|
@@ -510,4 +560,5 @@ if __name__ == "__main__":
|
|
|
510
560
|
except SystemExit:
|
|
511
561
|
raise
|
|
512
562
|
except Exception:
|
|
513
|
-
|
|
563
|
+
# Stop hook must never break the turn.
|
|
564
|
+
raise SystemExit(0) from None
|
package/core/runtime/pricing.py
CHANGED
|
@@ -6,25 +6,59 @@ their public per-token pricing. It is used to compute an optional
|
|
|
6
6
|
any model-selection logic — that is explicitly forbidden by the
|
|
7
7
|
LLM-agnostic contract.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
(https://openai.com/api/pricing)
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
Snapshot 2026-07-18: values sourced from the public Anthropic pricing
|
|
10
|
+
page (https://platform.claude.com/docs/en/about-claude/pricing) and
|
|
11
|
+
OpenAI (https://openai.com/api/pricing). Refresh when model families
|
|
12
|
+
change. Unknown models return `None` from `estimate_cost_usd` and are
|
|
13
|
+
logged with a null cost — never a guessed number.
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
# USD per 1M tokens. Only the `cache_read` and `cache_write` keys apply
|
|
20
|
-
# to providers that expose prompt caching (currently Anthropic
|
|
21
|
-
#
|
|
20
|
+
# to providers that expose prompt caching (currently Anthropic; rates
|
|
21
|
+
# are the 0.1x / 1.25x input multipliers for 5-minute cache writes).
|
|
22
|
+
# Missing keys fall back to 0 cost contribution rather than raising.
|
|
22
23
|
PRICING: dict[str, dict[str, float]] = {
|
|
24
|
+
"claude-fable-5": {
|
|
25
|
+
"input": 10.00,
|
|
26
|
+
"output": 50.00,
|
|
27
|
+
"cache_read": 1.00,
|
|
28
|
+
"cache_write": 12.50,
|
|
29
|
+
},
|
|
30
|
+
"claude-opus-4-8": {
|
|
31
|
+
"input": 5.00,
|
|
32
|
+
"output": 25.00,
|
|
33
|
+
"cache_read": 0.50,
|
|
34
|
+
"cache_write": 6.25,
|
|
35
|
+
},
|
|
23
36
|
"claude-opus-4-7": {
|
|
24
|
-
"input":
|
|
25
|
-
"output":
|
|
26
|
-
"cache_read":
|
|
27
|
-
"cache_write":
|
|
37
|
+
"input": 5.00,
|
|
38
|
+
"output": 25.00,
|
|
39
|
+
"cache_read": 0.50,
|
|
40
|
+
"cache_write": 6.25,
|
|
41
|
+
},
|
|
42
|
+
"claude-opus-4-6": {
|
|
43
|
+
"input": 5.00,
|
|
44
|
+
"output": 25.00,
|
|
45
|
+
"cache_read": 0.50,
|
|
46
|
+
"cache_write": 6.25,
|
|
47
|
+
},
|
|
48
|
+
"claude-opus-4-5": {
|
|
49
|
+
"input": 5.00,
|
|
50
|
+
"output": 25.00,
|
|
51
|
+
"cache_read": 0.50,
|
|
52
|
+
"cache_write": 6.25,
|
|
53
|
+
},
|
|
54
|
+
# Introductory pricing ($2/$10) is in effect through 2026-08-31;
|
|
55
|
+
# from 2026-09-01 the standard rate is $3/$15 (cache $0.30/$3.75).
|
|
56
|
+
# Refresh this row when the introductory window closes.
|
|
57
|
+
"claude-sonnet-5": {
|
|
58
|
+
"input": 2.00,
|
|
59
|
+
"output": 10.00,
|
|
60
|
+
"cache_read": 0.20,
|
|
61
|
+
"cache_write": 2.50,
|
|
28
62
|
},
|
|
29
63
|
"claude-sonnet-4-6": {
|
|
30
64
|
"input": 3.00,
|
|
@@ -33,19 +67,19 @@ PRICING: dict[str, dict[str, float]] = {
|
|
|
33
67
|
"cache_write": 3.75,
|
|
34
68
|
},
|
|
35
69
|
"claude-haiku-4-5-20251001": {
|
|
36
|
-
"input":
|
|
37
|
-
"output":
|
|
38
|
-
"cache_read": 0.
|
|
39
|
-
"cache_write": 1.
|
|
70
|
+
"input": 1.00,
|
|
71
|
+
"output": 5.00,
|
|
72
|
+
"cache_read": 0.10,
|
|
73
|
+
"cache_write": 1.25,
|
|
40
74
|
},
|
|
41
75
|
# Generic (undated) alias of the dated haiku row above — native
|
|
42
76
|
# transcripts sometimes report the tier id without the date suffix.
|
|
43
77
|
# Same published price; NOT an invented number.
|
|
44
78
|
"claude-haiku-4-5": {
|
|
45
|
-
"input":
|
|
46
|
-
"output":
|
|
47
|
-
"cache_read": 0.
|
|
48
|
-
"cache_write": 1.
|
|
79
|
+
"input": 1.00,
|
|
80
|
+
"output": 5.00,
|
|
81
|
+
"cache_read": 0.10,
|
|
82
|
+
"cache_write": 1.25,
|
|
49
83
|
},
|
|
50
84
|
"gpt-4": {
|
|
51
85
|
"input": 30.00,
|