arkaos 2.20.1 → 2.21.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 (247) hide show
  1. package/VERSION +1 -1
  2. package/arka/SKILL.md +14 -0
  3. package/arka/skills/flow/SKILL.md +14 -0
  4. package/arka/skills/forge/SKILL.md +14 -0
  5. package/config/hooks/post-tool-use.ps1 +80 -0
  6. package/config/hooks/post-tool-use.sh +47 -0
  7. package/config/hooks/pre-tool-use.ps1 +81 -8
  8. package/config/hooks/pre-tool-use.sh +81 -7
  9. package/config/hooks/stop.ps1 +79 -0
  10. package/config/hooks/stop.sh +88 -0
  11. package/config/hooks/user-prompt-submit.ps1 +50 -0
  12. package/config/hooks/user-prompt-submit.sh +24 -0
  13. package/core/cognition/__pycache__/auto_documentor.cpython-313.pyc +0 -0
  14. package/core/cognition/auto_documentor.py +410 -0
  15. package/core/jobs/__init__.py +14 -3
  16. package/core/jobs/__pycache__/__init__.cpython-313.pyc +0 -0
  17. package/core/jobs/__pycache__/auto_doc_worker.cpython-313.pyc +0 -0
  18. package/core/jobs/auto_doc_worker.py +257 -0
  19. package/core/obsidian/__init__.py +30 -3
  20. package/core/obsidian/__pycache__/__init__.cpython-313.pyc +0 -0
  21. package/core/obsidian/__pycache__/cataloger.cpython-313.pyc +0 -0
  22. package/core/obsidian/__pycache__/relator.cpython-313.pyc +0 -0
  23. package/core/obsidian/__pycache__/taxonomy.cpython-313.pyc +0 -0
  24. package/core/obsidian/cataloger.py +251 -0
  25. package/core/obsidian/relator.py +241 -0
  26. package/core/obsidian/taxonomy.py +100 -0
  27. package/core/synapse/__init__.py +8 -1
  28. package/core/synapse/__pycache__/__init__.cpython-313.pyc +0 -0
  29. package/core/synapse/__pycache__/engine.cpython-313.pyc +0 -0
  30. package/core/synapse/__pycache__/kb_cache.cpython-313.pyc +0 -0
  31. package/core/synapse/__pycache__/layers.cpython-313.pyc +0 -0
  32. package/core/synapse/engine.py +15 -1
  33. package/core/synapse/kb_cache.py +125 -6
  34. package/core/synapse/layers.py +296 -0
  35. package/core/workflow/__pycache__/flow_enforcer.cpython-313.pyc +0 -0
  36. package/core/workflow/__pycache__/kb_first_decider.cpython-313.pyc +0 -0
  37. package/core/workflow/__pycache__/marker_cache.cpython-313.pyc +0 -0
  38. package/core/workflow/__pycache__/research_gate.cpython-313.pyc +0 -0
  39. package/core/workflow/flow_enforcer.py +14 -3
  40. package/core/workflow/kb_first_decider.py +63 -0
  41. package/core/workflow/marker_cache.py +147 -0
  42. package/core/workflow/research_gate.py +301 -0
  43. package/departments/brand/SKILL.md +14 -0
  44. package/departments/brand/skills/archetype-finder/SKILL.md +14 -0
  45. package/departments/brand/skills/colors/SKILL.md +14 -0
  46. package/departments/brand/skills/design-system/SKILL.md +14 -0
  47. package/departments/brand/skills/identity-system/SKILL.md +14 -0
  48. package/departments/brand/skills/logo-brief/SKILL.md +14 -0
  49. package/departments/brand/skills/mockup-generate/SKILL.md +14 -0
  50. package/departments/brand/skills/naming-evaluate/SKILL.md +14 -0
  51. package/departments/brand/skills/positioning-statement/SKILL.md +14 -0
  52. package/departments/brand/skills/primal-audit/SKILL.md +14 -0
  53. package/departments/brand/skills/ux-audit/SKILL.md +14 -0
  54. package/departments/brand/skills/voice-guide/SKILL.md +14 -0
  55. package/departments/brand/skills/wireframe/SKILL.md +14 -0
  56. package/departments/community/SKILL.md +14 -0
  57. package/departments/community/skills/ai-community/SKILL.md +14 -0
  58. package/departments/community/skills/betting-setup/SKILL.md +14 -0
  59. package/departments/community/skills/business-model/SKILL.md +14 -0
  60. package/departments/community/skills/content-calendar/SKILL.md +14 -0
  61. package/departments/community/skills/events-plan/SKILL.md +14 -0
  62. package/departments/community/skills/gamification-design/SKILL.md +14 -0
  63. package/departments/community/skills/growth-plan/SKILL.md +14 -0
  64. package/departments/community/skills/metrics-track/SKILL.md +14 -0
  65. package/departments/community/skills/moderation/SKILL.md +14 -0
  66. package/departments/community/skills/monetize-plan/SKILL.md +14 -0
  67. package/departments/community/skills/niche-setup/SKILL.md +14 -0
  68. package/departments/community/skills/onboarding-flow/SKILL.md +14 -0
  69. package/departments/community/skills/platform-select/SKILL.md +14 -0
  70. package/departments/content/SKILL.md +14 -0
  71. package/departments/content/skills/ai-workflow/SKILL.md +14 -0
  72. package/departments/content/skills/analytics/SKILL.md +14 -0
  73. package/departments/content/skills/calendar/SKILL.md +14 -0
  74. package/departments/content/skills/content-system/SKILL.md +14 -0
  75. package/departments/content/skills/monetization-plan/SKILL.md +14 -0
  76. package/departments/content/skills/newsletter-write/SKILL.md +14 -0
  77. package/departments/content/skills/platform-optimize/SKILL.md +14 -0
  78. package/departments/content/skills/repurpose-plan/SKILL.md +14 -0
  79. package/departments/content/skills/script-structure/SKILL.md +14 -0
  80. package/departments/content/skills/short-form/SKILL.md +14 -0
  81. package/departments/content/skills/thumbnail-package/SKILL.md +14 -0
  82. package/departments/content/skills/viral-design/SKILL.md +14 -0
  83. package/departments/content/skills/youtube-strategy/SKILL.md +14 -0
  84. package/departments/dev/SKILL.md +14 -0
  85. package/departments/dev/skills/ai-assisted-dev/SKILL.md +14 -0
  86. package/departments/dev/skills/architecture-design/SKILL.md +14 -0
  87. package/departments/dev/skills/code-review/SKILL.md +14 -0
  88. package/departments/dev/skills/db-design/SKILL.md +14 -0
  89. package/departments/dev/skills/ddd-model/SKILL.md +14 -0
  90. package/departments/dev/skills/demo-gif/SKILL.md +14 -0
  91. package/departments/dev/skills/deploy/SKILL.md +14 -0
  92. package/departments/dev/skills/devops-pipeline/SKILL.md +14 -0
  93. package/departments/dev/skills/docs/SKILL.md +14 -0
  94. package/departments/dev/skills/mcp/SKILL.md +14 -0
  95. package/departments/dev/skills/performance-audit/SKILL.md +14 -0
  96. package/departments/dev/skills/refactor-plan/SKILL.md +14 -0
  97. package/departments/dev/skills/research/SKILL.md +14 -0
  98. package/departments/dev/skills/security-compliance/SKILL.md +14 -0
  99. package/departments/dev/skills/stack-check/SKILL.md +14 -0
  100. package/departments/ecom/SKILL.md +14 -0
  101. package/departments/ecom/skills/analytics/SKILL.md +14 -0
  102. package/departments/ecom/skills/browse-competitor/SKILL.md +14 -0
  103. package/departments/ecom/skills/cart-recovery/SKILL.md +14 -0
  104. package/departments/ecom/skills/cro-optimize/SKILL.md +14 -0
  105. package/departments/ecom/skills/customer-journey/SKILL.md +14 -0
  106. package/departments/ecom/skills/fulfillment-plan/SKILL.md +14 -0
  107. package/departments/ecom/skills/marketplace-manage/SKILL.md +14 -0
  108. package/departments/ecom/skills/pricing-strategy/SKILL.md +14 -0
  109. package/departments/ecom/skills/product-launch/SKILL.md +14 -0
  110. package/departments/ecom/skills/rfm-segment/SKILL.md +14 -0
  111. package/departments/ecom/skills/social-commerce/SKILL.md +14 -0
  112. package/departments/ecom/skills/store-audit/SKILL.md +14 -0
  113. package/departments/ecom/skills/subscription-model/SKILL.md +14 -0
  114. package/departments/finance/SKILL.md +14 -0
  115. package/departments/finance/skills/budget-plan/SKILL.md +14 -0
  116. package/departments/finance/skills/cashflow-forecast/SKILL.md +14 -0
  117. package/departments/finance/skills/ciso-advisor/SKILL.md +14 -0
  118. package/departments/finance/skills/financial-model/SKILL.md +14 -0
  119. package/departments/finance/skills/pitch-deck/SKILL.md +14 -0
  120. package/departments/finance/skills/scenario-analysis/SKILL.md +14 -0
  121. package/departments/finance/skills/unit-economics/SKILL.md +14 -0
  122. package/departments/finance/skills/valuation-model/SKILL.md +14 -0
  123. package/departments/kb/SKILL.md +14 -0
  124. package/departments/kb/skills/ai-research/SKILL.md +14 -0
  125. package/departments/kb/skills/competitive-intel/SKILL.md +14 -0
  126. package/departments/kb/skills/knowledge-review/SKILL.md +14 -0
  127. package/departments/kb/skills/learn-content/SKILL.md +14 -0
  128. package/departments/kb/skills/moc-create/SKILL.md +14 -0
  129. package/departments/kb/skills/persona-build/SKILL.md +14 -0
  130. package/departments/kb/skills/research-plan/SKILL.md +14 -0
  131. package/departments/kb/skills/search-kb/SKILL.md +14 -0
  132. package/departments/kb/skills/source-evaluate/SKILL.md +14 -0
  133. package/departments/kb/skills/taxonomy-manage/SKILL.md +14 -0
  134. package/departments/kb/skills/write-as-persona/SKILL.md +14 -0
  135. package/departments/landing/SKILL.md +14 -0
  136. package/departments/landing/skills/ab-test/SKILL.md +14 -0
  137. package/departments/landing/skills/affiliate-bridge/SKILL.md +14 -0
  138. package/departments/landing/skills/awareness-diagnose/SKILL.md +14 -0
  139. package/departments/landing/skills/email-sequence/SKILL.md +14 -0
  140. package/departments/landing/skills/funnel-metrics/SKILL.md +14 -0
  141. package/departments/landing/skills/headline-write/SKILL.md +14 -0
  142. package/departments/landing/skills/launch-sequence/SKILL.md +14 -0
  143. package/departments/landing/skills/offer-create/SKILL.md +14 -0
  144. package/departments/landing/skills/optimize-page/SKILL.md +14 -0
  145. package/departments/landing/skills/page-architect/SKILL.md +14 -0
  146. package/departments/landing/skills/persuasion-apply/SKILL.md +14 -0
  147. package/departments/landing/skills/webinar-funnel/SKILL.md +14 -0
  148. package/departments/leadership/SKILL.md +14 -0
  149. package/departments/leadership/skills/change-manage/SKILL.md +14 -0
  150. package/departments/leadership/skills/conflict-resolve/SKILL.md +14 -0
  151. package/departments/leadership/skills/culture-audit/SKILL.md +14 -0
  152. package/departments/leadership/skills/delegation-matrix/SKILL.md +14 -0
  153. package/departments/leadership/skills/disc-assess/SKILL.md +14 -0
  154. package/departments/leadership/skills/feedback-give/SKILL.md +14 -0
  155. package/departments/leadership/skills/hiring-plan/SKILL.md +14 -0
  156. package/departments/leadership/skills/performance-review/SKILL.md +14 -0
  157. package/departments/marketing/SKILL.md +14 -0
  158. package/departments/marketing/skills/ab-test/SKILL.md +14 -0
  159. package/departments/marketing/skills/analytics-report/SKILL.md +14 -0
  160. package/departments/marketing/skills/audience-segment/SKILL.md +14 -0
  161. package/departments/marketing/skills/calendar-plan/SKILL.md +14 -0
  162. package/departments/marketing/skills/competitor-analysis/SKILL.md +14 -0
  163. package/departments/marketing/skills/content-audit/SKILL.md +14 -0
  164. package/departments/marketing/skills/email-sequence/SKILL.md +14 -0
  165. package/departments/marketing/skills/growth-loop/SKILL.md +14 -0
  166. package/departments/marketing/skills/marketing-automation/SKILL.md +14 -0
  167. package/departments/marketing/skills/paid-campaign/SKILL.md +14 -0
  168. package/departments/marketing/skills/programmatic-seo/SKILL.md +14 -0
  169. package/departments/marketing/skills/seo-audit/SKILL.md +14 -0
  170. package/departments/marketing/skills/social-strategy/SKILL.md +14 -0
  171. package/departments/ops/SKILL.md +14 -0
  172. package/departments/ops/skills/bottleneck-find/SKILL.md +14 -0
  173. package/departments/ops/skills/dashboard-build/SKILL.md +14 -0
  174. package/departments/ops/skills/gdpr-compliance/SKILL.md +14 -0
  175. package/departments/ops/skills/gtd-setup/SKILL.md +14 -0
  176. package/departments/ops/skills/integration-design/SKILL.md +14 -0
  177. package/departments/ops/skills/iso27001/SKILL.md +14 -0
  178. package/departments/ops/skills/lean-audit/SKILL.md +14 -0
  179. package/departments/ops/skills/metrics-dashboard/SKILL.md +14 -0
  180. package/departments/ops/skills/n8n-flow/SKILL.md +14 -0
  181. package/departments/ops/skills/quality-management/SKILL.md +14 -0
  182. package/departments/ops/skills/risk-management/SKILL.md +14 -0
  183. package/departments/ops/skills/soc2-compliance/SKILL.md +14 -0
  184. package/departments/ops/skills/sop-create/SKILL.md +14 -0
  185. package/departments/ops/skills/workflow-automate/SKILL.md +14 -0
  186. package/departments/ops/skills/zapier-flow/SKILL.md +14 -0
  187. package/departments/org/SKILL.md +14 -0
  188. package/departments/org/skills/compensation-plan/SKILL.md +14 -0
  189. package/departments/org/skills/culture-define/SKILL.md +14 -0
  190. package/departments/org/skills/decision-framework/SKILL.md +14 -0
  191. package/departments/org/skills/hiring-plan/SKILL.md +14 -0
  192. package/departments/org/skills/meeting-optimize/SKILL.md +14 -0
  193. package/departments/org/skills/onboarding-design/SKILL.md +14 -0
  194. package/departments/org/skills/org-design/SKILL.md +14 -0
  195. package/departments/org/skills/remote-setup/SKILL.md +14 -0
  196. package/departments/org/skills/sop-process/SKILL.md +14 -0
  197. package/departments/org/skills/team-assess/SKILL.md +14 -0
  198. package/departments/pm/SKILL.md +14 -0
  199. package/departments/pm/skills/backlog-groom/SKILL.md +14 -0
  200. package/departments/pm/skills/discovery-plan/SKILL.md +14 -0
  201. package/departments/pm/skills/estimate-forecast/SKILL.md +14 -0
  202. package/departments/pm/skills/impact-map/SKILL.md +14 -0
  203. package/departments/pm/skills/kanban-setup/SKILL.md +14 -0
  204. package/departments/pm/skills/risk-register/SKILL.md +14 -0
  205. package/departments/pm/skills/roadmap-build/SKILL.md +14 -0
  206. package/departments/pm/skills/sprint-plan/SKILL.md +14 -0
  207. package/departments/pm/skills/stakeholder-map/SKILL.md +14 -0
  208. package/departments/pm/skills/standup-run/SKILL.md +14 -0
  209. package/departments/pm/skills/story-write/SKILL.md +14 -0
  210. package/departments/saas/SKILL.md +14 -0
  211. package/departments/saas/skills/benchmark-compare/SKILL.md +14 -0
  212. package/departments/saas/skills/churn-analysis/SKILL.md +14 -0
  213. package/departments/saas/skills/customer-success/SKILL.md +14 -0
  214. package/departments/saas/skills/growth-plan/SKILL.md +14 -0
  215. package/departments/saas/skills/gtm-strategy/SKILL.md +14 -0
  216. package/departments/saas/skills/launch-execute/SKILL.md +14 -0
  217. package/departments/saas/skills/metrics-dashboard/SKILL.md +14 -0
  218. package/departments/saas/skills/micro-saas-stack/SKILL.md +14 -0
  219. package/departments/saas/skills/mvp-build/SKILL.md +14 -0
  220. package/departments/saas/skills/niche-evaluate/SKILL.md +14 -0
  221. package/departments/saas/skills/onboarding-optimize/SKILL.md +14 -0
  222. package/departments/saas/skills/plg-setup/SKILL.md +14 -0
  223. package/departments/saas/skills/pricing-strategy/SKILL.md +14 -0
  224. package/departments/saas/skills/validate-idea/SKILL.md +14 -0
  225. package/departments/sales/SKILL.md +14 -0
  226. package/departments/sales/skills/challenger-sell/SKILL.md +14 -0
  227. package/departments/sales/skills/deal-qualify/SKILL.md +14 -0
  228. package/departments/sales/skills/discovery-call/SKILL.md +14 -0
  229. package/departments/sales/skills/forecast-revenue/SKILL.md +14 -0
  230. package/departments/sales/skills/negotiate-plan/SKILL.md +14 -0
  231. package/departments/sales/skills/objection-handle/SKILL.md +14 -0
  232. package/departments/sales/skills/pipeline-manage/SKILL.md +14 -0
  233. package/departments/sales/skills/pricing-negotiate/SKILL.md +14 -0
  234. package/departments/strategy/SKILL.md +14 -0
  235. package/departments/strategy/skills/blue-ocean/SKILL.md +14 -0
  236. package/departments/strategy/skills/bmc/SKILL.md +14 -0
  237. package/departments/strategy/skills/board-advisor/SKILL.md +14 -0
  238. package/departments/strategy/skills/cto-advisor/SKILL.md +14 -0
  239. package/departments/strategy/skills/extract-data/SKILL.md +14 -0
  240. package/departments/strategy/skills/five-forces/SKILL.md +14 -0
  241. package/departments/strategy/skills/growth-strategy/SKILL.md +14 -0
  242. package/departments/strategy/skills/moat-analysis/SKILL.md +14 -0
  243. package/departments/strategy/skills/position/SKILL.md +14 -0
  244. package/departments/strategy/skills/scenario-plan/SKILL.md +14 -0
  245. package/package.json +3 -3
  246. package/pyproject.toml +1 -1
  247. package/scripts/migrate_skills_kb_first.py +137 -0
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.20.1
1
+ 2.21.0
package/arka/SKILL.md CHANGED
@@ -7,6 +7,20 @@ description: >
7
7
  allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, Agent, WebFetch, WebSearch]
