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.
Files changed (167) hide show
  1. package/README.md +2 -2
  2. package/VERSION +1 -1
  3. package/arka/SKILL.md +16 -22
  4. package/arka/skills/flow/SKILL.md +108 -234
  5. package/config/claude-agents/eduardo-copy.md +53 -0
  6. package/config/claude-agents/francisca-tech.md +52 -0
  7. package/config/claude-agents/marta-cqo.md +52 -0
  8. package/config/claude-agents/paulo-tech-lead.md +50 -0
  9. package/config/cognition/schedules.yaml +15 -0
  10. package/config/constitution.yaml +17 -21
  11. package/config/hooks/_lib/workflow-classifier.sh +1 -1
  12. package/config/hooks/post-tool-use.sh +40 -539
  13. package/config/hooks/pre-tool-use.sh +32 -281
  14. package/config/hooks/session-start.sh +8 -10
  15. package/config/hooks/stop.sh +30 -425
  16. package/config/hooks/user-prompt-submit.sh +42 -459
  17. package/core/cognition/__pycache__/dreaming.cpython-313.pyc +0 -0
  18. package/core/cognition/dreaming.py +5 -0
  19. package/core/cognition/scheduler/__pycache__/daemon.cpython-313.pyc +0 -0
  20. package/core/cognition/scheduler/daemon.py +10 -0
  21. package/core/forge/__init__.py +2 -0
  22. package/core/forge/__pycache__/__init__.cpython-313.pyc +0 -0
  23. package/core/forge/__pycache__/orchestrator.cpython-313.pyc +0 -0
  24. package/core/forge/__pycache__/persistence.cpython-313.pyc +0 -0
  25. package/core/forge/__pycache__/renderer.cpython-313.pyc +0 -0
  26. package/core/forge/__pycache__/runtime_dispatcher.cpython-313.pyc +0 -0
  27. package/core/forge/__pycache__/schema.cpython-313.pyc +0 -0
  28. package/core/forge/orchestrator.py +50 -27
  29. package/core/forge/persistence.py +16 -0
  30. package/core/forge/renderer.py +16 -0
  31. package/core/forge/runtime_dispatcher.py +34 -19
  32. package/core/forge/schema.py +12 -0
  33. package/core/governance/__pycache__/__init__.cpython-312.pyc +0 -0
  34. package/core/governance/__pycache__/closing_marker_check.cpython-313.pyc +0 -0
  35. package/core/governance/__pycache__/compliance_telemetry.cpython-313.pyc +0 -0
  36. package/core/governance/__pycache__/constitution.cpython-312.pyc +0 -0
  37. package/core/governance/__pycache__/evidence_checks.cpython-313.pyc +0 -0
  38. package/core/governance/__pycache__/meta_tag_check.cpython-313.pyc +0 -0
  39. package/core/governance/__pycache__/qg_verdict.cpython-313.pyc +0 -0
  40. package/core/governance/__pycache__/review_workflow.cpython-313.pyc +0 -0
  41. package/core/governance/__pycache__/skill_proposer.cpython-313.pyc +0 -0
  42. package/core/governance/closing_marker_check.py +9 -5
  43. package/core/governance/compliance_telemetry.py +1 -1
  44. package/core/governance/compliance_telemetry_cli.py +1 -1
  45. package/core/governance/evidence_checks.py +421 -0
  46. package/core/governance/meta_tag_check.py +36 -0
  47. package/core/governance/qg_verdict.py +78 -0
  48. package/core/governance/review_workflow.py +34 -1
  49. package/core/governance/skill_proposer.py +2 -1
  50. package/core/hooks/__init__.py +12 -0
  51. package/core/hooks/__pycache__/__init__.cpython-312.pyc +0 -0
  52. package/core/hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  53. package/core/hooks/__pycache__/_shared.cpython-312.pyc +0 -0
  54. package/core/hooks/__pycache__/_shared.cpython-313.pyc +0 -0
  55. package/core/hooks/__pycache__/post_tool_use.cpython-312.pyc +0 -0
  56. package/core/hooks/__pycache__/post_tool_use.cpython-313.pyc +0 -0
  57. package/core/hooks/__pycache__/pre_tool_use.cpython-312.pyc +0 -0
  58. package/core/hooks/__pycache__/pre_tool_use.cpython-313.pyc +0 -0
  59. package/core/hooks/__pycache__/stop.cpython-312.pyc +0 -0
  60. package/core/hooks/__pycache__/stop.cpython-313.pyc +0 -0
  61. package/core/hooks/__pycache__/user_prompt_submit.cpython-312.pyc +0 -0
  62. package/core/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
  63. package/core/hooks/_shared.py +110 -0
  64. package/core/hooks/post_tool_use.py +689 -0
  65. package/core/hooks/pre_tool_use.py +267 -0
  66. package/core/hooks/stop.py +395 -0
  67. package/core/hooks/user_prompt_submit.py +600 -0
  68. package/core/jobs/__pycache__/__init__.cpython-312.pyc +0 -0
  69. package/core/jobs/__pycache__/auto_doc_worker.cpython-312.pyc +0 -0
  70. package/core/jobs/__pycache__/manager.cpython-312.pyc +0 -0
  71. package/core/knowledge/__pycache__/embedder.cpython-312.pyc +0 -0
  72. package/core/knowledge/__pycache__/embedder.cpython-313.pyc +0 -0
  73. package/core/knowledge/__pycache__/vector_store.cpython-312.pyc +0 -0
  74. package/core/knowledge/__pycache__/vector_store.cpython-313.pyc +0 -0
  75. package/core/knowledge/embedder.py +118 -11
  76. package/core/knowledge/vector_store.py +111 -14
  77. package/core/runtime/__pycache__/__init__.cpython-312.pyc +0 -0
  78. package/core/runtime/__pycache__/__init__.cpython-313.pyc +0 -0
  79. package/core/runtime/__pycache__/base.cpython-312.pyc +0 -0
  80. package/core/runtime/__pycache__/base.cpython-313.pyc +0 -0
  81. package/core/runtime/__pycache__/capabilities_cli.cpython-312.pyc +0 -0
  82. package/core/runtime/__pycache__/capabilities_cli.cpython-313.pyc +0 -0
  83. package/core/runtime/__pycache__/claude_code.cpython-312.pyc +0 -0
  84. package/core/runtime/__pycache__/claude_code.cpython-313.pyc +0 -0
  85. package/core/runtime/__pycache__/codex_cli.cpython-312.pyc +0 -0
  86. package/core/runtime/__pycache__/codex_cli.cpython-313.pyc +0 -0
  87. package/core/runtime/__pycache__/cost_governor.cpython-312.pyc +0 -0
  88. package/core/runtime/__pycache__/cost_governor.cpython-313.pyc +0 -0
  89. package/core/runtime/__pycache__/cursor.cpython-312.pyc +0 -0
  90. package/core/runtime/__pycache__/cursor.cpython-313.pyc +0 -0
  91. package/core/runtime/__pycache__/gemini_cli.cpython-312.pyc +0 -0
  92. package/core/runtime/__pycache__/gemini_cli.cpython-313.pyc +0 -0
  93. package/core/runtime/__pycache__/llm_provider.cpython-312.pyc +0 -0
  94. package/core/runtime/__pycache__/llm_provider.cpython-313.pyc +0 -0
  95. package/core/runtime/__pycache__/llm_retry.cpython-312.pyc +0 -0
  96. package/core/runtime/__pycache__/llm_retry.cpython-313.pyc +0 -0
  97. package/core/runtime/__pycache__/native_usage.cpython-312.pyc +0 -0
  98. package/core/runtime/__pycache__/native_usage.cpython-313.pyc +0 -0
  99. package/core/runtime/__pycache__/path_resolver.cpython-312.pyc +0 -0
  100. package/core/runtime/__pycache__/pricing.cpython-312.pyc +0 -0
  101. package/core/runtime/__pycache__/pricing.cpython-313.pyc +0 -0
  102. package/core/runtime/__pycache__/registry.cpython-312.pyc +0 -0
  103. package/core/runtime/__pycache__/registry.cpython-313.pyc +0 -0
  104. package/core/runtime/__pycache__/squad_orchestrator.cpython-312.pyc +0 -0
  105. package/core/runtime/base.py +29 -0
  106. package/core/runtime/capabilities_cli.py +74 -0
  107. package/core/runtime/claude_code.py +8 -0
  108. package/core/runtime/codex_cli.py +205 -37
  109. package/core/runtime/cost_governor.py +184 -0
  110. package/core/runtime/cursor.py +8 -0
  111. package/core/runtime/gemini_cli.py +8 -0
  112. package/core/runtime/llm_provider.py +32 -13
  113. package/core/runtime/llm_retry.py +233 -0
  114. package/core/runtime/native_usage.py +186 -0
  115. package/core/runtime/pricing.py +9 -0
  116. package/core/runtime/registry.py +3 -0
  117. package/core/shared/__pycache__/test_evidence.cpython-313-pytest-9.1.1.pyc +0 -0
  118. package/core/shared/__pycache__/test_evidence.cpython-313.pyc +0 -0
  119. package/core/shared/test_evidence.py +34 -0
  120. package/core/synapse/__pycache__/agent_experiences_layer.cpython-312.pyc +0 -0
  121. package/core/synapse/__pycache__/engine.cpython-312.pyc +0 -0
  122. package/core/synapse/__pycache__/engine.cpython-313.pyc +0 -0
  123. package/core/synapse/__pycache__/graph_context_layer.cpython-313.pyc +0 -0
  124. package/core/synapse/__pycache__/kb_cache.cpython-312.pyc +0 -0
  125. package/core/synapse/__pycache__/kb_cache.cpython-313.pyc +0 -0
  126. package/core/synapse/__pycache__/layers.cpython-312.pyc +0 -0
  127. package/core/synapse/__pycache__/layers.cpython-313.pyc +0 -0
  128. package/core/synapse/engine.py +7 -0
  129. package/core/synapse/graph_context_layer.py +212 -0
  130. package/core/synapse/kb_cache.py +3 -0
  131. package/core/synapse/layers.py +104 -20
  132. package/core/workflow/__pycache__/enforcer.cpython-313.pyc +0 -0
  133. package/core/workflow/__pycache__/flow_enforcer.cpython-312.pyc +0 -0
  134. package/core/workflow/__pycache__/flow_enforcer.cpython-313.pyc +0 -0
  135. package/core/workflow/__pycache__/gate_checkpoint.cpython-312.pyc +0 -0
  136. package/core/workflow/__pycache__/gate_checkpoint.cpython-313.pyc +0 -0
  137. package/core/workflow/__pycache__/research_gate.cpython-313.pyc +0 -0
  138. package/core/workflow/__pycache__/rules_registry.cpython-313.pyc +0 -0
  139. package/core/workflow/__pycache__/specialist_enforcer.cpython-312.pyc +0 -0
  140. package/core/workflow/__pycache__/specialist_enforcer.cpython-313.pyc +0 -0
  141. package/core/workflow/enforcer.py +5 -16
  142. package/core/workflow/flow_enforcer.py +36 -11
  143. package/core/workflow/gate_checkpoint.py +149 -0
  144. package/core/workflow/research_gate.py +15 -3
  145. package/core/workflow/rules_registry.py +137 -389
  146. package/core/workflow/specialist_enforcer.py +21 -4
  147. package/dashboard/app/pages/knowledge/index.vue +4 -1
  148. package/departments/ops/skills/n8n-flow/SKILL.md +13 -0
  149. package/departments/ops/skills/workflow-automate/SKILL.md +16 -0
  150. package/departments/quality/SKILL.md +45 -5
  151. package/departments/quality/agents/copy-director.yaml +3 -1
  152. package/departments/quality/agents/tech-director.yaml +3 -1
  153. package/installer/adapters/claude-code.js +46 -2
  154. package/installer/config-seed.js +39 -14
  155. package/installer/doctor.js +8 -0
  156. package/installer/graphify.js +153 -0
  157. package/installer/index.js +20 -0
  158. package/installer/init.js +11 -0
  159. package/installer/update.js +19 -0
  160. package/package.json +1 -1
  161. package/pyproject.toml +1 -1
  162. package/scripts/__pycache__/dashboard-api.cpython-313.pyc +0 -0
  163. package/scripts/__pycache__/knowledge-index.cpython-313.pyc +0 -0
  164. package/scripts/__pycache__/synapse-bridge.cpython-312.pyc +0 -0
  165. package/scripts/__pycache__/synapse-bridge.cpython-313.pyc +0 -0
  166. package/scripts/knowledge-index.py +8 -2
  167. package/scripts/synapse-bridge.py +102 -26
