@hassangameryt/freeflow 0.5.0 → 0.7.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 (301) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/.codex-plugin/plugin.json +4 -5
  4. package/README.md +141 -163
  5. package/capabilities/cognitive-routing/SKILL.md +387 -0
  6. package/capabilities/context-virtualization/SKILL.md +103 -0
  7. package/capabilities/conversation-history/SKILL.md +53 -0
  8. package/command-surface.json +6 -37
  9. package/hooks/freeflow-runtime-context.mjs +50 -541
  10. package/hooks/hooks.json +1 -26
  11. package/hooks/tests/check-runtime-context-hook.sh +114 -308
  12. package/package.json +27 -17
  13. package/pi-extension/dist/cognitive-routing/commands.js +96 -0
  14. package/pi-extension/dist/cognitive-routing/config.js +232 -0
  15. package/pi-extension/dist/cognitive-routing/controller.js +1292 -0
  16. package/pi-extension/dist/cognitive-routing/history.js +451 -0
  17. package/pi-extension/dist/cognitive-routing/host.js +188 -0
  18. package/pi-extension/dist/cognitive-routing/pi-routing-session.js +414 -0
  19. package/pi-extension/dist/cognitive-routing/pi-session-control.js +320 -0
  20. package/pi-extension/dist/cognitive-routing/runtime.js +43 -0
  21. package/pi-extension/dist/cognitive-routing/tool.js +212 -0
  22. package/pi-extension/dist/cognitive-routing/types.js +6 -0
  23. package/pi-extension/dist/context-virtualization/commands.js +89 -0
  24. package/pi-extension/dist/context-virtualization/projector.js +42 -0
  25. package/pi-extension/dist/context-virtualization/runtime.js +356 -0
  26. package/pi-extension/dist/context-virtualization/state.js +57 -0
  27. package/pi-extension/dist/context-virtualization/types.js +10 -0
  28. package/pi-extension/dist/conversation-history/passages.js +66 -0
  29. package/pi-extension/dist/conversation-history/ranking.js +105 -0
  30. package/pi-extension/dist/conversation-history/runtime.js +226 -0
  31. package/pi-extension/dist/conversation-history/search.js +56 -0
  32. package/pi-extension/dist/conversation-history/types.js +1 -0
  33. package/pi-extension/dist/freeflow-context/resolver.js +120 -0
  34. package/pi-extension/dist/freeflow-context/runtime.js +80 -0
  35. package/pi-extension/dist/freeflow-context/source-projector.js +95 -0
  36. package/pi-extension/dist/freeflow-context/tool.js +308 -0
  37. package/pi-extension/dist/freeflow-context/types.js +12 -0
  38. package/pi-extension/dist/freeflow-context/visibility.js +28 -0
  39. package/pi-extension/dist/index.js +564 -129
  40. package/pi-extension/dist/runtime/runtime-context.js +357 -470
  41. package/pi-extension/dist/runtime/runtime-identity.js +5 -0
  42. package/pi-extension/dist/settings/settings-tui.js +78 -0
  43. package/pi-extension/dist/settings/settings-ui.js +572 -826
  44. package/pi-extension/dist/ui/text-component.js +57 -0
  45. package/pi-extension/src/cognitive-routing/commands.ts +129 -0
  46. package/pi-extension/src/cognitive-routing/config.ts +303 -0
  47. package/pi-extension/src/cognitive-routing/controller.ts +1628 -0
  48. package/pi-extension/src/cognitive-routing/history.ts +650 -0
  49. package/pi-extension/src/cognitive-routing/host.ts +266 -0
  50. package/pi-extension/src/cognitive-routing/pi-routing-session.ts +538 -0
  51. package/pi-extension/src/cognitive-routing/pi-session-control.ts +444 -0
  52. package/pi-extension/src/cognitive-routing/runtime.ts +57 -0
  53. package/pi-extension/src/cognitive-routing/tool.ts +273 -0
  54. package/pi-extension/src/cognitive-routing/types.ts +89 -0
  55. package/pi-extension/src/context-virtualization/commands.ts +111 -0
  56. package/pi-extension/src/context-virtualization/projector.ts +62 -0
  57. package/pi-extension/src/context-virtualization/runtime.ts +406 -0
  58. package/pi-extension/src/context-virtualization/state.ts +79 -0
  59. package/pi-extension/src/context-virtualization/types.ts +92 -0
  60. package/pi-extension/src/conversation-history/passages.ts +81 -0
  61. package/pi-extension/src/conversation-history/ranking.ts +155 -0
  62. package/pi-extension/src/conversation-history/runtime.ts +250 -0
  63. package/pi-extension/src/conversation-history/search.ts +79 -0
  64. package/pi-extension/src/conversation-history/types.ts +31 -0
  65. package/pi-extension/src/freeflow-context/resolver.ts +139 -0
  66. package/pi-extension/src/freeflow-context/runtime.ts +100 -0
  67. package/pi-extension/src/freeflow-context/source-projector.ts +106 -0
  68. package/pi-extension/src/freeflow-context/tool.ts +360 -0
  69. package/pi-extension/src/freeflow-context/types.ts +70 -0
  70. package/pi-extension/src/freeflow-context/visibility.ts +53 -0
  71. package/pi-extension/src/index.ts +597 -135
  72. package/pi-extension/src/runtime/runtime-context.ts +373 -491
  73. package/pi-extension/src/runtime/runtime-identity.ts +8 -0
  74. package/pi-extension/src/settings/settings-tui.ts +93 -0
  75. package/pi-extension/src/settings/settings-ui.ts +679 -910
  76. package/pi-extension/src/ui/text-component.ts +66 -0
  77. package/pi-extension/tests/cognitive-routing/commands.test.js +134 -0
  78. package/pi-extension/tests/cognitive-routing/controller.test.js +1128 -0
  79. package/pi-extension/tests/cognitive-routing/extension-lifecycle.test.js +1142 -0
  80. package/pi-extension/tests/cognitive-routing/history.test.js +274 -0
  81. package/pi-extension/tests/cognitive-routing/host-fixture.js +4 -0
  82. package/pi-extension/tests/cognitive-routing/host-identity.test.js +63 -0
  83. package/pi-extension/tests/cognitive-routing/pi-normal-lifecycle.test.js +434 -0
  84. package/pi-extension/tests/cognitive-routing/pi-session-control.test.js +174 -0
  85. package/pi-extension/tests/cognitive-routing/pi-session-history.test.js +91 -0
  86. package/pi-extension/tests/cognitive-routing/profile-resolution.test.js +279 -0
  87. package/pi-extension/tests/cognitive-routing/tool.test.js +230 -0
  88. package/pi-extension/tests/context-virtualization/extension.test.js +749 -0
  89. package/pi-extension/tests/context-virtualization/projector.test.js +110 -0
  90. package/pi-extension/tests/context-virtualization/runtime.test.js +216 -0
  91. package/pi-extension/tests/conversation-history/runtime.test.js +98 -0
  92. package/pi-extension/tests/conversation-history/search.test.js +97 -0
  93. package/pi-extension/tests/integration/mode-free-core.test.js +218 -0
  94. package/pi-extension/tests/integration/pi-extension.test.js +532 -3701
  95. package/pi-extension/tests/integration/prompt-architecture.test.js +350 -0
  96. package/pi-extension/tests/integration/unaffected-regressions.test.js +411 -0
  97. package/runtime/prompts/cognitive-routing.md +10 -0
  98. package/runtime/prompts/context-virtualization.md +3 -0
  99. package/runtime/prompts/conversation-history.md +3 -0
  100. package/runtime/prompts/core.md +84 -0
  101. package/runtime/prompts/interaction-contract.md +11 -0
  102. package/skills/action-selection/SKILL.md +140 -0
  103. package/skills/action-selection/references/trajectory-stalls.md +71 -0
  104. package/skills/bypass/SKILL.md +109 -38
  105. package/skills/commit-work/SKILL.md +94 -55
  106. package/skills/commit-work/references/git-state-edges.md +94 -0
  107. package/skills/commit-work/references/simple-push.md +92 -0
  108. package/skills/commit-work/references/staging-decisions.md +79 -46
  109. package/skills/decision-gate/SKILL.md +80 -22
  110. package/skills/design-for-depth/SKILL.md +206 -60
  111. package/skills/design-for-depth/references/design-pressure-signals.md +108 -240
  112. package/skills/design-for-depth/references/interface-design-loop.md +77 -97
  113. package/skills/design-for-depth/references/module-and-dependency-design.md +147 -0
  114. package/skills/design-for-depth/references/software-design-philosophy.md +128 -174
  115. package/skills/design-for-depth/references/state-and-failure-boundaries.md +136 -0
  116. package/skills/diagnose-failure/SKILL.md +200 -48
  117. package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +18 -6
  118. package/skills/diagnose-failure/references/{flaky-and-performance.md → flaky-and-performance-diagnosis.md} +13 -5
  119. package/skills/discuss/SKILL.md +119 -65
  120. package/skills/discuss/references/discussion-continuity.md +123 -0
  121. package/skills/evaluate-skill/SKILL.md +166 -52
  122. package/skills/evaluate-skill/references/{definition-schema.md → evaluation-definition-schema.md} +43 -3
  123. package/skills/evaluate-skill/references/evaluation-design.md +56 -30
  124. package/skills/evaluate-skill/references/execution-and-evidence.md +8 -3
  125. package/skills/evaluate-skill/references/review-and-revision.md +62 -21
  126. package/skills/evaluate-skill/scripts/lib/definitions.mjs +114 -3
  127. package/skills/evaluate-skill/scripts/lib/grade-interaction.mjs +156 -1
  128. package/skills/evaluate-skill/scripts/lib/grade.mjs +9 -1
  129. package/skills/evaluate-skill/scripts/lib/pi.mjs +147 -32
  130. package/skills/evaluate-skill/scripts/lib/rpc.mjs +4 -4
  131. package/skills/evaluate-skill/scripts/lib/runner.mjs +36 -14
  132. package/skills/evaluate-skill/scripts/lib/sandbox.mjs +92 -0
  133. package/skills/evaluate-skill/scripts/pi-guard.mjs +1 -1
  134. package/skills/evaluate-skill/scripts/pi-observer.mjs +66 -0
  135. package/skills/evaluate-skill/scripts/skill-eval.mjs +6 -5
  136. package/skills/execute-work/SKILL.md +99 -57
  137. package/skills/execute-work/references/code-practices.md +4 -4
  138. package/skills/execute-work/references/execute-work-edges.md +62 -0
  139. package/skills/finish-branch/SKILL.md +2 -2
  140. package/skills/finish-branch/references/integration-options.md +1 -1
  141. package/skills/handoff/SKILL.md +3 -3
  142. package/skills/launch-work/SKILL.md +1 -1
  143. package/skills/launch-work/references/launch-readiness.md +2 -2
  144. package/skills/migration-work/SKILL.md +2 -2
  145. package/skills/migration-work/references/migration-lifecycle.md +1 -1
  146. package/skills/release-work/SKILL.md +1 -1
  147. package/skills/release-work/references/release-evidence.md +1 -1
  148. package/skills/review-artifact/SKILL.md +129 -66
  149. package/skills/review-artifact/references/adjudicate-artifact-review.md +101 -0
  150. package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +159 -0
  151. package/skills/review-work/SKILL.md +113 -68
  152. package/skills/review-work/references/adjudicate-work-review.md +97 -0
  153. package/skills/review-work/references/independent-work-reviewer-contract.md +139 -0
  154. package/skills/review-work/references/security-risk-lens.md +18 -16
  155. package/skills/setup-freeflow/SKILL.md +16 -17
  156. package/skills/setup-freeflow/references/activation-contract.md +24 -30
  157. package/skills/setup-freeflow/references/host-setup.md +6 -7
  158. package/skills/simplify-code/SKILL.md +97 -39
  159. package/skills/simplify-code/references/simplification-patterns.md +1 -1
  160. package/skills/tdd/SKILL.md +100 -53
  161. package/skills/tdd/references/test-design.md +3 -3
  162. package/skills/track-work/SKILL.md +195 -58
  163. package/skills/track-work/references/working-record-format.md +515 -0
  164. package/skills/track-work/scripts/lib/document.mjs +713 -0
  165. package/skills/track-work/scripts/lib/format.mjs +166 -0
  166. package/skills/track-work/scripts/lib/store.mjs +233 -0
  167. package/skills/track-work/scripts/lib/transitions.mjs +790 -0
  168. package/skills/track-work/scripts/lib/views.mjs +40 -0
  169. package/skills/track-work/scripts/working-record.mjs +316 -0
  170. package/skills/verify-work/SKILL.md +57 -19
  171. package/skills/verify-work/references/browser-runtime-evidence.md +2 -2
  172. package/skills/verify-work/references/integration-evidence.md +1 -7
  173. package/skills/verify-work/references/performance-evidence.md +2 -2
  174. package/skills/workflow/SKILL.md +137 -55
  175. package/skills/workflow/references/domain-skill-composition.md +26 -40
  176. package/skills/write-plan/SKILL.md +1 -1
  177. package/skills/write-skill/SKILL.md +218 -61
  178. package/skills/write-skill/references/activation-boundaries.md +63 -21
  179. package/skills/write-skill/references/agent-first-instructions.md +61 -27
  180. package/skills/write-skill/references/progressive-disclosure.md +97 -33
  181. package/skills/write-skill/references/skill-dependency-graphs.md +190 -0
  182. package/capabilities/output-router/SKILL.md +0 -206
  183. package/capabilities/output-router/references/safety-policy.md +0 -40
  184. package/capabilities/output-router/references/setup.md +0 -110
  185. package/pi-extension/dist/output-router/host-producer-identification.js +0 -232
  186. package/pi-extension/dist/output-router/native-safety-net.js +0 -216
  187. package/pi-extension/dist/output-router/observed-tool-routing.js +0 -122
  188. package/pi-extension/dist/output-router/renderers.js +0 -1023
  189. package/pi-extension/dist/output-router/router-tools.js +0 -554
  190. package/pi-extension/dist/output-router/schemas.js +0 -383
  191. package/pi-extension/dist/output-router/status.js +0 -744
  192. package/pi-extension/dist/output-router/utils.js +0 -502
  193. package/pi-extension/src/output-router/host-producer-identification.ts +0 -256
  194. package/pi-extension/src/output-router/native-safety-net.ts +0 -248
  195. package/pi-extension/src/output-router/observed-tool-routing.ts +0 -134
  196. package/pi-extension/src/output-router/renderers.ts +0 -1108
  197. package/pi-extension/src/output-router/router-tools.ts +0 -579
  198. package/pi-extension/src/output-router/schemas.ts +0 -387
  199. package/pi-extension/src/output-router/status.ts +0 -791
  200. package/pi-extension/src/output-router/utils.ts +0 -554
  201. package/pi-extension/tests/output-router/observed-producers.test.js +0 -132
  202. package/pi-extension/tests/output-router/search.test.js +0 -722
  203. package/router/dist/benchmarks/benchmark-harness.d.ts +0 -35
  204. package/router/dist/benchmarks/benchmark-harness.js +0 -92
  205. package/router/dist/benchmarks/benchmarks.d.ts +0 -109
  206. package/router/dist/benchmarks/benchmarks.js +0 -979
  207. package/router/dist/benchmarks/codex-qa-benchmarks.d.ts +0 -95
  208. package/router/dist/benchmarks/codex-qa-benchmarks.js +0 -500
  209. package/router/dist/benchmarks/command-benchmarks.d.ts +0 -143
  210. package/router/dist/benchmarks/command-benchmarks.js +0 -698
  211. package/router/dist/benchmarks/context-mode-normalized-benchmarks.d.ts +0 -82
  212. package/router/dist/benchmarks/context-mode-normalized-benchmarks.js +0 -773
  213. package/router/dist/benchmarks/context-mode-real-deep-benchmark.d.ts +0 -132
  214. package/router/dist/benchmarks/context-mode-real-deep-benchmark.js +0 -1380
  215. package/router/dist/benchmarks/context-saving-baseline.d.ts +0 -60
  216. package/router/dist/benchmarks/context-saving-baseline.js +0 -470
  217. package/router/dist/benchmarks/index-benchmarks.d.ts +0 -103
  218. package/router/dist/benchmarks/index-benchmarks.js +0 -862
  219. package/router/dist/benchmarks/storage-policy-benchmarks.d.ts +0 -101
  220. package/router/dist/benchmarks/storage-policy-benchmarks.js +0 -618
  221. package/router/dist/benchmarks/vault-index-benchmarks.d.ts +0 -56
  222. package/router/dist/benchmarks/vault-index-benchmarks.js +0 -322
  223. package/router/dist/config/config.d.ts +0 -103
  224. package/router/dist/config/config.js +0 -632
  225. package/router/dist/config/router-contract.d.ts +0 -10
  226. package/router/dist/config/router-contract.js +0 -54
  227. package/router/dist/config/schema.d.ts +0 -27
  228. package/router/dist/config/schema.js +0 -648
  229. package/router/dist/config/types.d.ts +0 -573
  230. package/router/dist/config/types.js +0 -41
  231. package/router/dist/evidence/bounded-evidence.d.ts +0 -40
  232. package/router/dist/evidence/bounded-evidence.js +0 -323
  233. package/router/dist/evidence/evidence-range-selector.d.ts +0 -24
  234. package/router/dist/evidence/evidence-range-selector.js +0 -232
  235. package/router/dist/evidence/evidence-search.d.ts +0 -27
  236. package/router/dist/evidence/evidence-search.js +0 -490
  237. package/router/dist/evidence/evidence.d.ts +0 -38
  238. package/router/dist/evidence/evidence.js +0 -200
  239. package/router/dist/evidence/failure-contracts.d.ts +0 -37
  240. package/router/dist/evidence/failure-contracts.js +0 -166
  241. package/router/dist/evidence/line-ranges.d.ts +0 -24
  242. package/router/dist/evidence/line-ranges.js +0 -22
  243. package/router/dist/experiments/local-index.d.ts +0 -64
  244. package/router/dist/experiments/local-index.js +0 -581
  245. package/router/dist/index.d.ts +0 -30
  246. package/router/dist/index.js +0 -32
  247. package/router/dist/local/local-traversal.d.ts +0 -18
  248. package/router/dist/local/local-traversal.js +0 -334
  249. package/router/dist/processing/engine.d.ts +0 -132
  250. package/router/dist/processing/engine.js +0 -533
  251. package/router/dist/processing/reducers.d.ts +0 -280
  252. package/router/dist/processing/reducers.js +0 -1673
  253. package/router/dist/processing/renderers.d.ts +0 -31
  254. package/router/dist/processing/renderers.js +0 -195
  255. package/router/dist/processing/scripts.d.ts +0 -91
  256. package/router/dist/processing/scripts.js +0 -386
  257. package/router/dist/repo/repo-traversal.d.ts +0 -18
  258. package/router/dist/repo/repo-traversal.js +0 -245
  259. package/router/dist/routing/observed-reducers.d.ts +0 -41
  260. package/router/dist/routing/observed-reducers.js +0 -661
  261. package/router/dist/routing/observed-routing.d.ts +0 -26
  262. package/router/dist/routing/observed-routing.js +0 -378
  263. package/router/dist/routing/parsers.d.ts +0 -16
  264. package/router/dist/routing/parsers.js +0 -521
  265. package/router/dist/routing/run-filters.d.ts +0 -60
  266. package/router/dist/routing/run-filters.js +0 -238
  267. package/router/dist/routing/run-reducers.d.ts +0 -49
  268. package/router/dist/routing/run-reducers.js +0 -122
  269. package/router/dist/sandbox/adapter-roots.d.ts +0 -46
  270. package/router/dist/sandbox/adapter-roots.js +0 -66
  271. package/router/dist/sandbox/eryx-python-adapter.d.ts +0 -13
  272. package/router/dist/sandbox/eryx-python-adapter.js +0 -868
  273. package/router/dist/sandbox/jq-wasm-adapter.d.ts +0 -9
  274. package/router/dist/sandbox/jq-wasm-adapter.js +0 -429
  275. package/router/dist/sandbox/quickjs-wasi-adapter.d.ts +0 -13
  276. package/router/dist/sandbox/quickjs-wasi-adapter.js +0 -384
  277. package/router/dist/sandbox/script-sandbox.d.ts +0 -134
  278. package/router/dist/sandbox/script-sandbox.js +0 -337
  279. package/router/dist/setup/script-transform-adapters.d.ts +0 -32
  280. package/router/dist/setup/script-transform-adapters.js +0 -278
  281. package/router/dist/tools/batch.d.ts +0 -33
  282. package/router/dist/tools/batch.js +0 -586
  283. package/router/dist/tools/run.d.ts +0 -62
  284. package/router/dist/tools/run.js +0 -1304
  285. package/router/dist/tools/search.d.ts +0 -66
  286. package/router/dist/tools/search.js +0 -1364
  287. package/router/dist/transform/engine.d.ts +0 -168
  288. package/router/dist/transform/engine.js +0 -2072
  289. package/router/dist/vault/vault-index.d.ts +0 -125
  290. package/router/dist/vault/vault-index.js +0 -416
  291. package/router/dist/vault/vault.d.ts +0 -138
  292. package/router/dist/vault/vault.js +0 -630
  293. package/runtime/interaction-contract.md +0 -16
  294. package/skills/discuss/references/checkpoints.md +0 -66
  295. package/skills/execute-work/references/execution-loop.md +0 -77
  296. package/skills/mode-contract/SKILL.md +0 -104
  297. package/skills/review-artifact/references/reviewer-prompt.md +0 -148
  298. package/skills/review-work/references/reviewer-prompt.md +0 -134
  299. package/skills/track-work/references/working-record-schema.md +0 -378
  300. package/skills/workflow/references/workflow-loop.md +0 -92
  301. /package/skills/handoff/references/{templates.md → handoff-templates.md} +0 -0