8
8
  ---
9
9
 
10
+ <!-- arka:kb-first-prefix begin -->
11
+ ## KB-First Research (non-negotiable)
12
+
13
+ Before any external research (Context7, WebSearch, WebFetch, Firecrawl):
14
+
15
+ 1. Call `mcp__obsidian__search_notes` on the query first.
16
+ 2. Cite relevant hits with `[[wikilinks]]` or explicitly declare a KB gap.
17
+ 3. Only after (1) and (2) may external tools run.
18
+
19
+ The Synapse L2.5 layer pre-injects top KB matches on every user prompt;
20
+ treat them as your default source. External research supplements, it
21
+ does not replace the vault.
22
+ <!-- arka:kb-first-prefix end -->
23
+
10
24
  # ArkaOS v2 — Main Orchestrator
11
25
 
12
26
  > **The Operating System for AI Agent Teams**
@@ -7,6 +7,20 @@ description: >
7
7
  allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, Agent, WebFetch, WebSearch]
8
8
  ---
9
9
 
10
+ <!-- arka:kb-first-prefix begin -->
11
+ ## KB-First Research (non-negotiable)
12
+
13
+ Before any external research (Context7, WebSearch, WebFetch, Firecrawl):
14
+
15
+ 1. Call `mcp__obsidian__search_notes` on the query first.
16
+ 2. Cite relevant hits with `[[wikilinks]]` or explicitly declare a KB gap.
17
+ 3. Only after (1) and (2) may external tools run.
18
+
19
+ The Synapse L2.5 layer pre-injects top KB matches on every user prompt;
20
+ treat them as your default source. External research supplements, it
21
+ does not replace the vault.
22
+ <!-- arka:kb-first-prefix end -->
23
+
10
24
  # ArkaOS — Mandatory Workflow