@@ -14,14 +14,61 @@ Exit codes: 0 = success, 1 = degraded (partial layers), 2 = error
14
14
  import argparse
15
15
  import json
16
16
  import os
17
+ import re
17
18
  import sys
18
19
  import time
19
20
  from pathlib import Path
21
+ from typing import Any
20
22
 
21
23
  # Resolve ArkaOS root from environment or script location
22
24
  ARKAOS_ROOT = Path(os.environ.get("ARKAOS_ROOT", Path(__file__).resolve().parent.parent))
23
25
  sys.path.insert(0, str(ARKAOS_ROOT))
24
26
 
27
+ # Layer tags carrying the actually-injected KB counts (ground truth for
28
+ # reconciling the model's self-reported `[arka:meta] kb=N`). The optional
29
+ # ` degraded=keyword` suffix (RAG honesty, PR-3 v4.1) must still count.
30
+ _KB_CONTEXT_TAG_RE = re.compile(r"\[kb-context:(\d+)[^\]]*\]")
31
+ _KNOWLEDGE_TAG_RE = re.compile(r"\[knowledge:(\d+) chunks?[^\]]*\]")
32
+ _KB_INJECTED_DIR = Path("/tmp/arkaos-kb-injected")
33
+
34
+
35
+ def _count_injected_kb(result: Any) -> tuple[int, int]:
36
+ """Count KB notes (L2.5) and knowledge chunks (L3.5) actually injected."""
37
+ kb_notes = 0
38
+ chunks = 0
39
+ for lr in result.layers:
40
+ tag = lr.tag or ""
41
+ if lr.layer_id == "L2.5":
42
+ match = _KB_CONTEXT_TAG_RE.search(tag)
43
+ kb_notes = int(match.group(1)) if match else 0
44
+ elif lr.layer_id == "L3.5":
45
+ match = _KNOWLEDGE_TAG_RE.search(tag)
46
+ chunks = int(match.group(1)) if match else 0
47
+ return kb_notes, chunks
48
+
49
+
50
+ def write_kb_injected_state(result: Any, session_id: str) -> None:
51
+ """Persist injected KB counts so the Stop hook can reconcile kb=N.
52
+
53
+ Skips silently when no real session id is available (a pid-derived
54
+ fallback id would never match the runtime's session id at Stop time).
55
+ """
56
+ from core.shared.safe_session_id import safe_session_id
57
+
58
+ sid = safe_session_id(session_id)
59
+ if not sid:
60
+ return
61
+ kb_notes, chunks = _count_injected_kb(result)
62
+ prev_umask = os.umask(0o077)
63
+ try:
64
+ _KB_INJECTED_DIR.mkdir(parents=True, exist_ok=True)
65
+ payload = {"kb_injected": kb_notes, "l35_chunks": chunks, "ts": time.time()}
66
+ (_KB_INJECTED_DIR / f"{sid}.json").write_text(
67
+ json.dumps(payload), encoding="utf-8"
68
+ )
69
+ finally:
70
+ os.umask(prev_umask)
71
+
25
72
 
