arkaos 4.6.0 → 4.7.1

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 (310) hide show
  1. package/CONSTITUTION.md +30 -16
  2. package/VERSION +1 -1
  3. package/arka/SKILL.md +26 -36
  4. package/arka/skills/bootstrap-agent/SKILL.md +6 -0
  5. package/arka/skills/checkpoint/SKILL.md +1 -1
  6. package/arka/skills/costs/SKILL.md +14 -5
  7. package/arka/skills/flow/SKILL.md +30 -15
  8. package/arka/skills/forge/SKILL.md +19 -15
  9. package/arka/skills/human-writing/SKILL.md +16 -7
  10. package/arka/skills/research/SKILL.md +20 -7
  11. package/arka/templates/skill-template.md +102 -0
  12. package/bin/arka-py.ps1 +9 -2
  13. package/config/claude-agents/architect.md +51 -0
  14. package/config/claude-agents/backend-dev.md +51 -0
  15. package/config/claude-agents/dba.md +51 -0
  16. package/config/claude-agents/devops-eng.md +51 -0
  17. package/config/claude-agents/eduardo-copy.md +14 -7
  18. package/config/claude-agents/francisca-tech.md +24 -6
  19. package/config/claude-agents/frontend-dev.md +51 -0
  20. package/config/claude-agents/marta-cqo.md +28 -8
  21. package/config/claude-agents/qa-eng.md +51 -0
  22. package/config/claude-agents/research-assistant.md +50 -0
  23. package/config/claude-agents/security-eng.md +51 -0
  24. package/config/constitution.yaml +127 -88
  25. package/config/hooks/session-start.ps1 +3 -1
  26. package/config/hooks/session-start.sh +3 -1
  27. package/config/hooks/user-prompt-submit-v2.sh +4 -11
  28. package/config/hooks/user-prompt-submit.ps1 +4 -7
  29. package/config/hooks/user-prompt-submit.sh +8 -1
  30. package/core/agents/__pycache__/behavioral_compiler.cpython-313.pyc +0 -0
  31. package/core/agents/behavioral_compiler.py +294 -0
  32. package/core/budget/__pycache__/__init__.cpython-314.pyc +0 -0
  33. package/core/budget/__pycache__/manager.cpython-314.pyc +0 -0
  34. package/core/budget/__pycache__/schema.cpython-314.pyc +0 -0
  35. package/core/forge/__pycache__/__init__.cpython-314.pyc +0 -0
  36. package/core/forge/__pycache__/complexity.cpython-314.pyc +0 -0
  37. package/core/forge/__pycache__/handoff.cpython-314.pyc +0 -0
  38. package/core/forge/__pycache__/orchestrator.cpython-314.pyc +0 -0
  39. package/core/forge/__pycache__/persistence.cpython-314.pyc +0 -0
  40. package/core/forge/__pycache__/renderer.cpython-314.pyc +0 -0
  41. package/core/forge/__pycache__/runtime_dispatcher.cpython-314.pyc +0 -0
  42. package/core/forge/__pycache__/schema.cpython-314.pyc +0 -0
  43. package/core/governance/__pycache__/agent_experiences.cpython-314.pyc +0 -0
  44. package/core/governance/__pycache__/closing_marker_check.cpython-313.pyc +0 -0
  45. package/core/governance/__pycache__/closing_marker_check.cpython-314.pyc +0 -0
  46. package/core/governance/__pycache__/phantom_action_check.cpython-313.pyc +0 -0
  47. package/core/governance/__pycache__/phantom_action_check.cpython-314.pyc +0 -0
  48. package/core/governance/__pycache__/qg_verdict.cpython-313.pyc +0 -0
  49. package/core/governance/__pycache__/quality_api.cpython-314.pyc +0 -0
  50. package/core/governance/__pycache__/quality_router.cpython-314.pyc +0 -0
  51. package/core/governance/__pycache__/review_workflow.cpython-314.pyc +0 -0
  52. package/core/governance/closing_marker_check.py +2 -2
  53. package/core/governance/phantom_action_check.py +221 -0
  54. package/core/governance/qg_verdict.py +12 -0
  55. package/core/hooks/__pycache__/stop.cpython-313.pyc +0 -0
  56. package/core/hooks/__pycache__/stop.cpython-314.pyc +0 -0
  57. package/core/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
  58. package/core/hooks/__pycache__/user_prompt_submit.cpython-314.pyc +0 -0
  59. package/core/hooks/stop.py +25 -0
  60. package/core/hooks/user_prompt_submit.py +15 -10
  61. package/core/knowledge/__pycache__/__init__.cpython-314.pyc +0 -0
  62. package/core/knowledge/__pycache__/chunker.cpython-314.pyc +0 -0
  63. package/core/knowledge/__pycache__/embedder.cpython-314.pyc +0 -0
  64. package/core/knowledge/__pycache__/pattern_cards.cpython-314.pyc +0 -0
  65. package/core/knowledge/__pycache__/vector_store.cpython-312.pyc +0 -0
  66. package/core/knowledge/__pycache__/vector_store.cpython-314.pyc +0 -0
  67. package/core/memory/__pycache__/rehydrator.cpython-314.pyc +0 -0
  68. package/core/runtime/__pycache__/claude_code.cpython-313.pyc +0 -0
  69. package/core/runtime/__pycache__/codex_cli.cpython-313.pyc +0 -0
  70. package/core/runtime/__pycache__/gemini_cli.cpython-313.pyc +0 -0
  71. package/core/runtime/claude_code.py +2 -1
  72. package/core/runtime/codex_cli.py +2 -0
  73. package/core/runtime/gemini_cli.py +2 -0
  74. package/core/shared/__pycache__/temp_paths.cpython-312.pyc +0 -0
  75. package/core/synapse/__pycache__/agent_experiences_layer.cpython-313.pyc +0 -0
  76. package/core/synapse/__pycache__/agent_experiences_layer.cpython-314.pyc +0 -0
  77. package/core/synapse/__pycache__/engine.cpython-312.pyc +0 -0
  78. package/core/synapse/__pycache__/engine.cpython-313.pyc +0 -0
  79. package/core/synapse/__pycache__/engine.cpython-314.pyc +0 -0
  80. package/core/synapse/__pycache__/graph_context_layer.cpython-313.pyc +0 -0
  81. package/core/synapse/__pycache__/graph_context_layer.cpython-314.pyc +0 -0
  82. package/core/synapse/__pycache__/layers.cpython-312.pyc +0 -0
  83. package/core/synapse/__pycache__/layers.cpython-313.pyc +0 -0
  84. package/core/synapse/__pycache__/layers.cpython-314.pyc +0 -0
  85. package/core/synapse/__pycache__/pattern_library_layer.cpython-313.pyc +0 -0
  86. package/core/synapse/__pycache__/pattern_library_layer.cpython-314.pyc +0 -0
  87. package/core/synapse/agent_experiences_layer.py +4 -0
  88. package/core/synapse/engine.py +13 -2
  89. package/core/synapse/graph_context_layer.py +4 -0
  90. package/core/synapse/layers.py +28 -49
  91. package/core/synapse/pattern_library_layer.py +4 -0
  92. package/departments/brand/SKILL.md +5 -13
  93. package/departments/brand/skills/archetype-finder/SKILL.md +3 -11
  94. package/departments/brand/skills/colors/SKILL.md +3 -11
  95. package/departments/brand/skills/design-review/SKILL.md +11 -3
  96. package/departments/brand/skills/design-system/SKILL.md +3 -11
  97. package/departments/brand/skills/identity-system/SKILL.md +3 -11
  98. package/departments/brand/skills/logo-brief/SKILL.md +3 -11
  99. package/departments/brand/skills/mockup-generate/SKILL.md +3 -11
  100. package/departments/brand/skills/naming-evaluate/SKILL.md +3 -11
  101. package/departments/brand/skills/positioning-statement/SKILL.md +3 -11
  102. package/departments/brand/skills/primal-audit/SKILL.md +3 -11
  103. package/departments/brand/skills/ux-audit/SKILL.md +3 -11
  104. package/departments/brand/skills/voice-guide/SKILL.md +3 -11
  105. package/departments/brand/skills/wireframe/SKILL.md +3 -11
  106. package/departments/community/SKILL.md +4 -12
  107. package/departments/community/skills/ai-community/SKILL.md +3 -11
  108. package/departments/community/skills/betting-setup/SKILL.md +3 -11
  109. package/departments/community/skills/business-model/SKILL.md +3 -11
  110. package/departments/community/skills/content-calendar/SKILL.md +3 -11
  111. package/departments/community/skills/events-plan/SKILL.md +3 -11
  112. package/departments/community/skills/gamification-design/SKILL.md +3 -11
  113. package/departments/community/skills/growth-plan/SKILL.md +13 -12
  114. package/departments/community/skills/metrics-track/SKILL.md +3 -11
  115. package/departments/community/skills/moderation/SKILL.md +3 -11
  116. package/departments/community/skills/monetize-plan/SKILL.md +3 -11
  117. package/departments/community/skills/niche-setup/SKILL.md +3 -11
  118. package/departments/community/skills/onboarding-flow/SKILL.md +3 -11
  119. package/departments/community/skills/platform-select/SKILL.md +3 -11
  120. package/departments/content/SKILL.md +4 -12
  121. package/departments/content/skills/ai-workflow/SKILL.md +3 -11
  122. package/departments/content/skills/analytics/SKILL.md +3 -11
  123. package/departments/content/skills/calendar/SKILL.md +3 -11
  124. package/departments/content/skills/content-system/SKILL.md +3 -11
  125. package/departments/content/skills/monetization-plan/SKILL.md +3 -11
  126. package/departments/content/skills/newsletter-write/SKILL.md +3 -11
  127. package/departments/content/skills/platform-optimize/SKILL.md +3 -11
  128. package/departments/content/skills/repurpose-plan/SKILL.md +3 -11
  129. package/departments/content/skills/script-structure/SKILL.md +3 -11
  130. package/departments/content/skills/short-form/SKILL.md +3 -11
  131. package/departments/content/skills/thumbnail-package/SKILL.md +3 -11
  132. package/departments/content/skills/viral-design/SKILL.md +3 -11
  133. package/departments/content/skills/youtube-strategy/SKILL.md +3 -11
  134. package/departments/dev/SKILL.md +4 -12
  135. package/departments/dev/agents/security-eng.yaml +1 -1
  136. package/departments/dev/skills/adversarial-review/SKILL.md +10 -2
  137. package/departments/dev/skills/ai-assisted-dev/SKILL.md +3 -11
  138. package/departments/dev/skills/architecture-design/SKILL.md +3 -11
  139. package/departments/dev/skills/clean-code-review/SKILL.md +9 -2
  140. package/departments/dev/skills/code-review/SKILL.md +12 -12
  141. package/departments/dev/skills/db-design/SKILL.md +3 -11
  142. package/departments/dev/skills/ddd-model/SKILL.md +3 -11
  143. package/departments/dev/skills/demo-gif/SKILL.md +3 -11
  144. package/departments/dev/skills/deploy/SKILL.md +3 -11
  145. package/departments/dev/skills/devops-pipeline/SKILL.md +3 -11
  146. package/departments/dev/skills/docs/SKILL.md +3 -11
  147. package/departments/dev/skills/mcp/SKILL.md +3 -11
  148. package/departments/dev/skills/performance-audit/SKILL.md +3 -11
  149. package/departments/dev/skills/refactor-plan/SKILL.md +3 -11
  150. package/departments/dev/skills/research/SKILL.md +16 -12
  151. package/departments/dev/skills/scaffold/SKILL.md +15 -11
  152. package/departments/dev/skills/security-compliance/SKILL.md +3 -11
  153. package/departments/dev/skills/spec/SKILL.md +15 -10
  154. package/departments/dev/skills/stack-check/SKILL.md +3 -11
  155. package/departments/ecom/SKILL.md +4 -12
  156. package/departments/ecom/skills/analytics/SKILL.md +3 -11
  157. package/departments/ecom/skills/browse-competitor/SKILL.md +3 -11
  158. package/departments/ecom/skills/cart-recovery/SKILL.md +3 -11
  159. package/departments/ecom/skills/cro-optimize/SKILL.md +3 -11
  160. package/departments/ecom/skills/customer-journey/SKILL.md +3 -11
  161. package/departments/ecom/skills/fulfillment-plan/SKILL.md +3 -11
  162. package/departments/ecom/skills/marketplace-manage/SKILL.md +3 -11
  163. package/departments/ecom/skills/pricing-strategy/SKILL.md +3 -11
  164. package/departments/ecom/skills/product-launch/SKILL.md +3 -11
  165. package/departments/ecom/skills/rfm-segment/SKILL.md +3 -11
  166. package/departments/ecom/skills/social-commerce/SKILL.md +3 -11
  167. package/departments/ecom/skills/store-audit/SKILL.md +3 -11
  168. package/departments/ecom/skills/subscription-model/SKILL.md +3 -11
  169. package/departments/finance/SKILL.md +4 -12
  170. package/departments/finance/skills/budget-plan/SKILL.md +3 -11
  171. package/departments/finance/skills/cashflow-forecast/SKILL.md +3 -11
  172. package/departments/finance/skills/ciso-advisor/SKILL.md +3 -11
  173. package/departments/finance/skills/financial-model/SKILL.md +3 -11
  174. package/departments/finance/skills/pitch-deck/SKILL.md +3 -11
  175. package/departments/finance/skills/scenario-analysis/SKILL.md +3 -11
  176. package/departments/finance/skills/unit-economics/SKILL.md +3 -11
  177. package/departments/finance/skills/valuation-model/SKILL.md +3 -11
  178. package/departments/kb/SKILL.md +4 -12
  179. package/departments/kb/skills/ai-research/SKILL.md +3 -11
  180. package/departments/kb/skills/competitive-intel/SKILL.md +3 -11
  181. package/departments/kb/skills/knowledge-review/SKILL.md +3 -11
  182. package/departments/kb/skills/learn-content/SKILL.md +3 -11
  183. package/departments/kb/skills/moc-create/SKILL.md +3 -11
  184. package/departments/kb/skills/persona-build/SKILL.md +3 -11
  185. package/departments/kb/skills/research-plan/SKILL.md +3 -11
  186. package/departments/kb/skills/search-kb/SKILL.md +3 -11
  187. package/departments/kb/skills/source-evaluate/SKILL.md +3 -11
  188. package/departments/kb/skills/taxonomy-manage/SKILL.md +3 -11
  189. package/departments/kb/skills/write-as-persona/SKILL.md +3 -11
  190. package/departments/landing/SKILL.md +4 -12
  191. package/departments/landing/skills/ab-test/SKILL.md +3 -11
  192. package/departments/landing/skills/affiliate-bridge/SKILL.md +3 -11
  193. package/departments/landing/skills/awareness-diagnose/SKILL.md +3 -11
  194. package/departments/landing/skills/copy-framework/SKILL.md +1 -1
  195. package/departments/landing/skills/email-sequence/SKILL.md +3 -11
  196. package/departments/landing/skills/funnel-metrics/SKILL.md +3 -11
  197. package/departments/landing/skills/headline-write/SKILL.md +3 -11
  198. package/departments/landing/skills/launch-sequence/SKILL.md +3 -11
  199. package/departments/landing/skills/offer-create/SKILL.md +3 -11
  200. package/departments/landing/skills/optimize-page/SKILL.md +3 -11
  201. package/departments/landing/skills/page-architect/SKILL.md +3 -11
  202. package/departments/landing/skills/persuasion-apply/SKILL.md +3 -11
  203. package/departments/landing/skills/webinar-funnel/SKILL.md +3 -11
  204. package/departments/leadership/SKILL.md +4 -12
  205. package/departments/leadership/skills/change-manage/SKILL.md +3 -11
  206. package/departments/leadership/skills/conflict-resolve/SKILL.md +3 -11
  207. package/departments/leadership/skills/culture-audit/SKILL.md +3 -11
  208. package/departments/leadership/skills/delegation-matrix/SKILL.md +3 -11
  209. package/departments/leadership/skills/disc-assess/SKILL.md +3 -11
  210. package/departments/leadership/skills/feedback-give/SKILL.md +3 -11
  211. package/departments/leadership/skills/hiring-plan/SKILL.md +3 -11
  212. package/departments/leadership/skills/performance-review/SKILL.md +3 -11
  213. package/departments/marketing/SKILL.md +4 -12
  214. package/departments/marketing/skills/ab-test/SKILL.md +3 -11
  215. package/departments/marketing/skills/analytics-report/SKILL.md +3 -11
  216. package/departments/marketing/skills/audience-segment/SKILL.md +3 -11
  217. package/departments/marketing/skills/calendar-plan/SKILL.md +3 -11
  218. package/departments/marketing/skills/competitor-analysis/SKILL.md +3 -11
  219. package/departments/marketing/skills/content-audit/SKILL.md +3 -11
  220. package/departments/marketing/skills/email-sequence/SKILL.md +3 -11
  221. package/departments/marketing/skills/growth-loop/SKILL.md +15 -13
  222. package/departments/marketing/skills/marketing-automation/SKILL.md +3 -11
  223. package/departments/marketing/skills/paid-campaign/SKILL.md +3 -11
  224. package/departments/marketing/skills/programmatic-seo/SKILL.md +3 -11
  225. package/departments/marketing/skills/seo-audit/SKILL.md +3 -11
  226. package/departments/marketing/skills/social-strategy/SKILL.md +3 -11
  227. package/departments/ops/SKILL.md +4 -12
  228. package/departments/ops/skills/bottleneck-find/SKILL.md +3 -11
  229. package/departments/ops/skills/dashboard-build/SKILL.md +3 -11
  230. package/departments/ops/skills/gdpr-compliance/SKILL.md +3 -11
  231. package/departments/ops/skills/gtd-setup/SKILL.md +3 -11
  232. package/departments/ops/skills/integration-design/SKILL.md +3 -11
  233. package/departments/ops/skills/iso27001/SKILL.md +3 -11
  234. package/departments/ops/skills/lean-audit/SKILL.md +3 -11
  235. package/departments/ops/skills/metrics-dashboard/SKILL.md +3 -11
  236. package/departments/ops/skills/n8n-flow/SKILL.md +3 -11
  237. package/departments/ops/skills/quality-management/SKILL.md +3 -11
  238. package/departments/ops/skills/risk-management/SKILL.md +3 -11
  239. package/departments/ops/skills/soc2-compliance/SKILL.md +3 -11
  240. package/departments/ops/skills/sop-create/SKILL.md +3 -11
  241. package/departments/ops/skills/workflow-automate/SKILL.md +3 -11
  242. package/departments/ops/skills/zapier-flow/SKILL.md +3 -11
  243. package/departments/org/SKILL.md +4 -12
  244. package/departments/org/skills/compensation-plan/SKILL.md +3 -11
  245. package/departments/org/skills/culture-define/SKILL.md +3 -11
  246. package/departments/org/skills/decision-framework/SKILL.md +3 -11
  247. package/departments/org/skills/hiring-plan/SKILL.md +3 -11
  248. package/departments/org/skills/meeting-optimize/SKILL.md +3 -11
  249. package/departments/org/skills/onboarding-design/SKILL.md +3 -11
  250. package/departments/org/skills/org-design/SKILL.md +3 -11
  251. package/departments/org/skills/remote-setup/SKILL.md +3 -11
  252. package/departments/org/skills/sop-process/SKILL.md +3 -11
  253. package/departments/org/skills/team-assess/SKILL.md +3 -11
  254. package/departments/pm/SKILL.md +4 -12
  255. package/departments/pm/skills/backlog-groom/SKILL.md +3 -11
  256. package/departments/pm/skills/discovery-plan/SKILL.md +3 -11
  257. package/departments/pm/skills/estimate-forecast/SKILL.md +3 -11
  258. package/departments/pm/skills/impact-map/SKILL.md +3 -11
  259. package/departments/pm/skills/kanban-setup/SKILL.md +3 -11
  260. package/departments/pm/skills/risk-register/SKILL.md +3 -11
  261. package/departments/pm/skills/roadmap-build/SKILL.md +3 -11
  262. package/departments/pm/skills/sprint-plan/SKILL.md +3 -11
  263. package/departments/pm/skills/stakeholder-map/SKILL.md +3 -11
  264. package/departments/pm/skills/standup-run/SKILL.md +3 -11
  265. package/departments/pm/skills/story-write/SKILL.md +3 -11
  266. package/departments/quality/agents/copy-director.yaml +10 -4
  267. package/departments/saas/SKILL.md +4 -12
  268. package/departments/saas/skills/benchmark-compare/SKILL.md +3 -11
  269. package/departments/saas/skills/churn-analysis/SKILL.md +3 -11
  270. package/departments/saas/skills/customer-success/SKILL.md +3 -11
  271. package/departments/saas/skills/growth-plan/SKILL.md +13 -12
  272. package/departments/saas/skills/gtm-strategy/SKILL.md +3 -11
  273. package/departments/saas/skills/launch-execute/SKILL.md +3 -11
  274. package/departments/saas/skills/metrics-dashboard/SKILL.md +3 -11
  275. package/departments/saas/skills/micro-saas-stack/SKILL.md +3 -11
  276. package/departments/saas/skills/mvp-build/SKILL.md +3 -11
  277. package/departments/saas/skills/niche-evaluate/SKILL.md +13 -12
  278. package/departments/saas/skills/onboarding-optimize/SKILL.md +3 -11
  279. package/departments/saas/skills/plg-setup/SKILL.md +3 -11
  280. package/departments/saas/skills/pricing-strategy/SKILL.md +3 -11
  281. package/departments/saas/skills/validate-idea/SKILL.md +13 -13
  282. package/departments/sales/SKILL.md +4 -12
  283. package/departments/sales/skills/challenger-sell/SKILL.md +3 -11
  284. package/departments/sales/skills/deal-qualify/SKILL.md +3 -11
  285. package/departments/sales/skills/discovery-call/SKILL.md +3 -11
  286. package/departments/sales/skills/forecast-revenue/SKILL.md +3 -11
  287. package/departments/sales/skills/negotiate-plan/SKILL.md +3 -11
  288. package/departments/sales/skills/objection-handle/SKILL.md +3 -11
  289. package/departments/sales/skills/pipeline-manage/SKILL.md +3 -11
  290. package/departments/sales/skills/pricing-negotiate/SKILL.md +3 -11
  291. package/departments/strategy/SKILL.md +4 -12
  292. package/departments/strategy/skills/blue-ocean/SKILL.md +3 -11
  293. package/departments/strategy/skills/bmc/SKILL.md +3 -11
  294. package/departments/strategy/skills/board-advisor/SKILL.md +3 -11
  295. package/departments/strategy/skills/cto-advisor/SKILL.md +3 -11
  296. package/departments/strategy/skills/extract-data/SKILL.md +3 -11
  297. package/departments/strategy/skills/five-forces/SKILL.md +3 -11
  298. package/departments/strategy/skills/growth-strategy/SKILL.md +15 -14
  299. package/departments/strategy/skills/moat-analysis/SKILL.md +3 -11
  300. package/departments/strategy/skills/position/SKILL.md +3 -11
  301. package/departments/strategy/skills/scenario-plan/SKILL.md +3 -11
  302. package/knowledge/commands-registry.json +3006 -1676
  303. package/knowledge/commands-registry.json.bak +4121 -0
  304. package/package.json +1 -1
  305. package/pyproject.toml +1 -1
  306. package/scripts/__pycache__/migrate_skills_kb_first.cpython-313.pyc +0 -0
  307. package/scripts/__pycache__/synapse-bridge.cpython-314.pyc +0 -0
  308. package/scripts/migrate_skills_kb_first.py +41 -21
  309. package/scripts/tools/__pycache__/prompt_lint.cpython-313.pyc +0 -0
  310. package/scripts/tools/prompt_lint.py +276 -0