11
25
 
12
26
  > This flow runs on **every** user request inside an ArkaOS-managed context.
@@ -8,6 +8,20 @@ description: >
8
8
  allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, Agent, WebFetch, WebSearch]
9
9
  ---
10
10
 
11
+ <!-- arka:kb-first-prefix begin -->
12
+ ## KB-First Research (non-negotiable)
13
+
14
+ Before any external research (Context7, WebSearch, WebFetch, Firecrawl):
15
+
16
+ 1. Call `mcp__obsidian__search_notes` on the query first.
17
+ 2. Cite relevant hits with `[[wikilinks]]` or explicitly declare a KB gap.
18
+ 3. Only after (1) and (2) may external tools run.
19
+
20
+ The Synapse L2.5 layer pre-injects top KB matches on every user prompt;
21
+ treat them as your default source. External research supplements, it
22
+ does not replace the vault.
23
+ <!-- arka:kb-first-prefix end -->
24
+
11
25
  # The Forge — ArkaOS Intelligent Planning Engine
12
26
 
13
27
  > **Engine:** `core/forge/` | **Plans stored:** `~/.arkaos/plans/` | **Obsidian:** `ArkaOS/Forge/`
@@ -120,6 +120,86 @@ if ($shouldProcessGotchas -and $null -ne $payload) {
120
120
  $exitCode = if ($null -ne $payload.exit_code) { [string]$payload.exit_code } else { '0' }
121
121
  $cwd = if ($null -ne $payload.cwd) { [string]$payload.cwd } else { '' }
122
122
 
123
+ # --- Flow marker cache write (v2 ALLOW accelerator) ------------------
124
+ # Mirror of the bash hook: detect [arka:routing] or [arka:trivial] in
125
+ # $payload.assistant_message and persist via core.workflow.marker_cache.
126
+ # Non-blocking — any failure is swallowed.
127
+ try {
128
+ $sessionIdPtu = if ($null -ne $payload.session_id) { [string]$payload.session_id } else { '' }
129
+ $assistantMsg = if ($null -ne $payload.assistant_message) { [string]$payload.assistant_message } else { '' }
130
+ if ($sessionIdPtu -and $assistantMsg) {
131
+ $routingRe = [regex]'(?i)\[arka:routing\]\s*([A-Za-z_-]+)\s*->\s*([A-Za-z_-]+)'
132
+ $trivialRe = [regex]'(?i)\[arka:trivial\]\s*\S+'
133
+ $markerKind = ''
134
+ $markerDept = ''
135
+ $markerLead = ''
136
+ $routingMatch = $routingRe.Match($assistantMsg)
137
+ if ($routingMatch.Success) {
138
+ $markerKind = 'routing'
139
+ $markerDept = $routingMatch.Groups[1].Value
140
+ $markerLead = $routingMatch.Groups[2].Value
141
+ } elseif ($trivialRe.IsMatch($assistantMsg)) {
142
+ $markerKind = 'trivial'
143
+ }
144
+ if ($markerKind) {
145
+ $arkaosRootPtu = $env:ARKAOS_ROOT
146
+ if (-not $arkaosRootPtu) {
147
+ $repoPathFile = Join-Path $env:USERPROFILE '.arkaos\.repo-path'
148
+ if (Test-Path -LiteralPath $repoPathFile) {
149
+ try {
150
+ $arkaosRootPtu = (Get-Content -Raw -LiteralPath $repoPathFile -Encoding UTF8).Trim()
151
+ } catch { }
152
+ }
153
+ }
154
+ if (-not $arkaosRootPtu) {
155
+ $arkaosRootPtu = Join-Path $env:USERPROFILE '.arkaos'
156
+ }
157
+ # Locate Python (venv-first, then system).
158
+ $pythonForMarker = $null
159
+ $venvPy = Join-Path $env:USERPROFILE '.arkaos\venv\Scripts\python.exe'
160
+ if (Test-Path -LiteralPath $venvPy) {
161
+ $pythonForMarker = $venvPy
162
+ } else {
163
+ foreach ($cmd in 'python3','python','py') {
164
+ $resolved = Get-Command $cmd -ErrorAction SilentlyContinue
165
+ if ($resolved) { $pythonForMarker = $resolved.Source; break }
166
+ }
167
+ }
168
+ if ($pythonForMarker) {
169
+ $pyCode = @"
170
+ import os
171
+ try:
172
+ from core.workflow.marker_cache import write_marker
173
+ write_marker(
174
+ os.environ.get('SESSION_ID_PTU', ''),
175
+ os.environ.get('MARKER_KIND', ''),
176
+ os.environ.get('MARKER_DEPT', ''),
177
+ os.environ.get('MARKER_LEAD', ''),
178
+ )
179
+ except Exception:
180
+ pass
181
+ "@
182
+ $psi = New-Object System.Diagnostics.ProcessStartInfo
183
+ $psi.FileName = $pythonForMarker
184
+ $psi.Arguments = "-c `"$($pyCode -replace '"','\"' -replace "`r?`n",'; ')`""
185
+ $psi.UseShellExecute = $false
186
+ $psi.CreateNoWindow = $true
187
+ $psi.RedirectStandardOutput = $true
188
+ $psi.RedirectStandardError = $true
189
+ [void]$psi.EnvironmentVariables.Add('SESSION_ID_PTU', $sessionIdPtu)
190
+ [void]$psi.EnvironmentVariables.Add('MARKER_KIND', $markerKind)
191
+ [void]$psi.EnvironmentVariables.Add('MARKER_DEPT', $markerDept)
192
+ [void]$psi.EnvironmentVariables.Add('MARKER_LEAD', $markerLead)
193
+ [void]$psi.EnvironmentVariables.Add('PYTHONPATH', $arkaosRootPtu)
194
+ try {
195
+ $proc = [System.Diagnostics.Process]::Start($psi)
196
+ if (-not $proc.WaitForExit(1500)) { try { $proc.Kill() } catch { } }
197
+ } catch { }
198
+ }
199
+ }
200
+ }
201
+ } catch { }
202
+
123
203
  # ─── Only process when there is actually an error ─────────────────
124
204
  $errorPattern = '(?i)(error:|fatal:|exception:|failed|ENOENT|EACCES|EPERM|panic:)'
125
205
  if ($exitCode -eq '0' -or [string]::IsNullOrEmpty($exitCode)) {
@@ -24,6 +24,53 @@ TOOL_NAME=$(echo "$input" | jq -r '.tool_name // ""' 2>/dev/null)
24
24
  TOOL_OUTPUT=$(echo "$input" | jq -r '.tool_output // ""' 2>/dev/null)
25
25
  EXIT_CODE=$(echo "$input" | jq -r '.exit_code // "0"' 2>/dev/null)
26
26
  CWD=$(echo "$input" | jq -r '.cwd // ""' 2>/dev/null)
27
+ SESSION_ID_PTU=$(echo "$input" | jq -r '.session_id // ""' 2>/dev/null)
28
+ ASSISTANT_MSG=$(echo "$input" | jq -r '.assistant_message // ""' 2>/dev/null)
29
+
30
+ # ─── Flow marker cache write (v2 — turn-scoped ALLOW accelerator) ───────
31
+ # Detect [arka:routing] or [arka:trivial] in the assistant message that
32
+ # accompanied this tool call, and persist it so the PreToolUse enforcer
33
+ # can short-circuit the transcript scan for the rest of the turn.
34
+ # Never blocks the hook — all failures are swallowed.
35
+ if [ -n "$SESSION_ID_PTU" ] && [ -n "$ASSISTANT_MSG" ] && command -v python3 &>/dev/null; then
36
+ _MARKER_KIND=""
37
+ _MARKER_DEPT=""
38
+ _MARKER_LEAD=""
39
+ if printf '%s' "$ASSISTANT_MSG" | grep -qiE '\[arka:routing\][[:space:]]*[A-Za-z_-]+[[:space:]]*->[[:space:]]*[A-Za-z_-]+'; then
40
+ _MARKER_KIND="routing"
41
+ _ROUTE_LINE=$(printf '%s' "$ASSISTANT_MSG" | grep -iEo '\[arka:routing\][[:space:]]*[A-Za-z_-]+[[:space:]]*->[[:space:]]*[A-Za-z_-]+' | head -1)
42
+ _MARKER_DEPT=$(printf '%s' "$_ROUTE_LINE" | sed -E 's/.*\[arka:routing\][[:space:]]*([A-Za-z_-]+).*/\1/')
43
+ _MARKER_LEAD=$(printf '%s' "$_ROUTE_LINE" | sed -E 's/.*->[[:space:]]*([A-Za-z_-]+).*/\1/')
44
+ elif printf '%s' "$ASSISTANT_MSG" | grep -qiE '\[arka:trivial\][[:space:]]*\S+'; then
45
+ _MARKER_KIND="trivial"
46
+ fi
47
+
48
+ if [ -n "$_MARKER_KIND" ]; then
49
+ _MARKER_ROOT="${ARKAOS_ROOT:-}"
50
+ if [ -z "$_MARKER_ROOT" ] && [ -f "$HOME/.arkaos/.repo-path" ]; then
51
+ _MARKER_ROOT=$(cat "$HOME/.arkaos/.repo-path" 2>/dev/null)
52
+ fi
53
+ [ -z "$_MARKER_ROOT" ] && _MARKER_ROOT="$HOME/.arkaos"
54
+ SESSION_ID_PTU="$SESSION_ID_PTU" \
55
+ MARKER_KIND="$_MARKER_KIND" \
56
+ MARKER_DEPT="$_MARKER_DEPT" \
57
+ MARKER_LEAD="$_MARKER_LEAD" \
58
+ PYTHONPATH="$_MARKER_ROOT" \
59
+ python3 -c "
60
+ import os, sys
61
+ try:
62
+ from core.workflow.marker_cache import write_marker
63
+ write_marker(
64
+ os.environ.get('SESSION_ID_PTU', ''),
65
+ os.environ.get('MARKER_KIND', ''),
66
+ os.environ.get('MARKER_DEPT', ''),
67
+ os.environ.get('MARKER_LEAD', ''),
68
+ )
69
+ except Exception:
70
+ pass
71
+ " 2>/dev/null || true
72
+ fi
73
+ fi
27
74
 
28
75
  # Only process if there was an error
29
76
  if [ "$EXIT_CODE" = "0" ] || [ -z "$EXIT_CODE" ]; then
@@ -27,11 +27,6 @@ $transcriptPath = [string]$inp.transcript_path
27
27
  $sessionId = [string]$inp.session_id
28
28
  $cwd = [string]$inp.cwd
29
29
 
30
- # --- Fast allow: not a gated tool ---
31
- if ($toolName -ne "Write" -and $toolName -ne "Edit" -and $toolName -ne "MultiEdit") {
32
- exit 0
33
- }
34
-
35
30
  # --- Resolve ARKAOS_ROOT ---
36
31
  if ([string]::IsNullOrWhiteSpace($env:ARKAOS_ROOT)) {
37
32
  $repoPathFile = Join-Path $HOME ".arkaos/.repo-path"
@@ -44,13 +39,91 @@ if ([string]::IsNullOrWhiteSpace($env:ARKAOS_ROOT)) {
44
39
  }
45
40
  }
46
41
 
47
- $enforcerPy = Join-Path $env:ARKAOS_ROOT "core/workflow/flow_enforcer.py"
48
- if (-not (Test-Path $enforcerPy)) { exit 0 }
49
-
50
42
  $python = Get-Command python3 -ErrorAction SilentlyContinue
51
43
  if (-not $python) { $python = Get-Command python -ErrorAction SilentlyContinue }
52
44
  if (-not $python) { exit 0 }
53
45
 
46
+ # --- KB-first gate (Task #6, runs before flow-marker gate) ---
47
+ $queryHint = ""
48
+ if ($inp.tool_input) {
49
+ if ($inp.tool_input.query) { $queryHint = [string]$inp.tool_input.query }
50
+ elseif ($inp.tool_input.prompt) { $queryHint = [string]$inp.tool_input.prompt }
51
+ elseif ($inp.tool_input.url) { $queryHint = [string]$inp.tool_input.url }
52
+ if ($queryHint.Length -gt 500) { $queryHint = $queryHint.Substring(0, 500) }
53
+ }
54
+
55
+ $researchGatePy = Join-Path $env:ARKAOS_ROOT "core/workflow/research_gate.py"
56
+ if (Test-Path $researchGatePy) {
57
+ $env:TOOL_NAME = $toolName
58
+ $env:SESSION_ID = $sessionId
59
+ $env:QUERY_HINT = $queryHint
60
+
61
+ $kbScript = @'
62
+ import json
63
+ import os
64
+ import sys
65
+
66
+ sys.path.insert(0, os.environ["ARKAOS_ROOT"])
67
+ try:
68
+ from core.workflow.research_gate import evaluate_research_gate, record_telemetry
69
+ except Exception:
70
+ print(json.dumps({"allow": True, "nudge": False, "reason": "kb-gate-import-failed"}))
71
+ sys.exit(0)
72
+
73
+ decision = evaluate_research_gate(
74
+ tool_name=os.environ.get("TOOL_NAME", ""),
75
+ session_id=os.environ.get("SESSION_ID", ""),
76
+ query=os.environ.get("QUERY_HINT", ""),
77
+ )
78
+ try:
79
+ record_telemetry(
80
+ session_id=os.environ.get("SESSION_ID", ""),
81
+ tool=os.environ.get("TOOL_NAME", ""),
82
+ decision=decision,
83
+ )
84
+ except Exception:
85
+ pass
86
+ print(json.dumps({
87
+ "allow": decision.allow,
88
+ "nudge": decision.nudge,
89
+ "reason": decision.reason,
90
+ "stderr_msg": decision.to_stderr_message(),
91
+ }))
92
+ '@
93
+
94
+ $kbDecisionJson = $kbScript | & $python.Source -
95
+ if (-not [string]::IsNullOrWhiteSpace($kbDecisionJson)) {
96
+ try {
97
+ $kbDecision = $kbDecisionJson | ConvertFrom-Json
98
+ } catch { $kbDecision = $null }
99
+
100
+ if ($kbDecision -and -not $kbDecision.allow) {
101
+ [Console]::Error.WriteLine($kbDecision.stderr_msg)
102
+ $denyOut = @{
103
+ hookSpecificOutput = @{
104
+ hookEventName = "PreToolUse"
105
+ permissionDecision = "deny"
106
+ permissionDecisionReason = $kbDecision.stderr_msg
107
+ }
108
+ } | ConvertTo-Json -Compress -Depth 5
109
+ Write-Output $denyOut
110
+ exit 2
111
+ }
112
+
113
+ if ($kbDecision -and $kbDecision.nudge -and -not [string]::IsNullOrWhiteSpace($kbDecision.stderr_msg)) {
114
+ [Console]::Error.WriteLine($kbDecision.stderr_msg)
115
+ }
116
+ }
117
+ }
118
+
119
+ # --- Fast allow: not a flow-gated tool ---
120
+ if ($toolName -ne "Write" -and $toolName -ne "Edit" -and $toolName -ne "MultiEdit") {
121
+ exit 0
122
+ }
123
+
124
+ $enforcerPy = Join-Path $env:ARKAOS_ROOT "core/workflow/flow_enforcer.py"
125
+ if (-not (Test-Path $enforcerPy)) { exit 0 }
126
+
54
127
  # --- Delegate to Python enforcer ---
55
128
  $env:TOOL_NAME = $toolName
56
129
  $env:TRANSCRIPT_PATH = $transcriptPath
@@ -31,12 +31,6 @@ if command -v jq &>/dev/null; then
31
31
  CWD=$(echo "$input" | jq -r '.cwd // ""' 2>/dev/null)
32
32
  fi
33
33
 
34
- # ─── Fast allow: not a gated tool
35
- case "$TOOL_NAME" in
36
- Write|Edit|MultiEdit) ;;
37
- *) exit 0 ;;
38
- esac
39
-
40
34
  # ─── Resolve ARKAOS_ROOT (same rules as user-prompt-submit.sh) ──────────
41
35
  if [ -z "${ARKAOS_ROOT:-}" ]; then
42
36
  if [ -f "$HOME/.arkaos/.repo-path" ]; then
@@ -48,10 +42,90 @@ if [ -z "${ARKAOS_ROOT:-}" ]; then
48
42
  fi
49
43
  fi
50
44
 
51
- # ─── Degrade gracefully if Python or module is unavailable ──────────────
45
+ # ─── Degrade gracefully if Python is unavailable ────────────────────────
52
46
  if ! command -v python3 &>/dev/null; then
53
47
  exit 0
54
48
  fi
49
+
50
+ # ─── KB-first gate (Task #6, independent from flow_enforcer) ────────────
51
+ # Runs BEFORE the flow-marker gate so that external research tools are
52
+ # always KB-checked regardless of whether the tool is Write/Edit/MultiEdit.
53
+ # Extract the user query (if present) to feed the nudge generator.
54
+ QUERY_HINT=""
55
+ if command -v jq &>/dev/null; then
56
+ QUERY_HINT=$(echo "$input" | jq -r '.tool_input.query // .tool_input.prompt // .tool_input.url // ""' 2>/dev/null | head -c 500)
57
+ fi
58
+
59
+ if [ -f "$ARKAOS_ROOT/core/workflow/research_gate.py" ]; then
60
+ KB_DECISION_JSON=$(TOOL_NAME="$TOOL_NAME" \
61
+ SESSION_ID="$SESSION_ID" \
62
+ QUERY_HINT="$QUERY_HINT" \
63
+ ARKAOS_ROOT="$ARKAOS_ROOT" \
64
+ python3 - <<'PY' 2>/dev/null
65
+ import json
66
+ import os
67
+ import sys
68
+
69
+ sys.path.insert(0, os.environ["ARKAOS_ROOT"])
70
+ try:
71
+ from core.workflow.research_gate import evaluate_research_gate, record_telemetry
72
+ except Exception:
73
+ print(json.dumps({"allow": True, "nudge": False, "reason": "kb-gate-import-failed"}))
74
+ sys.exit(0)
75
+
76
+ decision = evaluate_research_gate(
77
+ tool_name=os.environ.get("TOOL_NAME", ""),
78
+ session_id=os.environ.get("SESSION_ID", ""),
79
+ query=os.environ.get("QUERY_HINT", ""),
80
+ )
81
+ try:
82
+ record_telemetry(
83
+ session_id=os.environ.get("SESSION_ID", ""),
84
+ tool=os.environ.get("TOOL_NAME", ""),
85
+ decision=decision,
86
+ )
87
+ except Exception:
88
+ pass
89
+ print(json.dumps({
90
+ "allow": decision.allow,
91
+ "nudge": decision.nudge,
92
+ "reason": decision.reason,
93
+ "stderr_msg": decision.to_stderr_message(),
94
+ }))
95
+ PY
96
+ )
97
+
98
+ if [ -n "$KB_DECISION_JSON" ]; then
99
+ KB_ALLOW=$(echo "$KB_DECISION_JSON" | python3 -c "import json,sys; print(json.load(sys.stdin).get('allow', True))" 2>/dev/null)
100
+ KB_NUDGE=$(echo "$KB_DECISION_JSON" | python3 -c "import json,sys; print(json.load(sys.stdin).get('nudge', False))" 2>/dev/null)
101
+ KB_STDERR=$(echo "$KB_DECISION_JSON" | python3 -c "import json,sys; print(json.load(sys.stdin).get('stderr_msg',''))" 2>/dev/null)
102
+
103
+ if [ "$KB_ALLOW" != "True" ] && [ "$KB_ALLOW" != "true" ]; then
104
+ echo "$KB_STDERR" >&2
105
+ STDERR_MSG="$KB_STDERR" python3 - <<'PY'
106
+ import json, os
107
+ print(json.dumps({"hookSpecificOutput": {
108
+ "hookEventName": "PreToolUse",
109
+ "permissionDecision": "deny",
110
+ "permissionDecisionReason": os.environ.get("STDERR_MSG", ""),
111
+ }}))
112
+ PY
113
+ exit 2
114
+ fi
115
+
116
+ # Nudge path: emit advisory to stderr, continue to flow-marker gate.
117
+ if [ "$KB_NUDGE" = "True" ] || [ "$KB_NUDGE" = "true" ]; then
118
+ [ -n "$KB_STDERR" ] && echo "$KB_STDERR" >&2
119
+ fi
120
+ fi
121
+ fi
122
+
123
+ # ─── Fast allow: not a flow-gated tool (Write/Edit/MultiEdit) ───────────
124
+ case "$TOOL_NAME" in
125
+ Write|Edit|MultiEdit) ;;
126
+ *) exit 0 ;;
127
+ esac
128
+
55
129
  if [ ! -f "$ARKAOS_ROOT/core/workflow/flow_enforcer.py" ]; then
56
130
  exit 0
57
131
  fi
@@ -104,6 +104,85 @@ except Exception:
104
104
 
105
105
  $pyScript | & $python.Source - | Out-Null
106
106
 
107
+ # ─── Auto-documentor enqueue (fire-and-forget) ─────────────────────────
108
+ # Queues a background job when classifier flagged flow, QG approved, and
109
+ # external research happened. Never blocks the Stop hook.
110
+ $env:SESSION_ID_VAL = $sessionId
111
+ $env:TRANSCRIPT_PATH_VAL = $transcriptPath
112
+ $env:CWD_VAL = $cwd
113
+ $env:ARKAOS_ROOT = $env:ARKAOS_ROOT
114
+
115
+ $autoDocScript = @'
116
+ import json
117
+ import os
118
+ import re
119
+ import sys
120
+ from pathlib import Path
121
+
122
+ sys.path.insert(0, os.environ.get("ARKAOS_ROOT", ""))
123
+ try:
124
+ from core.jobs.auto_doc_worker import enqueue_job
125
+ from core.workflow.flow_enforcer import _load_last_assistant_messages
126
+ except Exception:
127
+ sys.exit(0)
128
+
129
+ session_id = os.environ.get("SESSION_ID_VAL", "")
130
+ transcript_path = os.environ.get("TRANSCRIPT_PATH_VAL", "")
131
+ if not session_id or not transcript_path:
132
+ sys.exit(0)
133
+
134
+ last = ""
135
+ try:
136
+ msgs = _load_last_assistant_messages(transcript_path, n=1)
137
+ last = msgs[-1] if msgs else ""
138
+ except Exception:
139
+ last = ""
140
+
141
+ qg_approved = bool(re.search(r"\[arka:qg:approved\]", last, re.IGNORECASE))
142
+ if not qg_approved:
143
+ qg_log = Path.home() / ".arkaos" / "telemetry" / "qg.jsonl"
144
+ if qg_log.exists():
145
+ try:
146
+ for line in reversed(qg_log.read_text(encoding="utf-8").splitlines()):
147
+ if not line.strip():
148
+ continue
149
+ try:
150
+ rec = json.loads(line)
151
+ except Exception:
152
+ continue
153
+ if rec.get("session_id") == session_id:
154
+ qg_approved = rec.get("verdict", "").upper() == "APPROVED"
155
+ break
156
+ except Exception:
157
+ pass
158
+ if not qg_approved:
159
+ sys.exit(0)
160
+
161
+ external_markers = (
162
+ "WebFetch", "WebSearch", "mcp__context7", "mcp__firecrawl",
163
+ "http://", "https://",
164
+ )
165
+ has_external = False
166
+ try:
167
+ data = Path(transcript_path).read_text(encoding="utf-8", errors="replace")
168
+ has_external = any(marker in data for marker in external_markers)
169
+ except Exception:
170
+ has_external = False
171
+ if not has_external:
172
+ sys.exit(0)
173
+
174
+ try:
175
+ enqueue_job(session_id, transcript_path, "APPROVED")
176
+ except Exception:
177
+ pass
178
+ '@
179
+
180
+ try {
181
+ $autoDocScript | & $python.Source - | Out-Null
182
+ } catch {
183
+ # Swallow — enqueue is fire-and-forget.
184
+ }
185
+
107
186
  # Belt-and-braces marker cleanup (safe even if the Python block crashed).
108
187
  if ($sessionId -match '^[A-Za-z0-9._-]{1,128}$') {
109
188
  Remove-Item -LiteralPath $wfMarker -ErrorAction SilentlyContinue
@@ -115,6 +115,94 @@ except Exception:
115
115
  pass
116
116
  PY
117
117
 
118
+ # ─── Auto-documentor enqueue (fire-and-forget) ──────────────────────────
119
+ # Queues a background job when:
120
+ # (a) the session was flagged flow-required (classifier match above),
121
+ # (b) Quality Gate approved — last assistant message carries
122
+ # `[arka:qg:approved]`, OR the most recent entry for this session
123
+ # in ~/.arkaos/telemetry/qg.jsonl has verdict APPROVED, AND
124
+ # (c) at least one external research tool was invoked this session
125
+ # (URL, WebFetch/WebSearch, Context7, Firecrawl in the transcript).
126
+ # The actual documentation runs async via `core/jobs/auto_doc_worker.py`;
127
+ # this block never blocks Stop — 2s Python budget, errors swallowed.
128
+ if command -v timeout &>/dev/null; then
129
+ _ARKA_AUTO_DOC_RUNNER=(timeout 2s python3 -)
130
+ elif command -v gtimeout &>/dev/null; then
131
+ _ARKA_AUTO_DOC_RUNNER=(gtimeout 2s python3 -)
132
+ else
133
+ _ARKA_AUTO_DOC_RUNNER=(python3 -)
134
+ fi
135
+
136
+ SESSION_ID_VAL="$SESSION_ID" \
137
+ TRANSCRIPT_PATH_VAL="$TRANSCRIPT_PATH" \
138
+ CWD_VAL="$CWD" \
139
+ ARKAOS_ROOT_VAL="$ARKAOS_ROOT" \
140
+ "${_ARKA_AUTO_DOC_RUNNER[@]}" <<'PY' 2>/dev/null || true
141
+ import json
142
+ import os
143
+ import re
144
+ import sys
145
+ from pathlib import Path
146
+
147
+ sys.path.insert(0, os.environ["ARKAOS_ROOT_VAL"])
148
+ try:
149
+ from core.jobs.auto_doc_worker import enqueue_job
150
+ from core.workflow.flow_enforcer import _load_last_assistant_messages
151
+ except Exception:
152
+ sys.exit(0)
153
+
154
+ session_id = os.environ.get("SESSION_ID_VAL", "")
155
+ transcript_path = os.environ.get("TRANSCRIPT_PATH_VAL", "")
156
+ if not session_id or not transcript_path:
157
+ sys.exit(0)
158
+
159
+ last = ""
160
+ try:
161
+ msgs = _load_last_assistant_messages(transcript_path, n=1)
162
+ last = msgs[-1] if msgs else ""
163
+ except Exception:
164
+ last = ""
165
+
166
+ qg_approved = bool(re.search(r"\[arka:qg:approved\]", last, re.IGNORECASE))
167
+ if not qg_approved:
168
+ qg_log = Path.home() / ".arkaos" / "telemetry" / "qg.jsonl"
169
+ if qg_log.exists():
170
+ try:
171
+ for line in reversed(qg_log.read_text(encoding="utf-8").splitlines()):
172
+ if not line.strip():
173
+ continue
174
+ try:
175
+ rec = json.loads(line)
176
+ except Exception:
177
+ continue
178
+ if rec.get("session_id") == session_id:
179
+ qg_approved = rec.get("verdict", "").upper() == "APPROVED"
180
+ break
181
+ except Exception:
182
+ pass
183
+ if not qg_approved:
184
+ sys.exit(0)
185
+
186
+ # Heuristic check that some external research happened this session.
187
+ external_markers = (
188
+ "WebFetch", "WebSearch", "mcp__context7", "mcp__firecrawl",
189
+ "http://", "https://",
190
+ )
191
+ has_external = False
192
+ try:
193
+ data = Path(transcript_path).read_text(encoding="utf-8", errors="replace")
194
+ has_external = any(marker in data for marker in external_markers)
195
+ except Exception:
196
+ has_external = False
197
+ if not has_external:
198
+ sys.exit(0)
199
+
200
+ try:
201
+ enqueue_job(session_id, transcript_path, "APPROVED")
202
+ except Exception:
203
+ pass
204
+ PY
205
+
118
206
  # Belt-and-braces: remove the marker at shell level in case the Python
119
207
  # block above crashed before reaching clear_flow_required(). Session_id
120
208
  # is already validated by the Python helper; this shell remove is scoped
@@ -63,6 +63,56 @@ if (-not $v2Installed) {
63
63
  # --- Performance timing ----------------------------------------------------
64
64
  $sw = [System.Diagnostics.Stopwatch]::StartNew()
65
65
 
66
+ # --- Flow marker cache invalidation (v2 — new turn resets ALLOW cache) ---
67
+ # Runs before the Synapse bridge so a stuck Python call cannot leave a
68
+ # stale marker across turns. Non-blocking — all failures swallowed.
69
+ try {
70
+ $sessionIdUps = ''
71
+ if ($payload -and $payload.session_id) {
72
+ $sessionIdUps = [string]$payload.session_id
73
+ }
74
+ if ($sessionIdUps) {
75
+ $arkaosRootUps = $env:ARKAOS_ROOT
76
+ if (-not $arkaosRootUps) {
77
+ $repoPathFileUps = Join-Path $env:USERPROFILE '.arkaos\.repo-path'
78
+ if (Test-Path -LiteralPath $repoPathFileUps) {
79
+ try {
80
+ $arkaosRootUps = (Get-Content -Raw -LiteralPath $repoPathFileUps -Encoding UTF8).Trim()
81
+ } catch { }
82
+ }
83
+ }
84
+ if (-not $arkaosRootUps) {
85
+ $arkaosRootUps = Join-Path $env:USERPROFILE '.arkaos'
86
+ }
87
+ $pythonForInvalidate = $null
88
+ $venvPyUps = Join-Path $env:USERPROFILE '.arkaos\venv\Scripts\python.exe'
89
+ if (Test-Path -LiteralPath $venvPyUps) {
90
+ $pythonForInvalidate = $venvPyUps
91
+ } else {
92
+ foreach ($cmd in 'python3','python','py') {
93
+ $resolvedUps = Get-Command $cmd -ErrorAction SilentlyContinue
94
+ if ($resolvedUps) { $pythonForInvalidate = $resolvedUps.Source; break }
95
+ }
96
+ }
97
+ if ($pythonForInvalidate) {
98
+ $pyCode = "import os`ntry:`n from core.workflow.marker_cache import invalidate_marker`n invalidate_marker(os.environ.get('SESSION_ID_UPS',''))`nexcept Exception:`n pass`ntry:`n from core.synapse.kb_cache import invalidate_obsidian_query`n invalidate_obsidian_query(os.environ.get('SESSION_ID_UPS',''))`nexcept Exception:`n pass"
99
+ $psi = New-Object System.Diagnostics.ProcessStartInfo
100
+ $psi.FileName = $pythonForInvalidate
101
+ $psi.Arguments = "-c `"$($pyCode -replace '"','\"' -replace "`r?`n",'; ')`""
102
+ $psi.UseShellExecute = $false
103
+ $psi.CreateNoWindow = $true
104
+ $psi.RedirectStandardOutput = $true
105
+ $psi.RedirectStandardError = $true
106
+ [void]$psi.EnvironmentVariables.Add('SESSION_ID_UPS', $sessionIdUps)
107
+ [void]$psi.EnvironmentVariables.Add('PYTHONPATH', $arkaosRootUps)
108
+ try {
109
+ $procUps = [System.Diagnostics.Process]::Start($psi)
110
+ if (-not $procUps.WaitForExit(1500)) { try { $procUps.Kill() } catch { } }
111
+ } catch { }
112
+ }
113
+ }
114
+ } catch { }
115
+
66
116
  # --- Sync version detection ------------------------------------------------
67
117
  $syncNotice = ''
68
118
  $arkaosHome = Join-Path $env:USERPROFILE '.arkaos'