26
73
  def load_constitution(root: Path) -> str:
27
74
  """Load and compress constitution rules."""
@@ -73,26 +120,21 @@ def load_commands_registry(root: Path) -> list:
73
120
  return []
74
121
 
75
122
 
76
- def main() -> int:
77
- parser = argparse.ArgumentParser(description="Synapse Bridge — context injection for hooks")
78
- parser.add_argument(
79
- "--layers-only",
80
- action="store_true",
81
- help="Output layer breakdown instead of context string",
82
- )
83
- parser.add_argument("--root", type=str, default=str(ARKAOS_ROOT), help="ArkaOS root directory")
84
- args = parser.parse_args()
123
+ def run_bridge(
124
+ input_data: dict,
125
+ root: Path,
126
+ layers_only: bool = False,
127
+ raw: str = "",
128
+ ) -> tuple[dict, int]:
129
+ """Run the Synapse engine for a hook payload. Returns (output, exit_code).
85
130
 
86
- root = Path(args.root)
131
+ Extracted from ``main()`` (PR-6 hook consolidation) so
132
+ ``core.hooks.user_prompt_submit`` can call the bridge in-process
133
+ instead of spawning a second python3. Exit codes match the script:
134
+ 0 = success, 1 = degraded (import error), 2 = error.
135
+ """
87
136
  start = time.time()