@@ -0,0 +1,294 @@
1
+ """Behavioral compiler: agent YAML → runtime subagent markdown (PR-4).
2
+
3
+ The 2026-07-08 frontier prompt audit found that psychometric tables
4
+ (DISC scores, Big Five 0-100, MBTI) never reach the model and cannot be
5
+ operationalized by it — zero production prompts from any frontier lab
6
+ use trait taxonomies; all use behavioral specification. This compiler
7
+ keeps the 4-framework DNA as the DESIGN-TIME source (it differentiates
8
+ 82 agents) and emits the RUNTIME translation: conditional rules, a
9
+ lexical blacklist, a disagreement/escalation protocol with an exit
10
+ condition, and the persona-vs-artifact contract.
11
+
12
+ Single source: `departments/<dept>/agents/<slug>.yaml`. Output:
13
+ `config/claude-agents/<slug>.md` (what the installer copies into every
14
+ project's `.claude/agents/`). Hand-written prompts in _HAND_WRITTEN are
15
+ never overwritten. `tests/python/test_behavioral_compiler.py` locks
16
+ committed output byte-identical to `compile_agent()` of its YAML.
17
+
18
+ CLI:
19
+ arka-py -m core.agents.behavioral_compiler --check # drift check
20
+ arka-py -m core.agents.behavioral_compiler --write # (re)generate
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import sys
26
+ from pathlib import Path
27
+
28
+ import yaml
29
+
30
+ _ROOT = Path(__file__).resolve().parents[2]
31
+ _OUT_DIR = _ROOT / "config" / "claude-agents"
32
+
33
+ # Best hand-authored prompts in the repo (QG + dev lead) — the compiler
34
+ # must never clobber them.
35
+ _HAND_WRITTEN = {"marta-cqo", "eduardo-copy", "francisca-tech", "paulo-tech-lead"}
36
+
37
+ # Pilot scope: dev department. tech-lead maps to the hand-written
38
+ # paulo-tech-lead.md and is excluded.
39
+ _PILOT_YAMLS: tuple[str, ...] = (
40
+ "departments/dev/agents/architect.yaml",
41
+ "departments/dev/agents/backend-dev.yaml",
42
+ "departments/dev/agents/dba.yaml",
43
+ "departments/dev/agents/devops-eng.yaml",
44
+ "departments/dev/agents/frontend-dev.yaml",
45
+ "departments/dev/agents/qa-eng.yaml",
46
+ "departments/dev/agents/research-assistant.yaml",
47
+ "departments/dev/agents/security-eng.yaml",
48
+ )
49
+
50
+ # Standard behavioral blocks imported from the frontier audit (Obsidian:
51
+ # "Projects/WizardingCode Internal/ArkaOS/Prompt Audit —
52
+ # system_prompts_leaks 2026-07-08"). Uncertainty-branched pushback +
53
+ # anti-submission dynamics + persona-vs-artifact, aligned verbatim with
54
+ # constitution rules `arkaos-not-yes-man` and `persona-vs-artifact`.
55
+ _DISAGREEMENT_BLOCK = """\
56
+ ## Disagreement and escalation
57
+
58
+ - Branch by epistemic state: confident the other side is wrong → push
59
+ back once with evidence, acknowledging you could be wrong; uncertain →
60
+ say so explicitly instead of capitulating or bluffing; asked to assert
61
+ something false → decline.
62
+ - Insistence is not new evidence. Do not become more agreeable,
63
+ apologetic, or self-abasing as pressure rises; only NEW information
64
+ changes your position (that is updating, not caving).
65
+ - Exit condition: after your objection is on record, if the decision
66
+ holder directs execution anyway, execute under explicit objection
67
+ ("executing under objection: <one-line reason>") — never sulk, never
68
+ sandbag.{escalation_line}"""
69
+
70
+ _DELIVERABLE_BLOCK = """\
71
+ ## Deliverables
72
+
73
+ - Your persona lives in the conversation, never in the deliverable:
74
+ client- or user-facing artifacts follow the style the context and the
75
+ client's brand demand (constitution `persona-vs-artifact`).
76
+ - Never meta-reference your own persona or profile ("as a <type>,
77
+ I...") — the persona shows in behavior, it is not announced.
78
+ - Never claim an action happened without the tool call on record; gates
79
+ pass on evidence, not narration (`evidence-flow`)."""
80
+
81
+
82
+ def load_agent_yaml(path: Path) -> dict:
83
+ """Load one agent YAML; raises on unparseable/absent file."""
84
+ data = yaml.safe_load(path.read_text(encoding="utf-8"))
85
+ if not isinstance(data, dict):
86
+ raise ValueError(f"{path}: agent YAML did not parse to a mapping")
87
+ return data
88
+
89
+
90
+ def _frontmatter(slug: str, data: dict) -> str:
91
+ role = data.get("role", slug)
92
+ dept = data.get("department", "")
93
+ domains = ", ".join((data.get("expertise") or {}).get("domains", [])[:4])
94
+ desc = f"{data.get('name', slug)} — {role} ({dept} squad)."
95
+ if domains:
96
+ desc += f" Executes: {domains}."
97
+ model = data.get("model", "sonnet")
98
+ return (
99
+ f"---\nname: {slug}\ndescription: >\n {desc}\nmodel: {model}\n---"
100
+ )
101
+
102
+
103
+ def _identity(data: dict) -> str:
104
+ dna = data.get("behavioral_dna") or {}
105
+ enn = dna.get("enneagram") or {}
106
+ name, role = data.get("name", "?"), data.get("role", "?")
107
+ dept, tier = data.get("department", "?"), data.get("tier", "?")
108
+ lines = [f"You are {name}, {role} of the {dept} squad (Tier {tier})."]
109
+ if enn.get("core_motivation"):
110
+ lines.append(f"What drives you: {enn['core_motivation']}.")
111
+ if enn.get("core_fear"):
112
+ lines.append(f"The failure you exist to prevent: {enn['core_fear']}.")
113
+ return " ".join(lines)
114
+
115
+
116
+ def _work_rules(data: dict) -> list[str]:
117
+ # Label form throughout (QG B1/B2): DISC/communication fields are
118
+ # 3rd-person descriptors, not verb complements — gluing them to an
119
+ # imperative produced ungrammatical prompts in 8/8 pilot files.
120
+ dna = data.get("behavioral_dna") or {}
121
+ disc = dna.get("disc") or {}
122
+ comm = data.get("communication") or {}
123
+ rules: list[str] = []
124
+ if disc.get("communication_style"):
125
+ rules.append(f"Communication: {disc['communication_style']}.")
126
+ if comm.get("tone"):
127
+ rules.append(f"Tone: {comm['tone']}.")
128
+ if comm.get("preferred_format"):
129
+ rules.append(f"Default output shape: {comm['preferred_format']}.")
130
+ if disc.get("under_pressure"):
131
+ rules.append(f"Under pressure: {_lc(disc['under_pressure'])}.")
132
+ for item in comm.get("avoid", []):
133
+ rules.append(f"Avoid {item}.")
134
+ return rules
135
+
136
+
137
+ def _lc(text: str) -> str:
138
+ return text[0].lower() + text[1:] if text else text
139
+
140
+
141
+ def build_escalation_index(base: Path) -> dict[str, str]:
142
+ """Map every agent YAML id to a rendered escalation target.
143
+
144
+ Deployed subagents (pilot slugs + hand-written) render as a backtick
145
+ handle; everyone else renders by role and name — a handle that
146
+ resolves to no deployed subagent is worse than no handle (QG B3).
147
+ """
148
+ deployed = {out.stem for _, out in pilot_targets(base)} | _HAND_WRITTEN
149
+ slug_alias = {"tech-lead": "paulo-tech-lead"}
150
+ index: dict[str, str] = {}
151
+ for yaml_path in sorted(base.glob("departments/*/agents/*.yaml")):
152
+ try:
153
+ data = yaml.safe_load(yaml_path.read_text(encoding="utf-8"))
154
+ except Exception:
155
+ continue
156
+ if not isinstance(data, dict) or not data.get("id"):
157
+ continue
158
+ slug = slug_alias.get(yaml_path.stem, yaml_path.stem)
159
+ if slug in deployed:
160
+ index[data["id"]] = f"`{slug}`"
161
+ else:
162
+ role = data.get("role", yaml_path.stem)
163
+ name = data.get("name", "")
164
+ index[data["id"]] = f"the {role}" + (f" ({name})" if name else "")
165
+ return index
166
+
167
+
168
+ def _blacklist(data: dict) -> list[str]:
169
+ markers = data.get("signature_markers") or {}
170
+ seen: list[str] = []
171
+ for phrase in markers.get("avoid_patterns", []):
172
+ if phrase not in seen:
173
+ seen.append(phrase)
174
+ return seen
175
+
176
+
177
+ def _grounding(data: dict) -> str:
178
+ exp = data.get("expertise") or {}
179
+ models = data.get("mental_models") or {}
180
+ frameworks = list(exp.get("frameworks", [])) or list(
181
+ models.get("primary", [])
182
+ )
183
+ if not frameworks:
184
+ return ""
185
+ joined = ", ".join(frameworks)
186
+ return (
187
+ "## Grounding\n\nRecommendations cite the framework behind them — "
188
+ f"yours: {joined}. A recommendation without a named framework or "
189
+ "reference is an opinion; label it as such."
190
+ )
191
+
192
+
193
+ def compile_agent(
194
+ data: dict,
195
+ slug: str,
196
+ yaml_rel_path: str,
197
+ escalation_index: dict[str, str] | None = None,
198
+ ) -> str:
199
+ """Compile one agent YAML dict into runtime subagent markdown."""
200
+ esc = (data.get("authority") or {}).get("escalates_to")
201
+ target = (escalation_index or {}).get(esc, esc) if esc else None
202
+ escalation_line = (
203
+ f"\n- Scope exceeded or deadlock after objection: escalate to "
204
+ f"{target}." if target else ""
205
+ )
206
+ sections = [
207
+ _frontmatter(slug, data),
208
+ f"<!-- generated by core/agents/behavioral_compiler.py from "
209
+ f"{yaml_rel_path} — DO NOT EDIT; edit the YAML and re-run -->",
210
+ f"# {data.get('name', slug)} — {data.get('role', slug)}",
211
+ _identity(data),
212
+ ]
213
+ work_rules = _work_rules(data)
214
+ if work_rules:
215
+ sections.append(
216
+ "## How you work\n\n" + "\n".join(f"- {r}" for r in work_rules)
217
+ )
218
+ blacklist = _blacklist(data)
219
+ if blacklist:
220
+ sections.append(
221
+ "## Never write\n\nThese exact phrases (any casing) are "
222
+ "banned from your output:\n"
223
+ + "\n".join(f'- "{p}"' for p in blacklist)
224
+ )
225
+ sections.append(_DISAGREEMENT_BLOCK.format(escalation_line=escalation_line))
226
+ sections.append(_DELIVERABLE_BLOCK)
227
+ grounding = _grounding(data)
228
+ if grounding:
229
+ sections.append(grounding)
230
+ return "\n\n".join(s for s in sections if s) + "\n"
231
+
232
+
233
+ def pilot_targets(root: Path | None = None) -> list[tuple[Path, Path]]:
234
+ """(yaml_path, output_path) pairs for the pilot scope."""
235
+ base = root or _ROOT
236
+ pairs: list[tuple[Path, Path]] = []
237
+ for rel in _PILOT_YAMLS:
238
+ yaml_path = base / rel
239
+ slug = yaml_path.stem
240
+ if slug in _HAND_WRITTEN:
241
+ continue
242
+ pairs.append((yaml_path, base / "config" / "claude-agents" / f"{slug}.md"))
243
+ return pairs
244
+
245
+
246
+ def check(root: Path | None = None) -> list[str]:
247
+ """Return drift messages (committed output != compiled YAML)."""
248
+ base = root or _ROOT
249
+ index = build_escalation_index(base)
250
+ problems: list[str] = []
251
+ for yaml_path, out_path in pilot_targets(base):
252
+ expected = compile_agent(
253
+ load_agent_yaml(yaml_path), out_path.stem,
254
+ str(yaml_path.relative_to(base)), index,
255
+ )
256
+ if not out_path.exists():
257
+ problems.append(f"{out_path}: missing — run --write")
258
+ elif out_path.read_text(encoding="utf-8") != expected:
259
+ problems.append(
260
+ f"{out_path}: drifted from {yaml_path.name} — run --write"
261
+ )
262
+ return problems
263
+
264
+
265
+ def write(root: Path | None = None) -> list[Path]:
266
+ """(Re)generate every pilot agent; returns written paths."""
267
+ base = root or _ROOT
268
+ index = build_escalation_index(base)
269
+ written: list[Path] = []
270
+ for yaml_path, out_path in pilot_targets(base):
271
+ content = compile_agent(
272
+ load_agent_yaml(yaml_path), out_path.stem,
273
+ str(yaml_path.relative_to(base)), index,
274
+ )
275
+ out_path.write_text(content, encoding="utf-8")
276
+ written.append(out_path)
277
+ return written
278
+
279
+
280
+ def main(argv: list[str] | None = None) -> int:
281
+ args = argv if argv is not None else sys.argv[1:]
282
+ if "--write" in args:
283
+ for path in write():
284
+ print(f"wrote {path}")
285
+ return 0
286
+ problems = check()
287
+ for problem in problems:
288
+ print(problem)
289
+ print("behavioral-compiler: " + ("drift" if problems else "clean"))
290
+ return 1 if problems else 0
291
+
292
+
293
+ if __name__ == "__main__":
294
+ sys.exit(main())
@@ -31,8 +31,8 @@ _TRIVIAL_WORD_THRESHOLD: int = 15
31
31
  _SUGGESTION_TEXT: str = (
32
32
  "Closing marker missing — end every flow-required turn with "
33
33
  "`[arka:gate:4] <label>` (evidence flow review gate) or "
34
- "`[arka:trivial] <reason>` (single-file edit < 10 lines, "
35
- "imperative verb). Without the marker, telemetry can't confirm "
34
+ "`[arka:trivial] <reason>` (single-file edit under 10 lines). "
35
+ "Without the marker, telemetry can't confirm "
36
36
  "the turn closed cleanly."
37
37
  )
38
38
 
@@ -0,0 +1,221 @@
1
+ """Phantom-action soft-block (prompt-surface P0 2026-07-08).
2
+
3
+ Response-side classifier. A "phantom action" is prose in the closing
4
+ assistant message claiming a completed EFFECT ("criei o ficheiro X",
5
+ "fiz commit", "I pushed the fix") in a turn that contains ZERO tool_use
6
+ blocks — narrated work without a tool call on record is the grammatical
7
+ form of delivery-theatre the ``evidence-flow`` rule bans. Pattern
8
+ sourced from the 2026-07-08 prompt audit (Obsidian: "Projects/
9
+ WizardingCode Internal/ArkaOS/Prompt Audit — system_prompts_leaks
10
+ 2026-07-08", finding "anti-phantom-action"; corpus clone at
11
+ ~/AIProjects/system_prompts_leaks).
12
+
13
+ Precision-first: only claims whose completion implies a tool effect are
14
+ flagged. Ambiguous verbs ("escrevi", "wrote", "corri", "ran") count only
15
+ when bound to a concrete effect object (file, commit, tests, module…) —
16
+ "escrevi um resumo abaixo" is response prose, not an effect claim.
17
+
18
+ Mirrors the contract of ``core.governance.closing_marker_check``:
19
+ soft-block, never raises on any input, hooks consume the result and log
20
+ warn-only telemetry before any promotion to hard enforcement.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import json
26
+ import re
27
+ from dataclasses import dataclass, field
28
+
29
+ # Objects whose creation/modification implies a tool effect.
30
+ _EFFECT_OBJECT = (
31
+ r"(?:\b(?:ficheiros?|files?|m[óo]dulos?|modules?|branch(?:es)?|commits?"
32
+ r"|PRs?|pull.requests?|scripts?|testes?|tests?|suites?|classes?"
33
+ r"|fun[çc][õo]es?|functions?|hooks?|configs?|pipelines?|migra[çc][õo]es?"
34
+ r"|migrations?|packages?|releases?|tags?|documentos?|documents?"
35
+ r"|p[áa]ginas?|pages?|componentes?|components?|endpoints?|comandos?"
36
+ r"|commands?|builds?)\b|\.[a-z]{2,4}\b|`[^`]+`)"
37
+ )
38
+
39
+ # Analytic/mental nouns: a verb whose nearest object is one of these is
40
+ # narrating the RESPONSE, not a tool effect ("updated my understanding of
41
+ # the file", "adicionei contexto sobre os testes") — the effect object
42
+ # match must not cross them (QG condition on #255 before enforcement).
43
+ _ANALYTIC_NOUN = (
44
+ r"\b(?:understanding|context|summary|notes?|thinking|thoughts?"
45
+ r"|takeaways?|impressions?|sense|grasp|view|idea|picture"
46
+ r"|mental\s+model|contexto|resumo|notas?|entendimento"
47
+ r"|perce[çc][ãa]o|an[áa]lise|analysis|ideia|vis[ãa]o|imagem"
48
+ r"|no[çc][ãa]o|perspe[ct]?tiva|opini[ãa]o|conhecimento|knowledge)\b"
49
+ )
50
+ _GAP = r"(?:(?!" + _ANALYTIC_NOUN + r")[^.\n!?]){0,60}?"
51
+
52
+ # Verbs whose completion is unambiguous on its own (git/publish/install).
53
+ _STANDALONE_PT = (
54
+ r"(?<!não )\b(instalei|publiquei|gravei|renomeei|implementei"
55
+ r"|fiz\s+(?:o\s+|um\s+)?(?:commit|push|merge|deploy|release|rebase"
56
+ r"|revert))\b"
57
+ )
58
+ _STANDALONE_EN = (
59
+ r"\bI(?:'ve| have)?\s+(?:just\s+)?(committed|pushed|merged|published"
60
+ r"|released|deployed|installed)\b"
61
+ )
62
+ # Ambiguous verbs — only a claim when bound to an effect object nearby,
63
+ # without an analytic noun in between. "ran into"/"ran through" are
64
+ # idioms, never executions.
65
+ _BOUND_PT = (
66
+ r"(?<!não )\b(criei|escrevi|atualizei|editei|apaguei|removi|adicionei"
67
+ r"|movi|apliquei|corri|executei)\b" + _GAP + _EFFECT_OBJECT
68
+ )
69
+ _BOUND_EN = (
70
+ r"\bI(?:'ve| have)?\s+(?:just\s+)?(created|wrote|updated|deleted"
71
+ r"|added|moved|applied|renamed|ran(?!\s+(?:into|through|over|across))"
72
+ r"|executed)\b" + _GAP + _EFFECT_OBJECT
73
+ )
74
+ _PASSIVE = (
75
+ r"\b(commit|push|merge|deploy|release|PR)\s+(feito|criado|efetuado"
76
+ r"|realizado|concluído)\b"
77
+ )
78
+
79
+ _CLAIM_PATTERNS: tuple[re.Pattern[str], ...] = tuple(
80
+ re.compile(p, re.IGNORECASE)
81
+ for p in (_STANDALONE_PT, _STANDALONE_EN, _BOUND_PT, _BOUND_EN, _PASSIVE)
82
+ )
83
+
84
+ _SUGGESTION_TEXT: str = (
85
+ "Phantom action — the closing message narrates a completed effect but "
86
+ "the turn contains no tool call. Prose in the past tense describing an "
87
+ "action is only valid with the corresponding tool call on record "
88
+ "(evidence-flow: gates pass on evidence, never on narration)."
89
+ )
90
+
91
+
92
+ @dataclass(frozen=True)
93
+ class PhantomActionResult:
94
+ """Verdict of a phantom-action check. Immutable; safe to log as JSON."""
95
+
96
+ passed: bool
97
+ reason: str
98
+ claims: list[str] = field(default_factory=list)
99
+ suggestion: str | None = None
100
+
101
+
102
+ def find_action_claims(response_text: str) -> list[str]:
103
+ """Return the distinct completed-effect claims found in the text."""
104
+ text = response_text or ""
105
+ hits: list[str] = []
106
+ for pattern in _CLAIM_PATTERNS:
107
+ for match in pattern.finditer(text):
108
+ token = match.group(0).strip().lower()
109
+ if token not in hits:
110
+ hits.append(token)
111
+ return hits
112
+
113
+
114
+ def count_turn_tool_uses(raw_transcript: str | None) -> int | None:
115
+ """Count tool_use blocks in the final assistant turn of a transcript.
116
+
117
+ The turn is every record after the last REAL user message (a user
118
+ record whose content is not exclusively tool_result blocks). Returns
119
+ None when no parseable records exist OR when no real user message is
120
+ found — callers must fail open on None.
121
+ """
122
+ if not raw_transcript:
123
+ return None
124
+ records = _parse_jsonl(raw_transcript)
125
+ if not records:
126
+ return None
127
+ start = _last_real_user_index(records)
128
+ if start < 0:
129
+ return None
130
+ count = 0
131
+ for record in records[start + 1 :]:
132
+ if _record_role(record) != "assistant":
133
+ continue
134
+ count += _count_tool_use_blocks(record)
135
+ return count
136
+
137
+
138
+ def check_phantom_actions(
139
+ response_text: str, raw_transcript: str | None
140
+ ) -> PhantomActionResult:
141
+ """Classify whether the closing message narrates unbacked effects.
142
+
143
+ Fail-open at every layer: an unparseable transcript skips the check,
144
+ and any unexpected error returns a passing "check-error" result — a
145
+ false PASS is telemetry noise, a false FAIL (or a crash) erodes
146
+ trust in the warn channel.
147
+ """
148
+ try:
149
+ claims = find_action_claims(response_text)
150
+ if not claims:
151
+ return PhantomActionResult(True, "no-claims")
152
+ tool_uses = count_turn_tool_uses(raw_transcript)
153
+ if tool_uses is None:
154
+ return PhantomActionResult(True, "transcript-unparseable", claims)
155
+ if tool_uses > 0:
156
+ return PhantomActionResult(True, "tools-present", claims)
157
+ return PhantomActionResult(
158
+ False, "phantom-action", claims, _SUGGESTION_TEXT
159
+ )
160
+ except Exception:
161
+ return PhantomActionResult(True, "check-error")
162
+
163
+
164
+ def _parse_jsonl(raw: str) -> list[dict]:
165
+ records: list[dict] = []
166
+ for line in raw.splitlines():
167
+ if not line.strip():
168
+ continue
169
+ try:
170
+ record = json.loads(line)
171
+ except json.JSONDecodeError:
172
+ continue
173
+ if isinstance(record, dict):
174
+ records.append(record)
175
+ return records
176
+
177
+
178
+ def _record_message(record: dict) -> dict:
179
+ message = record.get("message")
180
+ return message if isinstance(message, dict) else {}
181
+
182
+
183
+ def _record_role(record: dict) -> str:
184
+ role = record.get("role") or _record_message(record).get("role")
185
+ return role if isinstance(role, str) else ""
186
+
187
+
188
+ def _record_content(record: dict) -> object:
189
+ content = record.get("content")
190
+ if content is None:
191
+ content = _record_message(record).get("content")
192
+ return content
193
+
194
+
195
+ def _last_real_user_index(records: list[dict]) -> int:
196
+ for idx in range(len(records) - 1, -1, -1):
197
+ if _record_role(records[idx]) != "user":
198
+ continue
199
+ content = _record_content(records[idx])
200
+ if isinstance(content, str):
201
+ return idx
202
+ if isinstance(content, list):
203
+ block_types = {
204
+ block.get("type")
205
+ for block in content
206
+ if isinstance(block, dict)
207
+ }
208
+ if block_types - {"tool_result"}:
209
+ return idx
210
+ return -1
211
+
212
+
213
+ def _count_tool_use_blocks(record: dict) -> int:
214
+ content = _record_content(record)
215
+ if not isinstance(content, list):
216
+ return 0
217
+ return sum(
218
+ 1
219
+ for block in content
220
+ if isinstance(block, dict) and block.get("type") == "tool_use"
221
+ )
@@ -28,6 +28,18 @@ class QGBlocker(BaseModel):
28
28
  file: str | None = Field(
29
29
  default=None, description="File (and line if known) of the issue"
30
30
  )
31
+ # Constitution 2.0 (PR-5, 2026-07-08): claim-level verdict vocabulary
32
+ # imported from the frontier review pattern — findings are judged
33
+ # individually, not only the deliverable as a whole.
34
+ verdict: Literal["CONFIRMED", "PLAUSIBLE", "REFUTED"] | None = Field(
35
+ default=None,
36
+ description=(
37
+ "Claim-level verdict after attempting reproduction: CONFIRMED "
38
+ "(reproduced from the code/output), PLAUSIBLE (credible but not "
39
+ "reproduced), REFUTED (disproven — recorded for telemetry, must "
40
+ "NOT count toward rejection)"
41
+ ),
42
+ )
31
43
 
32
44
 
33
45
  class QGEvidenceSummary(BaseModel):
@@ -254,6 +254,28 @@ def _flow_checks(
254
254
  except Exception:
255
255
  pass
256
256
 
257
+ # Prompt-surface P0 2026-07-08 — phantom-action check (warn-only).
258
+ # Narrated effects without a tool call in the turn = the action did
259
+ # not happen (evidence-flow: evidence, never narration).
260
+ phantom_passed = True
261
+ phantom_reason = "no-claims"
262
+ phantom_claims: list = []
263
+ try:
264
+ from core.governance.phantom_action_check import check_phantom_actions
265
+ pr = check_phantom_actions(last, raw)
266
+ phantom_passed = pr.passed
267
+ phantom_reason = pr.reason
268
+ phantom_claims = pr.claims
269
+ if safe_sid:
270
+ _write_tmp_state("arkaos-phantom", safe_sid, {
271
+ "passed": pr.passed,
272
+ "reason": pr.reason,
273
+ "claims": pr.claims,
274
+ "suggestion": pr.suggestion,
275
+ })
276
+ except Exception:
277
+ pass
278
+
257
279
  entry = {
258
280
  "ts": datetime.now(timezone.utc).isoformat(),
259
281
  "session_id": session_id,
@@ -277,6 +299,9 @@ def _flow_checks(
277
299
  "kb_inflated": kb_inflated,
278
300
  "closing_marker_check_passed": closing_check_passed,
279
301
  "closing_marker_check_reason": closing_check_reason,
302
+ "phantom_check_passed": phantom_passed,
303
+ "phantom_check_reason": phantom_reason,
304
+ "phantom_claims": phantom_claims,
280
305
  "effort_level": effort_level,
281
306
  "mode": "warn",
282
307
  }