@@ -0,0 +1,444 @@
1
+ import type { CognitiveRoutingThinkingLevel } from "./types.js";
2
+
3
+ export const PI_SESSION_MODEL_STATE_ENTRY = "freeflow-cognitive-routing-model-state";
4
+
5
+ export function supportsPiSessionModelStateApi(pi: unknown): boolean {
6
+ if (!pi || typeof pi !== "object") return false;
7
+ const candidate = pi as Record<string, unknown>;
8
+ return (
9
+ typeof candidate.appendEntry === "function" &&
10
+ typeof candidate.setModel === "function" &&
11
+ typeof candidate.setThinkingLevel === "function"
12
+ );
13
+ }
14
+
15
+ export type PiSessionModelStatePair = {
16
+ provider: string;
17
+ modelId: string;
18
+ thinkingLevel: CognitiveRoutingThinkingLevel;
19
+ };
20
+
21
+ export type PiSessionModelStateRequest = PiSessionModelStatePair & {
22
+ correlationId: string;
23
+ };
24
+
25
+ type PiModel = {
26
+ provider: string;
27
+ id: string;
28
+ };
29
+
30
+ type PiSessionModelStatePi = {
31
+ setModel(model: PiModel): Promise<boolean>;
32
+ setThinkingLevel(level: CognitiveRoutingThinkingLevel): void;
33
+ appendEntry(customType: string, data?: unknown): void;
34
+ };
35
+
36
+ type PiSessionModelStateContext = {
37
+ readonly model?: PiModel;
38
+ readonly thinkingLevel?: CognitiveRoutingThinkingLevel;
39
+ readonly modelRegistry?: {
40
+ find(provider: string, modelId: string): PiModel | undefined;
41
+ };
42
+ };
43
+
44
+ export type PiSessionModelStateCommit = {
45
+ version: 1;
46
+ phase: "prepared" | "committed" | "aborted";
47
+ status: "prepared" | "applied" | "rolled-back" | "rollback-failed";
48
+ correlationId: string;
49
+ fromPair: PiSessionModelStatePair;
50
+ target: PiSessionModelStatePair;
51
+ failure?:
52
+ | "model-change-failed"
53
+ | "thinking-level-change-failed"
54
+ | "pair-verification-failed"
55
+ | "rollback-failed"
56
+ | "commit-persistence-failed"
57
+ | "interrupted-transition";
58
+ observedPair?: PiSessionModelStatePair;
59
+ origin: {
60
+ source: "pi";
61
+ operation: "session-model-state-control";
62
+ };
63
+ };
64
+
65
+ const THINKING_LEVELS = new Set<CognitiveRoutingThinkingLevel>([
66
+ "off",
67
+ "minimal",
68
+ "low",
69
+ "medium",
70
+ "high",
71
+ "xhigh",
72
+ "max",
73
+ ]);
74
+
75
+ type RecordValue = Record<string, unknown>;
76
+
77
+ function isRecord(value: unknown): value is RecordValue {
78
+ return typeof value === "object" && value !== null;
79
+ }
80
+
81
+ function isThinkingLevel(value: unknown): value is CognitiveRoutingThinkingLevel {
82
+ return typeof value === "string" && THINKING_LEVELS.has(value as CognitiveRoutingThinkingLevel);
83
+ }
84
+
85
+ function appendModelStateCommit(pi: PiSessionModelStatePi, commit: PiSessionModelStateCommit): boolean {
86
+ try {
87
+ pi.appendEntry(PI_SESSION_MODEL_STATE_ENTRY, commit);
88
+ return true;
89
+ } catch {
90
+ return false;
91
+ }
92
+ }
93
+
94
+ function pairFrom(value: unknown): PiSessionModelStatePair | undefined {
95
+ if (!isRecord(value)) return undefined;
96
+ if (
97
+ typeof value.provider !== "string" ||
98
+ typeof value.modelId !== "string" ||
99
+ !isThinkingLevel(value.thinkingLevel)
100
+ ) {
101
+ return undefined;
102
+ }
103
+ return {
104
+ provider: value.provider,
105
+ modelId: value.modelId,
106
+ thinkingLevel: value.thinkingLevel,
107
+ };
108
+ }
109
+
110
+ function failureFrom(value: unknown): PiSessionModelStateCommit["failure"] | undefined {
111
+ if (
112
+ value === "model-change-failed" ||
113
+ value === "thinking-level-change-failed" ||
114
+ value === "pair-verification-failed" ||
115
+ value === "rollback-failed" ||
116
+ value === "commit-persistence-failed" ||
117
+ value === "interrupted-transition"
118
+ ) {
119
+ return value;
120
+ }
121
+ return undefined;
122
+ }
123
+
124
+ function originFrom(value: unknown): PiSessionModelStateCommit["origin"] | undefined {
125
+ if (!isRecord(value)) return undefined;
126
+ if (value.source !== "pi" || value.operation !== "session-model-state-control") return undefined;
127
+ return { source: "pi", operation: "session-model-state-control" };
128
+ }
129
+
130
+ export function parsePiSessionModelStateCommit(value: unknown): PiSessionModelStateCommit | undefined {
131
+ if (!isRecord(value) || value.version !== 1) return undefined;
132
+ if (value.phase !== "prepared" && value.phase !== "committed" && value.phase !== "aborted") return undefined;
133
+ if (
134
+ value.status !== "prepared" &&
135
+ value.status !== "applied" &&
136
+ value.status !== "rolled-back" &&
137
+ value.status !== "rollback-failed"
138
+ ) {
139
+ return undefined;
140
+ }
141
+ if (typeof value.correlationId !== "string") return undefined;
142
+
143
+ const fromPair = pairFrom(value.fromPair);
144
+ const target = pairFrom(value.target);
145
+ const origin = originFrom(value.origin);
146
+ if (!fromPair || !target || !origin) return undefined;
147
+ if (value.phase === "prepared" && value.status !== "prepared") return undefined;
148
+ if (value.phase === "committed" && value.status !== "applied") return undefined;
149
+ if (value.phase === "aborted" && (value.status === "prepared" || value.status === "applied")) return undefined;
150
+
151
+ const failure = failureFrom(value.failure);
152
+ if ((value.phase === "prepared" || value.phase === "committed") && value.failure !== undefined) return undefined;
153
+ if (value.phase === "aborted" && !failure) return undefined;
154
+
155
+ let observedPair: PiSessionModelStatePair | undefined;
156
+ if (value.observedPair !== undefined) {
157
+ observedPair = pairFrom(value.observedPair);
158
+ if (!observedPair) return undefined;
159
+ }
160
+
161
+ return {
162
+ version: 1,
163
+ phase: value.phase,
164
+ status: value.status,
165
+ correlationId: value.correlationId,
166
+ fromPair,
167
+ target,
168
+ ...(failure ? { failure } : {}),
169
+ ...(observedPair ? { observedPair } : {}),
170
+ origin,
171
+ };
172
+ }
173
+
174
+ type PiSessionModelStateLease = {
175
+ setState(request: PiSessionModelStateRequest): Promise<{ status: "applied" | "rejected" }>;
176
+ release(): Promise<{ status: "released" }>;
177
+ };
178
+
179
+ export type PiSessionModelStateAcquisition =
180
+ { status: "acquired"; lease: PiSessionModelStateLease } | { status: "conflict"; owner: string };
181
+
182
+ function currentPair(ctx: PiSessionModelStateContext): PiSessionModelStatePair | undefined {
183
+ const model = ctx.model;
184
+ if (!model || typeof model.provider !== "string" || typeof model.id !== "string") return undefined;
185
+ if (!ctx.thinkingLevel) return undefined;
186
+ return {
187
+ provider: model.provider,
188
+ modelId: model.id,
189
+ thinkingLevel: ctx.thinkingLevel,
190
+ };
191
+ }
192
+
193
+ function pairsEqual(left: PiSessionModelStatePair | undefined, right: PiSessionModelStatePair): boolean {
194
+ return (
195
+ left?.provider === right.provider && left.modelId === right.modelId && left.thinkingLevel === right.thinkingLevel
196
+ );
197
+ }
198
+
199
+ async function restorePair(
200
+ pi: PiSessionModelStatePi,
201
+ ctx: PiSessionModelStateContext,
202
+ pair: PiSessionModelStatePair,
203
+ ): Promise<boolean> {
204
+ const model = ctx.modelRegistry?.find(pair.provider, pair.modelId);
205
+ if (!model) return false;
206
+
207
+ try {
208
+ if (!(await pi.setModel(model))) return false;
209
+ pi.setThinkingLevel(pair.thinkingLevel);
210
+ return pairsEqual(currentPair(ctx), pair);
211
+ } catch {
212
+ return false;
213
+ }
214
+ }
215
+
216
+ export function createPiSessionControllerHost({
217
+ pi,
218
+ ctx,
219
+ }: {
220
+ pi: PiSessionModelStatePi;
221
+ ctx: PiSessionModelStateContext;
222
+ }) {
223
+ const control = createPiSessionModelStateControl({ pi, ctx });
224
+ return {
225
+ appendEntryDurable(customType: string, data: unknown): void {
226
+ pi.appendEntry(customType, data);
227
+ },
228
+ acquireModelStateControl: control.acquireModelStateControl,
229
+ recoverPreparedModelState: control.recoverPreparedModelState,
230
+ };
231
+ }
232
+
233
+ export function createPiSessionModelStateControl({
234
+ pi,
235
+ ctx,
236
+ }: {
237
+ pi: PiSessionModelStatePi;
238
+ ctx: PiSessionModelStateContext;
239
+ }) {
240
+ let owner: string | undefined;
241
+
242
+ return {
243
+ async recoverPreparedModelState({
244
+ fromPair,
245
+ target,
246
+ correlationId,
247
+ }: {
248
+ fromPair: PiSessionModelStatePair;
249
+ target: PiSessionModelStatePair;
250
+ correlationId: string;
251
+ }): Promise<{ status: "restored" | "rollback-failed" | "rejected" }> {
252
+ const current = currentPair(ctx);
253
+ if (!current || !pairsEqual(current, fromPair)) {
254
+ if (!(await restorePair(pi, ctx, fromPair))) {
255
+ const rollbackFailed: PiSessionModelStateCommit = {
256
+ version: 1,
257
+ phase: "aborted",
258
+ status: "rollback-failed",
259
+ correlationId,
260
+ fromPair,
261
+ target,
262
+ failure: "rollback-failed",
263
+ ...(currentPair(ctx) ? { observedPair: currentPair(ctx) } : {}),
264
+ origin: { source: "pi", operation: "session-model-state-control" },
265
+ };
266
+ try {
267
+ pi.appendEntry(PI_SESSION_MODEL_STATE_ENTRY, rollbackFailed);
268
+ } catch {
269
+ return { status: "rejected" };
270
+ }
271
+ return { status: "rollback-failed" };
272
+ }
273
+ }
274
+
275
+ const aborted: PiSessionModelStateCommit = {
276
+ version: 1,
277
+ phase: "aborted",
278
+ status: "rolled-back",
279
+ correlationId,
280
+ fromPair,
281
+ target,
282
+ failure: "interrupted-transition",
283
+ origin: { source: "pi", operation: "session-model-state-control" },
284
+ };
285
+ try {
286
+ pi.appendEntry(PI_SESSION_MODEL_STATE_ENTRY, aborted);
287
+ } catch {
288
+ return { status: "rejected" };
289
+ }
290
+ return { status: "restored" };
291
+ },
292
+ async acquireModelStateControl({ label }: { label: string }): Promise<PiSessionModelStateAcquisition> {
293
+ if (owner !== undefined) return { status: "conflict", owner };
294
+ owner = label;
295
+ let released = false;
296
+
297
+ return {
298
+ status: "acquired",
299
+ lease: {
300
+ async setState(request) {
301
+ if (released) return { status: "rejected" };
302
+
303
+ const fromPair = currentPair(ctx);
304
+ const targetModel = ctx.modelRegistry?.find(request.provider, request.modelId);
305
+ if (!fromPair || !targetModel) return { status: "rejected" };
306
+
307
+ const target = {
308
+ provider: request.provider,
309
+ modelId: request.modelId,
310
+ thinkingLevel: request.thinkingLevel,
311
+ } satisfies PiSessionModelStatePair;
312
+ const prepared: PiSessionModelStateCommit = {
313
+ version: 1,
314
+ phase: "prepared",
315
+ status: "prepared",
316
+ correlationId: request.correlationId,
317
+ fromPair,
318
+ target,
319
+ origin: { source: "pi", operation: "session-model-state-control" },
320
+ };
321
+ try {
322
+ pi.appendEntry(PI_SESSION_MODEL_STATE_ENTRY, prepared);
323
+ } catch {
324
+ return { status: "rejected" };
325
+ }
326
+
327
+ let failure: PiSessionModelStateCommit["failure"];
328
+
329
+ try {
330
+ const applied = await pi.setModel(targetModel);
331
+ if (!applied) {
332
+ const aborted: PiSessionModelStateCommit = {
333
+ version: 1,
334
+ phase: "aborted",
335
+ status: "rolled-back",
336
+ correlationId: request.correlationId,
337
+ fromPair,
338
+ target,
339
+ failure: "model-change-failed",
340
+ origin: { source: "pi", operation: "session-model-state-control" },
341
+ };
342
+ appendModelStateCommit(pi, aborted);
343
+ return { status: "rejected" };
344
+ }
345
+ try {
346
+ pi.setThinkingLevel(request.thinkingLevel);
347
+ } catch {
348
+ failure = "thinking-level-change-failed";
349
+ }
350
+ if (!failure && !pairsEqual(currentPair(ctx), target)) {
351
+ failure = "pair-verification-failed";
352
+ }
353
+ } catch {
354
+ failure = "model-change-failed";
355
+ }
356
+
357
+ if (failure) {
358
+ const restored = await restorePair(pi, ctx, fromPair);
359
+ if (!restored) {
360
+ const rollbackFailed: PiSessionModelStateCommit = {
361
+ version: 1,
362
+ phase: "aborted",
363
+ status: "rollback-failed",
364
+ correlationId: request.correlationId,
365
+ fromPair,
366
+ target,
367
+ failure: "rollback-failed",
368
+ ...(currentPair(ctx) ? { observedPair: currentPair(ctx) } : {}),
369
+ origin: { source: "pi", operation: "session-model-state-control" },
370
+ };
371
+ appendModelStateCommit(pi, rollbackFailed);
372
+ return { status: "rejected" };
373
+ }
374
+
375
+ const aborted: PiSessionModelStateCommit = {
376
+ version: 1,
377
+ phase: "aborted",
378
+ status: "rolled-back",
379
+ correlationId: request.correlationId,
380
+ fromPair,
381
+ target,
382
+ failure,
383
+ origin: { source: "pi", operation: "session-model-state-control" },
384
+ };
385
+ appendModelStateCommit(pi, aborted);
386
+ return { status: "rejected" };
387
+ }
388
+
389
+ const commit: PiSessionModelStateCommit = {
390
+ version: 1,
391
+ phase: "committed",
392
+ status: "applied",
393
+ correlationId: request.correlationId,
394
+ fromPair,
395
+ target,
396
+ origin: { source: "pi", operation: "session-model-state-control" },
397
+ };
398
+ try {
399
+ if (!appendModelStateCommit(pi, commit)) throw new Error("commit persistence failed");
400
+ return { status: "applied" };
401
+ } catch {
402
+ const restored = await restorePair(pi, ctx, fromPair);
403
+ if (!restored) {
404
+ const rollbackFailed: PiSessionModelStateCommit = {
405
+ version: 1,
406
+ phase: "aborted",
407
+ status: "rollback-failed",
408
+ correlationId: request.correlationId,
409
+ fromPair,
410
+ target,
411
+ failure: "rollback-failed",
412
+ ...(currentPair(ctx) ? { observedPair: currentPair(ctx) } : {}),
413
+ origin: { source: "pi", operation: "session-model-state-control" },
414
+ };
415
+ appendModelStateCommit(pi, rollbackFailed);
416
+ return { status: "rejected" };
417
+ }
418
+
419
+ const aborted: PiSessionModelStateCommit = {
420
+ version: 1,
421
+ phase: "aborted",
422
+ status: "rolled-back",
423
+ correlationId: request.correlationId,
424
+ fromPair,
425
+ target,
426
+ failure: "commit-persistence-failed",
427
+ origin: { source: "pi", operation: "session-model-state-control" },
428
+ };
429
+ appendModelStateCommit(pi, aborted);
430
+ return { status: "rejected" };
431
+ }
432
+ },
433
+ async release() {
434
+ if (!released) {
435
+ released = true;
436
+ if (owner === label) owner = undefined;
437
+ }
438
+ return { status: "released" };
439
+ },
440
+ },
441
+ };
442
+ },
443
+ };
444
+ }
@@ -0,0 +1,57 @@
1
+ import { resolveCognitiveRoutingConfig } from "./config.js";
2
+ import { preflightCognitiveRoutingProfiles } from "./host.js";
3
+ import type {
4
+ CognitiveRoutingBlockingReason,
5
+ CognitiveRoutingCapabilityState,
6
+ CognitiveRoutingConfigResolution,
7
+ } from "./types.js";
8
+
9
+ function blockingReason(code: CognitiveRoutingBlockingReason["code"], message: string): CognitiveRoutingBlockingReason {
10
+ return { code, message };
11
+ }
12
+
13
+ function baseState(config: CognitiveRoutingConfigResolution): CognitiveRoutingCapabilityState {
14
+ return {
15
+ configured: config.configured,
16
+ configValid: config.valid,
17
+ enabled: config.enabled,
18
+ effective: false,
19
+ enabledSource: config.enabledSource,
20
+ profiles: config.profiles,
21
+ profileSources: config.profileSources,
22
+ sessionStart: config.sessionStart,
23
+ sessionStartSources: config.sessionStartSources,
24
+ resolvedProfiles: {},
25
+ blockingReason: blockingReason("disabled", "Cognitive Routing is disabled"),
26
+ };
27
+ }
28
+
29
+ export async function resolveCognitiveRoutingState(
30
+ repositoryConfig: unknown,
31
+ personalConfig: unknown,
32
+ host: unknown,
33
+ ): Promise<CognitiveRoutingCapabilityState> {
34
+ const config = resolveCognitiveRoutingConfig(repositoryConfig, personalConfig);
35
+ const state = baseState(config);
36
+
37
+ if (!config.valid) {
38
+ return {
39
+ ...state,
40
+ blockingReason: blockingReason(
41
+ "config_invalid",
42
+ config.error?.message ?? "Cognitive Routing configuration is invalid",
43
+ ),
44
+ };
45
+ }
46
+ if (!config.enabled) {
47
+ return state;
48
+ }
49
+
50
+ const preflight = await preflightCognitiveRoutingProfiles(config, host);
51
+ return {
52
+ ...state,
53
+ effective: preflight.effective,
54
+ resolvedProfiles: preflight.resolvedProfiles,
55
+ blockingReason: preflight.blockingReason ?? blockingReason("disabled", "Cognitive Routing is not effective"),
56
+ };
57
+ }