88
137
 
89
- # Read input from stdin
90
- try:
91
- raw = sys.stdin.read().strip()
92
- input_data = json.loads(raw) if raw else {}
93
- except (json.JSONDecodeError, Exception):
94
- input_data = {}
95
-
96
138
  # Extract context fields
97
139
  user_input = input_data.get("user_input", "")
98
140
  if not user_input:
@@ -141,12 +183,15 @@ def main() -> int:
141
183
  except Exception:
142
184
  branch = ""
143
185
 
144
- session_id = (
186
+ # Real runtime session id (used for kb=N reconciliation); the
187
+ # pid-derived fallback below is only for cache scoping and is
188
+ # deliberately excluded from reconciliation state.
189
+ runtime_session_id = (
145
190
  input_data.get("session_id")
146
191
  or os.environ.get("ARKAOS_SESSION_ID", "")
147
192
  or os.environ.get("CLAUDE_SESSION_ID", "")
148
- or f"bridge-{os.getpid()}"
149
193
  )
194
+ session_id = runtime_session_id or f"bridge-{os.getpid()}"
150
195
 
151
196
  ctx = PromptContext(
152
197
  user_input=user_input,
@@ -162,6 +207,15 @@ def main() -> int:
162
207
  result = engine.inject(ctx)
163
208
  total_ms = int((time.time() - start) * 1000)
164
209
 
210
+ # Structural honesty: record how many KB notes L2.5 actually
211
+ # injected. Never raise — reconciliation is telemetry-only and
212
+ # must not degrade context injection itself.
213
+ try:
214
+ if runtime_session_id:
215
+ write_kb_injected_state(result, runtime_session_id)
216
+ except Exception:
217
+ pass
218
+
165
219
  # Record token usage in budget tracker
166
220
  try:
167
221
  from core.budget.manager import BudgetManager
@@ -183,7 +237,7 @@ def main() -> int:
183
237
  except Exception:
184
238
  pass # Never block on budget tracking
185
239
 
186
- if args.layers_only:
240
+ if layers_only:
187
241
  output = {
188
242
  "context_string": result.context_string,
189
243
  "layers": [
@@ -204,19 +258,41 @@ def main() -> int:
204
258
  else:
205
259
  output = {"context_string": result.context_string, "total_ms": total_ms}
206
260
 
207
- print(json.dumps(output))
208
- return 0
261
+ return output, 0
209
262
 
210
263
  except ImportError as e:
211
264
  # Python dependencies not available — output minimal context
212
265
  sys.stderr.write(f"synapse-bridge: import error: {e}\n")
213
- print(json.dumps({"context_string": "", "error": str(e)}))
214
- return 1
266
+ return {"context_string": "", "error": str(e)}, 1
215
267
 
216
268
  except Exception as e:
217
269
  sys.stderr.write(f"synapse-bridge: error: {e}\n")
218
- print(json.dumps({"context_string": "", "error": str(e)}))
219
- return 2
270
+ return {"context_string": "", "error": str(e)}, 2
271
+
272
+
273
+ def main() -> int:
274
+ parser = argparse.ArgumentParser(description="Synapse Bridge — context injection for hooks")
275
+ parser.add_argument(
276
+ "--layers-only",
277
+ action="store_true",
278
+ help="Output layer breakdown instead of context string",
279
+ )
280
+ parser.add_argument("--root", type=str, default=str(ARKAOS_ROOT), help="ArkaOS root directory")
281
+ args = parser.parse_args()
282
+
283
+ # Read input from stdin
284
+ try:
285
+ raw = sys.stdin.read().strip()
286
+ input_data = json.loads(raw) if raw else {}
287
+ except (json.JSONDecodeError, Exception):
288
+ input_data = {}
289
+ raw = ""
290
+
291
+ output, code = run_bridge(
292
+ input_data, Path(args.root), layers_only=args.layers_only, raw=raw
293
+ )
294
+ print(json.dumps(output))
295
+ return code
220
296
 
221
297
 
222
298
  if __name__ == "__main__":